scoutfs: add alloc foreach cb iterator

Add an alloc call which reads all the persistent allocators and calls a
callback for each.  This is going to be used to calculate free blocks
in clients for df, and in an ioctl to give a more detailed view of
allocators.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2020-10-12 10:46:16 -07:00
committed by Zach Brown
parent 8bf4c078df
commit fb66372988
3 changed files with 149 additions and 0 deletions

View File

@@ -1110,3 +1110,140 @@ bool scoutfs_alloc_meta_lo_thresh(struct super_block *sb,
return lo;
}
/*
* Call the callers callback for every persistent allocator structure
* we can find.
*/
int scoutfs_alloc_foreach(struct super_block *sb,
scoutfs_alloc_foreach_cb_t cb, void *arg)
{
struct scoutfs_btree_ref stale_refs[2] = {{0,}};
struct scoutfs_btree_ref refs[2] = {{0,}};
struct scoutfs_super_block *super = NULL;
struct scoutfs_srch_compact_input *scin;
struct scoutfs_log_trees_val ltv;
SCOUTFS_BTREE_ITEM_REF(iref);
struct scoutfs_key key;
int ret;
super = kmalloc(sizeof(struct scoutfs_super_block), GFP_NOFS);
scin = kmalloc(sizeof(struct scoutfs_srch_compact_input), GFP_NOFS);
if (!super || !scin) {
ret = -ENOMEM;
goto out;
}
retry:
ret = scoutfs_read_super(sb, super);
if (ret < 0)
goto out;
refs[0] = super->logs_root.ref;
refs[1] = super->srch_root.ref;
/* all the server allocators */
ret = cb(sb, arg, SCOUTFS_ALLOC_OWNER_SERVER, 0, true, true,
le64_to_cpu(super->meta_alloc[0].total_len)) ?:
cb(sb, arg, SCOUTFS_ALLOC_OWNER_SERVER, 0, true, true,
le64_to_cpu(super->meta_alloc[1].total_len)) ?:
cb(sb, arg, SCOUTFS_ALLOC_OWNER_SERVER, 0, false, true,
le64_to_cpu(super->data_alloc.total_len)) ?:
cb(sb, arg, SCOUTFS_ALLOC_OWNER_SERVER, 1, true, true,
le64_to_cpu(super->server_meta_avail[0].total_nr)) ?:
cb(sb, arg, SCOUTFS_ALLOC_OWNER_SERVER, 1, true, true,
le64_to_cpu(super->server_meta_avail[1].total_nr)) ?:
cb(sb, arg, SCOUTFS_ALLOC_OWNER_SERVER, 1, true, false,
le64_to_cpu(super->server_meta_freed[0].total_nr)) ?:
cb(sb, arg, SCOUTFS_ALLOC_OWNER_SERVER, 1, true, false,
le64_to_cpu(super->server_meta_freed[1].total_nr));
if (ret < 0)
goto out;
/* mount fs transaction allocators */
scoutfs_key_init_log_trees(&key, 0, 0);
for (;;) {
ret = scoutfs_btree_next(sb, &super->logs_root, &key, &iref);
if (ret == -ENOENT)
break;
if (ret < 0)
goto out;
if (iref.val_len == sizeof(ltv)) {
key = *iref.key;
memcpy(&ltv, iref.val, sizeof(ltv));
} else {
ret = -EIO;
}
scoutfs_btree_put_iref(&iref);
if (ret < 0)
goto out;
ret = cb(sb, arg, SCOUTFS_ALLOC_OWNER_MOUNT,
le64_to_cpu(key.sklt_rid), true, true,
le64_to_cpu(ltv.meta_avail.total_nr)) ?:
cb(sb, arg, SCOUTFS_ALLOC_OWNER_MOUNT,
le64_to_cpu(key.sklt_rid), true, false,
le64_to_cpu(ltv.meta_freed.total_nr)) ?:
cb(sb, arg, SCOUTFS_ALLOC_OWNER_MOUNT,
le64_to_cpu(key.sklt_rid), false, true,
le64_to_cpu(ltv.data_avail.total_len)) ?:
cb(sb, arg, SCOUTFS_ALLOC_OWNER_MOUNT,
le64_to_cpu(key.sklt_rid), false, false,
le64_to_cpu(ltv.data_freed.total_len));
if (ret < 0)
goto out;
scoutfs_key_inc(&key);
}
/* srch compaction allocators */
memset(&key, 0, sizeof(key));
key.sk_zone = SCOUTFS_SRCH_ZONE;
key.sk_type = SCOUTFS_SRCH_BUSY_TYPE;
for (;;) {
/* _BUSY_ is last type, _next won't see other types */
ret = scoutfs_btree_next(sb, &super->srch_root, &key, &iref);
if (ret == -ENOENT)
break;
if (ret == 0) {
if (iref.val_len == sizeof(scin)) {
key = *iref.key;
memcpy(scin, iref.val, iref.val_len);
} else {
ret = -EIO;
}
scoutfs_btree_put_iref(&iref);
}
if (ret < 0)
goto out;
ret = cb(sb, arg, SCOUTFS_ALLOC_OWNER_SRCH,
le64_to_cpu(scin->id), true, true,
le64_to_cpu(scin->meta_avail.total_nr)) ?:
cb(sb, arg, SCOUTFS_ALLOC_OWNER_SRCH,
le64_to_cpu(scin->id), true, false,
le64_to_cpu(scin->meta_freed.total_nr));
if (ret < 0)
goto out;
scoutfs_key_inc(&key);
}
ret = 0;
out:
if (ret == -ESTALE) {
if (memcmp(&stale_refs, &refs, sizeof(refs)) == 0) {
ret = -EIO;
} else {
BUILD_BUG_ON(sizeof(stale_refs) != sizeof(refs));
memcpy(stale_refs, refs, sizeof(stale_refs));
goto retry;
}
}
kfree(super);
kfree(scin);
return ret;
}

View File

@@ -122,4 +122,10 @@ int scoutfs_alloc_splice_list(struct super_block *sb,
bool scoutfs_alloc_meta_lo_thresh(struct super_block *sb,
struct scoutfs_alloc *alloc);
typedef int (*scoutfs_alloc_foreach_cb_t)(struct super_block *sb, void *arg,
int owner, u64 id,
bool meta, bool avail, u64 blocks);
int scoutfs_alloc_foreach(struct super_block *sb,
scoutfs_alloc_foreach_cb_t cb, void *arg);
#endif

View File

@@ -297,6 +297,12 @@ struct scoutfs_alloc_root {
struct scoutfs_btree_root root;
}__packed;
/* types of allocators, exposed to alloc_detail ioctl */
#define SCOUTFS_ALLOC_OWNER_NONE 0
#define SCOUTFS_ALLOC_OWNER_SERVER 1
#define SCOUTFS_ALLOC_OWNER_MOUNT 2
#define SCOUTFS_ALLOC_OWNER_SRCH 3
struct scoutfs_mounted_client_btree_val {
__u8 flags;
} __packed;