linux-btrfs.vger.kernel.org archive mirror
 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
  -- strict thread matches above, loose matches on Subject: below --
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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).