Merge branch 'core/softlockup-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.git] / arch / powerpc / platforms / cell / spufs / inode.c
index 0c32a05..7123472 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <linux/file.h>
 #include <linux/fs.h>
+#include <linux/fsnotify.h>
 #include <linux/backing-dev.h>
 #include <linux/init.h>
 #include <linux/ioctl.h>
 
 #include "spufs.h"
 
+struct spufs_sb_info {
+       int debug;
+};
+
 static struct kmem_cache *spufs_inode_cache;
 char *isolated_loader;
 static int isolated_loader_size;
 
+static struct spufs_sb_info *spufs_get_sb_info(struct super_block *sb)
+{
+       return sb->s_fs_info;
+}
+
 static struct inode *
 spufs_alloc_inode(struct super_block *sb)
 {
@@ -108,7 +118,7 @@ spufs_setattr(struct dentry *dentry, struct iattr *attr)
 static int
 spufs_new_file(struct super_block *sb, struct dentry *dentry,
                const struct file_operations *fops, int mode,
-               struct spu_context *ctx)
+               size_t size, struct spu_context *ctx)
 {
        static struct inode_operations spufs_file_iops = {
                .setattr = spufs_setattr,
@@ -124,6 +134,7 @@ spufs_new_file(struct super_block *sb, struct dentry *dentry,
        ret = 0;
        inode->i_op = &spufs_file_iops;
        inode->i_fop = fops;
+       inode->i_size = size;
        inode->i_private = SPUFS_I(inode)->i_ctx = get_spu_context(ctx);
        d_add(dentry, inode);
 out:
@@ -176,7 +187,7 @@ static int spufs_rmdir(struct inode *parent, struct dentry *dir)
        return simple_rmdir(parent, dir);
 }
 
-static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files,
+static int spufs_fill_dir(struct dentry *dir, struct spufs_tree_descr *files,
                          int mode, struct spu_context *ctx)
 {
        struct dentry *dentry, *tmp;
@@ -188,7 +199,7 @@ static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files,
                if (!dentry)
                        goto out;
                ret = spufs_new_file(dir->d_sb, dentry, files->ops,
-                                       files->mode & mode, ctx);
+                                       files->mode & mode, files->size, ctx);
                if (ret)
                        goto out;
                files++;
@@ -223,7 +234,7 @@ static int spufs_dir_close(struct inode *inode, struct file *file)
        parent = dir->d_parent->d_inode;
        ctx = SPUFS_I(dir->d_inode)->i_ctx;
 
-       mutex_lock(&parent->i_mutex);
+       mutex_lock_nested(&parent->i_mutex, I_MUTEX_PARENT);
        ret = spufs_rmdir(parent, dir);
        mutex_unlock(&parent->i_mutex);
        WARN_ON(ret);
@@ -278,6 +289,13 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,
        if (ret)
                goto out_free_ctx;
 
+       if (spufs_get_sb_info(dir->i_sb)->debug)
+               ret = spufs_fill_dir(dentry, spufs_dir_debug_contents,
+                               mode, ctx);
+
+       if (ret)
+               goto out_free_ctx;
+
        d_instantiate(dentry, inode);
        dget(dentry);
        dir->i_nlink++;
@@ -618,12 +636,15 @@ long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode,
        mode &= ~current->fs->umask;
 
        if (flags & SPU_CREATE_GANG)
-               return spufs_create_gang(nd->path.dentry->d_inode,
+               ret = spufs_create_gang(nd->path.dentry->d_inode,
                                         dentry, nd->path.mnt, mode);
        else
-               return spufs_create_context(nd->path.dentry->d_inode,
+               ret = spufs_create_context(nd->path.dentry->d_inode,
                                            dentry, nd->path.mnt, flags, mode,
                                            filp);
+       if (ret >= 0)
+               fsnotify_mkdir(nd->path.dentry->d_inode, dentry);
+       return ret;
 
 out_dput:
        dput(dentry);
@@ -635,18 +656,19 @@ out:
 
 /* File system initialization */
 enum {
-       Opt_uid, Opt_gid, Opt_mode, Opt_err,
+       Opt_uid, Opt_gid, Opt_mode, Opt_debug, Opt_err,
 };
 
 static match_table_t spufs_tokens = {
-       { Opt_uid,  "uid=%d" },
-       { Opt_gid,  "gid=%d" },
-       { Opt_mode, "mode=%o" },
-       { Opt_err,   NULL  },
+       { Opt_uid,   "uid=%d" },
+       { Opt_gid,   "gid=%d" },
+       { Opt_mode,  "mode=%o" },
+       { Opt_debug, "debug" },
+       { Opt_err,    NULL  },
 };
 
 static int
-spufs_parse_options(char *options, struct inode *root)
+spufs_parse_options(struct super_block *sb, char *options, struct inode *root)
 {
        char *p;
        substring_t args[MAX_OPT_ARGS];
@@ -674,6 +696,9 @@ spufs_parse_options(char *options, struct inode *root)
                                return 0;
                        root->i_mode = option | S_IFDIR;
                        break;
+               case Opt_debug:
+                       spufs_get_sb_info(sb)->debug = 1;
+                       break;
                default:
                        return 0;
                }
@@ -732,7 +757,7 @@ spufs_create_root(struct super_block *sb, void *data)
        SPUFS_I(inode)->i_ctx = NULL;
 
        ret = -EINVAL;
-       if (!spufs_parse_options(data, inode))
+       if (!spufs_parse_options(sb, data, inode))
                goto out_iput;
 
        ret = -ENOMEM;
@@ -750,6 +775,7 @@ out:
 static int
 spufs_fill_super(struct super_block *sb, void *data, int silent)
 {
+       struct spufs_sb_info *info;
        static struct super_operations s_ops = {
                .alloc_inode = spufs_alloc_inode,
                .destroy_inode = spufs_destroy_inode,
@@ -761,11 +787,16 @@ spufs_fill_super(struct super_block *sb, void *data, int silent)
 
        save_mount_options(sb, data);
 
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
        sb->s_maxbytes = MAX_LFS_FILESIZE;
        sb->s_blocksize = PAGE_CACHE_SIZE;
        sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
        sb->s_magic = SPUFS_MAGIC;
        sb->s_op = &s_ops;
+       sb->s_fs_info = info;
 
        return spufs_create_root(sb, data);
 }