SUNRPC: Clean up rpc_populate/depopulate
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Sun, 9 Aug 2009 19:14:20 +0000 (15:14 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Sun, 9 Aug 2009 19:14:20 +0000 (15:14 -0400)
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
net/sunrpc/rpc_pipe.c

index 3633851..e5f37de 100644 (file)
@@ -401,7 +401,6 @@ static const struct file_operations rpc_info_operations = {
  * We have a single directory with 1 node in it.
  */
 enum {
-       RPCAUTH_Root = 1,
        RPCAUTH_lockd,
        RPCAUTH_mount,
        RPCAUTH_nfs,
@@ -415,12 +414,12 @@ enum {
  * Description of fs contents.
  */
 struct rpc_filelist {
-       char *name;
+       const char *name;
        const struct file_operations *i_fop;
        umode_t mode;
 };
 
-static struct rpc_filelist files[] = {
+static const struct rpc_filelist files[] = {
        [RPCAUTH_lockd] = {
                .name = "lockd",
                .mode = S_IFDIR | S_IRUGO | S_IXUGO,
@@ -448,11 +447,11 @@ static struct rpc_filelist files[] = {
 };
 
 enum {
-       RPCAUTH_info = 2,
+       RPCAUTH_info,
        RPCAUTH_EOF
 };
 
-static struct rpc_filelist authfiles[] = {
+static const struct rpc_filelist authfiles[] = {
        [RPCAUTH_info] = {
                .name = "info",
                .i_fop = &rpc_info_operations,
@@ -564,6 +563,20 @@ out_err:
        return -ENOMEM;
 }
 
+static int __rpc_create(struct inode *dir, struct dentry *dentry,
+                       umode_t mode,
+                       const struct file_operations *i_fop,
+                       void *private)
+{
+       int err;
+
+       err = __rpc_create_common(dir, dentry, S_IFREG | mode, i_fop, private);
+       if (err)
+               return err;
+       fsnotify_create(dir, dentry);
+       return 0;
+}
+
 static int __rpc_mkdir(struct inode *dir, struct dentry *dentry,
                       umode_t mode,
                       const struct file_operations *i_fop,
@@ -601,6 +614,17 @@ static int __rpc_mkpipe(struct inode *dir, struct dentry *dentry,
        return 0;
 }
 
+static int __rpc_rmdir(struct inode *dir, struct dentry *dentry)
+{
+       int ret;
+
+       dget(dentry);
+       ret = simple_rmdir(dir, dentry);
+       d_delete(dentry);
+       dput(dentry);
+       return ret;
+}
+
 static int __rpc_unlink(struct inode *dir, struct dentry *dentry)
 {
        int ret;
@@ -678,100 +702,96 @@ static struct dentry *rpc_lookup_negative(const char *path,
 /*
  * FIXME: This probably has races.
  */
-static void rpc_depopulate(struct dentry *parent,
-                          unsigned long start, unsigned long eof)
+static void __rpc_depopulate(struct dentry *parent,
+                            const struct rpc_filelist *files,
+                            int start, int eof)
 {
        struct inode *dir = parent->d_inode;
-       struct list_head *pos, *next;
-       struct dentry *dentry, *dvec[10];
-       int n = 0;
+       struct dentry *dentry;
+       struct qstr name;
+       int i;
 
-       mutex_lock_nested(&dir->i_mutex, I_MUTEX_CHILD);
-repeat:
-       spin_lock(&dcache_lock);
-       list_for_each_safe(pos, next, &parent->d_subdirs) {
-               dentry = list_entry(pos, struct dentry, d_u.d_child);
-               if (!dentry->d_inode ||
-                               dentry->d_inode->i_ino < start ||
-                               dentry->d_inode->i_ino >= eof)
+       for (i = start; i < eof; i++) {
+               name.name = files[i].name;
+               name.len = strlen(files[i].name);
+               name.hash = full_name_hash(name.name, name.len);
+               dentry = d_lookup(parent, &name);
+
+               if (dentry == NULL)
                        continue;
-               spin_lock(&dentry->d_lock);
-               if (!d_unhashed(dentry)) {
-                       dget_locked(dentry);
-                       __d_drop(dentry);
-                       spin_unlock(&dentry->d_lock);
-                       dvec[n++] = dentry;
-                       if (n == ARRAY_SIZE(dvec))
+               if (dentry->d_inode == NULL)
+                       goto next;
+               switch (dentry->d_inode->i_mode & S_IFMT) {
+                       default:
+                               BUG();
+                       case S_IFREG:
+                               __rpc_unlink(dir, dentry);
                                break;
-               } else
-                       spin_unlock(&dentry->d_lock);
-       }
-       spin_unlock(&dcache_lock);
-       if (n) {
-               do {
-                       dentry = dvec[--n];
-                       if (S_ISREG(dentry->d_inode->i_mode))
-                               simple_unlink(dir, dentry);
-                       else if (S_ISDIR(dentry->d_inode->i_mode))
-                               simple_rmdir(dir, dentry);
-                       d_delete(dentry);
-                       dput(dentry);
-               } while (n);
-               goto repeat;
+                       case S_IFDIR:
+                               __rpc_rmdir(dir, dentry);
+               }
+next:
+               dput(dentry);
        }
+}
+
+static void rpc_depopulate(struct dentry *parent,
+                          const struct rpc_filelist *files,
+                          int start, int eof)
+{
+       struct inode *dir = parent->d_inode;
+
+       mutex_lock_nested(&dir->i_mutex, I_MUTEX_CHILD);
+       __rpc_depopulate(parent, files, start, eof);
        mutex_unlock(&dir->i_mutex);
 }
 
-static int
-rpc_populate(struct dentry *parent,
-               struct rpc_filelist *files,
-               int start, int eof)
+static int rpc_populate(struct dentry *parent,
+                       const struct rpc_filelist *files,
+                       int start, int eof,
+                       void *private)
 {
-       struct inode *inode, *dir = parent->d_inode;
-       void *private = RPC_I(dir)->private;
+       struct inode *dir = parent->d_inode;
        struct dentry *dentry;
-       umode_t mode;
-       int i;
+       int i, err;
 
        mutex_lock(&dir->i_mutex);
        for (i = start; i < eof; i++) {
-               dentry = d_alloc_name(parent, files[i].name);
-               if (!dentry)
-                       goto out_bad;
-               dentry->d_op = &rpc_dentry_operations;
-               mode = files[i].mode;
-               inode = rpc_get_inode(dir->i_sb, mode);
-               if (!inode) {
-                       dput(dentry);
+               struct qstr q;
+
+               q.name = files[i].name;
+               q.len = strlen(files[i].name);
+               q.hash = full_name_hash(q.name, q.len);
+               dentry = __rpc_lookup_create_exclusive(parent, &q);
+               err = PTR_ERR(dentry);
+               if (IS_ERR(dentry))
                        goto out_bad;
+               switch (files[i].mode & S_IFMT) {
+                       default:
+                               BUG();
+                       case S_IFREG:
+                               err = __rpc_create(dir, dentry,
+                                               files[i].mode,
+                                               files[i].i_fop,
+                                               private);
+                               break;
+                       case S_IFDIR:
+                               err = __rpc_mkdir(dir, dentry,
+                                               files[i].mode,
+                                               NULL,
+                                               private);
                }
-               inode->i_ino = i;
-               if (files[i].i_fop)
-                       inode->i_fop = files[i].i_fop;
-               if (private)
-                       rpc_inode_setowner(inode, private);
-               if (S_ISDIR(mode))
-                       inc_nlink(dir);
-               d_add(dentry, inode);
-               fsnotify_create(dir, dentry);
+               if (err != 0)
+                       goto out_bad;
        }
        mutex_unlock(&dir->i_mutex);
        return 0;
 out_bad:
+       __rpc_depopulate(parent, files, start, eof);
        mutex_unlock(&dir->i_mutex);
        printk(KERN_WARNING "%s: %s failed to populate directory %s\n",
                        __FILE__, __func__, parent->d_name.name);
-       return -ENOMEM;
-}
-
-static int
-__rpc_rmdir(struct inode *dir, struct dentry *dentry)
-{
-       int error;
-       error = simple_rmdir(dir, dentry);
-       if (!error)
-               d_delete(dentry);
-       return error;
+       return err;
 }
 
 /**
@@ -800,16 +820,14 @@ rpc_mkdir(char *path, struct rpc_clnt *rpc_client)
        if (error != 0)
                goto out_err;
        error = rpc_populate(dentry, authfiles,
-                       RPCAUTH_info, RPCAUTH_EOF);
+                       RPCAUTH_info, RPCAUTH_EOF, rpc_client);
        if (error)
-               goto err_depopulate;
-       dget(dentry);
+               goto err_rmdir;
 out:
        mutex_unlock(&dir->i_mutex);
        rpc_release_path(&nd);
        return dentry;
-err_depopulate:
-       rpc_depopulate(dentry, RPCAUTH_info, RPCAUTH_EOF);
+err_rmdir:
        __rpc_rmdir(dir, dentry);
 out_err:
        printk(KERN_WARNING "%s: %s() failed to create directory %s (errno = %d)\n",
@@ -832,9 +850,8 @@ rpc_rmdir(struct dentry *dentry)
        parent = dget_parent(dentry);
        dir = parent->d_inode;
        mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
-       rpc_depopulate(dentry, RPCAUTH_info, RPCAUTH_EOF);
+       rpc_depopulate(dentry, authfiles, RPCAUTH_info, RPCAUTH_EOF);
        error = __rpc_rmdir(dir, dentry);
-       dput(dentry);
        mutex_unlock(&dir->i_mutex);
        dput(parent);
        return error;
@@ -900,7 +917,6 @@ struct dentry *rpc_mkpipe(struct dentry *parent, const char *name,
                           private, ops, flags);
        if (err)
                goto out_err;
-       dget(dentry);
 out:
        mutex_unlock(&dir->i_mutex);
        return dentry;
@@ -932,7 +948,6 @@ rpc_unlink(struct dentry *dentry)
        dir = parent->d_inode;
        mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
        error = __rpc_rmpipe(dir, dentry);
-       dput(dentry);
        mutex_unlock(&dir->i_mutex);
        dput(parent);
        return error;
@@ -970,7 +985,7 @@ rpc_fill_super(struct super_block *sb, void *data, int silent)
                iput(inode);
                return -ENOMEM;
        }
-       if (rpc_populate(root, files, RPCAUTH_Root + 1, RPCAUTH_RootEOF))
+       if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL))
                goto out;
        sb->s_root = root;
        return 0;