All of lore.kernel.org
 help / color / mirror / Atom feed
* [patch 00/13] sysfs publishing patchset
@ 2013-10-21 21:19 Jeff Mahoney
  2013-10-21 21:19 ` [patch 01/13] btrfs: add ioctls to query/change feature bits online Jeff Mahoney
                   ` (14 more replies)
  0 siblings, 15 replies; 22+ messages in thread
From: Jeff Mahoney @ 2013-10-21 21:19 UTC (permalink / raw)
  To: linux-btrfs

This patchset implements the stubbed-out sysfs interface for btrfs. Or
at least begins to do so.

We publish:
- Features supported by the file system implementation
- Features enabled on the file system, including features unknown to
  the implemenation. These attributes can also be used to enable or
  disable features at runtime, subjecting to a safety mask.
- Uses the attribute names to print feature names when declining to
  mount a file system.
- The allocation data: global metadata reservation size and reserved,
  space_infos, and sums of the block groups total and used bytes.
- Device membership via links to the block devices.
- FS label, which is writeable.

- I've also added matching ioctls for some of the functionality here so
  that btrfsprogs can use the information without jumping through hoops
  to read/parse the sysfs files. There are ioctls to query the supported
  features and to query/set features on a particular file system. There's
  also one to export the size of the global metadata reservation. I have
  a patch for btrfs-progs that uses this to print useful info in 'btrfs
  fi df' output.

Ultimately, the tree structure looks like the following, under /sys/fs/btrfs.
This is from a test file system, using two devices in raid1. You'll notice
the 'single' and 'raid1' directories under the {data,metadata,system} dirs.
The raid profiles are created and removed as the first/last block group
of a certain profile is added and removed.

<fsid>/devices/sdc1
<fsid>/devices/sdd1
<fsid>/label
<fsid>/allocation/data/flags
<fsid>/allocation/data/raid1/used_bytes
<fsid>/allocation/data/raid1/total_bytes
<fsid>/allocation/data/bytes_pinned
<fsid>/allocation/data/bytes_may_use
<fsid>/allocation/data/total_bytes_pinned
<fsid>/allocation/data/bytes_reserved
<fsid>/allocation/data/bytes_used
<fsid>/allocation/data/single/used_bytes
<fsid>/allocation/data/single/total_bytes
<fsid>/allocation/data/total_bytes
<fsid>/allocation/data/disk_total
<fsid>/allocation/data/disk_used
<fsid>/allocation/metadata/flags
<fsid>/allocation/metadata/raid1/used_bytes
<fsid>/allocation/metadata/raid1/total_bytes
<fsid>/allocation/metadata/bytes_pinned
<fsid>/allocation/metadata/bytes_may_use
<fsid>/allocation/metadata/total_bytes_pinned
<fsid>/allocation/metadata/bytes_reserved
<fsid>/allocation/metadata/bytes_used
<fsid>/allocation/metadata/single/used_bytes
<fsid>/allocation/metadata/single/total_bytes
<fsid>/allocation/metadata/total_bytes
<fsid>/allocation/metadata/disk_total
<fsid>/allocation/metadata/disk_used
<fsid>/allocation/global_rsv_size
<fsid>/allocation/global_rsv_reserved
<fsid>/allocation/system/flags
<fsid>/allocation/system/raid1/used_bytes
<fsid>/allocation/system/raid1/total_bytes
<fsid>/allocation/system/bytes_pinned
<fsid>/allocation/system/bytes_may_use
<fsid>/allocation/system/total_bytes_pinned
<fsid>/allocation/system/bytes_reserved
<fsid>/allocation/system/bytes_used
<fsid>/allocation/system/single/used_bytes
<fsid>/allocation/system/single/total_bytes
<fsid>/allocation/system/total_bytes
<fsid>/allocation/system/disk_total
<fsid>/allocation/system/disk_used
<fsid>/features/mixed_backref
<fsid>/features/extended_iref
features/compress_lzo
features/big_metadata
features/compress_lzov2
features/default_subvol
features/mixed_backref
features/raid56
features/mixed_groups
features/skinny_metadata
features/extended_iref

-Jeff



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [patch 01/13] btrfs: add ioctls to query/change feature bits online
  2013-10-21 21:19 [patch 00/13] sysfs publishing patchset Jeff Mahoney
@ 2013-10-21 21:19 ` Jeff Mahoney
  2013-10-21 21:19 ` [patch 02/13] kobject: export kobj_sysfs_ops Jeff Mahoney
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Jeff Mahoney @ 2013-10-21 21:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

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, as well as querying for which features are changeable with mounted.
- BTRFS_IOC_SET_FEATURES: change features on a per-fs basis.

We introduce two new masks per feature set (_SAFE_SET and _SAFE_CLEAR) that
allow us to define which features are safe to change at runtime.

The failure modes for BTRFS_IOC_SET_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

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
 fs/btrfs/ctree.h           |    9 ++
 fs/btrfs/ioctl.c           |  145 +++++++++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/btrfs.h |   12 +++
 3 files changed, 166 insertions(+)

--- a/fs/btrfs/ctree.h	2013-09-11 21:40:48.939758689 -0400
+++ b/fs/btrfs/ctree.h	2013-09-16 13:37:13.020197254 -0400
@@ -512,7 +512,12 @@ struct btrfs_super_block {
 #define BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA	(1ULL << 8)
 
 #define BTRFS_FEATURE_COMPAT_SUPP		0ULL
+#define BTRFS_FEATURE_COMPAT_SAFE_SET		0ULL
+#define BTRFS_FEATURE_COMPAT_SAFE_CLEAR		0ULL
 #define BTRFS_FEATURE_COMPAT_RO_SUPP		0ULL
+#define BTRFS_FEATURE_COMPAT_RO_SAFE_SET	0ULL
+#define BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR	0ULL
+
 #define BTRFS_FEATURE_INCOMPAT_SUPP			\
 	(BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF |		\
 	 BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL |	\
@@ -523,6 +528,10 @@ struct btrfs_super_block {
 	 BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF |		\
 	 BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA)
 
+#define BTRFS_FEATURE_INCOMPAT_SAFE_SET			\
+	(BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF)
+#define BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR		0ULL
+
 /*
  * 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)
--- a/fs/btrfs/ioctl.c	2013-09-11 21:40:48.991757905 -0400
+++ b/fs/btrfs/ioctl.c	2013-09-16 13:37:09.720237996 -0400
@@ -4098,6 +4098,145 @@ out_unlock:
 	return ret;
 }
 
+static int btrfs_ioctl_get_supported_features(struct file *file,
+					      void __user *arg)
+{
+	struct btrfs_ioctl_feature_flags features[3];
+
+	features[0].compat_flags = BTRFS_FEATURE_COMPAT_SUPP;
+	features[0].compat_ro_flags = BTRFS_FEATURE_COMPAT_RO_SUPP;
+	features[0].incompat_flags = BTRFS_FEATURE_INCOMPAT_SUPP;
+
+	features[1].compat_flags = BTRFS_FEATURE_COMPAT_SAFE_SET;
+	features[1].compat_ro_flags = BTRFS_FEATURE_COMPAT_RO_SAFE_SET;
+	features[1].incompat_flags = BTRFS_FEATURE_INCOMPAT_SAFE_SET;
+
+	features[2].compat_flags = BTRFS_FEATURE_COMPAT_SAFE_CLEAR;
+	features[2].compat_ro_flags = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR;
+	features[2].incompat_flags = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR;
+
+	if (copy_to_user(arg, &features, sizeof(features)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int btrfs_ioctl_get_features(struct file *file, void __user *arg)
+{
+	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
+	struct btrfs_super_block *super_block = root->fs_info->super_copy;
+	struct btrfs_ioctl_feature_flags features;
+
+	features.compat_flags = btrfs_super_compat_flags(super_block);
+	features.compat_ro_flags = btrfs_super_compat_ro_flags(super_block);
+	features.incompat_flags = btrfs_super_incompat_flags(super_block);
+
+	if (copy_to_user(arg, &features, sizeof(features)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int check_feature_bits(struct btrfs_root *root, const char *type,
+			      u64 change_mask, u64 flags, u64 supported_flags,
+			      u64 safe_set, u64 safe_clear)
+{
+	u64 disallowed, unsupported;
+	u64 set_mask = flags & change_mask;
+	u64 clear_mask = ~flags & change_mask;
+
+	unsupported = set_mask & ~supported_flags;
+	if (unsupported) {
+		btrfs_warn(root->fs_info,
+			   "this kernel does not support %s bits 0x%llx",
+			   type, unsupported);
+		return -EOPNOTSUPP;
+	}
+
+	disallowed = set_mask & ~safe_set;
+	if (disallowed) {
+		btrfs_warn(root->fs_info,
+			   "can't set %s bits 0x%llx while mounted",
+			   type, disallowed);
+		return -EPERM;
+	}
+
+	disallowed = clear_mask & ~safe_clear;
+	if (disallowed) {
+		btrfs_warn(root->fs_info,
+			   "can't clear %s bits 0x%llx while mounted",
+			   type, disallowed);
+		return -EPERM;
+	}
+
+	return 0;
+}
+
+#define check_feature(root, change_mask, flags, mask_base)	\
+check_feature_bits(root, # mask_base, change_mask, flags,	\
+		   BTRFS_FEATURE_ ## mask_base ## _SUPP,	\
+		   BTRFS_FEATURE_ ## mask_base ## _SAFE_SET,	\
+		   BTRFS_FEATURE_ ## mask_base ## _SAFE_CLEAR)
+
+static int btrfs_ioctl_set_features(struct file *file, void __user *arg)
+{
+	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
+	struct btrfs_super_block *super_block = root->fs_info->super_copy;
+	struct btrfs_ioctl_feature_flags flags[2];
+	struct btrfs_trans_handle *trans;
+	u64 newflags;
+	int ret;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (copy_from_user(flags, arg, sizeof(flags)))
+		return -EFAULT;
+
+	/* Nothing to do */
+	if (!flags[0].compat_flags && !flags[0].compat_ro_flags &&
+	    !flags[0].incompat_flags)
+		return 0;
+
+	ret = check_feature(root, flags[0].compat_flags,
+			    flags[1].compat_flags, COMPAT);
+	if (ret)
+		return ret;
+
+	ret = check_feature(root, flags[0].compat_ro_flags,
+			    flags[1].compat_ro_flags, COMPAT_RO);
+	if (ret)
+		return ret;
+
+	ret = check_feature(root, flags[0].incompat_flags,
+			    flags[1].incompat_flags, INCOMPAT);
+	if (ret)
+		return ret;
+
+	trans = btrfs_start_transaction(root, 1);
+	if (IS_ERR(trans))
+		return PTR_ERR(trans);
+
+	spin_lock(&root->fs_info->super_lock);
+	newflags = btrfs_super_compat_flags(super_block);
+	newflags |= flags[0].compat_flags & flags[1].compat_flags;
+	newflags &= ~(flags[0].compat_flags & ~flags[1].compat_flags);
+	btrfs_set_super_compat_flags(super_block, newflags);
+
+	newflags = btrfs_super_compat_ro_flags(super_block);
+	newflags |= flags[0].compat_ro_flags & flags[1].compat_ro_flags;
+	newflags &= ~(flags[0].compat_ro_flags & ~flags[1].compat_ro_flags);
+	btrfs_set_super_compat_ro_flags(super_block, newflags);
+
+	newflags = btrfs_super_incompat_flags(super_block);
+	newflags |= flags[0].incompat_flags & flags[1].incompat_flags;
+	newflags &= ~(flags[0].incompat_flags & ~flags[1].incompat_flags);
+	btrfs_set_super_incompat_flags(super_block, newflags);
+	spin_unlock(&root->fs_info->super_lock);
+
+	return btrfs_end_transaction(trans, root);
+}
+
 long btrfs_ioctl(struct file *file, unsigned int
 		cmd, unsigned long arg)
 {
@@ -4208,6 +4347,12 @@ long btrfs_ioctl(struct file *file, unsi
 		return btrfs_ioctl_set_fslabel(file, argp);
 	case BTRFS_IOC_FILE_EXTENT_SAME:
 		return btrfs_ioctl_file_extent_same(file, argp);
+	case BTRFS_IOC_GET_SUPPORTED_FEATURES:
+		return btrfs_ioctl_get_supported_features(file, argp);
+	case BTRFS_IOC_GET_FEATURES:
+		return btrfs_ioctl_get_features(file, argp);
+	case BTRFS_IOC_SET_FEATURES:
+		return btrfs_ioctl_set_features(file, argp);
 	}
 
 	return -ENOTTY;
--- a/include/uapi/linux/btrfs.h	2013-09-10 12:36:31.643763746 -0400
+++ b/include/uapi/linux/btrfs.h	2013-09-16 13:38:03.251588809 -0400
@@ -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,5 +585,11 @@ static inline char *btrfs_err_str(enum b
 				    struct btrfs_ioctl_dev_replace_args)
 #define BTRFS_IOC_FILE_EXTENT_SAME _IOWR(BTRFS_IOCTL_MAGIC, 54, \
 					 struct btrfs_ioctl_same_args)
+#define BTRFS_IOC_GET_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \
+				   struct btrfs_ioctl_feature_flags)
+#define BTRFS_IOC_SET_FEATURES _IOW(BTRFS_IOCTL_MAGIC, 57, \
+				   struct btrfs_ioctl_feature_flags[2])
+#define BTRFS_IOC_GET_SUPPORTED_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \
+				   struct btrfs_ioctl_feature_flags[3])
 
 #endif /* _UAPI_LINUX_BTRFS_H */



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [patch 02/13] kobject: export kobj_sysfs_ops
  2013-10-21 21:19 [patch 00/13] sysfs publishing patchset Jeff Mahoney
  2013-10-21 21:19 ` [patch 01/13] btrfs: add ioctls to query/change feature bits online Jeff Mahoney
@ 2013-10-21 21:19 ` Jeff Mahoney
  2013-10-22 14:44   ` Jeff Mahoney
  2013-10-21 21:19 ` [patch 03/13] btrfs: publish supported featured in sysfs Jeff Mahoney
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 22+ messages in thread
From: Jeff Mahoney @ 2013-10-21 21:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

struct kobj_attribute implements the baseline attribute functionality
that can be used all over the place. We should export the ops associated
with it.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---

 lib/kobject.c |    1 +
 1 file changed, 1 insertion(+)

--- a/lib/kobject.c	2013-10-21 16:09:51.868220920 -0400
+++ b/lib/kobject.c	2013-10-21 16:10:00.216037635 -0400
@@ -726,6 +726,7 @@ const struct sysfs_ops kobj_sysfs_ops =
 	.show	= kobj_attr_show,
 	.store	= kobj_attr_store,
 };
+EXPORT_SYMBOL_GPL(kobj_sysfs_ops);
 
 /**
  * kset_register - initialize and add a kset.





^ permalink raw reply	[flat|nested] 22+ messages in thread

* [patch 03/13] btrfs: publish supported featured in sysfs
  2013-10-21 21:19 [patch 00/13] sysfs publishing patchset Jeff Mahoney
  2013-10-21 21:19 ` [patch 01/13] btrfs: add ioctls to query/change feature bits online Jeff Mahoney
  2013-10-21 21:19 ` [patch 02/13] kobject: export kobj_sysfs_ops Jeff Mahoney
@ 2013-10-21 21:19 ` Jeff Mahoney
  2013-10-21 21:19 ` [patch 04/13] btrfs: publish per-super attributes " Jeff Mahoney
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Jeff Mahoney @ 2013-10-21 21:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

This patch adds the ability to publish supported features to sysfs under
/sys/fs/btrfs/features.

The files are module-wide and export which features the kernel supports.

The content, for now, is just "0\n".

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
 fs/btrfs/sysfs.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 fs/btrfs/sysfs.h |   43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 87 insertions(+)

--- a/fs/btrfs/sysfs.c	2013-10-21 16:09:52.760201346 -0400
+++ b/fs/btrfs/sysfs.c	2013-10-21 16:09:59.816046422 -0400
@@ -26,20 +26,64 @@
 #include "ctree.h"
 #include "disk-io.h"
 #include "transaction.h"
+#include "sysfs.h"
+
+static ssize_t btrfs_feature_attr_show(struct kobject *kobj,
+				       struct kobj_attribute *a, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "0\n");
+}
+
+BTRFS_FEAT_ATTR_INCOMPAT(mixed_backref, MIXED_BACKREF);
+BTRFS_FEAT_ATTR_INCOMPAT(default_subvol, DEFAULT_SUBVOL);
+BTRFS_FEAT_ATTR_INCOMPAT(mixed_groups, MIXED_GROUPS);
+BTRFS_FEAT_ATTR_INCOMPAT(compress_lzo, COMPRESS_LZO);
+BTRFS_FEAT_ATTR_INCOMPAT(compress_lzov2, COMPRESS_LZOv2);
+BTRFS_FEAT_ATTR_INCOMPAT(big_metadata, BIG_METADATA);
+BTRFS_FEAT_ATTR_INCOMPAT(extended_iref, EXTENDED_IREF);
+BTRFS_FEAT_ATTR_INCOMPAT(raid56, RAID56);
+BTRFS_FEAT_ATTR_INCOMPAT(skinny_metadata, SKINNY_METADATA);
+
+static struct attribute *btrfs_supported_feature_attrs[] = {
+	BTRFS_FEAT_ATTR_PTR(mixed_backref),
+	BTRFS_FEAT_ATTR_PTR(default_subvol),
+	BTRFS_FEAT_ATTR_PTR(mixed_groups),
+	BTRFS_FEAT_ATTR_PTR(compress_lzo),
+	BTRFS_FEAT_ATTR_PTR(compress_lzov2),
+	BTRFS_FEAT_ATTR_PTR(big_metadata),
+	BTRFS_FEAT_ATTR_PTR(extended_iref),
+	BTRFS_FEAT_ATTR_PTR(raid56),
+	BTRFS_FEAT_ATTR_PTR(skinny_metadata),
+	NULL
+};
+
+static const struct attribute_group btrfs_feature_attr_group = {
+	.name = "features",
+	.attrs = btrfs_supported_feature_attrs,
+};
 
 /* /sys/fs/btrfs/ entry */
 static struct kset *btrfs_kset;
 
 int btrfs_init_sysfs(void)
 {
+	int ret;
 	btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj);
 	if (!btrfs_kset)
 		return -ENOMEM;
+
+	ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_feature_attr_group);
+	if (ret) {
+		kset_unregister(btrfs_kset);
+		return ret;
+	}
+
 	return 0;
 }
 
 void btrfs_exit_sysfs(void)
 {
+	sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group);
 	kset_unregister(btrfs_kset);
 }
 
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ b/fs/btrfs/sysfs.h	2013-10-21 16:09:59.816046422 -0400
@@ -0,0 +1,43 @@
+#ifndef _BTRFS_SYSFS_H_
+#define _BTRFS_SYSFS_H_
+
+enum btrfs_feature_set {
+	FEAT_COMPAT,
+	FEAT_COMPAT_RO,
+	FEAT_INCOMPAT,
+	FEAT_MAX
+};
+
+#define __INIT_KOBJ_ATTR(_name, _mode, _show, _store)			\
+{									\
+	.attr	= { .name = __stringify(_name), .mode = _mode },	\
+	.show	= _show,						\
+	.store	= _store,						\
+}
+
+struct btrfs_feature_attr {
+	struct kobj_attribute kobj_attr;
+	enum btrfs_feature_set feature_set;
+	u64 feature_bit;
+};
+
+#define BTRFS_FEAT_ATTR(_name, _feature_set, _prefix, _feature_bit)	     \
+static struct btrfs_feature_attr btrfs_attr_##_name = {			     \
+	.kobj_attr = __INIT_KOBJ_ATTR(_name, S_IRUGO,			     \
+				      btrfs_feature_attr_show, NULL),	     \
+	.feature_set	= _feature_set,					     \
+	.feature_bit	= _prefix ##_## _feature_bit,			     \
+}
+#define BTRFS_FEAT_ATTR_PTR(_name)    (&btrfs_attr_##_name.kobj_attr.attr)
+
+#define BTRFS_FEAT_ATTR_COMPAT(name, feature) \
+	BTRFS_FEAT_ATTR(name, FEAT_COMPAT, BTRFS_FEATURE_COMPAT, feature)
+#define BTRFS_FEAT_ATTR_COMPAT_RO(name, feature) \
+	BTRFS_FEAT_ATTR(name, FEAT_COMPAT_RO, BTRFS_FEATURE_COMPAT, feature)
+#define BTRFS_FEAT_ATTR_INCOMPAT(name, feature) \
+	BTRFS_FEAT_ATTR(name, FEAT_INCOMPAT, BTRFS_FEATURE_INCOMPAT, feature)
+
+/* convert from attribute */
+#define to_btrfs_feature_attr(a) \
+			container_of(a, struct btrfs_feature_attr, kobj_attr)
+#endif /* _BTRFS_SYSFS_H_ */




^ permalink raw reply	[flat|nested] 22+ messages in thread

* [patch 04/13] btrfs: publish per-super attributes in sysfs
  2013-10-21 21:19 [patch 00/13] sysfs publishing patchset Jeff Mahoney
                   ` (2 preceding siblings ...)
  2013-10-21 21:19 ` [patch 03/13] btrfs: publish supported featured in sysfs Jeff Mahoney
@ 2013-10-21 21:19 ` Jeff Mahoney
  2013-10-21 21:19 ` [patch 05/13] btrfs: publish per-super features " Jeff Mahoney
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Jeff Mahoney @ 2013-10-21 21:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

This patch adds per-super attributes to sysfs.

It doesn't publish any attributes yet, but does the proper lifetime
handling as well as the basic infrastructure to add new attributes.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
 fs/btrfs/ctree.h   |    2 ++
 fs/btrfs/disk-io.c |    9 +++++++++
 fs/btrfs/sysfs.c   |   36 ++++++++++++++++++++++++++++++++++++
 fs/btrfs/sysfs.h   |   10 ++++++++++
 4 files changed, 57 insertions(+)

--- a/fs/btrfs/ctree.h	2013-10-21 16:30:27.122204722 -0400
+++ b/fs/btrfs/ctree.h	2013-10-21 16:30:39.390053476 -0400
@@ -3771,6 +3771,8 @@ int btrfs_defrag_leaves(struct btrfs_tra
 /* sysfs.c */
 int btrfs_init_sysfs(void);
 void btrfs_exit_sysfs(void);
+int btrfs_sysfs_add_one(struct btrfs_fs_info *fs_info);
+void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info);
 
 /* xattr.c */
 ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
--- a/fs/btrfs/disk-io.c	2013-10-21 16:30:27.126204673 -0400
+++ b/fs/btrfs/disk-io.c	2013-10-21 16:30:39.394053427 -0400
@@ -49,6 +49,7 @@
 #include "rcu-string.h"
 #include "dev-replace.h"
 #include "raid56.h"
+#include "sysfs.h"
 
 #ifdef CONFIG_X86
 #include <asm/cpufeature.h>
@@ -2751,6 +2752,12 @@ retry_root_backup:
 
 	btrfs_close_extra_devices(fs_info, fs_devices, 1);
 
+	ret = btrfs_sysfs_add_one(fs_info);
+	if (ret) {
+		pr_err("btrfs: failed to init sysfs interface: %d\n", ret);
+		goto fail_block_groups;
+	}
+
 	ret = btrfs_init_space_info(fs_info);
 	if (ret) {
 		printk(KERN_ERR "Failed to initial space info: %d\n", ret);
@@ -3618,6 +3625,8 @@ int close_ctree(struct btrfs_root *root)
 
 	btrfs_stop_all_workers(fs_info);
 
+	btrfs_sysfs_remove_one(fs_info);
+
 	del_fs_roots(fs_info);
 
 	free_root_pointers(fs_info, 1);
--- a/fs/btrfs/sysfs.c	2013-10-21 16:30:27.126204673 -0400
+++ b/fs/btrfs/sysfs.c	2013-10-21 16:30:39.394053427 -0400
@@ -28,6 +28,25 @@
 #include "transaction.h"
 #include "sysfs.h"
 
+static void btrfs_release_super_kobj(struct kobject *kobj);
+static struct kobj_type btrfs_ktype = {
+	.sysfs_ops	= &kobj_sysfs_ops,
+	.release	= btrfs_release_super_kobj,
+};
+
+static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj)
+{
+	if (kobj->ktype != &btrfs_ktype)
+		return NULL;
+	return container_of(kobj, struct btrfs_fs_info, super_kobj);
+}
+
+static void btrfs_release_super_kobj(struct kobject *kobj)
+{
+	struct btrfs_fs_info *fs_info = to_fs_info(kobj);
+	complete(&fs_info->kobj_unregister);
+}
+
 static ssize_t btrfs_feature_attr_show(struct kobject *kobj,
 				       struct kobj_attribute *a, char *buf)
 {
@@ -65,6 +84,23 @@ static const struct attribute_group btrf
 /* /sys/fs/btrfs/ entry */
 static struct kset *btrfs_kset;
 
+void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info)
+{
+	kobject_del(&fs_info->super_kobj);
+	kobject_put(&fs_info->super_kobj);
+	wait_for_completion(&fs_info->kobj_unregister);
+}
+
+int btrfs_sysfs_add_one(struct btrfs_fs_info *fs_info)
+{
+	int error;
+
+	init_completion(&fs_info->kobj_unregister);
+	error = kobject_init_and_add(&fs_info->super_kobj, &btrfs_ktype, NULL,
+				     "%pU", fs_info->fsid);
+	return error;
+}
+
 int btrfs_init_sysfs(void)
 {
 	int ret;
--- a/fs/btrfs/sysfs.h	2013-10-21 16:30:27.126204673 -0400
+++ b/fs/btrfs/sysfs.h	2013-10-21 16:30:39.394053427 -0400
@@ -15,6 +15,13 @@ enum btrfs_feature_set {
 	.store	= _store,						\
 }
 
+#define BTRFS_ATTR_RW(_name, _mode, _show, _store)			\
+static struct kobj_attribute btrfs_attr_##_name =			\
+			__INIT_KOBJ_ATTR(_name, _mode, _show, _store)
+#define BTRFS_ATTR(_name, _mode, _show)					\
+	BTRFS_ATTR_RW(_name, _mode, _show, NULL)
+#define BTRFS_ATTR_PTR(_name)    (&btrfs_attr_##_name.attr)
+
 struct btrfs_feature_attr {
 	struct kobj_attribute kobj_attr;
 	enum btrfs_feature_set feature_set;
@@ -40,4 +47,7 @@ static struct btrfs_feature_attr btrfs_a
 /* convert from attribute */
 #define to_btrfs_feature_attr(a) \
 			container_of(a, struct btrfs_feature_attr, kobj_attr)
+#define attr_to_btrfs_attr(a) container_of(a, struct kobj_attribute, attr)
+#define attr_to_btrfs_feature_attr(a) \
+			to_btrfs_feature_attr(attr_to_btrfs_attr(a))
 #endif /* _BTRFS_SYSFS_H_ */



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [patch 05/13] btrfs: publish per-super features in sysfs
  2013-10-21 21:19 [patch 00/13] sysfs publishing patchset Jeff Mahoney
                   ` (3 preceding siblings ...)
  2013-10-21 21:19 ` [patch 04/13] btrfs: publish per-super attributes " Jeff Mahoney
@ 2013-10-21 21:19 ` Jeff Mahoney
  2013-10-21 21:19 ` [patch 06/13] btrfs: publish unknown feature bits " Jeff Mahoney
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Jeff Mahoney @ 2013-10-21 21:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

This patch publishes information on which features are enabled in the
file system on a per-super basis. At this point, it only publishes
information on features supported by the file system implementation.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
 fs/btrfs/sysfs.c |   81 ++++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 65 insertions(+), 16 deletions(-)

--- a/fs/btrfs/sysfs.c	2013-10-21 16:10:00.216037635 -0400
+++ b/fs/btrfs/sysfs.c	2013-10-21 16:10:00.700027002 -0400
@@ -28,29 +28,53 @@
 #include "transaction.h"
 #include "sysfs.h"
 
-static void btrfs_release_super_kobj(struct kobject *kobj);
-static struct kobj_type btrfs_ktype = {
-	.sysfs_ops	= &kobj_sysfs_ops,
-	.release	= btrfs_release_super_kobj,
-};
+static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj);
 
-static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj)
+static u64 get_features(struct btrfs_fs_info *fs_info,
+			enum btrfs_feature_set set)
 {
-	if (kobj->ktype != &btrfs_ktype)
-		return NULL;
-	return container_of(kobj, struct btrfs_fs_info, super_kobj);
+	struct btrfs_super_block *disk_super = fs_info->super_copy;
+	if (set == FEAT_COMPAT)
+		return btrfs_super_compat_flags(disk_super);
+	else if (set == FEAT_COMPAT_RO)
+		return btrfs_super_compat_ro_flags(disk_super);
+	else
+		return btrfs_super_incompat_flags(disk_super);
 }
 
-static void btrfs_release_super_kobj(struct kobject *kobj)
+static ssize_t btrfs_feature_attr_show(struct kobject *kobj,
+				       struct kobj_attribute *a, char *buf)
 {
+	int val = 0;
 	struct btrfs_fs_info *fs_info = to_fs_info(kobj);
-	complete(&fs_info->kobj_unregister);
+	if (fs_info) {
+		struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a);
+		u64 features = get_features(fs_info, fa->feature_set);
+		if (features & fa->feature_bit)
+			val = 1;
+	}
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
 }
 
-static ssize_t btrfs_feature_attr_show(struct kobject *kobj,
-				       struct kobj_attribute *a, char *buf)
+static umode_t btrfs_feature_visible(struct kobject *kobj,
+				     struct attribute *attr, int unused)
 {
-	return snprintf(buf, PAGE_SIZE, "0\n");
+	struct btrfs_fs_info *fs_info = to_fs_info(kobj);
+	umode_t mode = attr->mode;
+
+	if (fs_info) {
+		struct btrfs_feature_attr *fa;
+		u64 features;
+
+		fa = attr_to_btrfs_feature_attr(attr);
+		features = get_features(fs_info, fa->feature_set);
+
+		if (!(features & fa->feature_bit))
+			mode = 0;
+	}
+
+	return mode;
 }
 
 BTRFS_FEAT_ATTR_INCOMPAT(mixed_backref, MIXED_BACKREF);
@@ -78,11 +102,27 @@ static struct attribute *btrfs_supported
 
 static const struct attribute_group btrfs_feature_attr_group = {
 	.name = "features",
+	.is_visible = btrfs_feature_visible,
 	.attrs = btrfs_supported_feature_attrs,
 };
 
-/* /sys/fs/btrfs/ entry */
-static struct kset *btrfs_kset;
+static void btrfs_release_super_kobj(struct kobject *kobj)
+{
+	struct btrfs_fs_info *fs_info = to_fs_info(kobj);
+	complete(&fs_info->kobj_unregister);
+}
+
+static struct kobj_type btrfs_ktype = {
+	.sysfs_ops	= &kobj_sysfs_ops,
+	.release	= btrfs_release_super_kobj,
+};
+
+static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj)
+{
+	if (kobj->ktype != &btrfs_ktype)
+		return NULL;
+	return container_of(kobj, struct btrfs_fs_info, super_kobj);
+}
 
 void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info)
 {
@@ -91,13 +131,22 @@ void btrfs_sysfs_remove_one(struct btrfs
 	wait_for_completion(&fs_info->kobj_unregister);
 }
 
+/* /sys/fs/btrfs/ entry */
+static struct kset *btrfs_kset;
+
 int btrfs_sysfs_add_one(struct btrfs_fs_info *fs_info)
 {
 	int error;
 
 	init_completion(&fs_info->kobj_unregister);
+	fs_info->super_kobj.kset = btrfs_kset;
 	error = kobject_init_and_add(&fs_info->super_kobj, &btrfs_ktype, NULL,
 				     "%pU", fs_info->fsid);
+
+	error = sysfs_create_group(&fs_info->super_kobj,
+				   &btrfs_feature_attr_group);
+	if (error)
+		btrfs_sysfs_remove_one(fs_info);
 	return error;
 }
 




^ permalink raw reply	[flat|nested] 22+ messages in thread

* [patch 06/13] btrfs: publish unknown feature bits in sysfs
  2013-10-21 21:19 [patch 00/13] sysfs publishing patchset Jeff Mahoney
                   ` (4 preceding siblings ...)
  2013-10-21 21:19 ` [patch 05/13] btrfs: publish per-super features " Jeff Mahoney
@ 2013-10-21 21:19 ` Jeff Mahoney
  2013-10-21 21:19 ` [patch 07/13] btrfs: add ability to change features via sysfs Jeff Mahoney
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Jeff Mahoney @ 2013-10-21 21:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

With the compat and compat-ro bits, it's possible for file systems to
exist that have features that aren't supported by the kernel's file system
implementation yet still be mountable.

This patch publishes read-only info on those features using a prefix:number
format, where the number is the bit number rather than the shifted value.
e.g. "compat:12"

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
 fs/btrfs/sysfs.c |  108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 107 insertions(+), 1 deletion(-)

--- a/fs/btrfs/sysfs.c	2013-10-21 16:10:00.700027002 -0400
+++ b/fs/btrfs/sysfs.c	2013-10-21 16:10:01.076018741 -0400
@@ -22,6 +22,7 @@
 #include <linux/completion.h>
 #include <linux/buffer_head.h>
 #include <linux/kobject.h>
+#include <linux/bug.h>
 
 #include "ctree.h"
 #include "disk-io.h"
@@ -131,6 +132,101 @@ void btrfs_sysfs_remove_one(struct btrfs
 	wait_for_completion(&fs_info->kobj_unregister);
 }
 
+const char * const btrfs_feature_set_names[3] = {
+	[FEAT_COMPAT]	 = "compat",
+	[FEAT_COMPAT_RO] = "compat_ro",
+	[FEAT_INCOMPAT]	 = "incompat",
+};
+
+#define NUM_FEATURE_BITS 64
+static char btrfs_unknown_feature_names[3][NUM_FEATURE_BITS][13];
+static struct btrfs_feature_attr btrfs_feature_attrs[3][NUM_FEATURE_BITS];
+
+static void init_feature_attrs(void)
+{
+	struct btrfs_feature_attr *fa;
+	int set, i;
+
+	BUILD_BUG_ON(ARRAY_SIZE(btrfs_unknown_feature_names) !=
+		     ARRAY_SIZE(btrfs_feature_attrs));
+	BUILD_BUG_ON(ARRAY_SIZE(btrfs_unknown_feature_names[0]) !=
+		     ARRAY_SIZE(btrfs_feature_attrs[0]));
+
+	for (i = 0; btrfs_supported_feature_attrs[i]; i++) {
+		struct btrfs_feature_attr *sfa;
+		struct attribute *a = btrfs_supported_feature_attrs[i];
+		sfa = attr_to_btrfs_feature_attr(a);
+		fa = &btrfs_feature_attrs[sfa->feature_set][sfa->feature_bit];
+
+		fa->kobj_attr.attr.name = sfa->kobj_attr.attr.name;
+	}
+
+	for (set = 0; set < FEAT_MAX; set++) {
+		for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) {
+			char *name = btrfs_unknown_feature_names[set][i];
+			fa = &btrfs_feature_attrs[set][i];
+
+			if (fa->kobj_attr.attr.name)
+				continue;
+
+			snprintf(name, 13, "%s:%u",
+				 btrfs_feature_set_names[set], i);
+
+			fa->kobj_attr.attr.name = name;
+			fa->kobj_attr.attr.mode = S_IRUGO;
+			fa->feature_set = set;
+			fa->feature_bit = 1ULL << i;
+		}
+	}
+}
+
+static u64 supported_feature_masks[3] = {
+	[FEAT_COMPAT]    = BTRFS_FEATURE_COMPAT_SUPP,
+	[FEAT_COMPAT_RO] = BTRFS_FEATURE_COMPAT_RO_SUPP,
+	[FEAT_INCOMPAT]  = BTRFS_FEATURE_INCOMPAT_SUPP,
+};
+
+static int add_unknown_feature_attrs(struct btrfs_fs_info *fs_info)
+{
+	int set;
+
+	for (set = 0; set < FEAT_MAX; set++) {
+		int i, count, ret, index = 0;
+		struct attribute **attrs;
+		struct attribute_group agroup = {
+			.name = "features",
+		};
+		u64 features = get_features(fs_info, set);
+		features &= ~supported_feature_masks[set];
+
+		count = hweight64(features);
+
+		if (!count)
+			continue;
+
+		attrs = kcalloc(count + 1, sizeof(void *), GFP_KERNEL);
+
+		for (i = 0; i < NUM_FEATURE_BITS; i++) {
+			struct btrfs_feature_attr *fa;
+
+			if (!(features & (1ULL << i)))
+				continue;
+
+			fa = &btrfs_feature_attrs[set][i];
+			attrs[index++] = &fa->kobj_attr.attr;
+		}
+
+		attrs[index] = NULL;
+		agroup.attrs = attrs;
+
+		ret = sysfs_merge_group(&fs_info->super_kobj, &agroup);
+		kfree(attrs);
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
 /* /sys/fs/btrfs/ entry */
 static struct kset *btrfs_kset;
 
@@ -146,7 +242,15 @@ int btrfs_sysfs_add_one(struct btrfs_fs_
 	error = sysfs_create_group(&fs_info->super_kobj,
 				   &btrfs_feature_attr_group);
 	if (error)
-		btrfs_sysfs_remove_one(fs_info);
+		goto failure;
+
+	error = add_unknown_feature_attrs(fs_info);
+	if (error)
+		goto failure;
+
+	return 0;
+failure:
+	btrfs_sysfs_remove_one(fs_info);
 	return error;
 }
 
@@ -157,6 +261,8 @@ int btrfs_init_sysfs(void)
 	if (!btrfs_kset)
 		return -ENOMEM;
 
+	init_feature_attrs();
+
 	ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_feature_attr_group);
 	if (ret) {
 		kset_unregister(btrfs_kset);




^ permalink raw reply	[flat|nested] 22+ messages in thread

* [patch 07/13] btrfs: add ability to change features via sysfs
  2013-10-21 21:19 [patch 00/13] sysfs publishing patchset Jeff Mahoney
                   ` (5 preceding siblings ...)
  2013-10-21 21:19 ` [patch 06/13] btrfs: publish unknown feature bits " Jeff Mahoney
@ 2013-10-21 21:19 ` Jeff Mahoney
  2013-10-21 21:19 ` [patch 08/13] btrfs: use feature attribute names to print better error messages Jeff Mahoney
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Jeff Mahoney @ 2013-10-21 21:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

This patch adds the ability to change (set/clear) features while the file
system is mounted. A bitmask is added for each feature set for the
support to set and clear the bits. A message indicating which bit
has been set or cleared is issued when it's been changed and also when
permission or support for a particular bit has been denied.

Since the the attributes can now be writable, we need to introduce
another struct attribute to hold the different permissions.

If neither set or clear is supported, the file will have 0444 permissions.
If either set or clear is supported, the file will have 0644 permissions
and the store handler will filter out the write based on the bitmask.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
 fs/btrfs/sysfs.c |  118 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 fs/btrfs/sysfs.h |    3 -
 2 files changed, 117 insertions(+), 4 deletions(-)

--- a/fs/btrfs/sysfs.c	2013-10-21 16:10:01.076018741 -0400
+++ b/fs/btrfs/sysfs.c	2013-10-21 16:10:01.456010390 -0400
@@ -43,21 +43,131 @@ static u64 get_features(struct btrfs_fs_
 		return btrfs_super_incompat_flags(disk_super);
 }
 
+static void set_features(struct btrfs_fs_info *fs_info,
+			 enum btrfs_feature_set set, u64 features)
+{
+	struct btrfs_super_block *disk_super = fs_info->super_copy;
+	if (set == FEAT_COMPAT)
+		btrfs_set_super_compat_flags(disk_super, features);
+	else if (set == FEAT_COMPAT_RO)
+		btrfs_set_super_compat_ro_flags(disk_super, features);
+	else
+		btrfs_set_super_incompat_flags(disk_super, features);
+}
+
+static int can_modify_feature(struct btrfs_feature_attr *fa)
+{
+	int val = 0;
+	u64 set, clear;
+	switch (fa->feature_set) {
+	case FEAT_COMPAT:
+		set = BTRFS_FEATURE_COMPAT_SAFE_SET;
+		clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR;
+		break;
+	case FEAT_COMPAT_RO:
+		set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET;
+		clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR;
+		break;
+	case FEAT_INCOMPAT:
+		set = BTRFS_FEATURE_INCOMPAT_SAFE_SET;
+		clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR;
+		break;
+	default:
+		BUG();
+	}
+
+	if (set & fa->feature_bit)
+		val |= 1;
+	if (clear & fa->feature_bit)
+		val |= 2;
+
+	return val;
+}
+
 static ssize_t btrfs_feature_attr_show(struct kobject *kobj,
 				       struct kobj_attribute *a, char *buf)
 {
 	int val = 0;
 	struct btrfs_fs_info *fs_info = to_fs_info(kobj);
+	struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a);
 	if (fs_info) {
-		struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a);
 		u64 features = get_features(fs_info, fa->feature_set);
 		if (features & fa->feature_bit)
 			val = 1;
-	}
+	} else
+		val = can_modify_feature(fa);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", val);
 }
 
+static ssize_t btrfs_feature_attr_store(struct kobject *kobj,
+					struct kobj_attribute *a,
+					const char *buf, size_t count)
+{
+	struct btrfs_fs_info *fs_info;
+	struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a);
+	struct btrfs_trans_handle *trans;
+	u64 features, set, clear;
+	unsigned long val;
+	int ret;
+
+	fs_info = to_fs_info(kobj);
+	if (!fs_info)
+		return -EPERM;
+
+	ret = kstrtoul(skip_spaces(buf), 0, &val);
+	if (ret)
+		return ret;
+
+	if (fa->feature_set == FEAT_COMPAT) {
+		set = BTRFS_FEATURE_COMPAT_SAFE_SET;
+		clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR;
+	} else if (fa->feature_set == FEAT_COMPAT_RO) {
+		set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET;
+		clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR;
+	} else {
+		set = BTRFS_FEATURE_INCOMPAT_SAFE_SET;
+		clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR;
+	}
+
+	features = get_features(fs_info, fa->feature_set);
+
+	/* Nothing to do */
+	if ((val && (features & fa->feature_bit)) ||
+	    (!val && !(features & fa->feature_bit)))
+		return count;
+
+	if ((val && !(set & fa->feature_bit)) ||
+	    (!val && !(clear & fa->feature_bit))) {
+		btrfs_info(fs_info,
+			"%sabling feature %s on mounted fs is not supported.",
+			val ? "En" : "Dis", fa->kobj_attr.attr.name);
+		return -EPERM;
+	}
+
+	btrfs_info(fs_info, "%s %s feature flag",
+		   val ? "Setting" : "Clearing", fa->kobj_attr.attr.name);
+
+	trans = btrfs_start_transaction(fs_info->fs_root, 1);
+	if (IS_ERR(trans))
+		return PTR_ERR(trans);
+
+	spin_lock(&fs_info->super_lock);
+	features = get_features(fs_info, fa->feature_set);
+	if (val)
+		features |= fa->feature_bit;
+	else
+		features &= ~fa->feature_bit;
+	set_features(fs_info, fa->feature_set, features);
+	spin_unlock(&fs_info->super_lock);
+
+	ret = btrfs_commit_transaction(trans, fs_info->fs_root);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
 static umode_t btrfs_feature_visible(struct kobject *kobj,
 				     struct attribute *attr, int unused)
 {
@@ -71,7 +181,9 @@ static umode_t btrfs_feature_visible(str
 		fa = attr_to_btrfs_feature_attr(attr);
 		features = get_features(fs_info, fa->feature_set);
 
-		if (!(features & fa->feature_bit))
+		if (can_modify_feature(fa))
+			mode |= S_IWUSR;
+		else if (!(features & fa->feature_bit))
 			mode = 0;
 	}
 
--- a/fs/btrfs/sysfs.h	2013-10-21 16:10:00.216037635 -0400
+++ b/fs/btrfs/sysfs.h	2013-10-21 16:10:01.460010303 -0400
@@ -31,7 +31,8 @@ struct btrfs_feature_attr {
 #define BTRFS_FEAT_ATTR(_name, _feature_set, _prefix, _feature_bit)	     \
 static struct btrfs_feature_attr btrfs_attr_##_name = {			     \
 	.kobj_attr = __INIT_KOBJ_ATTR(_name, S_IRUGO,			     \
-				      btrfs_feature_attr_show, NULL),	     \
+				      btrfs_feature_attr_show,		     \
+				      btrfs_feature_attr_store),	     \
 	.feature_set	= _feature_set,					     \
 	.feature_bit	= _prefix ##_## _feature_bit,			     \
 }



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [patch 08/13] btrfs: use feature attribute names to print better error messages
  2013-10-21 21:19 [patch 00/13] sysfs publishing patchset Jeff Mahoney
                   ` (6 preceding siblings ...)
  2013-10-21 21:19 ` [patch 07/13] btrfs: add ability to change features via sysfs Jeff Mahoney
@ 2013-10-21 21:19 ` Jeff Mahoney
  2013-10-21 21:19 ` [patch 09/13] btrfs: add ioctl to export size of global metadata reservation Jeff Mahoney
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Jeff Mahoney @ 2013-10-21 21:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

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>
---
 fs/btrfs/ioctl.c |   35 ++++++++++++++++++++++++++++++-----
 fs/btrfs/sysfs.c |   33 ++++++++++++++++++++++++++++++++-
 fs/btrfs/sysfs.h |    2 ++
 3 files changed, 64 insertions(+), 6 deletions(-)

--- a/fs/btrfs/ioctl.c	2013-10-21 16:09:48.844287259 -0400
+++ b/fs/btrfs/ioctl.c	2013-10-21 16:10:01.856001602 -0400
@@ -57,6 +57,7 @@
 #include "rcu-string.h"
 #include "send.h"
 #include "dev-replace.h"
+#include "sysfs.h"
 
 static int btrfs_clone(struct inode *src, struct inode *inode,
 		       u64 off, u64 olen, u64 olen_aligned, u64 destoff);
@@ -4531,17 +4532,27 @@ static int btrfs_ioctl_get_features(stru
 	return 0;
 }
 
-static int check_feature_bits(struct btrfs_root *root, const char *type,
+static int check_feature_bits(struct btrfs_root *root,
+			      enum btrfs_feature_set set,
 			      u64 change_mask, u64 flags, u64 supported_flags,
 			      u64 safe_set, u64 safe_clear)
 {
+	const char *type = btrfs_feature_set_names[set];
+	char *names;
 	u64 disallowed, unsupported;
 	u64 set_mask = flags & change_mask;
 	u64 clear_mask = ~flags & change_mask;
 
 	unsupported = set_mask & ~supported_flags;
 	if (unsupported) {
-		btrfs_warn(root->fs_info,
+		names = btrfs_printable_features(set, unsupported);
+		if (names) {
+			btrfs_warn(root->fs_info,
+			   "this kernel does not support the %s feature bit%s",
+			   names, strchr(names, ',') ? "s" : "");
+			kfree(names);
+		} else
+			btrfs_warn(root->fs_info,
 			   "this kernel does not support %s bits 0x%llx",
 			   type, unsupported);
 		return -EOPNOTSUPP;
@@ -4549,7 +4560,14 @@ static int check_feature_bits(struct btr
 
 	disallowed = set_mask & ~safe_set;
 	if (disallowed) {
-		btrfs_warn(root->fs_info,
+		names = btrfs_printable_features(set, disallowed);
+		if (names) {
+			btrfs_warn(root->fs_info,
+			   "can't set the %s feature bit%s while mounted",
+			   names, strchr(names, ',') ? "s" : "");
+			kfree(names);
+		} else
+			btrfs_warn(root->fs_info,
 			   "can't set %s bits 0x%llx while mounted",
 			   type, disallowed);
 		return -EPERM;
@@ -4557,7 +4575,14 @@ static int check_feature_bits(struct btr
 
 	disallowed = clear_mask & ~safe_clear;
 	if (disallowed) {
-		btrfs_warn(root->fs_info,
+		names = btrfs_printable_features(set, disallowed);
+		if (names) {
+			btrfs_warn(root->fs_info,
+			   "can't clear the %s feature bit%s while mounted",
+			   names, strchr(names, ',') ? "s" : "");
+			kfree(names);
+		} else
+			btrfs_warn(root->fs_info,
 			   "can't clear %s bits 0x%llx while mounted",
 			   type, disallowed);
 		return -EPERM;
@@ -4567,7 +4592,7 @@ static int check_feature_bits(struct btr
 }
 
 #define check_feature(root, change_mask, flags, mask_base)	\
-check_feature_bits(root, # mask_base, change_mask, flags,	\
+check_feature_bits(root, FEAT_##mask_base, change_mask, flags,	\
 		   BTRFS_FEATURE_ ## mask_base ## _SUPP,	\
 		   BTRFS_FEATURE_ ## mask_base ## _SAFE_SET,	\
 		   BTRFS_FEATURE_ ## mask_base ## _SAFE_CLEAR)
--- a/fs/btrfs/sysfs.c	2013-10-21 16:10:01.456010390 -0400
+++ b/fs/btrfs/sysfs.c	2013-10-21 16:10:01.856001602 -0400
@@ -254,6 +254,31 @@ const char * const btrfs_feature_set_nam
 static char btrfs_unknown_feature_names[3][NUM_FEATURE_BITS][13];
 static struct btrfs_feature_attr btrfs_feature_attrs[3][NUM_FEATURE_BITS];
 
+char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags)
+{
+	size_t bufsize = 4096; /* safe max, 64 names * 64 bytes */
+	int len = 0;
+	int i;
+	char *str;
+
+	str = kmalloc(bufsize, GFP_KERNEL);
+	if (!str)
+		return str;
+
+	for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) {
+		const char *name;
+
+		if (!(flags & (1ULL << i)))
+			continue;
+
+		name = btrfs_feature_attrs[set][i].kobj_attr.attr.name;
+		len += snprintf(str + len, bufsize - len, "%s%s",
+				len ? "," : "", name);
+	}
+
+	return str;
+}
+
 static void init_feature_attrs(void)
 {
 	struct btrfs_feature_attr *fa;
@@ -264,11 +289,17 @@ static void init_feature_attrs(void)
 	BUILD_BUG_ON(ARRAY_SIZE(btrfs_unknown_feature_names[0]) !=
 		     ARRAY_SIZE(btrfs_feature_attrs[0]));
 
+	memset(btrfs_feature_attrs, 0, sizeof(btrfs_feature_attrs));
+	memset(btrfs_unknown_feature_names, 0,
+	       sizeof(btrfs_unknown_feature_names));
+
 	for (i = 0; btrfs_supported_feature_attrs[i]; i++) {
 		struct btrfs_feature_attr *sfa;
 		struct attribute *a = btrfs_supported_feature_attrs[i];
+		int bit;
 		sfa = attr_to_btrfs_feature_attr(a);
-		fa = &btrfs_feature_attrs[sfa->feature_set][sfa->feature_bit];
+		bit = ilog2(sfa->feature_bit);
+		fa = &btrfs_feature_attrs[sfa->feature_set][bit];
 
 		fa->kobj_attr.attr.name = sfa->kobj_attr.attr.name;
 	}
--- a/fs/btrfs/sysfs.h	2013-10-21 16:10:01.460010303 -0400
+++ b/fs/btrfs/sysfs.h	2013-10-21 16:10:01.860001514 -0400
@@ -51,4 +51,6 @@ static struct btrfs_feature_attr btrfs_a
 #define attr_to_btrfs_attr(a) container_of(a, struct kobj_attribute, attr)
 #define attr_to_btrfs_feature_attr(a) \
 			to_btrfs_feature_attr(attr_to_btrfs_attr(a))
+char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags);
+extern const char * const btrfs_feature_set_names[3];
 #endif /* _BTRFS_SYSFS_H_ */



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [patch 09/13] btrfs: add ioctl to export size of global metadata reservation
  2013-10-21 21:19 [patch 00/13] sysfs publishing patchset Jeff Mahoney
                   ` (7 preceding siblings ...)
  2013-10-21 21:19 ` [patch 08/13] btrfs: use feature attribute names to print better error messages Jeff Mahoney
@ 2013-10-21 21:19 ` Jeff Mahoney
  2013-10-21 21:19 ` [patch 10/13] btrfs: publish allocation data in sysfs Jeff Mahoney
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Jeff Mahoney @ 2013-10-21 21:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

btrfs filesystem df output will show the size of the metadata space
and how much of it is used, and the user assumes that the difference
is all usable space. Since that's not actually the case due to the
global metadata reservation, we should provide the full picture to the
user.

This patch adds an ioctl that exports the size of the global metadata
reservation so that btrfs filesystem df can report it.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
 fs/btrfs/ioctl.c           |   16 ++++++++++++++++
 include/uapi/linux/btrfs.h |    1 +
 2 files changed, 17 insertions(+)

--- a/fs/btrfs/ioctl.c	2013-10-21 16:10:01.856001602 -0400
+++ b/fs/btrfs/ioctl.c	2013-10-21 16:10:02.295991933 -0400
@@ -3511,6 +3511,20 @@ out:
 	return ret;
 }
 
+static long btrfs_ioctl_global_rsv(struct btrfs_root *root, void __user *arg)
+{
+	struct btrfs_block_rsv *block_rsv = &root->fs_info->global_block_rsv;
+	u64 reserved;
+
+	spin_lock(&block_rsv->lock);
+	reserved = block_rsv->reserved;
+	spin_unlock(&block_rsv->lock);
+
+	if (arg && copy_to_user(arg, &reserved, sizeof(reserved)))
+		return -EFAULT;
+	return 0;
+}
+
 /*
  * there are many ways the trans_start and trans_end ioctls can lead
  * to deadlocks.  They should only be used by applications that
@@ -4721,6 +4735,8 @@ long btrfs_ioctl(struct file *file, unsi
 		return btrfs_ioctl_logical_to_ino(root, argp);
 	case BTRFS_IOC_SPACE_INFO:
 		return btrfs_ioctl_space_info(root, argp);
+	case BTRFS_IOC_GLOBAL_RSV:
+		return btrfs_ioctl_global_rsv(root, argp);
 	case BTRFS_IOC_SYNC:
 		btrfs_sync_fs(file->f_dentry->d_sb, 1);
 		return 0;
--- a/include/uapi/linux/btrfs.h	2013-10-21 16:09:44.804375840 -0400
+++ b/include/uapi/linux/btrfs.h	2013-10-21 16:10:02.343990878 -0400
@@ -558,6 +558,7 @@ static inline char *btrfs_err_str(enum b
 #define BTRFS_IOC_DEFAULT_SUBVOL _IOW(BTRFS_IOCTL_MAGIC, 19, __u64)
 #define BTRFS_IOC_SPACE_INFO _IOWR(BTRFS_IOCTL_MAGIC, 20, \
 				    struct btrfs_ioctl_space_args)
+#define BTRFS_IOC_GLOBAL_RSV _IOR(BTRFS_IOCTL_MAGIC, 20, __u64)
 #define BTRFS_IOC_START_SYNC _IOR(BTRFS_IOCTL_MAGIC, 24, __u64)
 #define BTRFS_IOC_WAIT_SYNC  _IOW(BTRFS_IOCTL_MAGIC, 22, __u64)
 #define BTRFS_IOC_SNAP_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 23, \




^ permalink raw reply	[flat|nested] 22+ messages in thread

* [patch 10/13] btrfs: publish allocation data in sysfs
  2013-10-21 21:19 [patch 00/13] sysfs publishing patchset Jeff Mahoney
                   ` (8 preceding siblings ...)
  2013-10-21 21:19 ` [patch 09/13] btrfs: add ioctl to export size of global metadata reservation Jeff Mahoney
@ 2013-10-21 21:19 ` Jeff Mahoney
  2013-10-29 18:49   ` Jeff Mahoney
  2013-10-21 21:19 ` [patch 11/13] btrfs: publish device membership " Jeff Mahoney
                   ` (4 subsequent siblings)
  14 siblings, 1 reply; 22+ messages in thread
From: Jeff Mahoney @ 2013-10-21 21:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

While trying to debug ENOSPC issues, it's helpful to understand what the
kernel's view of the available space is. We export this information
via ioctl, but sysfs files are more easily used.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
 fs/btrfs/ctree.h       |    5 +
 fs/btrfs/extent-tree.c |   72 ++++++++++++++++++++++-
 fs/btrfs/sysfs.c       |  148 +++++++++++++++++++++++++++++++++++++++++++++++++
 fs/btrfs/sysfs.h       |    8 ++
 4 files changed, 228 insertions(+), 5 deletions(-)

--- a/fs/btrfs/ctree.h	2013-10-21 16:10:00.212037722 -0400
+++ b/fs/btrfs/ctree.h	2013-10-21 16:10:02.743982088 -0400
@@ -1143,6 +1143,9 @@ struct btrfs_space_info {
 	spinlock_t lock;
 	struct rw_semaphore groups_sem;
 	wait_queue_head_t wait;
+
+	struct kobject kobj;
+	struct kobject block_group_kobjs[BTRFS_NR_RAID_TYPES];
 };
 
 #define	BTRFS_BLOCK_RSV_GLOBAL		1
@@ -1518,6 +1521,7 @@ struct btrfs_fs_info {
 	int thread_pool_size;
 
 	struct kobject super_kobj;
+	struct kobject *space_info_kobj;
 	struct completion kobj_unregister;
 	int do_barriers;
 	int closing;
@@ -3171,6 +3175,7 @@ struct btrfs_block_group_cache *btrfs_lo
 						 struct btrfs_fs_info *info,
 						 u64 bytenr);
 void btrfs_put_block_group(struct btrfs_block_group_cache *cache);
+int get_block_group_index(struct btrfs_block_group_cache *cache);
 struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
 					struct btrfs_root *root, u32 blocksize,
 					u64 parent, u64 root_objectid,
--- a/fs/btrfs/extent-tree.c	2013-10-21 16:09:33.476623940 -0400
+++ b/fs/btrfs/extent-tree.c	2013-10-21 16:10:02.751981911 -0400
@@ -36,6 +36,7 @@
 #include "locking.h"
 #include "free-space-cache.h"
 #include "math.h"
+#include "sysfs.h"
 
 #undef SCRAMBLE_DELAYED_REFS
 
@@ -3389,6 +3390,13 @@ int btrfs_extent_readonly(struct btrfs_r
 	return readonly;
 }
 
+static const char * const alloc_names[] = {
+	"data",
+	"system",
+	"mixed",
+	"metadata",
+};
+
 static int update_space_info(struct btrfs_fs_info *info, u64 flags,
 			     u64 total_bytes, u64 bytes_used,
 			     struct btrfs_space_info **space_info)
@@ -3444,11 +3452,21 @@ static int update_space_info(struct btrf
 	found->chunk_alloc = 0;
 	found->flush = 0;
 	init_waitqueue_head(&found->wait);
+
+	ret = kobject_init_and_add(&found->kobj, &space_info_ktype,
+				    info->space_info_kobj, "%s",
+				    alloc_names[found->flags - 1]);
+	if (ret) {
+		kfree(found);
+		return ret;
+	}
+
 	*space_info = found;
 	list_add_rcu(&found->list, &info->space_info);
 	if (flags & BTRFS_BLOCK_GROUP_DATA)
 		info->data_sinfo = found;
-	return 0;
+
+	return ret;
 }
 
 static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
@@ -6090,11 +6108,29 @@ int __get_raid_index(u64 flags)
 	return BTRFS_RAID_SINGLE; /* BTRFS_BLOCK_GROUP_SINGLE */
 }
 
-static int get_block_group_index(struct btrfs_block_group_cache *cache)
+int get_block_group_index(struct btrfs_block_group_cache *cache)
 {
 	return __get_raid_index(cache->flags);
 }
 
+static const char *btrfs_raid_type_names[BTRFS_NR_RAID_TYPES] = {
+	[BTRFS_RAID_RAID10]	= "raid10",
+	[BTRFS_RAID_RAID1]	= "raid1",
+	[BTRFS_RAID_DUP]	= "dup",
+	[BTRFS_RAID_RAID0]	= "raid0",
+	[BTRFS_RAID_SINGLE]	= "single",
+	[BTRFS_RAID_RAID5]	= "raid5",
+	[BTRFS_RAID_RAID6]	= "raid6",
+};
+
+const char *get_raid_name(enum btrfs_raid_types type)
+{
+	if (type >= BTRFS_NR_RAID_TYPES)
+		return NULL;
+
+	return btrfs_raid_type_names[type];
+}
+
 enum btrfs_loop_type {
 	LOOP_CACHING_NOWAIT = 0,
 	LOOP_CACHING_WAIT = 1,
@@ -8272,6 +8308,8 @@ int btrfs_free_block_groups(struct btrfs
 	release_global_block_rsv(info);
 
 	while(!list_empty(&info->space_info)) {
+		int i;
+
 		space_info = list_entry(info->space_info.next,
 					struct btrfs_space_info,
 					list);
@@ -8283,9 +8321,17 @@ int btrfs_free_block_groups(struct btrfs
 				dump_space_info(space_info, 0, 0);
 			}
 		}
-		percpu_counter_destroy(&space_info->total_bytes_pinned);
 		list_del(&space_info->list);
-		kfree(space_info);
+		for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) {
+			struct kobject *kobj;
+			kobj = &space_info->block_group_kobjs[i];
+			if (kobj->parent) {
+				kobject_del(kobj);
+				kobject_put(kobj);
+			}
+		}
+		kobject_del(&space_info->kobj);
+		kobject_put(&space_info->kobj);
 	}
 	return 0;
 }
@@ -8296,6 +8342,19 @@ static void __link_block_group(struct bt
 	int index = get_block_group_index(cache);
 
 	down_write(&space_info->groups_sem);
+	if (list_empty(&space_info->block_groups[index])) {
+		struct kobject *kobj = &space_info->block_group_kobjs[index];
+		int ret;
+
+		kobject_get(&space_info->kobj); /* put in release */
+		ret = kobject_init_and_add(kobj, &btrfs_raid_ktype,
+					   &space_info->kobj,
+					   get_raid_name(index));
+		if (ret) {
+			pr_warn("btrfs: failed to add kobject for block cache. ignoring.\n");
+			kobject_put(&space_info->kobj);
+		}
+	}
 	list_add_tail(&cache->list, &space_info->block_groups[index]);
 	up_write(&space_info->groups_sem);
 }
@@ -8736,8 +8795,11 @@ int btrfs_remove_block_group(struct btrf
 	 * are still on the list after taking the semaphore
 	 */
 	list_del_init(&block_group->list);
-	if (list_empty(&block_group->space_info->block_groups[index]))
+	if (list_empty(&block_group->space_info->block_groups[index])) {
+		kobject_del(&block_group->space_info->block_group_kobjs[index]);
+		kobject_put(&block_group->space_info->block_group_kobjs[index]);
 		clear_avail_alloc_bits(root->fs_info, block_group->flags);
+	}
 	up_write(&block_group->space_info->groups_sem);
 
 	if (block_group->cached == BTRFS_CACHE_STARTED)
--- a/fs/btrfs/sysfs.c	2013-10-21 16:10:01.856001602 -0400
+++ b/fs/btrfs/sysfs.c	2013-10-21 16:10:02.751981911 -0400
@@ -219,6 +219,140 @@ static const struct attribute_group btrf
 	.attrs = btrfs_supported_feature_attrs,
 };
 
+static ssize_t btrfs_show_u64(u64 *value_ptr, spinlock_t *lock, char *buf)
+{
+	u64 val;
+	if (lock)
+		spin_lock(lock);
+	val = *value_ptr;
+	if (lock)
+		spin_unlock(lock);
+	return snprintf(buf, PAGE_SIZE, "%llu\n", val);
+}
+
+static ssize_t global_rsv_size_show(struct kobject *kobj,
+				    struct kobj_attribute *ka, char *buf)
+{
+	struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent);
+	struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
+	return btrfs_show_u64(&block_rsv->size, &block_rsv->lock, buf);
+}
+BTRFS_ATTR(global_rsv_size, 0444, global_rsv_size_show);
+
+static ssize_t global_rsv_reserved_show(struct kobject *kobj,
+					struct kobj_attribute *a, char *buf)
+{
+	struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent);
+	struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
+	return btrfs_show_u64(&block_rsv->reserved, &block_rsv->lock, buf);
+}
+BTRFS_ATTR(global_rsv_reserved, 0444, global_rsv_reserved_show);
+
+#define to_space_info(_kobj) container_of(_kobj, struct btrfs_space_info, kobj)
+
+static ssize_t raid_bytes_show(struct kobject *kobj,
+			       struct kobj_attribute *attr, char *buf);
+BTRFS_RAID_ATTR(total_bytes, raid_bytes_show);
+BTRFS_RAID_ATTR(used_bytes, raid_bytes_show);
+
+static ssize_t raid_bytes_show(struct kobject *kobj,
+			       struct kobj_attribute *attr, char *buf)
+
+{
+	struct btrfs_space_info *sinfo = to_space_info(kobj->parent);
+	struct btrfs_block_group_cache *block_group;
+	int index = kobj - sinfo->block_group_kobjs;
+	u64 val = 0;
+
+	down_read(&sinfo->groups_sem);
+	list_for_each_entry(block_group, &sinfo->block_groups[index], list) {
+		if (&attr->attr == BTRFS_RAID_ATTR_PTR(total_bytes))
+			val += block_group->key.offset;
+		else
+			val += btrfs_block_group_used(&block_group->item);
+	}
+	up_read(&sinfo->groups_sem);
+	return snprintf(buf, PAGE_SIZE, "%llu\n", val);
+}
+
+static struct attribute *raid_attributes[] = {
+	BTRFS_RAID_ATTR_PTR(total_bytes),
+	BTRFS_RAID_ATTR_PTR(used_bytes),
+	NULL
+};
+
+static void release_raid_kobj(struct kobject *kobj)
+{
+	kobject_put(kobj->parent);
+}
+
+struct kobj_type btrfs_raid_ktype = {
+	.sysfs_ops = &kobj_sysfs_ops,
+	.release = release_raid_kobj,
+	.default_attrs = raid_attributes,
+};
+
+#define SPACE_INFO_ATTR(field)						\
+static ssize_t btrfs_space_info_show_##field(struct kobject *kobj,	\
+					     struct kobj_attribute *a,	\
+					     char *buf)			\
+{									\
+	struct btrfs_space_info *sinfo = to_space_info(kobj);		\
+	return btrfs_show_u64(&sinfo->field, &sinfo->lock, buf);	\
+}									\
+BTRFS_ATTR(field, 0444, btrfs_space_info_show_##field)
+
+static ssize_t btrfs_space_info_show_total_bytes_pinned(struct kobject *kobj,
+						       struct kobj_attribute *a,
+						       char *buf)
+{
+	struct btrfs_space_info *sinfo = to_space_info(kobj);
+	s64 val = percpu_counter_sum(&sinfo->total_bytes_pinned);
+	return snprintf(buf, PAGE_SIZE, "%lld\n", val);
+}
+
+SPACE_INFO_ATTR(flags);
+SPACE_INFO_ATTR(total_bytes);
+SPACE_INFO_ATTR(bytes_used);
+SPACE_INFO_ATTR(bytes_pinned);
+SPACE_INFO_ATTR(bytes_reserved);
+SPACE_INFO_ATTR(bytes_may_use);
+SPACE_INFO_ATTR(disk_used);
+SPACE_INFO_ATTR(disk_total);
+BTRFS_ATTR(total_bytes_pinned, 0444, btrfs_space_info_show_total_bytes_pinned);
+
+static struct attribute *space_info_attrs[] = {
+	BTRFS_ATTR_PTR(flags),
+	BTRFS_ATTR_PTR(total_bytes),
+	BTRFS_ATTR_PTR(bytes_used),
+	BTRFS_ATTR_PTR(bytes_pinned),
+	BTRFS_ATTR_PTR(bytes_reserved),
+	BTRFS_ATTR_PTR(bytes_may_use),
+	BTRFS_ATTR_PTR(disk_used),
+	BTRFS_ATTR_PTR(disk_total),
+	BTRFS_ATTR_PTR(total_bytes_pinned),
+	NULL,
+};
+
+static void space_info_release(struct kobject *kobj)
+{
+	struct btrfs_space_info *sinfo = to_space_info(kobj);
+	percpu_counter_destroy(&sinfo->total_bytes_pinned);
+	kfree(sinfo);
+}
+
+struct kobj_type space_info_ktype = {
+	.sysfs_ops = &kobj_sysfs_ops,
+	.release = space_info_release,
+	.default_attrs = space_info_attrs,
+};
+
+static const struct attribute *allocation_attrs[] = {
+	BTRFS_ATTR_PTR(global_rsv_reserved),
+	BTRFS_ATTR_PTR(global_rsv_size),
+	NULL,
+};
+
 static void btrfs_release_super_kobj(struct kobject *kobj)
 {
 	struct btrfs_fs_info *fs_info = to_fs_info(kobj);
@@ -239,6 +373,9 @@ static inline struct btrfs_fs_info *to_f
 
 void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info)
 {
+	sysfs_remove_files(fs_info->space_info_kobj, allocation_attrs);
+	kobject_del(fs_info->space_info_kobj);
+	kobject_put(fs_info->space_info_kobj);
 	kobject_del(&fs_info->super_kobj);
 	kobject_put(&fs_info->super_kobj);
 	wait_for_completion(&fs_info->kobj_unregister);
@@ -391,6 +528,17 @@ int btrfs_sysfs_add_one(struct btrfs_fs_
 	if (error)
 		goto failure;
 
+	fs_info->space_info_kobj = kobject_create_and_add("allocation",
+						  &fs_info->super_kobj);
+	if (!fs_info->space_info_kobj) {
+		error = -ENOMEM;
+		goto failure;
+	}
+
+	error = sysfs_create_files(fs_info->space_info_kobj, allocation_attrs);
+	if (error)
+		goto failure;
+
 	return 0;
 failure:
 	btrfs_sysfs_remove_one(fs_info);
--- a/fs/btrfs/sysfs.h	2013-10-21 16:10:01.860001514 -0400
+++ b/fs/btrfs/sysfs.h	2013-10-21 16:10:02.751981911 -0400
@@ -22,6 +22,12 @@ static struct kobj_attribute btrfs_attr_
 	BTRFS_ATTR_RW(_name, _mode, _show, NULL)
 #define BTRFS_ATTR_PTR(_name)    (&btrfs_attr_##_name.attr)
 
+#define BTRFS_RAID_ATTR(_name, _show)					\
+static struct kobj_attribute btrfs_raid_attr_##_name =			\
+			__INIT_KOBJ_ATTR(_name, 0444, _show, NULL)
+#define BTRFS_RAID_ATTR_PTR(_name)    (&btrfs_raid_attr_##_name.attr)
+
+
 struct btrfs_feature_attr {
 	struct kobj_attribute kobj_attr;
 	enum btrfs_feature_set feature_set;
@@ -53,4 +59,6 @@ static struct btrfs_feature_attr btrfs_a
 			to_btrfs_feature_attr(attr_to_btrfs_attr(a))
 char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags);
 extern const char * const btrfs_feature_set_names[3];
+extern struct kobj_type space_info_ktype;
+extern struct kobj_type btrfs_raid_ktype;
 #endif /* _BTRFS_SYSFS_H_ */




^ permalink raw reply	[flat|nested] 22+ messages in thread

* [patch 11/13] btrfs: publish device membership in sysfs
  2013-10-21 21:19 [patch 00/13] sysfs publishing patchset Jeff Mahoney
                   ` (9 preceding siblings ...)
  2013-10-21 21:19 ` [patch 10/13] btrfs: publish allocation data in sysfs Jeff Mahoney
@ 2013-10-21 21:19 ` Jeff Mahoney
  2013-10-21 21:19 ` [patch 12/13] btrfs: publish fs label " Jeff Mahoney
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Jeff Mahoney @ 2013-10-21 21:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

Now that we have the infrastructure for per-super attributes, we can
publish device membership in /sys/fs/btrfs/<fsid>/devices. The information
is published as symlinks to the block devices.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
 fs/btrfs/ctree.h |    1 +
 fs/btrfs/sysfs.c |   32 ++++++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+)

--- a/fs/btrfs/ctree.h	2013-10-21 16:10:02.743982088 -0400
+++ b/fs/btrfs/ctree.h	2013-10-21 16:10:03.223971538 -0400
@@ -1522,6 +1522,7 @@ struct btrfs_fs_info {
 
 	struct kobject super_kobj;
 	struct kobject *space_info_kobj;
+	struct kobject *device_dir_kobj;
 	struct completion kobj_unregister;
 	int do_barriers;
 	int closing;
--- a/fs/btrfs/sysfs.c	2013-10-21 16:10:02.751981911 -0400
+++ b/fs/btrfs/sysfs.c	2013-10-21 16:10:03.227971451 -0400
@@ -23,11 +23,13 @@
 #include <linux/buffer_head.h>
 #include <linux/kobject.h>
 #include <linux/bug.h>
+#include <linux/genhd.h>
 
 #include "ctree.h"
 #include "disk-io.h"
 #include "transaction.h"
 #include "sysfs.h"
+#include "volumes.h"
 
 static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj);
 
@@ -374,6 +376,8 @@ static inline struct btrfs_fs_info *to_f
 void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info)
 {
 	sysfs_remove_files(fs_info->space_info_kobj, allocation_attrs);
+	kobject_del(fs_info->device_dir_kobj);
+	kobject_put(fs_info->device_dir_kobj);
 	kobject_del(fs_info->space_info_kobj);
 	kobject_put(fs_info->space_info_kobj);
 	kobject_del(&fs_info->super_kobj);
@@ -507,6 +511,30 @@ static int add_unknown_feature_attrs(str
 	return 0;
 }
 
+static int add_device_membership(struct btrfs_fs_info *fs_info)
+{
+	int error = 0;
+	struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
+	struct btrfs_device *dev;
+
+	fs_info->device_dir_kobj = kobject_create_and_add("devices",
+						&fs_info->super_kobj);
+	if (!fs_info->device_dir_kobj)
+		return -ENOMEM;
+
+	list_for_each_entry(dev, &fs_devices->devices, dev_list) {
+		struct hd_struct *disk = dev->bdev->bd_part;
+		struct kobject *disk_kobj = &part_to_dev(disk)->kobj;
+
+		error = sysfs_create_link(fs_info->device_dir_kobj,
+					  disk_kobj, disk_kobj->name);
+		if (error)
+			break;
+	}
+
+	return error;
+}
+
 /* /sys/fs/btrfs/ entry */
 static struct kset *btrfs_kset;
 
@@ -528,6 +556,10 @@ int btrfs_sysfs_add_one(struct btrfs_fs_
 	if (error)
 		goto failure;
 
+	error = add_device_membership(fs_info);
+	if (error)
+		goto failure;
+
 	fs_info->space_info_kobj = kobject_create_and_add("allocation",
 						  &fs_info->super_kobj);
 	if (!fs_info->space_info_kobj) {




^ permalink raw reply	[flat|nested] 22+ messages in thread

* [patch 12/13] btrfs: publish fs label in sysfs
  2013-10-21 21:19 [patch 00/13] sysfs publishing patchset Jeff Mahoney
                   ` (10 preceding siblings ...)
  2013-10-21 21:19 ` [patch 11/13] btrfs: publish device membership " Jeff Mahoney
@ 2013-10-21 21:19 ` Jeff Mahoney
  2013-10-21 21:19 ` [patch 13/13] btrfs: add tracing for failed reservations Jeff Mahoney
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Jeff Mahoney @ 2013-10-21 21:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

This adds a writeable attribute which describes the label.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
 fs/btrfs/sysfs.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

--- a/fs/btrfs/sysfs.c	2013-10-21 16:20:06.395804741 -0400
+++ b/fs/btrfs/sysfs.c	2013-10-21 16:23:57.402255196 -0400
@@ -355,6 +355,49 @@ static const struct attribute *allocatio
 	NULL,
 };
 
+static ssize_t btrfs_label_show(struct kobject *kobj,
+				struct kobj_attribute *a, char *buf)
+{
+	struct btrfs_fs_info *fs_info = to_fs_info(kobj);
+	return snprintf(buf, PAGE_SIZE, "%s\n", fs_info->super_copy->label);
+}
+
+static ssize_t btrfs_label_store(struct kobject *kobj,
+				 struct kobj_attribute *a,
+				 const char *buf, size_t len)
+{
+	struct btrfs_fs_info *fs_info = to_fs_info(kobj);
+	struct btrfs_trans_handle *trans;
+	struct btrfs_root *root = fs_info->fs_root;
+	int ret;
+
+	if (len >= BTRFS_LABEL_SIZE) {
+		pr_err("btrfs: unable to set label with more than %d bytes\n",
+		       BTRFS_LABEL_SIZE - 1);
+		return -EINVAL;
+	}
+
+	trans = btrfs_start_transaction(root, 0);
+	if (IS_ERR(trans))
+		return PTR_ERR(trans);
+
+	spin_lock(&root->fs_info->super_lock);
+	strcpy(fs_info->super_copy->label, buf);
+	spin_unlock(&root->fs_info->super_lock);
+	ret = btrfs_commit_transaction(trans, root);
+
+	if (!ret)
+		return len;
+
+	return ret;
+}
+BTRFS_ATTR_RW(label, 0644, btrfs_label_show, btrfs_label_store);
+
+static struct attribute *btrfs_attrs[] = {
+	BTRFS_ATTR_PTR(label),
+	NULL,
+};
+
 static void btrfs_release_super_kobj(struct kobject *kobj)
 {
 	struct btrfs_fs_info *fs_info = to_fs_info(kobj);
@@ -364,6 +407,7 @@ static void btrfs_release_super_kobj(str
 static struct kobj_type btrfs_ktype = {
 	.sysfs_ops	= &kobj_sysfs_ops,
 	.release	= btrfs_release_super_kobj,
+	.default_attrs	= btrfs_attrs,
 };
 
 static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj)




^ permalink raw reply	[flat|nested] 22+ messages in thread

* [patch 13/13] btrfs: add tracing for failed reservations
  2013-10-21 21:19 [patch 00/13] sysfs publishing patchset Jeff Mahoney
                   ` (11 preceding siblings ...)
  2013-10-21 21:19 ` [patch 12/13] btrfs: publish fs label " Jeff Mahoney
@ 2013-10-21 21:19 ` Jeff Mahoney
  2013-10-22 18:26 ` [patch 00/13] sysfs publishing patchset Josef Bacik
  2013-10-29 18:25 ` Goffredo Baroncelli
  14 siblings, 0 replies; 22+ messages in thread
From: Jeff Mahoney @ 2013-10-21 21:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

When debugging ENOSPC issues, it's nice to be able to see which
reservations failed as well as the ones which succeeded.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
 fs/btrfs/extent-tree.c |    7 +++++++
 1 file changed, 7 insertions(+)

--- a/fs/btrfs/extent-tree.c	2013-10-21 16:10:02.751981911 -0400
+++ b/fs/btrfs/extent-tree.c	2013-10-21 16:10:04.027953867 -0400
@@ -3699,6 +3699,9 @@ commit_trans:
 			goto again;
 		}
 
+		trace_btrfs_space_reservation(root->fs_info,
+					      "space_info:enospc",
+					      data_sinfo->flags, bytes, 1);
 		return -ENOSPC;
 	}
 	data_sinfo->bytes_may_use += bytes;
@@ -4350,6 +4353,10 @@ out:
 		    !block_rsv_use_bytes(global_rsv, orig_bytes))
 			ret = 0;
 	}
+	if (ret == -ENOSPC)
+		trace_btrfs_space_reservation(root->fs_info,
+					      "space_info:enospc",
+					      space_info->flags, orig_bytes, 1);
 	if (flushing) {
 		spin_lock(&space_info->lock);
 		space_info->flush = 0;




^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [patch 02/13] kobject: export kobj_sysfs_ops
  2013-10-21 21:19 ` [patch 02/13] kobject: export kobj_sysfs_ops Jeff Mahoney
@ 2013-10-22 14:44   ` Jeff Mahoney
  0 siblings, 0 replies; 22+ messages in thread
From: Jeff Mahoney @ 2013-10-22 14:44 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

[-- Attachment #1: Type: text/plain, Size: 1076 bytes --]

On 10/21/13 5:19 PM, Jeff Mahoney wrote:
> struct kobj_attribute implements the baseline attribute functionality
> that can be used all over the place. We should export the ops associated
> with it.
> 
> Signed-off-by: Jeff Mahoney <jeffm@suse.com>
> ---
> 
>  lib/kobject.c |    1 +
>  1 file changed, 1 insertion(+)
> 
> --- a/lib/kobject.c	2013-10-21 16:09:51.868220920 -0400
> +++ b/lib/kobject.c	2013-10-21 16:10:00.216037635 -0400
> @@ -726,6 +726,7 @@ const struct sysfs_ops kobj_sysfs_ops =
>  	.show	= kobj_attr_show,
>  	.store	= kobj_attr_store,
>  };
> +EXPORT_SYMBOL_GPL(kobj_sysfs_ops);
>  
>  /**
>   * kset_register - initialize and add a kset.
> 
> 
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

I posted this one on LKML, CC'ing Greg, and he gave his:
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

-Jeff

-- 
Jeff Mahoney
SUSE Labs


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 841 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [patch 00/13] sysfs publishing patchset
  2013-10-21 21:19 [patch 00/13] sysfs publishing patchset Jeff Mahoney
                   ` (12 preceding siblings ...)
  2013-10-21 21:19 ` [patch 13/13] btrfs: add tracing for failed reservations Jeff Mahoney
@ 2013-10-22 18:26 ` Josef Bacik
  2013-10-22 18:39   ` Jeff Mahoney
  2013-10-29 18:25 ` Goffredo Baroncelli
  14 siblings, 1 reply; 22+ messages in thread
From: Josef Bacik @ 2013-10-22 18:26 UTC (permalink / raw)
  To: Jeff Mahoney; +Cc: linux-btrfs

On Mon, Oct 21, 2013 at 05:19:40PM -0400, Jeff Mahoney wrote:
> This patchset implements the stubbed-out sysfs interface for btrfs. Or
> at least begins to do so.
> 
> We publish:
> - Features supported by the file system implementation
> - Features enabled on the file system, including features unknown to
>   the implemenation. These attributes can also be used to enable or
>   disable features at runtime, subjecting to a safety mask.
> - Uses the attribute names to print feature names when declining to
>   mount a file system.
> - The allocation data: global metadata reservation size and reserved,
>   space_infos, and sums of the block groups total and used bytes.
> - Device membership via links to the block devices.
> - FS label, which is writeable.
> 
> - I've also added matching ioctls for some of the functionality here so
>   that btrfsprogs can use the information without jumping through hoops
>   to read/parse the sysfs files. There are ioctls to query the supported
>   features and to query/set features on a particular file system. There's
>   also one to export the size of the global metadata reservation. I have
>   a patch for btrfs-progs that uses this to print useful info in 'btrfs
>   fi df' output.
> 
> Ultimately, the tree structure looks like the following, under /sys/fs/btrfs.
> This is from a test file system, using two devices in raid1. You'll notice
> the 'single' and 'raid1' directories under the {data,metadata,system} dirs.
> The raid profiles are created and removed as the first/last block group
> of a certain profile is added and removed.
> 

I'm not pulling in patches that add new functionality without an accompanying
xfstest so that we're not merging features without a way to test to make sure
they are working properly, this applies to the global metadata reservation ioctl
as well.  Thanks,

Josef

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [patch 00/13] sysfs publishing patchset
  2013-10-22 18:26 ` [patch 00/13] sysfs publishing patchset Josef Bacik
@ 2013-10-22 18:39   ` Jeff Mahoney
  2013-10-22 20:43     ` Josef Bacik
  0 siblings, 1 reply; 22+ messages in thread
From: Jeff Mahoney @ 2013-10-22 18:39 UTC (permalink / raw)
  To: Josef Bacik; +Cc: linux-btrfs

[-- Attachment #1: Type: text/plain, Size: 2199 bytes --]

On 10/22/13 2:26 PM, Josef Bacik wrote:
> On Mon, Oct 21, 2013 at 05:19:40PM -0400, Jeff Mahoney wrote:
>> This patchset implements the stubbed-out sysfs interface for btrfs. Or
>> at least begins to do so.
>>
>> We publish:
>> - Features supported by the file system implementation
>> - Features enabled on the file system, including features unknown to
>>   the implemenation. These attributes can also be used to enable or
>>   disable features at runtime, subjecting to a safety mask.
>> - Uses the attribute names to print feature names when declining to
>>   mount a file system.
>> - The allocation data: global metadata reservation size and reserved,
>>   space_infos, and sums of the block groups total and used bytes.
>> - Device membership via links to the block devices.
>> - FS label, which is writeable.
>>
>> - I've also added matching ioctls for some of the functionality here so
>>   that btrfsprogs can use the information without jumping through hoops
>>   to read/parse the sysfs files. There are ioctls to query the supported
>>   features and to query/set features on a particular file system. There's
>>   also one to export the size of the global metadata reservation. I have
>>   a patch for btrfs-progs that uses this to print useful info in 'btrfs
>>   fi df' output.
>>
>> Ultimately, the tree structure looks like the following, under /sys/fs/btrfs.
>> This is from a test file system, using two devices in raid1. You'll notice
>> the 'single' and 'raid1' directories under the {data,metadata,system} dirs.
>> The raid profiles are created and removed as the first/last block group
>> of a certain profile is added and removed.
>>
> 
> I'm not pulling in patches that add new functionality without an accompanying
> xfstest so that we're not merging features without a way to test to make sure

Sure, that's reasonable.

> they are working properly, this applies to the global metadata reservation ioctl
> as well.  Thanks,

What would a test look like for that? It's information that isn't
currently available anywhere in userspace and isn't represented in the
file system itself.

-Jeff


-- 
Jeff Mahoney
SUSE Labs


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 841 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [patch 00/13] sysfs publishing patchset
  2013-10-22 18:39   ` Jeff Mahoney
@ 2013-10-22 20:43     ` Josef Bacik
  0 siblings, 0 replies; 22+ messages in thread
From: Josef Bacik @ 2013-10-22 20:43 UTC (permalink / raw)
  To: Jeff Mahoney; +Cc: Josef Bacik, linux-btrfs

On Tue, Oct 22, 2013 at 02:39:06PM -0400, Jeff Mahoney wrote:
> On 10/22/13 2:26 PM, Josef Bacik wrote:
> > On Mon, Oct 21, 2013 at 05:19:40PM -0400, Jeff Mahoney wrote:
> >> This patchset implements the stubbed-out sysfs interface for btrfs. Or
> >> at least begins to do so.
> >>
> >> We publish:
> >> - Features supported by the file system implementation
> >> - Features enabled on the file system, including features unknown to
> >>   the implemenation. These attributes can also be used to enable or
> >>   disable features at runtime, subjecting to a safety mask.
> >> - Uses the attribute names to print feature names when declining to
> >>   mount a file system.
> >> - The allocation data: global metadata reservation size and reserved,
> >>   space_infos, and sums of the block groups total and used bytes.
> >> - Device membership via links to the block devices.
> >> - FS label, which is writeable.
> >>
> >> - I've also added matching ioctls for some of the functionality here so
> >>   that btrfsprogs can use the information without jumping through hoops
> >>   to read/parse the sysfs files. There are ioctls to query the supported
> >>   features and to query/set features on a particular file system. There's
> >>   also one to export the size of the global metadata reservation. I have
> >>   a patch for btrfs-progs that uses this to print useful info in 'btrfs
> >>   fi df' output.
> >>
> >> Ultimately, the tree structure looks like the following, under /sys/fs/btrfs.
> >> This is from a test file system, using two devices in raid1. You'll notice
> >> the 'single' and 'raid1' directories under the {data,metadata,system} dirs.
> >> The raid profiles are created and removed as the first/last block group
> >> of a certain profile is added and removed.
> >>
> > 
> > I'm not pulling in patches that add new functionality without an accompanying
> > xfstest so that we're not merging features without a way to test to make sure
> 
> Sure, that's reasonable.
> 
> > they are working properly, this applies to the global metadata reservation ioctl
> > as well.  Thanks,
> 
> What would a test look like for that? It's information that isn't
> currently available anywhere in userspace and isn't represented in the
> file system itself.
> 

I thought it did more than what it did, but still I'd like a sanity check, so
maybe mkfs and mount a scratch dev and make sure it comes back with > 0 and less
than say 10mb?  Thanks,

Josef

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [patch 00/13] sysfs publishing patchset
  2013-10-21 21:19 [patch 00/13] sysfs publishing patchset Jeff Mahoney
                   ` (13 preceding siblings ...)
  2013-10-22 18:26 ` [patch 00/13] sysfs publishing patchset Josef Bacik
@ 2013-10-29 18:25 ` Goffredo Baroncelli
  2013-10-29 20:26   ` Jeff Mahoney
  14 siblings, 1 reply; 22+ messages in thread
From: Goffredo Baroncelli @ 2013-10-29 18:25 UTC (permalink / raw)
  To: Jeff Mahoney; +Cc: linux-btrfs

Hi Jeff,

On 2013-10-21 23:19, Jeff Mahoney wrote:
> This patchset implements the stubbed-out sysfs interface for btrfs. Or
> at least begins to do so.
> 
> We publish:
> - Features supported by the file system implementation
> - Features enabled on the file system, including features unknown to
>   the implemenation. These attributes can also be used to enable or
>   disable features at runtime, subjecting to a safety mask.
> - Uses the attribute names to print feature names when declining to
>   mount a file system.
> - The allocation data: global metadata reservation size and reserved,
>   space_infos, and sums of the block groups total and used bytes.
> - Device membership via links to the block devices.
> - FS label, which is writeable.
> 
> - I've also added matching ioctls for some of the functionality here so
>   that btrfsprogs can use the information without jumping through hoops
>   to read/parse the sysfs files. There are ioctls to query the supported
>   features and to query/set features on a particular file system. There's
>   also one to export the size of the global metadata reservation. I have
>   a patch for btrfs-progs that uses this to print useful info in 'btrfs
>   fi df' output.
> 
> Ultimately, the tree structure looks like the following, under /sys/fs/btrfs.
> This is from a test file system, using two devices in raid1. You'll notice
> the 'single' and 'raid1' directories under the {data,metadata,system} dirs.
> The raid profiles are created and removed as the first/last block group
> of a certain profile is added and removed.

I really appreciate your work. In the past I tried to push a similar
patch set but without success [*]

I hope that it is not too late, but I have a request:
it is possible to move the filesystems under a fs/ directory ? Something
like

[...]
fs/<fsid>/allocation/system/disk_used
fs/<fsid>/features/mixed_backref
fs/<fsid>/features/extended_iref
features/compress_lzo
features/big_metadata
features/compress_lzov2
[...]

This for two reasons:
1) so it would be possible to show also the disks informations under a
dev/ directory. It would be possible to handle the case that some disks
are registered in btrfs but the related filesystems aren't mounted (like
after a "btrfs dev scan" command)
2) it would help the browsing of the /sys/btrfs/ hierarchy: every
directory under /sys/btrfs/fs/ represents a filesystem. With the current
structure not all the directory under /sys/btrfs are related to a
filesystem (like the features/ one, but I am sure that other directories
sooner or later will appear)

If you interested I can contribute with some patches.

BR
G.Baroncelli

[*] http://lwn.net/Articles/513706/

> 
> <fsid>/devices/sdc1
> <fsid>/devices/sdd1
> <fsid>/label
> <fsid>/allocation/data/flags
> <fsid>/allocation/data/raid1/used_bytes
> <fsid>/allocation/data/raid1/total_bytes
> <fsid>/allocation/data/bytes_pinned
> <fsid>/allocation/data/bytes_may_use
> <fsid>/allocation/data/total_bytes_pinned
> <fsid>/allocation/data/bytes_reserved
> <fsid>/allocation/data/bytes_used
> <fsid>/allocation/data/single/used_bytes
> <fsid>/allocation/data/single/total_bytes
> <fsid>/allocation/data/total_bytes
> <fsid>/allocation/data/disk_total
> <fsid>/allocation/data/disk_used
> <fsid>/allocation/metadata/flags
> <fsid>/allocation/metadata/raid1/used_bytes
> <fsid>/allocation/metadata/raid1/total_bytes
> <fsid>/allocation/metadata/bytes_pinned
> <fsid>/allocation/metadata/bytes_may_use
> <fsid>/allocation/metadata/total_bytes_pinned
> <fsid>/allocation/metadata/bytes_reserved
> <fsid>/allocation/metadata/bytes_used
> <fsid>/allocation/metadata/single/used_bytes
> <fsid>/allocation/metadata/single/total_bytes
> <fsid>/allocation/metadata/total_bytes
> <fsid>/allocation/metadata/disk_total
> <fsid>/allocation/metadata/disk_used
> <fsid>/allocation/global_rsv_size
> <fsid>/allocation/global_rsv_reserved
> <fsid>/allocation/system/flags
> <fsid>/allocation/system/raid1/used_bytes
> <fsid>/allocation/system/raid1/total_bytes
> <fsid>/allocation/system/bytes_pinned
> <fsid>/allocation/system/bytes_may_use
> <fsid>/allocation/system/total_bytes_pinned
> <fsid>/allocation/system/bytes_reserved
> <fsid>/allocation/system/bytes_used
> <fsid>/allocation/system/single/used_bytes
> <fsid>/allocation/system/single/total_bytes
> <fsid>/allocation/system/total_bytes
> <fsid>/allocation/system/disk_total
> <fsid>/allocation/system/disk_used
> <fsid>/features/mixed_backref
> <fsid>/features/extended_iref
> features/compress_lzo
> features/big_metadata
> features/compress_lzov2
> features/default_subvol
> features/mixed_backref
> features/raid56
> features/mixed_groups
> features/skinny_metadata
> features/extended_iref
> 
> -Jeff
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


-- 
gpg @keyserver.linux.it: Goffredo Baroncelli (kreijackATinwind.it>
Key fingerprint BBF5 1610 0B64 DAC6 5F7D  17B2 0EDA 9B37 8B82 E0B5

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [patch 10/13] btrfs: publish allocation data in sysfs
  2013-10-21 21:19 ` [patch 10/13] btrfs: publish allocation data in sysfs Jeff Mahoney
@ 2013-10-29 18:49   ` Jeff Mahoney
  0 siblings, 0 replies; 22+ messages in thread
From: Jeff Mahoney @ 2013-10-29 18:49 UTC (permalink / raw)
  To: linux-btrfs; +Cc: dsterba

[-- Attachment #1: Type: text/plain, Size: 13342 bytes --]

On 10/21/13, 5:19 PM, Jeff Mahoney wrote:
> While trying to debug ENOSPC issues, it's helpful to understand what the
> kernel's view of the available space is. We export this information
> via ioctl, but sysfs files are more easily used.
> 
> Signed-off-by: Jeff Mahoney <jeffm@suse.com>
> ---
>  fs/btrfs/ctree.h       |    5 +
>  fs/btrfs/extent-tree.c |   72 ++++++++++++++++++++++-
>  fs/btrfs/sysfs.c       |  148 +++++++++++++++++++++++++++++++++++++++++++++++++
>  fs/btrfs/sysfs.h       |    8 ++
>  4 files changed, 228 insertions(+), 5 deletions(-)
> 
> --- a/fs/btrfs/ctree.h	2013-10-21 16:10:00.212037722 -0400
> +++ b/fs/btrfs/ctree.h	2013-10-21 16:10:02.743982088 -0400
> @@ -1143,6 +1143,9 @@ struct btrfs_space_info {
>  	spinlock_t lock;
>  	struct rw_semaphore groups_sem;
>  	wait_queue_head_t wait;
> +
> +	struct kobject kobj;
> +	struct kobject block_group_kobjs[BTRFS_NR_RAID_TYPES];
>  };
>  
>  #define	BTRFS_BLOCK_RSV_GLOBAL		1
> @@ -1518,6 +1521,7 @@ struct btrfs_fs_info {
>  	int thread_pool_size;
>  
>  	struct kobject super_kobj;
> +	struct kobject *space_info_kobj;
>  	struct completion kobj_unregister;
>  	int do_barriers;
>  	int closing;
> @@ -3171,6 +3175,7 @@ struct btrfs_block_group_cache *btrfs_lo
>  						 struct btrfs_fs_info *info,
>  						 u64 bytenr);
>  void btrfs_put_block_group(struct btrfs_block_group_cache *cache);
> +int get_block_group_index(struct btrfs_block_group_cache *cache);
>  struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
>  					struct btrfs_root *root, u32 blocksize,
>  					u64 parent, u64 root_objectid,
> --- a/fs/btrfs/extent-tree.c	2013-10-21 16:09:33.476623940 -0400
> +++ b/fs/btrfs/extent-tree.c	2013-10-21 16:10:02.751981911 -0400
> @@ -36,6 +36,7 @@
>  #include "locking.h"
>  #include "free-space-cache.h"
>  #include "math.h"
> +#include "sysfs.h"
>  
>  #undef SCRAMBLE_DELAYED_REFS
>  
> @@ -3389,6 +3390,13 @@ int btrfs_extent_readonly(struct btrfs_r
>  	return readonly;
>  }
>  
> +static const char * const alloc_names[] = {
> +	"data",
> +	"system",
> +	"mixed",
> +	"metadata",
> +};
> +

Sigh. There was a missing quilt refresh here. This obviously doesn't work.

-Jeff


>  static int update_space_info(struct btrfs_fs_info *info, u64 flags,
>  			     u64 total_bytes, u64 bytes_used,
>  			     struct btrfs_space_info **space_info)
> @@ -3444,11 +3452,21 @@ static int update_space_info(struct btrf
>  	found->chunk_alloc = 0;
>  	found->flush = 0;
>  	init_waitqueue_head(&found->wait);
> +
> +	ret = kobject_init_and_add(&found->kobj, &space_info_ktype,
> +				    info->space_info_kobj, "%s",
> +				    alloc_names[found->flags - 1]);
> +	if (ret) {
> +		kfree(found);
> +		return ret;
> +	}
> +
>  	*space_info = found;
>  	list_add_rcu(&found->list, &info->space_info);
>  	if (flags & BTRFS_BLOCK_GROUP_DATA)
>  		info->data_sinfo = found;
> -	return 0;
> +
> +	return ret;
>  }
>  
>  static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
> @@ -6090,11 +6108,29 @@ int __get_raid_index(u64 flags)
>  	return BTRFS_RAID_SINGLE; /* BTRFS_BLOCK_GROUP_SINGLE */
>  }
>  
> -static int get_block_group_index(struct btrfs_block_group_cache *cache)
> +int get_block_group_index(struct btrfs_block_group_cache *cache)
>  {
>  	return __get_raid_index(cache->flags);
>  }
>  
> +static const char *btrfs_raid_type_names[BTRFS_NR_RAID_TYPES] = {
> +	[BTRFS_RAID_RAID10]	= "raid10",
> +	[BTRFS_RAID_RAID1]	= "raid1",
> +	[BTRFS_RAID_DUP]	= "dup",
> +	[BTRFS_RAID_RAID0]	= "raid0",
> +	[BTRFS_RAID_SINGLE]	= "single",
> +	[BTRFS_RAID_RAID5]	= "raid5",
> +	[BTRFS_RAID_RAID6]	= "raid6",
> +};
> +
> +const char *get_raid_name(enum btrfs_raid_types type)
> +{
> +	if (type >= BTRFS_NR_RAID_TYPES)
> +		return NULL;
> +
> +	return btrfs_raid_type_names[type];
> +}
> +
>  enum btrfs_loop_type {
>  	LOOP_CACHING_NOWAIT = 0,
>  	LOOP_CACHING_WAIT = 1,
> @@ -8272,6 +8308,8 @@ int btrfs_free_block_groups(struct btrfs
>  	release_global_block_rsv(info);
>  
>  	while(!list_empty(&info->space_info)) {
> +		int i;
> +
>  		space_info = list_entry(info->space_info.next,
>  					struct btrfs_space_info,
>  					list);
> @@ -8283,9 +8321,17 @@ int btrfs_free_block_groups(struct btrfs
>  				dump_space_info(space_info, 0, 0);
>  			}
>  		}
> -		percpu_counter_destroy(&space_info->total_bytes_pinned);
>  		list_del(&space_info->list);
> -		kfree(space_info);
> +		for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) {
> +			struct kobject *kobj;
> +			kobj = &space_info->block_group_kobjs[i];
> +			if (kobj->parent) {
> +				kobject_del(kobj);
> +				kobject_put(kobj);
> +			}
> +		}
> +		kobject_del(&space_info->kobj);
> +		kobject_put(&space_info->kobj);
>  	}
>  	return 0;
>  }
> @@ -8296,6 +8342,19 @@ static void __link_block_group(struct bt
>  	int index = get_block_group_index(cache);
>  
>  	down_write(&space_info->groups_sem);
> +	if (list_empty(&space_info->block_groups[index])) {
> +		struct kobject *kobj = &space_info->block_group_kobjs[index];
> +		int ret;
> +
> +		kobject_get(&space_info->kobj); /* put in release */
> +		ret = kobject_init_and_add(kobj, &btrfs_raid_ktype,
> +					   &space_info->kobj,
> +					   get_raid_name(index));
> +		if (ret) {
> +			pr_warn("btrfs: failed to add kobject for block cache. ignoring.\n");
> +			kobject_put(&space_info->kobj);
> +		}
> +	}
>  	list_add_tail(&cache->list, &space_info->block_groups[index]);
>  	up_write(&space_info->groups_sem);
>  }
> @@ -8736,8 +8795,11 @@ int btrfs_remove_block_group(struct btrf
>  	 * are still on the list after taking the semaphore
>  	 */
>  	list_del_init(&block_group->list);
> -	if (list_empty(&block_group->space_info->block_groups[index]))
> +	if (list_empty(&block_group->space_info->block_groups[index])) {
> +		kobject_del(&block_group->space_info->block_group_kobjs[index]);
> +		kobject_put(&block_group->space_info->block_group_kobjs[index]);
>  		clear_avail_alloc_bits(root->fs_info, block_group->flags);
> +	}
>  	up_write(&block_group->space_info->groups_sem);
>  
>  	if (block_group->cached == BTRFS_CACHE_STARTED)
> --- a/fs/btrfs/sysfs.c	2013-10-21 16:10:01.856001602 -0400
> +++ b/fs/btrfs/sysfs.c	2013-10-21 16:10:02.751981911 -0400
> @@ -219,6 +219,140 @@ static const struct attribute_group btrf
>  	.attrs = btrfs_supported_feature_attrs,
>  };
>  
> +static ssize_t btrfs_show_u64(u64 *value_ptr, spinlock_t *lock, char *buf)
> +{
> +	u64 val;
> +	if (lock)
> +		spin_lock(lock);
> +	val = *value_ptr;
> +	if (lock)
> +		spin_unlock(lock);
> +	return snprintf(buf, PAGE_SIZE, "%llu\n", val);
> +}
> +
> +static ssize_t global_rsv_size_show(struct kobject *kobj,
> +				    struct kobj_attribute *ka, char *buf)
> +{
> +	struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent);
> +	struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
> +	return btrfs_show_u64(&block_rsv->size, &block_rsv->lock, buf);
> +}
> +BTRFS_ATTR(global_rsv_size, 0444, global_rsv_size_show);
> +
> +static ssize_t global_rsv_reserved_show(struct kobject *kobj,
> +					struct kobj_attribute *a, char *buf)
> +{
> +	struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent);
> +	struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
> +	return btrfs_show_u64(&block_rsv->reserved, &block_rsv->lock, buf);
> +}
> +BTRFS_ATTR(global_rsv_reserved, 0444, global_rsv_reserved_show);
> +
> +#define to_space_info(_kobj) container_of(_kobj, struct btrfs_space_info, kobj)
> +
> +static ssize_t raid_bytes_show(struct kobject *kobj,
> +			       struct kobj_attribute *attr, char *buf);
> +BTRFS_RAID_ATTR(total_bytes, raid_bytes_show);
> +BTRFS_RAID_ATTR(used_bytes, raid_bytes_show);
> +
> +static ssize_t raid_bytes_show(struct kobject *kobj,
> +			       struct kobj_attribute *attr, char *buf)
> +
> +{
> +	struct btrfs_space_info *sinfo = to_space_info(kobj->parent);
> +	struct btrfs_block_group_cache *block_group;
> +	int index = kobj - sinfo->block_group_kobjs;
> +	u64 val = 0;
> +
> +	down_read(&sinfo->groups_sem);
> +	list_for_each_entry(block_group, &sinfo->block_groups[index], list) {
> +		if (&attr->attr == BTRFS_RAID_ATTR_PTR(total_bytes))
> +			val += block_group->key.offset;
> +		else
> +			val += btrfs_block_group_used(&block_group->item);
> +	}
> +	up_read(&sinfo->groups_sem);
> +	return snprintf(buf, PAGE_SIZE, "%llu\n", val);
> +}
> +
> +static struct attribute *raid_attributes[] = {
> +	BTRFS_RAID_ATTR_PTR(total_bytes),
> +	BTRFS_RAID_ATTR_PTR(used_bytes),
> +	NULL
> +};
> +
> +static void release_raid_kobj(struct kobject *kobj)
> +{
> +	kobject_put(kobj->parent);
> +}
> +
> +struct kobj_type btrfs_raid_ktype = {
> +	.sysfs_ops = &kobj_sysfs_ops,
> +	.release = release_raid_kobj,
> +	.default_attrs = raid_attributes,
> +};
> +
> +#define SPACE_INFO_ATTR(field)						\
> +static ssize_t btrfs_space_info_show_##field(struct kobject *kobj,	\
> +					     struct kobj_attribute *a,	\
> +					     char *buf)			\
> +{									\
> +	struct btrfs_space_info *sinfo = to_space_info(kobj);		\
> +	return btrfs_show_u64(&sinfo->field, &sinfo->lock, buf);	\
> +}									\
> +BTRFS_ATTR(field, 0444, btrfs_space_info_show_##field)
> +
> +static ssize_t btrfs_space_info_show_total_bytes_pinned(struct kobject *kobj,
> +						       struct kobj_attribute *a,
> +						       char *buf)
> +{
> +	struct btrfs_space_info *sinfo = to_space_info(kobj);
> +	s64 val = percpu_counter_sum(&sinfo->total_bytes_pinned);
> +	return snprintf(buf, PAGE_SIZE, "%lld\n", val);
> +}
> +
> +SPACE_INFO_ATTR(flags);
> +SPACE_INFO_ATTR(total_bytes);
> +SPACE_INFO_ATTR(bytes_used);
> +SPACE_INFO_ATTR(bytes_pinned);
> +SPACE_INFO_ATTR(bytes_reserved);
> +SPACE_INFO_ATTR(bytes_may_use);
> +SPACE_INFO_ATTR(disk_used);
> +SPACE_INFO_ATTR(disk_total);
> +BTRFS_ATTR(total_bytes_pinned, 0444, btrfs_space_info_show_total_bytes_pinned);
> +
> +static struct attribute *space_info_attrs[] = {
> +	BTRFS_ATTR_PTR(flags),
> +	BTRFS_ATTR_PTR(total_bytes),
> +	BTRFS_ATTR_PTR(bytes_used),
> +	BTRFS_ATTR_PTR(bytes_pinned),
> +	BTRFS_ATTR_PTR(bytes_reserved),
> +	BTRFS_ATTR_PTR(bytes_may_use),
> +	BTRFS_ATTR_PTR(disk_used),
> +	BTRFS_ATTR_PTR(disk_total),
> +	BTRFS_ATTR_PTR(total_bytes_pinned),
> +	NULL,
> +};
> +
> +static void space_info_release(struct kobject *kobj)
> +{
> +	struct btrfs_space_info *sinfo = to_space_info(kobj);
> +	percpu_counter_destroy(&sinfo->total_bytes_pinned);
> +	kfree(sinfo);
> +}
> +
> +struct kobj_type space_info_ktype = {
> +	.sysfs_ops = &kobj_sysfs_ops,
> +	.release = space_info_release,
> +	.default_attrs = space_info_attrs,
> +};
> +
> +static const struct attribute *allocation_attrs[] = {
> +	BTRFS_ATTR_PTR(global_rsv_reserved),
> +	BTRFS_ATTR_PTR(global_rsv_size),
> +	NULL,
> +};
> +
>  static void btrfs_release_super_kobj(struct kobject *kobj)
>  {
>  	struct btrfs_fs_info *fs_info = to_fs_info(kobj);
> @@ -239,6 +373,9 @@ static inline struct btrfs_fs_info *to_f
>  
>  void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info)
>  {
> +	sysfs_remove_files(fs_info->space_info_kobj, allocation_attrs);
> +	kobject_del(fs_info->space_info_kobj);
> +	kobject_put(fs_info->space_info_kobj);
>  	kobject_del(&fs_info->super_kobj);
>  	kobject_put(&fs_info->super_kobj);
>  	wait_for_completion(&fs_info->kobj_unregister);
> @@ -391,6 +528,17 @@ int btrfs_sysfs_add_one(struct btrfs_fs_
>  	if (error)
>  		goto failure;
>  
> +	fs_info->space_info_kobj = kobject_create_and_add("allocation",
> +						  &fs_info->super_kobj);
> +	if (!fs_info->space_info_kobj) {
> +		error = -ENOMEM;
> +		goto failure;
> +	}
> +
> +	error = sysfs_create_files(fs_info->space_info_kobj, allocation_attrs);
> +	if (error)
> +		goto failure;
> +
>  	return 0;
>  failure:
>  	btrfs_sysfs_remove_one(fs_info);
> --- a/fs/btrfs/sysfs.h	2013-10-21 16:10:01.860001514 -0400
> +++ b/fs/btrfs/sysfs.h	2013-10-21 16:10:02.751981911 -0400
> @@ -22,6 +22,12 @@ static struct kobj_attribute btrfs_attr_
>  	BTRFS_ATTR_RW(_name, _mode, _show, NULL)
>  #define BTRFS_ATTR_PTR(_name)    (&btrfs_attr_##_name.attr)
>  
> +#define BTRFS_RAID_ATTR(_name, _show)					\
> +static struct kobj_attribute btrfs_raid_attr_##_name =			\
> +			__INIT_KOBJ_ATTR(_name, 0444, _show, NULL)
> +#define BTRFS_RAID_ATTR_PTR(_name)    (&btrfs_raid_attr_##_name.attr)
> +
> +
>  struct btrfs_feature_attr {
>  	struct kobj_attribute kobj_attr;
>  	enum btrfs_feature_set feature_set;
> @@ -53,4 +59,6 @@ static struct btrfs_feature_attr btrfs_a
>  			to_btrfs_feature_attr(attr_to_btrfs_attr(a))
>  char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags);
>  extern const char * const btrfs_feature_set_names[3];
> +extern struct kobj_type space_info_ktype;
> +extern struct kobj_type btrfs_raid_ktype;
>  #endif /* _BTRFS_SYSFS_H_ */
> 
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


-- 
Jeff Mahoney
SUSE Labs


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 841 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [patch 00/13] sysfs publishing patchset
  2013-10-29 18:25 ` Goffredo Baroncelli
@ 2013-10-29 20:26   ` Jeff Mahoney
  2013-10-29 21:57     ` Goffredo Baroncelli
  0 siblings, 1 reply; 22+ messages in thread
From: Jeff Mahoney @ 2013-10-29 20:26 UTC (permalink / raw)
  To: kreijack; +Cc: linux-btrfs, Josef Bacik

[-- Attachment #1: Type: text/plain, Size: 7927 bytes --]

On 10/29/13, 2:25 PM, Goffredo Baroncelli wrote:
> Hi Jeff,
> 
> On 2013-10-21 23:19, Jeff Mahoney wrote:
>> This patchset implements the stubbed-out sysfs interface for btrfs. Or
>> at least begins to do so.
>>
>> We publish:
>> - Features supported by the file system implementation
>> - Features enabled on the file system, including features unknown to
>>   the implemenation. These attributes can also be used to enable or
>>   disable features at runtime, subjecting to a safety mask.
>> - Uses the attribute names to print feature names when declining to
>>   mount a file system.
>> - The allocation data: global metadata reservation size and reserved,
>>   space_infos, and sums of the block groups total and used bytes.
>> - Device membership via links to the block devices.
>> - FS label, which is writeable.
>>
>> - I've also added matching ioctls for some of the functionality here so
>>   that btrfsprogs can use the information without jumping through hoops
>>   to read/parse the sysfs files. There are ioctls to query the supported
>>   features and to query/set features on a particular file system. There's
>>   also one to export the size of the global metadata reservation. I have
>>   a patch for btrfs-progs that uses this to print useful info in 'btrfs
>>   fi df' output.
>>
>> Ultimately, the tree structure looks like the following, under /sys/fs/btrfs.
>> This is from a test file system, using two devices in raid1. You'll notice
>> the 'single' and 'raid1' directories under the {data,metadata,system} dirs.
>> The raid profiles are created and removed as the first/last block group
>> of a certain profile is added and removed.

Hi Goffredo -

> I really appreciate your work. In the past I tried to push a similar
> patch set but without success [*]

Thanks. Sysfs work can be touchy since it becomes part of the ABI like
an ioctl does.

> I hope that it is not too late, but I have a request:
> it is possible to move the filesystems under a fs/ directory ? Something
> like
> 
> [...]
> fs/<fsid>/allocation/system/disk_used
> fs/<fsid>/features/mixed_backref
> fs/<fsid>/features/extended_iref
> features/compress_lzo
> features/big_metadata
> features/compress_lzov2
> [...]
> 
> This for two reasons:
> 1) so it would be possible to show also the disks informations under a
> dev/ directory. It would be possible to handle the case that some disks
> are registered in btrfs but the related filesystems aren't mounted (like
> after a "btrfs dev scan" command)
>
> 2) it would help the browsing of the /sys/btrfs/ hierarchy: every
> directory under /sys/btrfs/fs/ represents a filesystem. With the current
> structure not all the directory under /sys/btrfs are related to a
> filesystem (like the features/ one, but I am sure that other directories
> sooner or later will appear)

I'd like to define /sys/fs/btrfs/<fsid> as filesystem-specific and
anything else as btrfs-wide. This is what ext4 already does with the
exception that they use block device names instead of fsids. Your device
use case is interesting, but a tough one to implement well since it is a
cache that can be wrong as soon as the user decides to mkfs a device
(either as btrfs or anything else) without calling btrfs dev scan
afterward. I wouldn't necessarily oppose such a feature; I just don't
think it merits moving the primary case of per-filesystem information
deeper into the hierarchy.

Outside of /sys/fs/, we can see something similar in /sys/block/<dev>.
You'll find "holders", "queue", a bunch of partition directories, and
regular files. They all have different purposes and that's fairly
obvious by their naming. Having a "partitions" directory in there would
make the hierarchy "cleaner" but at the cost of a kobject that's
essentially useless otherwise.

But the broader point is well taken. If there's a discussion to be had
here, I'd like to have it now, especially WRT to the hierarchy. You're
the first person to have any feedback on it, and I've generally been
taking the silence as tacit approval while waiting for it to land. Most
of this patchset is in the openSUSE 13.1 kernel already, which will be
released soon. We need the ability to enable extended_iref while online
to handle upgrades smoothly due to some packages overflowing the
hardlink limit. (So technically, it also needs to be added to a 12.3
update release too.) It's a limitation no other file system has, so our
packagers are rightly saying it should be fixed there. It's easier to
use the sysfs interface but I suppose we could back off to the ioctl
interface that's already been discussed. I don't want to introduce a
one-off sysfs ABI with openSUSE 13.1, so if there are other objections
or comments, please raise them now.

David already gave some review for the feature ioctl parts, which I've
integrated. I did some review on my own of the sysfs portions and ripped
out the kobj_completion stuff as unnecessary and switched to using
attribute_groups for features instead of creating files explicitly.
Josef asked for xfstests, and after a few false starts, those have been
posted in their (hopefully) final revision. If we can agree on this
implementation, great. If not, I'd like to at least agree on the
hierarchy so that I can get those changes integrated before openSUSE
13.1 is released in early November.

Thanks.

-Jeff

> BR
> G.Baroncelli
> 
> [*] http://lwn.net/Articles/513706/
> 
>>
>> <fsid>/devices/sdc1
>> <fsid>/devices/sdd1
>> <fsid>/label
>> <fsid>/allocation/data/flags
>> <fsid>/allocation/data/raid1/used_bytes
>> <fsid>/allocation/data/raid1/total_bytes
>> <fsid>/allocation/data/bytes_pinned
>> <fsid>/allocation/data/bytes_may_use
>> <fsid>/allocation/data/total_bytes_pinned
>> <fsid>/allocation/data/bytes_reserved
>> <fsid>/allocation/data/bytes_used
>> <fsid>/allocation/data/single/used_bytes
>> <fsid>/allocation/data/single/total_bytes
>> <fsid>/allocation/data/total_bytes
>> <fsid>/allocation/data/disk_total
>> <fsid>/allocation/data/disk_used
>> <fsid>/allocation/metadata/flags
>> <fsid>/allocation/metadata/raid1/used_bytes
>> <fsid>/allocation/metadata/raid1/total_bytes
>> <fsid>/allocation/metadata/bytes_pinned
>> <fsid>/allocation/metadata/bytes_may_use
>> <fsid>/allocation/metadata/total_bytes_pinned
>> <fsid>/allocation/metadata/bytes_reserved
>> <fsid>/allocation/metadata/bytes_used
>> <fsid>/allocation/metadata/single/used_bytes
>> <fsid>/allocation/metadata/single/total_bytes
>> <fsid>/allocation/metadata/total_bytes
>> <fsid>/allocation/metadata/disk_total
>> <fsid>/allocation/metadata/disk_used
>> <fsid>/allocation/global_rsv_size
>> <fsid>/allocation/global_rsv_reserved
>> <fsid>/allocation/system/flags
>> <fsid>/allocation/system/raid1/used_bytes
>> <fsid>/allocation/system/raid1/total_bytes
>> <fsid>/allocation/system/bytes_pinned
>> <fsid>/allocation/system/bytes_may_use
>> <fsid>/allocation/system/total_bytes_pinned
>> <fsid>/allocation/system/bytes_reserved
>> <fsid>/allocation/system/bytes_used
>> <fsid>/allocation/system/single/used_bytes
>> <fsid>/allocation/system/single/total_bytes
>> <fsid>/allocation/system/total_bytes
>> <fsid>/allocation/system/disk_total
>> <fsid>/allocation/system/disk_used
>> <fsid>/features/mixed_backref
>> <fsid>/features/extended_iref
>> features/compress_lzo
>> features/big_metadata
>> features/compress_lzov2
>> features/default_subvol
>> features/mixed_backref
>> features/raid56
>> features/mixed_groups
>> features/skinny_metadata
>> features/extended_iref
>>
>> -Jeff
>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
> 
> 


-- 
Jeff Mahoney
SUSE Labs


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 841 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [patch 00/13] sysfs publishing patchset
  2013-10-29 20:26   ` Jeff Mahoney
@ 2013-10-29 21:57     ` Goffredo Baroncelli
  0 siblings, 0 replies; 22+ messages in thread
From: Goffredo Baroncelli @ 2013-10-29 21:57 UTC (permalink / raw)
  To: Jeff Mahoney; +Cc: linux-btrfs

Hi Jeff

On 2013-10-29 21:26, Jeff Mahoney wrote:
>> This for two reasons:
>> > 1) so it would be possible to show also the disks informations under a
>> > dev/ directory. It would be possible to handle the case that some disks
>> > are registered in btrfs but the related filesystems aren't mounted (like
>> > after a "btrfs dev scan" command)
>> >
>> > 2) it would help the browsing of the /sys/btrfs/ hierarchy: every
>> > directory under /sys/btrfs/fs/ represents a filesystem. With the current
>> > structure not all the directory under /sys/btrfs are related to a
>> > filesystem (like the features/ one, but I am sure that other directories
>> > sooner or later will appear)

> I'd like to define /sys/fs/btrfs/<fsid> as filesystem-specific and
> anything else as btrfs-wide. 

I fully agree. My idea was to put under btrfs/dev *only* the device
which are registered in BTRFS by "btrfs dev scan" and/or mount commands.

> This is what ext4 already does with the
> exception that they use block device names instead of fsids. Your device
> use case is interesting, but a tough one to implement well since it is a
> cache that can be wrong as soon as the user decides to mkfs a device
> (either as btrfs or anything else) without calling btrfs dev scan
> afterward. 

Right, I never though about this case.


> I wouldn't necessarily oppose such a feature; I just don't
> think it merits moving the primary case of per-filesystem information
> deeper into the hierarchy.

Fortunately the two thing are unrelated. The
/sys/fs/btrfs/dev/<device-uuid>/... hierarchy can live with
/sys/fs/btrfs/<fsid>/... or /sys/fs/btrfs/fs/<fsid>.



BTW, I am playing with your patch. What is the means of the field
<fsid>/allocation/*/disk_total ? In a RAID5 it seems to be the space
available ( == (<number-of-disk> - 1)*<size-of-chunk> ) and not the disk
space consumed ( == <number-of-disk> * <size-of-chunk> ). In fact it
seems that disk_total == total_bytes...

Ok looking at the kernel code (update_space_info() in extent-tree.c) it
seems that the info contained in space_info is bogus in case of
RAID5/RAID6....



-- 
gpg @keyserver.linux.it: Goffredo Baroncelli (kreijackATinwind.it>
Key fingerprint BBF5 1610 0B64 DAC6 5F7D  17B2 0EDA 9B37 8B82 E0B5

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2013-10-29 22:03 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-10-21 21:19 [patch 00/13] sysfs publishing patchset Jeff Mahoney
2013-10-21 21:19 ` [patch 01/13] btrfs: add ioctls to query/change feature bits online Jeff Mahoney
2013-10-21 21:19 ` [patch 02/13] kobject: export kobj_sysfs_ops Jeff Mahoney
2013-10-22 14:44   ` Jeff Mahoney
2013-10-21 21:19 ` [patch 03/13] btrfs: publish supported featured in sysfs Jeff Mahoney
2013-10-21 21:19 ` [patch 04/13] btrfs: publish per-super attributes " Jeff Mahoney
2013-10-21 21:19 ` [patch 05/13] btrfs: publish per-super features " Jeff Mahoney
2013-10-21 21:19 ` [patch 06/13] btrfs: publish unknown feature bits " Jeff Mahoney
2013-10-21 21:19 ` [patch 07/13] btrfs: add ability to change features via sysfs Jeff Mahoney
2013-10-21 21:19 ` [patch 08/13] btrfs: use feature attribute names to print better error messages Jeff Mahoney
2013-10-21 21:19 ` [patch 09/13] btrfs: add ioctl to export size of global metadata reservation Jeff Mahoney
2013-10-21 21:19 ` [patch 10/13] btrfs: publish allocation data in sysfs Jeff Mahoney
2013-10-29 18:49   ` Jeff Mahoney
2013-10-21 21:19 ` [patch 11/13] btrfs: publish device membership " Jeff Mahoney
2013-10-21 21:19 ` [patch 12/13] btrfs: publish fs label " Jeff Mahoney
2013-10-21 21:19 ` [patch 13/13] btrfs: add tracing for failed reservations Jeff Mahoney
2013-10-22 18:26 ` [patch 00/13] sysfs publishing patchset Josef Bacik
2013-10-22 18:39   ` Jeff Mahoney
2013-10-22 20:43     ` Josef Bacik
2013-10-29 18:25 ` Goffredo Baroncelli
2013-10-29 20:26   ` Jeff Mahoney
2013-10-29 21:57     ` Goffredo Baroncelli

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.