Jiri Kosina 2028ed
From: David Sterba <dsterba@suse.cz>
Jiri Kosina 2028ed
Date: Fri, 18 Jan 2013 00:28:40 +0100
Jiri Kosina 2028ed
Patch-mainline: Never, SLES-specific
Jiri Kosina 2028ed
References: fate#314697
Jiri Kosina 2028ed
Subject: [PATCH] btrfs: add allow_unsupported module parameter
Jiri Kosina 2028ed
Jiri Kosina 2028ed
Disallow access to filesystem with unsupported features by default but
Jiri Kosina 2028ed
leave a chance to access the filesystem via module parameter override
Jiri Kosina 2028ed
(taints kernel).
Jiri Kosina 2028ed
Jiri Kosina 2028ed
The status can be toggled during runtime by changing the exported module
Jiri Kosina 2028ed
parameter in /sys/module/btrfs/parameters/allow_unsupported.
Jiri Kosina 2028ed
Jiri Kosina 2028ed
Current:
Jiri Kosina 2028ed
- mount: inode_cache - deny mount
Jiri Kosina 2028ed
- mount: autodefrag - deny mount
Jiri Kosina 2028ed
- ioctl: device replace - disallow
Jiri Kosina 2028ed
- mount: raid56 - remount RO
Jiri Kosina 2028ed
- mount: seeding device - deny mount
Jiri Kosina 2028ed
- balance: use of raid56 taints kernel
Jiri Kosina 2028ed
Jiri Kosina 2028ed
Signed-off-by: David Sterba <dsterba@suse.cz>
Jiri Kosina 2028ed
---
Jiri Kosina 2028ed
 fs/btrfs/ctree.h   |    7 +++++++
Jiri Kosina 2028ed
 fs/btrfs/disk-io.c |   15 +++++++++++++++
Jiri Kosina 2028ed
 fs/btrfs/ioctl.c   |    8 +++++++-
Jiri Kosina 2028ed
 fs/btrfs/super.c   |   20 ++++++++++++++++++++
Jiri Kosina 2028ed
 4 files changed, 49 insertions(+), 1 deletion(-)
Jiri Kosina 2028ed
Jiri Kosina 2028ed
--- a/fs/btrfs/ctree.h
Jiri Kosina 2028ed
+++ b/fs/btrfs/ctree.h
Jiri Kosina 2028ed
@@ -37,6 +37,7 @@
Jeff Mahoney dcc0c5
 #include <linux/sizes.h>
Jiri Kosina 2028ed
 #include <linux/dynamic_debug.h>
Jeff Mahoney dcc0c5
 #include <linux/refcount.h>
Jiri Kosina 2028ed
+#include <linux/unsupported-feature.h>
Jiri Kosina 2028ed
 #include "extent_io.h"
Jiri Kosina 2028ed
 #include "extent_map.h"
Jiri Kosina 2028ed
 #include "async-thread.h"
Jeff Mahoney dcc0c5
@@ -3555,4 +3556,11 @@ static inline int btrfs_test_is_dummy_ro
Jeff Mahoney dcc0c5
 #endif
Jiri Kosina 2028ed
 	return 0;
Jiri Kosina 2028ed
 }
Jeff Mahoney dcc0c5
+
Jiri Kosina 2028ed
+/*
Jiri Kosina 2028ed
+ * Module parameter
Jiri Kosina 2028ed
+ */
Jiri Kosina 2028ed
+DECLARE_SUSE_UNSUPPORTED_FEATURE(btrfs)
Jiri Kosina 2028ed
+#define btrfs_allow_unsupported btrfs_allow_unsupported()
Jiri Kosina 2028ed
+
Jiri Kosina 2028ed
 #endif
Jiri Kosina 2028ed
--- a/fs/btrfs/disk-io.c
Jiri Kosina 2028ed
+++ b/fs/btrfs/disk-io.c
Jiri Kosina 2028ed
@@ -2797,6 +2797,14 @@ int open_ctree(struct super_block *sb,
Jiri Kosina 2028ed
 	if (btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_ERROR)
Jiri Kosina 2028ed
 		set_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state);
Jiri Kosina 2028ed
 
Jiri Kosina 2028ed
+	if (btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_SEEDING) {
Jiri Kosina 2028ed
+		if (!btrfs_allow_unsupported) {
Jiri Kosina 2028ed
+			printk(KERN_WARNING "btrfs: seeding mode is not supported, load module with allow_unsupported=1\n");
Jiri Kosina 2028ed
+			ret = -EOPNOTSUPP;
Jiri Kosina 2028ed
+			goto fail_alloc;
Jiri Kosina 2028ed
+		}
Jiri Kosina 2028ed
+	}
Jiri Kosina 2028ed
+
Jiri Kosina 2028ed
 	/*
Jiri Kosina 2028ed
 	 * run through our array of backup supers and setup
Jiri Kosina 2028ed
 	 * our ring pointer to the oldest one
Jiri Kosina 2028ed
@@ -2863,6 +2871,13 @@ int open_ctree(struct super_block *sb,
Jiri Kosina 2028ed
 		goto fail_alloc;
Jiri Kosina 2028ed
 	}
Jiri Kosina 2028ed
 
Jiri Kosina 2028ed
+	if (features & BTRFS_FEATURE_INCOMPAT_RAID56) {
Jiri Kosina 2028ed
+		if (!btrfs_allow_unsupported) {
Jiri Kosina 2028ed
+			printk(KERN_WARNING "btrfs: RAID56 is supported read-only, load module with allow_unsupported=1\n");
Jiri Kosina 2028ed
+			sb->s_flags |= MS_RDONLY;
Jiri Kosina 2028ed
+		}
Jiri Kosina 2028ed
+	}
Jiri Kosina 2028ed
+
Jiri Kosina 2028ed
 	/*
Jiri Kosina 2028ed
 	 * Needn't use the lock because there is no other task which will
Jiri Kosina 2028ed
 	 * update the flag.
Jiri Kosina 2028ed
--- a/fs/btrfs/ioctl.c
Jiri Kosina 2028ed
+++ b/fs/btrfs/ioctl.c
Jiri Kosina 2028ed
@@ -5617,6 +5617,7 @@ long btrfs_ioctl(struct file *file, unsi
Jeff Mahoney dcc0c5
 	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
Jeff Mahoney dcc0c5
 	struct btrfs_root *root = BTRFS_I(inode)->root;
Jiri Kosina 2028ed
 	void __user *argp = (void __user *)arg;
Jiri Kosina 2028ed
+	int ret = -ENOTTY;
Jiri Kosina 2028ed
 
Jiri Kosina 2028ed
 	switch (cmd) {
Jiri Kosina 2028ed
 	case FS_IOC_GETFLAGS:
Jiri Kosina 2028ed
@@ -5737,6 +5738,11 @@ long btrfs_ioctl(struct file *file, unsi
Jiri Kosina 2028ed
 	case BTRFS_IOC_QUOTA_RESCAN_WAIT:
Jiri Kosina 2028ed
 		return btrfs_ioctl_quota_rescan_wait(file, argp);
Jiri Kosina 2028ed
 	case BTRFS_IOC_DEV_REPLACE:
Jiri Kosina 2028ed
+		if (!btrfs_allow_unsupported) {
Jiri Kosina 2028ed
+			printk(KERN_WARNING "btrfs: IOC_DEV_REPLACE is not supported, load module with allow_unsupported=1\n");
Jiri Kosina 2028ed
+			ret = -EOPNOTSUPP;
Jiri Kosina 2028ed
+			break;
Jiri Kosina 2028ed
+		}
Jeff Mahoney dcc0c5
 		return btrfs_ioctl_dev_replace(fs_info, argp);
Jiri Kosina 2028ed
 	case BTRFS_IOC_GET_FSLABEL:
Jiri Kosina 2028ed
 		return btrfs_ioctl_get_fslabel(file, argp);
Jiri Kosina 2028ed
@@ -5752,7 +5758,7 @@ long btrfs_ioctl(struct file *file, unsi
Jiri Kosina 2028ed
 		return btrfs_ioctl_set_features(file, argp);
Jiri Kosina 2028ed
 	}
Jiri Kosina 2028ed
 
Jiri Kosina 2028ed
-	return -ENOTTY;
Jiri Kosina 2028ed
+	return ret;
Jiri Kosina 2028ed
 }
Jiri Kosina 2028ed
 
Jiri Kosina 2028ed
 #ifdef CONFIG_COMPAT
Jiri Kosina 2028ed
--- a/fs/btrfs/super.c
Jiri Kosina 2028ed
+++ b/fs/btrfs/super.c
Jiri Kosina 2028ed
@@ -18,6 +18,7 @@
Jiri Kosina 2028ed
 
Jiri Kosina 2028ed
 #include <linux/blkdev.h>
Jiri Kosina 2028ed
 #include <linux/module.h>
Jiri Kosina 2028ed
+#include <linux/moduleparam.h>
Jiri Kosina 2028ed
 #include <linux/buffer_head.h>
Jiri Kosina 2028ed
 #include <linux/fs.h>
Jiri Kosina 2028ed
 #include <linux/pagemap.h>
Jiri Kosina 2028ed
@@ -64,6 +65,8 @@
Jiri Kosina 2028ed
 #define CREATE_TRACE_POINTS
Jiri Kosina 2028ed
 #include <trace/events/btrfs.h>
Jiri Kosina 2028ed
 
Jiri Kosina 2028ed
+DEFINE_SUSE_UNSUPPORTED_FEATURE(btrfs)
Jiri Kosina 2028ed
+
Jiri Kosina 2028ed
 static const struct super_operations btrfs_super_ops;
Jiri Kosina 2028ed
 static struct file_system_type btrfs_fs_type;
Jiri Kosina 2028ed
 
Jiri Kosina 2028ed
@@ -663,6 +666,11 @@ int btrfs_parse_options(struct btrfs_roo
Jeff Mahoney dcc0c5
 			}
Jiri Kosina 2028ed
 			break;
Jiri Kosina 2028ed
 		case Opt_inode_cache:
Jiri Kosina 2028ed
+			if (!btrfs_allow_unsupported) {
Jiri Kosina 2028ed
+				printk(KERN_WARNING "btrfs: inode_cache is not supported, load module with allow_unsupported=1\n");
Jiri Kosina 2028ed
+				ret = -EOPNOTSUPP;
Jiri Kosina 2028ed
+				break;
Jiri Kosina 2028ed
+			}
Jiri Kosina 2028ed
 			btrfs_set_pending_and_info(info, INODE_MAP_CACHE,
Jiri Kosina 2028ed
 					   "enabling inode map caching");
Jiri Kosina 2028ed
 			break;
Jiri Kosina 2028ed
@@ -684,6 +692,11 @@ int btrfs_parse_options(struct btrfs_roo
Jiri Kosina 2028ed
 			btrfs_clear_opt(info->mount_opt, ENOSPC_DEBUG);
Jiri Kosina 2028ed
 			break;
Jiri Kosina 2028ed
 		case Opt_defrag:
Jiri Kosina 2028ed
+			if (!btrfs_allow_unsupported) {
Jiri Kosina 2028ed
+				printk(KERN_WARNING "btrfs: autodefrag is not supported, load module with allow_unsupported=1\n");
Jiri Kosina 2028ed
+				ret = -EOPNOTSUPP;
Jiri Kosina 2028ed
+				break;
Jiri Kosina 2028ed
+			}
Jeff Mahoney dcc0c5
 			btrfs_set_and_info(info, AUTO_DEFRAG,
Jiri Kosina 2028ed
 					   "enabling auto defrag");
Jiri Kosina 2028ed
 			break;
Jiri Kosina 2028ed
@@ -1758,6 +1771,13 @@ static int btrfs_remount(struct super_bl
Jiri Kosina 2028ed
 			ret = -EACCES;
Jiri Kosina 2028ed
 			goto restore;
Jiri Kosina 2028ed
 		}
Jiri Kosina 2028ed
+		if ((btrfs_super_incompat_flags(fs_info->super_copy)
Jiri Kosina 2028ed
+					& BTRFS_FEATURE_INCOMPAT_RAID56)
Jiri Kosina 2028ed
+				&& !btrfs_allow_unsupported) {
Jiri Kosina 2028ed
+			printk(KERN_WARNING "btrfs: cannot remount RW, RAID56 is supported read-only, load module with allow_unsupported=1\n");
Jiri Kosina 2028ed
+			ret = -EINVAL;
Jiri Kosina 2028ed
+			goto restore;
Jiri Kosina 2028ed
+		}
Jiri Kosina 2028ed
 
Jiri Kosina 2028ed
 		if (btrfs_super_log_root(fs_info->super_copy) != 0) {
Jiri Kosina 2028ed
 			ret = -EINVAL;