Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d9b3dbdc authored by Al Viro's avatar Al Viro
Browse files

fuse: switch to ->iterate_shared()



Switch dcache pre-seeding on readdir to d_alloc_parallel();
nothing else is needed.

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent f50752ea
Loading
Loading
Loading
Loading
+45 −49
Original line number Diff line number Diff line
@@ -1162,7 +1162,6 @@ static int fuse_direntplus_link(struct file *file,
				struct fuse_direntplus *direntplus,
				u64 attr_version)
{
	int err;
	struct fuse_entry_out *o = &direntplus->entry_out;
	struct fuse_dirent *dirent = &direntplus->dirent;
	struct dentry *parent = file->f_path.dentry;
@@ -1172,6 +1171,7 @@ static int fuse_direntplus_link(struct file *file,
	struct inode *dir = d_inode(parent);
	struct fuse_conn *fc;
	struct inode *inode;
	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);

	if (!o->nodeid) {
		/*
@@ -1204,18 +1204,27 @@ static int fuse_direntplus_link(struct file *file,

	name.hash = full_name_hash(name.name, name.len);
	dentry = d_lookup(parent, &name);
	if (dentry) {
	if (!dentry) {
retry:
		dentry = d_alloc_parallel(parent, &name, &wq);
		if (IS_ERR(dentry))
			return PTR_ERR(dentry);
	}
	if (!d_in_lookup(dentry)) {
		struct fuse_inode *fi;
		inode = d_inode(dentry);
		if (!inode) {
			d_drop(dentry);
		} else if (get_node_id(inode) != o->nodeid ||
		if (!inode ||
		    get_node_id(inode) != o->nodeid ||
		    ((o->attr.mode ^ inode->i_mode) & S_IFMT)) {
			d_invalidate(dentry);
		} else if (is_bad_inode(inode)) {
			err = -EIO;
			goto out;
		} else {
			struct fuse_inode *fi;
			dput(dentry);
			goto retry;
		}
		if (is_bad_inode(inode)) {
			dput(dentry);
			return -EIO;
		}

		fi = get_fuse_inode(inode);
		spin_lock(&fc->lock);
		fi->nlookup++;
@@ -1224,45 +1233,32 @@ static int fuse_direntplus_link(struct file *file,
		fuse_change_attributes(inode, &o->attr,
				       entry_attr_timeout(o),
				       attr_version);

		/*
			 * The other branch to 'found' comes via fuse_iget()
		 * The other branch comes via fuse_iget()
		 * which bumps nlookup inside
		 */
			goto found;
		}
		dput(dentry);
	}

	dentry = d_alloc(parent, &name);
	err = -ENOMEM;
	if (!dentry)
		goto out;

	} else {
		inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
			  &o->attr, entry_attr_timeout(o), attr_version);
				  &o->attr, entry_attr_timeout(o),
				  attr_version);
		if (!inode)
		goto out;
			inode = ERR_PTR(-ENOMEM);

		alias = d_splice_alias(inode, dentry);
	err = PTR_ERR(alias);
	if (IS_ERR(alias))
		goto out;

		d_lookup_done(dentry);
		if (alias) {
			dput(dentry);
			dentry = alias;
		}

found:
		if (IS_ERR(dentry))
			return PTR_ERR(dentry);
	}
	if (fc->readdirplus_auto)
		set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state);
	fuse_change_entry_timeout(dentry, o);

	err = 0;
out:
	dput(dentry);
	return err;
	return 0;
}

static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
@@ -1892,7 +1888,7 @@ static const struct inode_operations fuse_dir_inode_operations = {
static const struct file_operations fuse_dir_operations = {
	.llseek		= generic_file_llseek,
	.read		= generic_read_dir,
	.iterate	= fuse_readdir,
	.iterate_shared	= fuse_readdir,
	.open		= fuse_dir_open,
	.release	= fuse_dir_release,
	.fsync		= fuse_dir_fsync,