All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jeff Mahoney <jeffm@suse.com>
To: linux-btrfs@vger.kernel.org
Cc: dsterba@suse.com
Subject: Re: [patch 10/13] btrfs: publish allocation data in sysfs
Date: Tue, 29 Oct 2013 14:49:15 -0400	[thread overview]
Message-ID: <5270032B.3050508@suse.com> (raw)
In-Reply-To: <20131021212008.047727368@suse.com>

[-- 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 --]

  reply	other threads:[~2013-10-29 18:49 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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
2013-11-01 17:06 [PATCH 00/13] [PATCH 00/13] sysfs publishing patchset (v2) Jeff Mahoney
2013-11-01 17:07 ` [PATCH 10/13] btrfs: publish allocation data in sysfs Jeff Mahoney
2013-11-15 20:33 [PATCH 00/13] sysfs publishing patchset (v3) Jeff Mahoney
2013-11-15 20:34 ` [PATCH 10/13] btrfs: publish allocation data in sysfs Jeff Mahoney

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5270032B.3050508@suse.com \
    --to=jeffm@suse.com \
    --cc=dsterba@suse.com \
    --cc=linux-btrfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.