Skip to contentSkip to conversation

btrfs: add ability to query/change feature bits online

PATCH In review Jeff Mahoney 3 participants 4 messages Aug 27, 2013 – Sep 9, 2013 Btrfs file system

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 btrfs: add ability to query/change feature bits online

There are some feature bits that require no offline setup and can be enabled online. I've only reviewed extended irefs, but there will probably be more.

We introduce three new ioctls:
- BTRFS_IOC_GET_SUPPORTED_FEATURES: query the kernel for supported features
- BTRFS_IOC_GET_FEATURES: query the kernel for enabled features on a per-fs basis.
- BTRFS_IOC_ADD_FEATURES: enable new features on a per-fs basis.

We introduce a new mask _SAFE_ONLINE that allows us to define which features are safe to enable at runtime.

The failure modes for BTRFS_IOC_ADD_FEATURES are as follows:
- Enabling a completely unsupported feature: warns and returns -ENOTSUPP
- Enabling a feature that can only be done offline: warns and returns -EPERM

The structure passed in is not modified on return since it is possible to isolate which features would bounce a -EPERM by subtracting the features provided by a GET_SUPPORTED_FEATURES call.

---
 fs/btrfs/ctree.h           |    6 ++
 fs/btrfs/ioctl.c           |  127 +++++++++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/btrfs.h |   12 ++++
 3 files changed, 145 insertions(+)
fs/btrfs/ctree.h +6 -0
@@ -512,7 +512,10 @@ struct btrfs_super_block {
 #define BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA	(1ULL << 8)
 
 #define BTRFS_FEATURE_COMPAT_SUPP		0ULL
+#define BTRFS_FEATURE_COMPAT_ONLINE_SAFE	0ULL
 #define BTRFS_FEATURE_COMPAT_RO_SUPP		0ULL
+#define BTRFS_FEATURE_COMPAT_RO_ONLINE_SAFE	0ULL
+
 #define BTRFS_FEATURE_INCOMPAT_SUPP			\
 	(BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF |		\
 	 BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL |	\
@@ -523,6 +526,9 @@ struct btrfs_super_block {
 	 BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF |		\
 	 BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA)
 
+#define BTRFS_FEATURE_INCOMPAT_ONLINE_SAFE	\
+	(BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF)
+
 /*
  * A leaf is full of items. offset and size tell us where to find
  * the item in the leaf (relative to the start of the data area)
fs/btrfs/ioctl.c +127 -0

139 lines not on this page · raw message

include/uapi/linux/btrfs.h +12 -0
@@ -184,6 +184,12 @@ struct btrfs_ioctl_fs_info_args {
 	__u64 reserved[124];			/* pad to 1k */
 };
 
+struct btrfs_ioctl_feature_flags {
+	__u64 compat_flags;
+	__u64 compat_ro_flags;
+	__u64 incompat_flags;
+};
+
 /* balance control ioctl modes */
 #define BTRFS_BALANCE_CTL_PAUSE		1
 #define BTRFS_BALANCE_CTL_CANCEL	2
@@ -579,4 +585,10 @@ static inline char *btrfs_err_str(enum b
 				      struct btrfs_ioctl_get_dev_stats)
 #define BTRFS_IOC_DEV_REPLACE _IOWR(BTRFS_IOCTL_MAGIC, 53, \
 				    struct btrfs_ioctl_dev_replace_args)
+#define BTRFS_IOC_GET_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 54, \
+				   struct btrfs_ioctl_feature_flags)
+#define BTRFS_IOC_ADD_FEATURES _IOW(BTRFS_IOCTL_MAGIC, 55, \
+				   struct btrfs_ioctl_feature_flags)
+#define BTRFS_IOC_GET_SUPPORTED_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 56, \
+				   struct btrfs_ioctl_feature_flags[2])
 #endif /* _UAPI_LINUX_BTRFS_H */
Signature · 2 lines
Jeff Mahoney
SUSE Labs
#1 lore raw
Quoted 22 lines · Jeff Mahoney

There are some feature bits that require no offline setup and can be enabled online. I've only reviewed extended irefs, but there will probably be more.

We introduce three new ioctls:
- BTRFS_IOC_GET_SUPPORTED_FEATURES: query the kernel for supported features
- BTRFS_IOC_GET_FEATURES: query the kernel for enabled features on a per-fs basis.
- BTRFS_IOC_ADD_FEATURES: enable new features on a per-fs basis.

We introduce a new mask _SAFE_ONLINE that allows us to define which features are safe to enable at runtime.

The failure modes for BTRFS_IOC_ADD_FEATURES are as follows:
- Enabling a completely unsupported feature: warns and returns -ENOTSUPP
- Enabling a feature that can only be done offline: warns and returns -EPERM

The structure passed in is not modified on return since it is possible to isolate which features would bounce a -EPERM by subtracting the features provided by a GET_SUPPORTED_FEATURES call.

[...]

Quoted 16 lines
include/uapi/linux/btrfs.h +6 -0
@@ -184,6 +184,12 @@ struct btrfs_ioctl_fs_info_args {
 	__u64 reserved[124];			/* pad to 1k */
 };
 
+struct btrfs_ioctl_feature_flags {
+	__u64 compat_flags;
+	__u64 compat_ro_flags;
+	__u64 incompat_flags;
+};
+
 /* balance control ioctl modes */
 #define BTRFS_BALANCE_CTL_PAUSE		1
 #define BTRFS_BALANCE_CTL_CANCEL	2

include/uapi/linux/btrfs.h static inline char *btrfs_err_str(enum b · line 591

Quoted 7 lines
include/uapi/linux/btrfs.h +4 -0
@@ -579,4 +585,10 @@ static inline char *btrfs_err_str(enum b
 				      struct btrfs_ioctl_get_dev_stats)
 #define BTRFS_IOC_DEV_REPLACE _IOWR(BTRFS_IOCTL_MAGIC, 53, \
 				    struct btrfs_ioctl_dev_replace_args)
+#define BTRFS_IOC_GET_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 54, \
+				   struct btrfs_ioctl_feature_flags)
+#define BTRFS_IOC_ADD_FEATURES _IOW(BTRFS_IOCTL_MAGIC, 55, \
+				   struct btrfs_ioctl_feature_flags)

#define BTRFS_IOC_ADD_FEATURES _IOW(BTRFS_IOCTL_MAGIC, 54, \
struct btrfs_ioctl_feature_flags)

Using 54 for both would also be possible since the directions are different. _IOR(54) for the get ioctl and _IOW(54) for the set/add ioctl.

include/uapi/linux/btrfs.h static inline char *btrfs_err_str(enum b · line 593

Quoted 2 lines
include/uapi/linux/btrfs.h +2 -0
+#define BTRFS_IOC_GET_SUPPORTED_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 56, \
+				   struct btrfs_ioctl_feature_flags[2])

This could share the type value 54 too, since the parameter size is different. There are only 8 bits for the type field.

And in order to support clearing feature bits you could replace the add ioctl with a set ioctl and use a mask + value scheme.
#define BTRFS_IOC_SET_FEATURES _IOW(BTRFS_IOCTL_MAGIC, 54, \
struct btrfs_ioctl_feature_flags[2])
btrfs_ioctl_feature_flags[0] is the mask and btrfs_ioctl_feature_flags[1] is the value. Only bits that are set to one in the mask are taken from the value and modified in the filesystem flags.

#2 lore raw
Quoted 55 lines · Stefan Behrens
Quoted 22 lines · Jeff Mahoney

There are some feature bits that require no offline setup and can be enabled online. I've only reviewed extended irefs, but there will probably be more.

We introduce three new ioctls:
- BTRFS_IOC_GET_SUPPORTED_FEATURES: query the kernel for supported features
- BTRFS_IOC_GET_FEATURES: query the kernel for enabled features on a per-fs basis.
- BTRFS_IOC_ADD_FEATURES: enable new features on a per-fs basis.

We introduce a new mask _SAFE_ONLINE that allows us to define which features are safe to enable at runtime.

The failure modes for BTRFS_IOC_ADD_FEATURES are as follows:
- Enabling a completely unsupported feature: warns and returns -ENOTSUPP
- Enabling a feature that can only be done offline: warns and returns -EPERM

The structure passed in is not modified on return since it is possible to isolate which features would bounce a -EPERM by subtracting the features provided by a GET_SUPPORTED_FEATURES call.

[...]

Quoted 16 lines
include/uapi/linux/btrfs.h +6 -0
@@ -184,6 +184,12 @@ struct btrfs_ioctl_fs_info_args {
 	__u64 reserved[124];			/* pad to 1k */
 };
 
+struct btrfs_ioctl_feature_flags {
+	__u64 compat_flags;
+	__u64 compat_ro_flags;
+	__u64 incompat_flags;
+};
+
 /* balance control ioctl modes */
 #define BTRFS_BALANCE_CTL_PAUSE		1
 #define BTRFS_BALANCE_CTL_CANCEL	2

include/uapi/linux/btrfs.h static inline char *btrfs_err_str(enum b · line 591

Quoted 7 lines
include/uapi/linux/btrfs.h +4 -0
@@ -579,4 +585,10 @@ static inline char *btrfs_err_str(enum b
 				      struct btrfs_ioctl_get_dev_stats)
 #define BTRFS_IOC_DEV_REPLACE _IOWR(BTRFS_IOCTL_MAGIC, 53, \
 				    struct btrfs_ioctl_dev_replace_args)
+#define BTRFS_IOC_GET_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 54, \
+				   struct btrfs_ioctl_feature_flags)
+#define BTRFS_IOC_ADD_FEATURES _IOW(BTRFS_IOCTL_MAGIC, 55, \
+				   struct btrfs_ioctl_feature_flags)

#define BTRFS_IOC_ADD_FEATURES _IOW(BTRFS_IOCTL_MAGIC, 54, \
struct btrfs_ioctl_feature_flags)

Using 54 for both would also be possible since the directions are different. _IOR(54) for the get ioctl and _IOW(54) for the set/add ioctl.

Quoted 5 lines

include/uapi/linux/btrfs.h static inline char *btrfs_err_str(enum b · line 593

Quoted 2 lines
include/uapi/linux/btrfs.h +2 -0
+#define BTRFS_IOC_GET_SUPPORTED_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 56, \
+				   struct btrfs_ioctl_feature_flags[2])

This could share the type value 54 too, since the parameter size is different. There are only 8 bits for the type field.

Ah, yep. You're right.

Quoted 7 lines

And in order to support clearing feature bits you could replace the add ioctl with a set ioctl and use a mask + value scheme.
#define BTRFS_IOC_SET_FEATURES _IOW(BTRFS_IOCTL_MAGIC, 54, \
struct btrfs_ioctl_feature_flags[2])
btrfs_ioctl_feature_flags[0] is the mask and btrfs_ioctl_feature_flags[1] is the value. Only bits that are set to one in the mask are taken from the value and modified in the filesystem flags.

Yep. Though for now I think I'd implement the clear as an EOPNOTSUPP.

-Jeff

Signature · 2 lines
Jeff Mahoney
SUSE Labs
#3 lore raw
In reply to Jeff Mahoney
Quoted 2 lines · Jeff Mahoney
fs/btrfs/ioctl.c +2 -0
+static int btrfs_ioctl_add_features(struct file *file, void __user *arg)
+{

...

		spin_lock(&fs_info->super_lock);

fs/btrfs/ioctl.c out_unlock: · line 4215

Quoted 11 lines
fs/btrfs/ioctl.c +11 -0
+		flags = btrfs_super_compat_flags(super_block);
+		flags |= features.compat_flags;
+		btrfs_set_super_compat_flags(super_block, flags);
+
+		flags = btrfs_super_compat_ro_flags(super_block);
+		flags |= features.compat_ro_flags;
+		btrfs_set_super_compat_ro_flags(super_block, flags);
+
+		flags = btrfs_super_incompat_flags(super_block);
+		flags |= features.incompat_flags;
+		btrfs_set_super_incompat_flags(super_block, flags);
		spin_unlock(&fs_info->super_lock);
Quoted 5 lines
fs/btrfs/ioctl.c +5 -0
+		return btrfs_end_transaction(trans, root);
+	}
+
+	return 0;
+}