[PATCH] spufs: fix sparse warnings
[firefly-linux-kernel-4.4.55.git] / arch / powerpc / platforms / cell / spufs / inode.c
index 45944012b06aa57dafe8aea2ee158457686da738..1f3507c75e90068c49a00b2adc66ca72a3cda90e 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/init.h>
 #include <linux/ioctl.h>
 #include <linux/module.h>
+#include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/pagemap.h>
 #include <linux/poll.h>
@@ -133,47 +134,18 @@ spufs_delete_inode(struct inode *inode)
        clear_inode(inode);
 }
 
-static int
-spufs_fill_dir(struct dentry *dir, struct tree_descr *files,
-               int mode, struct spu_context *ctx)
-{
-       struct dentry *dentry;
-       int ret;
-
-       while (files->name && files->name[0]) {
-               ret = -ENOMEM;
-               dentry = d_alloc_name(dir, files->name);
-               if (!dentry)
-                       goto out;
-               ret = spufs_new_file(dir->d_sb, dentry, files->ops,
-                                       files->mode & mode, ctx);
-               if (ret)
-                       goto out;
-               files++;
-       }
-       return 0;
-out:
-       // FIXME: remove all files that are left
-
-       return ret;
-}
-
-static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry)
+static void spufs_prune_dir(struct dentry *dir)
 {
        struct dentry *dentry, *tmp;
-       struct spu_context *ctx;
-
-       /* remove all entries */
-       down(&root->i_sem);
-       down(&dir_dentry->d_inode->i_sem);
-       list_for_each_entry_safe(dentry, tmp, &dir_dentry->d_subdirs, d_child) {
+       down(&dir->d_inode->i_sem);
+       list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_child) {
                spin_lock(&dcache_lock);
                spin_lock(&dentry->d_lock);
                if (!(d_unhashed(dentry)) && dentry->d_inode) {
                        dget_locked(dentry);
                        __d_drop(dentry);
                        spin_unlock(&dentry->d_lock);
-                       simple_unlink(dir_dentry->d_inode, dentry);
+                       simple_unlink(dir->d_inode, dentry);
                        spin_unlock(&dcache_lock);
                        dput(dentry);
                } else {
@@ -181,8 +153,17 @@ static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry)
                        spin_unlock(&dcache_lock);
                }
        }
-       shrink_dcache_parent(dir_dentry);
-       up(&dir_dentry->d_inode->i_sem);
+       shrink_dcache_parent(dir);
+       up(&dir->d_inode->i_sem);
+}
+
+static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry)
+{
+       struct spu_context *ctx;
+
+       /* remove all entries */
+       down(&root->i_sem);
+       spufs_prune_dir(dir_dentry);
        up(&root->i_sem);
 
        /* We have to give up the mm_struct */
@@ -193,6 +174,29 @@ static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry)
        return simple_rmdir(root, dir_dentry);
 }
 
+static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files,
+                         int mode, struct spu_context *ctx)
+{
+       struct dentry *dentry;
+       int ret;
+
+       while (files->name && files->name[0]) {
+               ret = -ENOMEM;
+               dentry = d_alloc_name(dir, files->name);
+               if (!dentry)
+                       goto out;
+               ret = spufs_new_file(dir->d_sb, dentry, files->ops,
+                                       files->mode & mode, ctx);
+               if (ret)
+                       goto out;
+               files++;
+       }
+       return 0;
+out:
+       spufs_prune_dir(dir);
+       return ret;
+}
+
 static int spufs_dir_close(struct inode *inode, struct file *file)
 {
        struct inode *dir;
@@ -212,7 +216,7 @@ struct inode_operations spufs_dir_inode_operations = {
        .lookup = simple_lookup,
 };
 
-struct file_operations spufs_autodelete_dir_operations = {
+struct file_operations spufs_context_fops = {
        .open           = dcache_dir_open,
        .release        = spufs_dir_close,
        .llseek         = dcache_dir_lseek,
@@ -251,6 +255,7 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        d_instantiate(dentry, inode);
        dget(dentry);
        dir->i_nlink++;
+       dentry->d_inode->i_nlink++;
        goto out;
 
 out_free_ctx:
@@ -261,18 +266,43 @@ out:
        return ret;
 }
 
-long
-spufs_create_thread(struct nameidata *nd, const char *name,
-                       unsigned int flags, mode_t mode)
+static int spufs_context_open(struct dentry *dentry, struct vfsmount *mnt)
 {
-       struct dentry *dentry;
+       int ret;
        struct file *filp;
+
+       ret = get_unused_fd();
+       if (ret < 0) {
+               dput(dentry);
+               mntput(mnt);
+               goto out;
+       }
+
+       filp = dentry_open(dentry, mnt, O_RDONLY);
+       if (IS_ERR(filp)) {
+               put_unused_fd(ret);
+               ret = PTR_ERR(filp);
+               goto out;
+       }
+
+       filp->f_op = &spufs_context_fops;
+       fd_install(ret, filp);
+out:
+       return ret;
+}
+
+static struct file_system_type spufs_type;
+
+long spufs_create_thread(struct nameidata *nd,
+                        unsigned int flags, mode_t mode)
+{
+       struct dentry *dentry;
        int ret;
 
        /* need to be at the root of spufs */
        ret = -EINVAL;
-       if (nd->dentry->d_sb->s_magic != SPUFS_MAGIC ||
-               nd->dentry != nd->dentry->d_sb->s_root)
+       if (nd->dentry->d_sb->s_type != &spufs_type ||
+           nd->dentry != nd->dentry->d_sb->s_root)
                goto out;
 
        dentry = lookup_create(nd, 1);
@@ -289,21 +319,13 @@ spufs_create_thread(struct nameidata *nd, const char *name,
        if (ret)
                goto out_dput;
 
-       ret = get_unused_fd();
+       /*
+        * get references for dget and mntget, will be released
+        * in error path of *_open().
+        */
+       ret = spufs_context_open(dget(dentry), mntget(nd->mnt));
        if (ret < 0)
-               goto out_dput;
-
-       dentry->d_inode->i_nlink++;
-
-       filp = filp_open(name, O_RDONLY, mode);
-       if (IS_ERR(filp)) {
-               // FIXME: remove directory again
-               put_unused_fd(ret);
-               ret = PTR_ERR(filp);
-       } else {
-               filp->f_op = &spufs_autodelete_dir_operations;
-               fd_install(ret, filp);
-       }
+               spufs_rmdir(nd->dentry->d_inode, dentry);
 
 out_dput:
        dput(dentry);