aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Mahoney <jeffm@suse.com>2013-11-01 13:07:02 -0400
committerChris Mason <clm@fb.com>2014-01-28 16:19:28 -0500
commit3b02a68a636400590dd6831a5fc046f0a7909a77 (patch)
tree4768baefa0c5ed4e76e215c444e100680c992746
parentba631941ef09c10e229661219dbd1707e56131d8 (diff)
btrfs: use feature attribute names to print better error messages
Now that we have the feature name strings available in the kernel via the sysfs attributes, we can use them for printing better failure messages from the ioctl path. Signed-off-by: Jeff Mahoney <jeffm@suse.com> Signed-off-by: Josef Bacik <jbacik@fusionio.com> Signed-off-by: Chris Mason <clm@fb.com>
-rw-r--r--fs/btrfs/ioctl.c35
-rw-r--r--fs/btrfs/sysfs.c33
-rw-r--r--fs/btrfs/sysfs.h2
3 files changed, 64 insertions, 6 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index d4e105b54091..93b01fe6c731 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -56,6 +56,7 @@
56#include "rcu-string.h" 56#include "rcu-string.h"
57#include "send.h" 57#include "send.h"
58#include "dev-replace.h" 58#include "dev-replace.h"
59#include "sysfs.h"
59 60
60static int btrfs_clone(struct inode *src, struct inode *inode, 61static int btrfs_clone(struct inode *src, struct inode *inode,
61 u64 off, u64 olen, u64 olen_aligned, u64 destoff); 62 u64 off, u64 olen, u64 olen_aligned, u64 destoff);
@@ -4516,17 +4517,27 @@ static int btrfs_ioctl_get_features(struct file *file, void __user *arg)
4516 return 0; 4517 return 0;
4517} 4518}
4518 4519
4519static int check_feature_bits(struct btrfs_root *root, const char *type, 4520static int check_feature_bits(struct btrfs_root *root,
4521 enum btrfs_feature_set set,
4520 u64 change_mask, u64 flags, u64 supported_flags, 4522 u64 change_mask, u64 flags, u64 supported_flags,
4521 u64 safe_set, u64 safe_clear) 4523 u64 safe_set, u64 safe_clear)
4522{ 4524{
4525 const char *type = btrfs_feature_set_names[set];
4526 char *names;
4523 u64 disallowed, unsupported; 4527 u64 disallowed, unsupported;
4524 u64 set_mask = flags & change_mask; 4528 u64 set_mask = flags & change_mask;
4525 u64 clear_mask = ~flags & change_mask; 4529 u64 clear_mask = ~flags & change_mask;
4526 4530
4527 unsupported = set_mask & ~supported_flags; 4531 unsupported = set_mask & ~supported_flags;
4528 if (unsupported) { 4532 if (unsupported) {
4529 btrfs_warn(root->fs_info, 4533 names = btrfs_printable_features(set, unsupported);
4534 if (names) {
4535 btrfs_warn(root->fs_info,
4536 "this kernel does not support the %s feature bit%s",
4537 names, strchr(names, ',') ? "s" : "");
4538 kfree(names);
4539 } else
4540 btrfs_warn(root->fs_info,
4530 "this kernel does not support %s bits 0x%llx", 4541 "this kernel does not support %s bits 0x%llx",
4531 type, unsupported); 4542 type, unsupported);
4532 return -EOPNOTSUPP; 4543 return -EOPNOTSUPP;
@@ -4534,7 +4545,14 @@ static int check_feature_bits(struct btrfs_root *root, const char *type,
4534 4545
4535 disallowed = set_mask & ~safe_set; 4546 disallowed = set_mask & ~safe_set;
4536 if (disallowed) { 4547 if (disallowed) {
4537 btrfs_warn(root->fs_info, 4548 names = btrfs_printable_features(set, disallowed);
4549 if (names) {
4550 btrfs_warn(root->fs_info,
4551 "can't set the %s feature bit%s while mounted",
4552 names, strchr(names, ',') ? "s" : "");
4553 kfree(names);
4554 } else
4555 btrfs_warn(root->fs_info,
4538 "can't set %s bits 0x%llx while mounted", 4556 "can't set %s bits 0x%llx while mounted",
4539 type, disallowed); 4557 type, disallowed);
4540 return -EPERM; 4558 return -EPERM;
@@ -4542,7 +4560,14 @@ static int check_feature_bits(struct btrfs_root *root, const char *type,
4542 4560
4543 disallowed = clear_mask & ~safe_clear; 4561 disallowed = clear_mask & ~safe_clear;
4544 if (disallowed) { 4562 if (disallowed) {
4545 btrfs_warn(root->fs_info, 4563 names = btrfs_printable_features(set, disallowed);
4564 if (names) {
4565 btrfs_warn(root->fs_info,
4566 "can't clear the %s feature bit%s while mounted",
4567 names, strchr(names, ',') ? "s" : "");
4568 kfree(names);
4569 } else
4570 btrfs_warn(root->fs_info,
4546 "can't clear %s bits 0x%llx while mounted", 4571 "can't clear %s bits 0x%llx while mounted",
4547 type, disallowed); 4572 type, disallowed);
4548 return -EPERM; 4573 return -EPERM;
@@ -4552,7 +4577,7 @@ static int check_feature_bits(struct btrfs_root *root, const char *type,
4552} 4577}
4553 4578
4554#define check_feature(root, change_mask, flags, mask_base) \ 4579#define check_feature(root, change_mask, flags, mask_base) \
4555check_feature_bits(root, # mask_base, change_mask, flags, \ 4580check_feature_bits(root, FEAT_##mask_base, change_mask, flags, \
4556 BTRFS_FEATURE_ ## mask_base ## _SUPP, \ 4581 BTRFS_FEATURE_ ## mask_base ## _SUPP, \
4557 BTRFS_FEATURE_ ## mask_base ## _SAFE_SET, \ 4582 BTRFS_FEATURE_ ## mask_base ## _SAFE_SET, \
4558 BTRFS_FEATURE_ ## mask_base ## _SAFE_CLEAR) 4583 BTRFS_FEATURE_ ## mask_base ## _SAFE_CLEAR)
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
index 7d340f352b77..562e346994d9 100644
--- a/fs/btrfs/sysfs.c
+++ b/fs/btrfs/sysfs.c
@@ -254,6 +254,31 @@ const char * const btrfs_feature_set_names[3] = {
254static char btrfs_unknown_feature_names[3][NUM_FEATURE_BITS][13]; 254static char btrfs_unknown_feature_names[3][NUM_FEATURE_BITS][13];
255static struct btrfs_feature_attr btrfs_feature_attrs[3][NUM_FEATURE_BITS]; 255static struct btrfs_feature_attr btrfs_feature_attrs[3][NUM_FEATURE_BITS];
256 256
257char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags)
258{
259 size_t bufsize = 4096; /* safe max, 64 names * 64 bytes */
260 int len = 0;
261 int i;
262 char *str;
263
264 str = kmalloc(bufsize, GFP_KERNEL);
265 if (!str)
266 return str;
267
268 for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) {
269 const char *name;
270
271 if (!(flags & (1ULL << i)))
272 continue;
273
274 name = btrfs_feature_attrs[set][i].kobj_attr.attr.name;
275 len += snprintf(str + len, bufsize - len, "%s%s",
276 len ? "," : "", name);
277 }
278
279 return str;
280}
281
257static void init_feature_attrs(void) 282static void init_feature_attrs(void)
258{ 283{
259 struct btrfs_feature_attr *fa; 284 struct btrfs_feature_attr *fa;
@@ -264,11 +289,17 @@ static void init_feature_attrs(void)
264 BUILD_BUG_ON(ARRAY_SIZE(btrfs_unknown_feature_names[0]) != 289 BUILD_BUG_ON(ARRAY_SIZE(btrfs_unknown_feature_names[0]) !=
265 ARRAY_SIZE(btrfs_feature_attrs[0])); 290 ARRAY_SIZE(btrfs_feature_attrs[0]));
266 291
292 memset(btrfs_feature_attrs, 0, sizeof(btrfs_feature_attrs));
293 memset(btrfs_unknown_feature_names, 0,
294 sizeof(btrfs_unknown_feature_names));
295
267 for (i = 0; btrfs_supported_feature_attrs[i]; i++) { 296 for (i = 0; btrfs_supported_feature_attrs[i]; i++) {
268 struct btrfs_feature_attr *sfa; 297 struct btrfs_feature_attr *sfa;
269 struct attribute *a = btrfs_supported_feature_attrs[i]; 298 struct attribute *a = btrfs_supported_feature_attrs[i];
299 int bit;
270 sfa = attr_to_btrfs_feature_attr(a); 300 sfa = attr_to_btrfs_feature_attr(a);
271 fa = &btrfs_feature_attrs[sfa->feature_set][sfa->feature_bit]; 301 bit = ilog2(sfa->feature_bit);
302 fa = &btrfs_feature_attrs[sfa->feature_set][bit];
272 303
273 fa->kobj_attr.attr.name = sfa->kobj_attr.attr.name; 304 fa->kobj_attr.attr.name = sfa->kobj_attr.attr.name;
274 } 305 }
diff --git a/fs/btrfs/sysfs.h b/fs/btrfs/sysfs.h
index 58c4b1f689d6..c49fd25c911f 100644
--- a/fs/btrfs/sysfs.h
+++ b/fs/btrfs/sysfs.h
@@ -51,4 +51,6 @@ static struct btrfs_feature_attr btrfs_attr_##_name = { \
51#define attr_to_btrfs_attr(a) container_of(a, struct kobj_attribute, attr) 51#define attr_to_btrfs_attr(a) container_of(a, struct kobj_attribute, attr)
52#define attr_to_btrfs_feature_attr(a) \ 52#define attr_to_btrfs_feature_attr(a) \
53 to_btrfs_feature_attr(attr_to_btrfs_attr(a)) 53 to_btrfs_feature_attr(attr_to_btrfs_attr(a))
54char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags);
55extern const char * const btrfs_feature_set_names[3];
54#endif /* _BTRFS_SYSFS_H_ */ 56#endif /* _BTRFS_SYSFS_H_ */