powerpc/spufs: only add ".ctx" file with "debug" mount option

Currently, the .ctx debug file in spu context directories is always
present.

We'd prefer to prevent users from relying on this file, so add a
"debug" mount option to spufs. The .ctx file will only be added to
the context directories when this option is present.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index fee645b..99c7306 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -2645,7 +2645,6 @@
 	{ "tid", &spufs_tid_fops, 0444, },
 	{ "stat", &spufs_stat_fops, 0444, },
 	{ "switch_log", &spufs_switch_log_fops, 0444 },
-	{ ".ctx", &spufs_ctx_fops, 0444, },
 	{},
 };
 
@@ -2671,6 +2670,10 @@
 	{ "object-id", &spufs_object_id_ops, 0666, },
 	{ "tid", &spufs_tid_fops, 0444, },
 	{ "stat", &spufs_stat_fops, 0444, },
+	{},
+};
+
+struct spufs_tree_descr spufs_dir_debug_contents[] = {
 	{ ".ctx", &spufs_ctx_fops, 0444, },
 	{},
 };
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index c662ca7..7123472 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -42,10 +42,19 @@
 
 #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)
 {
@@ -280,6 +289,13 @@
 	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++;
@@ -640,18 +656,19 @@
 
 /* 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];
@@ -679,6 +696,9 @@
 				return 0;
 			root->i_mode = option | S_IFDIR;
 			break;
+		case Opt_debug:
+			spufs_get_sb_info(sb)->debug = 1;
+			break;
 		default:
 			return 0;
 		}
@@ -737,7 +757,7 @@
 	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;
@@ -755,6 +775,7 @@
 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,
@@ -766,11 +787,16 @@
 
 	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);
 }
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 4136054..8ae8ef9 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -244,6 +244,7 @@
 
 extern struct spufs_tree_descr spufs_dir_contents[];
 extern struct spufs_tree_descr spufs_dir_nosched_contents[];
+extern struct spufs_tree_descr spufs_dir_debug_contents[];
 
 /* system call implementation */
 extern struct spufs_calls spufs_calls;