Loading fs/fuse/dir.c +45 −49 Original line number Original line Diff line number Diff line Loading @@ -1162,7 +1162,6 @@ static int fuse_direntplus_link(struct file *file, struct fuse_direntplus *direntplus, struct fuse_direntplus *direntplus, u64 attr_version) u64 attr_version) { { int err; struct fuse_entry_out *o = &direntplus->entry_out; struct fuse_entry_out *o = &direntplus->entry_out; struct fuse_dirent *dirent = &direntplus->dirent; struct fuse_dirent *dirent = &direntplus->dirent; struct dentry *parent = file->f_path.dentry; 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 inode *dir = d_inode(parent); struct fuse_conn *fc; struct fuse_conn *fc; struct inode *inode; struct inode *inode; DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); if (!o->nodeid) { 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); name.hash = full_name_hash(name.name, name.len); dentry = d_lookup(parent, &name); 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); inode = d_inode(dentry); if (!inode) { if (!inode || d_drop(dentry); get_node_id(inode) != o->nodeid || } else if (get_node_id(inode) != o->nodeid || ((o->attr.mode ^ inode->i_mode) & S_IFMT)) { ((o->attr.mode ^ inode->i_mode) & S_IFMT)) { d_invalidate(dentry); d_invalidate(dentry); } else if (is_bad_inode(inode)) { dput(dentry); err = -EIO; goto retry; goto out; } } else { if (is_bad_inode(inode)) { struct fuse_inode *fi; dput(dentry); return -EIO; } fi = get_fuse_inode(inode); fi = get_fuse_inode(inode); spin_lock(&fc->lock); spin_lock(&fc->lock); fi->nlookup++; fi->nlookup++; Loading @@ -1224,45 +1233,32 @@ static int fuse_direntplus_link(struct file *file, fuse_change_attributes(inode, &o->attr, fuse_change_attributes(inode, &o->attr, entry_attr_timeout(o), entry_attr_timeout(o), attr_version); attr_version); /* /* * The other branch to 'found' comes via fuse_iget() * The other branch comes via fuse_iget() * which bumps nlookup inside * which bumps nlookup inside */ */ goto found; } else { } dput(dentry); } dentry = d_alloc(parent, &name); err = -ENOMEM; if (!dentry) goto out; inode = fuse_iget(dir->i_sb, o->nodeid, o->generation, 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) if (!inode) goto out; inode = ERR_PTR(-ENOMEM); alias = d_splice_alias(inode, dentry); alias = d_splice_alias(inode, dentry); err = PTR_ERR(alias); d_lookup_done(dentry); if (IS_ERR(alias)) goto out; if (alias) { if (alias) { dput(dentry); dput(dentry); dentry = alias; dentry = alias; } } if (IS_ERR(dentry)) found: return PTR_ERR(dentry); } if (fc->readdirplus_auto) if (fc->readdirplus_auto) set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state); set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state); fuse_change_entry_timeout(dentry, o); fuse_change_entry_timeout(dentry, o); err = 0; out: dput(dentry); dput(dentry); return err; return 0; } } static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file, 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 = { static const struct file_operations fuse_dir_operations = { .llseek = generic_file_llseek, .llseek = generic_file_llseek, .read = generic_read_dir, .read = generic_read_dir, .iterate = fuse_readdir, .iterate_shared = fuse_readdir, .open = fuse_dir_open, .open = fuse_dir_open, .release = fuse_dir_release, .release = fuse_dir_release, .fsync = fuse_dir_fsync, .fsync = fuse_dir_fsync, Loading Loading
fs/fuse/dir.c +45 −49 Original line number Original line Diff line number Diff line Loading @@ -1162,7 +1162,6 @@ static int fuse_direntplus_link(struct file *file, struct fuse_direntplus *direntplus, struct fuse_direntplus *direntplus, u64 attr_version) u64 attr_version) { { int err; struct fuse_entry_out *o = &direntplus->entry_out; struct fuse_entry_out *o = &direntplus->entry_out; struct fuse_dirent *dirent = &direntplus->dirent; struct fuse_dirent *dirent = &direntplus->dirent; struct dentry *parent = file->f_path.dentry; 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 inode *dir = d_inode(parent); struct fuse_conn *fc; struct fuse_conn *fc; struct inode *inode; struct inode *inode; DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); if (!o->nodeid) { 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); name.hash = full_name_hash(name.name, name.len); dentry = d_lookup(parent, &name); 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); inode = d_inode(dentry); if (!inode) { if (!inode || d_drop(dentry); get_node_id(inode) != o->nodeid || } else if (get_node_id(inode) != o->nodeid || ((o->attr.mode ^ inode->i_mode) & S_IFMT)) { ((o->attr.mode ^ inode->i_mode) & S_IFMT)) { d_invalidate(dentry); d_invalidate(dentry); } else if (is_bad_inode(inode)) { dput(dentry); err = -EIO; goto retry; goto out; } } else { if (is_bad_inode(inode)) { struct fuse_inode *fi; dput(dentry); return -EIO; } fi = get_fuse_inode(inode); fi = get_fuse_inode(inode); spin_lock(&fc->lock); spin_lock(&fc->lock); fi->nlookup++; fi->nlookup++; Loading @@ -1224,45 +1233,32 @@ static int fuse_direntplus_link(struct file *file, fuse_change_attributes(inode, &o->attr, fuse_change_attributes(inode, &o->attr, entry_attr_timeout(o), entry_attr_timeout(o), attr_version); attr_version); /* /* * The other branch to 'found' comes via fuse_iget() * The other branch comes via fuse_iget() * which bumps nlookup inside * which bumps nlookup inside */ */ goto found; } else { } dput(dentry); } dentry = d_alloc(parent, &name); err = -ENOMEM; if (!dentry) goto out; inode = fuse_iget(dir->i_sb, o->nodeid, o->generation, 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) if (!inode) goto out; inode = ERR_PTR(-ENOMEM); alias = d_splice_alias(inode, dentry); alias = d_splice_alias(inode, dentry); err = PTR_ERR(alias); d_lookup_done(dentry); if (IS_ERR(alias)) goto out; if (alias) { if (alias) { dput(dentry); dput(dentry); dentry = alias; dentry = alias; } } if (IS_ERR(dentry)) found: return PTR_ERR(dentry); } if (fc->readdirplus_auto) if (fc->readdirplus_auto) set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state); set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state); fuse_change_entry_timeout(dentry, o); fuse_change_entry_timeout(dentry, o); err = 0; out: dput(dentry); dput(dentry); return err; return 0; } } static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file, 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 = { static const struct file_operations fuse_dir_operations = { .llseek = generic_file_llseek, .llseek = generic_file_llseek, .read = generic_read_dir, .read = generic_read_dir, .iterate = fuse_readdir, .iterate_shared = fuse_readdir, .open = fuse_dir_open, .open = fuse_dir_open, .release = fuse_dir_release, .release = fuse_dir_release, .fsync = fuse_dir_fsync, .fsync = fuse_dir_fsync, Loading