From: Jeff Mahoney <jeffm@suse.com>
To: linux-btrfs@vger.kernel.org
Cc: dsterba@suse.com
Subject: [patch 10/13] btrfs: publish allocation data in sysfs
Date: Mon, 21 Oct 2013 17:19:50 -0400 [thread overview]
Message-ID: <20131021212008.047727368@suse.com> (raw)
In-Reply-To: 20131021211940.432195222@suse.com
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_ */
next prev parent reply other threads:[~2013-10-21 21:20 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 ` Jeff Mahoney [this message]
2013-10-29 18:49 ` [patch 10/13] btrfs: publish allocation data in sysfs 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
-- 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=20131021212008.047727368@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).