From: David Sterba <dsterba@suse.cz>
Date: Fri, 18 Jan 2013 00:28:40 +0100
Patch-mainline: Never, SLES-specific
References: fate#314697
Subject: [PATCH] btrfs: add allow_unsupported module parameter
Disallow access to filesystem with unsupported features by default but
leave a chance to access the filesystem via module parameter override
(taints kernel).
The status can be toggled during runtime by changing the exported module
parameter in /sys/module/btrfs/parameters/allow_unsupported.
Current:
- mount: inode_cache - deny mount
- mount: autodefrag - deny mount
- mount: raid56 - remount RO
- mount: seeding device - deny mount
- balance: use of raid56 taints kernel
fate#325563 - allow device replace
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/ctree.h | 7 +++++++
fs/btrfs/disk-io.c | 15 +++++++++++++++
fs/btrfs/super.c | 20 ++++++++++++++++++++
3 files changed, 42 insertions(+)
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index f73b17694..0a852b5bc 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -29,6 +29,7 @@
#include <linux/dynamic_debug.h>
#include <linux/refcount.h>
#include <linux/crc32c.h>
+#include <linux/unsupported-feature.h>
#include "extent-io-tree.h"
#include "extent_io.h"
#include "extent_map.h"
@@ -3531,6 +3532,12 @@ static inline int btrfs_is_testing(struct btrfs_fs_info *fs_info)
}
#endif
+/*
+ * Module parameter
+ */
+DECLARE_SUSE_UNSUPPORTED_FEATURE(btrfs)
+#define btrfs_allow_unsupported btrfs_allow_unsupported()
+
static inline void cond_wake_up(struct wait_queue_head *wq)
{
/*
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index c97a20783..7a1eca676 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2945,6 +2945,14 @@ int __cold open_ctree(struct super_block *sb,
disk_super = fs_info->super_copy;
+ if (btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_SEEDING) {
+ if (!btrfs_allow_unsupported) {
+ printk(KERN_WARNING "btrfs: seeding mode is not supported, load module with allow_unsupported=1\n");
+ ret = -EOPNOTSUPP;
+ goto fail_alloc;
+ }
+ }
+
ASSERT(!memcmp(fs_info->fs_devices->fsid, fs_info->super_copy->fsid,
BTRFS_FSID_SIZE));
@@ -3045,6 +3053,13 @@ int __cold open_ctree(struct super_block *sb,
goto fail_alloc;
}
+ if (features & BTRFS_FEATURE_INCOMPAT_RAID56) {
+ if (!btrfs_allow_unsupported) {
+ printk(KERN_WARNING "btrfs: RAID56 is supported read-only, load module with allow_unsupported=1\n");
+ sb->s_flags |= SB_RDONLY;
+ }
+ }
+
/*
* Needn't use the lock because there is no other task which will
* update the flag.
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 831956f9f..ea57682f7 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -27,6 +27,7 @@
#include <linux/ratelimit.h>
#include <linux/crc32c.h>
#include <linux/btrfs.h>
+#include <linux/moduleparam.h>
#include "delayed-inode.h"
#include "ctree.h"
#include "disk-io.h"
@@ -50,6 +51,8 @@
#define CREATE_TRACE_POINTS
#include <trace/events/btrfs.h>
+DEFINE_SUSE_UNSUPPORTED_FEATURE(btrfs)
+
static const struct super_operations btrfs_super_ops;
/*
@@ -733,6 +736,11 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
}
break;
case Opt_inode_cache:
+ if (!btrfs_allow_unsupported) {
+ printk(KERN_WARNING "btrfs: inode_cache is not supported, load module with allow_unsupported=1\n");
+ ret = -EOPNOTSUPP;
+ break;
+ }
btrfs_set_pending_and_info(info, INODE_MAP_CACHE,
"enabling inode map caching");
break;
@@ -754,6 +762,11 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
btrfs_clear_opt(info->mount_opt, ENOSPC_DEBUG);
break;
case Opt_defrag:
+ if (!btrfs_allow_unsupported) {
+ printk(KERN_WARNING "btrfs: autodefrag is not supported, load module with allow_unsupported=1\n");
+ ret = -EOPNOTSUPP;
+ break;
+ }
btrfs_set_and_info(info, AUTO_DEFRAG,
"enabling auto defrag");
break;
@@ -1828,6 +1841,13 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
ret = -EACCES;
goto restore;
}
+ if ((btrfs_super_incompat_flags(fs_info->super_copy)
+ & BTRFS_FEATURE_INCOMPAT_RAID56)
+ && !btrfs_allow_unsupported) {
+ printk(KERN_WARNING "btrfs: cannot remount RW, RAID56 is supported read-only, load module with allow_unsupported=1\n");
+ ret = -EINVAL;
+ goto restore;
+ }
if (btrfs_super_log_root(fs_info->super_copy) != 0) {
ret = -EINVAL;
--
2.26.2