diff --git a/fs/afs/dynroot.c b/fs/afs/dynroot.c index d8bf52f77d93..faed91d65dc8 100644 --- a/fs/afs/dynroot.c +++ b/fs/afs/dynroot.c @@ -80,7 +80,7 @@ struct inode *afs_iget_pseudo_dir(struct super_block *sb, bool root) inode->i_size = 0; inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO; if (root) { - inode->i_op = &afs_dynroot_inode_operations; + inode->i_op = &simple_dir_inode_operations; inode->i_fop = &simple_dir_operations; } else { inode->i_op = &afs_autocell_inode_operations; @@ -185,31 +185,6 @@ struct inode *afs_try_auto_mntpt(struct dentry *dentry, struct inode *dir) return ret == -ENOENT ? NULL : ERR_PTR(ret); } -/* - * Look up an entry in a dynroot directory. - */ -static struct dentry *afs_dynroot_lookup(struct inode *dir, struct dentry *dentry, - unsigned int flags) -{ - _enter("%pd", dentry); - - ASSERTCMP(d_inode(dentry), ==, NULL); - - if (flags & LOOKUP_CREATE) - return ERR_PTR(-EOPNOTSUPP); - - if (dentry->d_name.len >= AFSNAMEMAX) { - _leave(" = -ENAMETOOLONG"); - return ERR_PTR(-ENAMETOOLONG); - } - - return d_splice_alias(afs_try_auto_mntpt(dentry, dir), dentry); -} - -const struct inode_operations afs_dynroot_inode_operations = { - .lookup = afs_dynroot_lookup, -}; - const struct dentry_operations afs_dynroot_dentry_operations = { .d_delete = always_delete_dentry, .d_release = afs_d_release, @@ -233,22 +208,20 @@ int afs_dynroot_mkdir(struct afs_net *net, struct afs_cell *cell) /* Let the ->lookup op do the creation */ root = sb->s_root; inode_lock(root->d_inode); - subdir = lookup_one_len(cell->name, root, cell->name_len); + subdir = start_creating_persistent(root, cell->name); if (IS_ERR(subdir)) { ret = PTR_ERR(subdir); goto unlock; } + d_add(subdir, afs_try_auto_mntpt(subdir, root->d_inode)); - dsubdir = lookup_one_len(dotname, root, cell->name_len + 1); + dsubdir = start_creating_persistent(root, dotname); if (IS_ERR(dsubdir)) { ret = PTR_ERR(dsubdir); - dput(subdir); + d_make_discardable(subdir); goto unlock; } - - /* Note that we're retaining extra refs on the dentries. */ - subdir->d_fsdata = (void *)1UL; - dsubdir->d_fsdata = (void *)1UL; + d_add(dsubdir, afs_try_auto_mntpt(dsubdir, root->d_inode)); ret = 0; unlock: inode_unlock(root->d_inode); @@ -257,23 +230,9 @@ int afs_dynroot_mkdir(struct afs_net *net, struct afs_cell *cell) static void afs_dynroot_rm_one_dir(struct dentry *root, const char *name, size_t name_len) { - struct dentry *subdir; - - /* Don't want to trigger a lookup call, which will re-add the cell */ - subdir = try_lookup_one_len(name, root, name_len); - if (IS_ERR_OR_NULL(subdir)) { - _debug("lookup %ld", PTR_ERR(subdir)); - return; - } - - _debug("rmdir %pd %u", subdir, d_count(subdir)); - - if (subdir->d_fsdata) { - _debug("unpin %u", d_count(subdir)); - subdir->d_fsdata = NULL; - dput(subdir); - } - dput(subdir); + struct dentry *subdir = lookup_positive_unlocked(name, root, name_len); + if (!IS_ERR(subdir)) + simple_recursive_removal(subdir, NULL); } /* @@ -288,10 +247,8 @@ void afs_dynroot_rmdir(struct afs_net *net, struct afs_cell *cell) if (!sb || atomic_read(&sb->s_active) == 0) return; - inode_lock(sb->s_root->d_inode); afs_dynroot_rm_one_dir(sb->s_root, cell->name, cell->name_len); afs_dynroot_rm_one_dir(sb->s_root, dotname, cell->name_len + 1); - inode_unlock(sb->s_root->d_inode); _leave(""); } @@ -349,14 +306,14 @@ static struct dentry *afs_dynroot_create_symlink(struct dentry *root, const char if (name[0] == '.') fid.vnode = 3; - dentry = d_alloc_name(root, name); - if (!dentry) - return ERR_PTR(-ENOMEM); + dentry = d_alloc_persistent(root, name); + if (IS_ERR(dentry)) + return dentry; inode = iget5_locked(dentry->d_sb, fid.vnode, afs_iget5_pseudo_test, afs_iget5_pseudo_set, &fid); if (!inode) { - dput(dentry); + d_make_discardable(dentry); return ERR_PTR(-ENOMEM); } @@ -365,7 +322,7 @@ static struct dentry *afs_dynroot_create_symlink(struct dentry *root, const char /* there shouldn't be an existing inode */ if (WARN_ON_ONCE(!(inode->i_state & I_NEW))) { iput(inode); - dput(dentry); + d_make_discardable(dentry); return ERR_PTR(-EIO); } @@ -382,7 +339,7 @@ static struct dentry *afs_dynroot_create_symlink(struct dentry *root, const char inode->i_flags |= S_NOATIME; unlock_new_inode(inode); - d_splice_alias(inode, dentry); + d_add(dentry, inode); return dentry; } @@ -407,13 +364,9 @@ static int afs_dynroot_symlink(struct afs_net *net) dsymlink = afs_dynroot_create_symlink(root, ".@cell"); if (IS_ERR(dsymlink)) { ret = PTR_ERR(dsymlink); - dput(symlink); + d_make_discardable(symlink); goto unlock; } - - /* Note that we're retaining extra refs on the dentries. */ - symlink->d_fsdata = (void *)1UL; - dsymlink->d_fsdata = (void *)1UL; ret = 0; unlock: inode_unlock(root->d_inode); @@ -459,26 +412,10 @@ int afs_dynroot_populate(struct super_block *sb) void afs_dynroot_depopulate(struct super_block *sb) { struct afs_net *net = afs_sb2net(sb); - struct dentry *root = sb->s_root, *subdir; /* Prevent more subdirs from being created */ mutex_lock(&net->proc_cells_lock); if (net->dynroot_sb == sb) net->dynroot_sb = NULL; mutex_unlock(&net->proc_cells_lock); - - if (root) { - struct hlist_node *n; - inode_lock(root->d_inode); - - /* Remove all the pins for dirs created for manually added cells */ - hlist_for_each_entry_safe(subdir, n, &root->d_children, d_sib) { - if (subdir->d_fsdata) { - subdir->d_fsdata = NULL; - dput(subdir); - } - } - - inode_unlock(root->d_inode); - } } diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 90f407774a9a..cb6d5c33c8fc 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -1108,7 +1108,6 @@ extern int afs_silly_iput(struct dentry *, struct inode *); /* * dynroot.c */ -extern const struct inode_operations afs_dynroot_inode_operations; extern const struct dentry_operations afs_dynroot_dentry_operations; extern struct inode *afs_try_auto_mntpt(struct dentry *, struct inode *);