Loading fs/fuse/dir.c +45 −49 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) { /* Loading Loading @@ -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++; Loading @@ -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, Loading Loading @@ -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, Loading Loading
fs/fuse/dir.c +45 −49 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) { /* Loading Loading @@ -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++; Loading @@ -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, Loading Loading @@ -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, Loading