#include "compress.h"
#include "sysfs.h"
#include "btree_cache.h"
+#include "btree_io.h"
#include "btree_iter.h"
#include "btree_update.h"
+#include "btree_update_interior.h"
#include "btree_gc.h"
#include "buckets.h"
#include "inode.h"
read_attribute(btree_node_size);
read_attribute(first_bucket);
read_attribute(nbuckets);
+read_attribute(durability);
read_attribute(iostats);
read_attribute(read_priority_stats);
read_attribute(write_priority_stats);
read_attribute(compression_stats);
read_attribute(journal_debug);
read_attribute(journal_pins);
+read_attribute(btree_updates);
+read_attribute(dirty_btree_nodes);
read_attribute(internal_uuid);
-read_attribute(available_buckets);
-read_attribute(free_buckets);
-read_attribute(dirty_data);
-read_attribute(dirty_bytes);
-read_attribute(dirty_buckets);
-read_attribute(cached_data);
-read_attribute(cached_bytes);
-read_attribute(cached_buckets);
-read_attribute(meta_buckets);
-read_attribute(alloc_buckets);
read_attribute(has_data);
read_attribute(alloc_debug);
write_attribute(wake_allocator);
rw_attribute(discard);
rw_attribute(cache_replacement_policy);
+rw_attribute(group);
rw_attribute(copy_gc_enabled);
sysfs_pd_controller_attribute(copy_gc);
-rw_attribute(tier);
-rw_attribute(tiering_enabled);
-rw_attribute(tiering_percent);
-sysfs_pd_controller_attribute(tiering);
-
+rw_attribute(rebalance_enabled);
+rw_attribute(rebalance_percent);
+sysfs_pd_controller_attribute(rebalance);
rw_attribute(pd_controllers_update_seconds);
sysfs_print(pd_controllers_update_seconds,
c->pd_controllers_update_seconds);
- sysfs_printf(tiering_enabled, "%i", c->tiering_enabled);
- sysfs_print(tiering_percent, c->tiering_percent);
+ sysfs_printf(rebalance_enabled, "%i", c->rebalance_enabled);
+ sysfs_print(rebalance_percent, c->rebalance_percent);
- sysfs_pd_controller_show(tiering, &c->tiers[1].pd); /* XXX */
+ sysfs_pd_controller_show(rebalance, &c->rebalance_pd); /* XXX */
sysfs_printf(meta_replicas_have, "%u", bch2_replicas_online(c, true));
sysfs_printf(data_replicas_have, "%u", bch2_replicas_online(c, false));
if (attr == &sysfs_journal_pins)
return bch2_journal_print_pins(&c->journal, buf);
+ if (attr == &sysfs_btree_updates)
+ return bch2_btree_updates_print(c, buf);
+
+ if (attr == &sysfs_dirty_btree_nodes)
+ return bch2_dirty_btree_nodes_print(c, buf);
+
if (attr == &sysfs_compression_stats)
return bch2_compression_stats(c, buf);
return ret;
}
- if (attr == &sysfs_tiering_enabled) {
- ssize_t ret = strtoul_safe(buf, c->tiering_enabled)
+ if (attr == &sysfs_rebalance_enabled) {
+ ssize_t ret = strtoul_safe(buf, c->rebalance_enabled)
?: (ssize_t) size;
- bch2_tiering_start(c); /* issue wakeups */
+ rebalance_wakeup(c);
return ret;
}
sysfs_strtoul(pd_controllers_update_seconds,
c->pd_controllers_update_seconds);
- sysfs_strtoul(tiering_percent, c->tiering_percent);
- sysfs_pd_controller_store(tiering, &c->tiers[1].pd); /* XXX */
+ sysfs_strtoul(rebalance_percent, c->rebalance_percent);
+ sysfs_pd_controller_store(rebalance, &c->rebalance_pd);
/* Debugging: */
&sysfs_journal_write_delay_ms,
&sysfs_journal_reclaim_delay_ms,
- &sysfs_tiering_percent,
+ &sysfs_rebalance_percent,
&sysfs_compression_stats,
NULL
&sysfs_alloc_debug,
&sysfs_journal_debug,
&sysfs_journal_pins,
+ &sysfs_btree_updates,
+ &sysfs_dirty_btree_nodes,
&sysfs_read_realloc_races,
&sysfs_extent_migrate_done,
&sysfs_prune_cache,
&sysfs_copy_gc_enabled,
- &sysfs_tiering_enabled,
- sysfs_pd_controller_files(tiering),
+ &sysfs_rebalance_enabled,
+ sysfs_pd_controller_files(rebalance),
&sysfs_internal_uuid,
#define BCH_DEBUG_PARAM(name, description) &sysfs_##name,
int id = opt - bch2_opt_table;
u64 v = bch2_opt_get_by_id(&c->opts, id);
- out += opt->type == BCH_OPT_STR
- ? bch2_scnprint_string_list(out, end - out, opt->choices, v)
- : scnprintf(out, end - out, "%lli", v);
+ out += bch2_opt_to_text(c, out, end - out, opt, v, OPT_SHOW_FULL_LIST);
out += scnprintf(out, end - out, "\n");
return out - buf;
int ret, id = opt - bch2_opt_table;
u64 v;
- ret = bch2_opt_parse(opt, buf, &v);
+ ret = bch2_opt_parse(c, opt, buf, &v);
if (ret < 0)
return ret;
- mutex_lock(&c->sb_lock);
-
- if (id == Opt_compression) {
+ if (id == Opt_compression ||
+ id == Opt_background_compression) {
int ret = bch2_check_set_has_compressed_data(c, v);
if (ret) {
mutex_unlock(&c->sb_lock);
}
if (opt->set_sb != SET_NO_SB_OPT) {
+ mutex_lock(&c->sb_lock);
opt->set_sb(c->disk_sb, v);
bch2_write_super(c);
+ mutex_unlock(&c->sb_lock);
}
bch2_opt_set_by_id(&c->opts, id, v);
- mutex_unlock(&c->sb_lock);
+ if ((id == Opt_background_target ||
+ id == Opt_background_compression) && v) {
+ bch2_rebalance_add_work(c, S64_MAX);
+ rebalance_wakeup(c);
+ }
return size;
}
NULL
};
-typedef unsigned (bucket_map_fn)(struct bch_dev *, struct bucket *, void *);
+typedef unsigned (bucket_map_fn)(struct bch_dev *, size_t, void *);
-static unsigned bucket_priority_fn(struct bch_dev *ca, struct bucket *g,
+static unsigned bucket_priority_fn(struct bch_dev *ca, size_t b,
void *private)
{
+ struct bucket *g = bucket(ca, b);
int rw = (private ? 1 : 0);
return ca->fs->prio_clock[rw].hand - g->prio[rw];
}
-static unsigned bucket_sectors_used_fn(struct bch_dev *ca, struct bucket *g,
+static unsigned bucket_sectors_used_fn(struct bch_dev *ca, size_t b,
void *private)
{
+ struct bucket *g = bucket(ca, b);
return bucket_sectors_used(g->mark);
}
-static unsigned bucket_oldest_gen_fn(struct bch_dev *ca, struct bucket *g,
+static unsigned bucket_oldest_gen_fn(struct bch_dev *ca, size_t b,
void *private)
{
- return bucket_gc_gen(ca, g);
+ return bucket_gc_gen(ca, b);
}
static ssize_t show_quantiles(struct bch_dev *ca, char *buf,
int cmp(const void *l, const void *r)
{ return *((unsigned *) r) - *((unsigned *) l); }
- size_t n = ca->mi.nbuckets, i;
+ size_t i, n;
/* Compute 31 quantiles */
unsigned q[31], *p;
ssize_t ret = 0;
- p = vzalloc(ca->mi.nbuckets * sizeof(unsigned));
- if (!p)
+ down_read(&ca->bucket_lock);
+ n = ca->mi.nbuckets;
+
+ p = vzalloc(n * sizeof(unsigned));
+ if (!p) {
+ up_read(&ca->bucket_lock);
return -ENOMEM;
+ }
for (i = ca->mi.first_bucket; i < n; i++)
- p[i] = fn(ca, &ca->buckets[i], private);
+ p[i] = fn(ca, i, private);
sort(p, n, sizeof(unsigned), cmp, NULL);
+ up_read(&ca->bucket_lock);
while (n &&
!p[n - 1])
buf[ret - 1] = '\n';
return ret;
-
}
static ssize_t show_reserve_stats(struct bch_dev *ca, char *buf)
"buckets:\n"
" capacity: %llu\n"
" alloc: %llu\n"
+ " sb: %llu\n"
+ " journal: %llu\n"
" meta: %llu\n"
- " dirty: %llu\n"
+ " user: %llu\n"
+ " cached: %llu\n"
" available: %llu\n"
"sectors:\n"
+ " sb: %llu\n"
+ " journal: %llu\n"
" meta: %llu\n"
- " dirty: %llu\n"
+ " user: %llu\n"
" cached: %llu\n"
"freelist_wait: %s\n"
"open buckets: %u/%u (reserved %u)\n"
fifo_used(&ca->free[RESERVE_NONE]), ca->free[RESERVE_NONE].size,
ca->mi.nbuckets - ca->mi.first_bucket,
stats.buckets_alloc,
- stats.buckets[S_META],
- stats.buckets[S_DIRTY],
+ stats.buckets[BCH_DATA_SB],
+ stats.buckets[BCH_DATA_JOURNAL],
+ stats.buckets[BCH_DATA_BTREE],
+ stats.buckets[BCH_DATA_USER],
+ stats.buckets[BCH_DATA_CACHED],
__dev_buckets_available(ca, stats),
- stats.sectors[S_META],
- stats.sectors[S_DIRTY],
- stats.sectors_cached,
+ stats.sectors[BCH_DATA_SB],
+ stats.sectors[BCH_DATA_JOURNAL],
+ stats.sectors[BCH_DATA_BTREE],
+ stats.sectors[BCH_DATA_USER],
+ stats.sectors[BCH_DATA_CACHED],
c->freelist_wait.list.first ? "waiting" : "empty",
c->open_buckets_nr_free, OPEN_BUCKETS_COUNT, BTREE_NODE_RESERVE,
c->open_buckets_wait.list.first ? "waiting" : "empty");
{
struct bch_dev *ca = container_of(kobj, struct bch_dev, kobj);
struct bch_fs *c = ca->fs;
- struct bch_dev_usage stats = bch2_dev_usage_read(c, ca);
char *out = buf, *end = buf + PAGE_SIZE;
sysfs_printf(uuid, "%pU\n", ca->uuid.b);
sysfs_print(block_size, block_bytes(c));
sysfs_print(first_bucket, ca->mi.first_bucket);
sysfs_print(nbuckets, ca->mi.nbuckets);
+ sysfs_print(durability, ca->mi.durability);
sysfs_print(discard, ca->mi.discard);
- sysfs_hprint(dirty_data, stats.sectors[S_DIRTY] << 9);
- sysfs_print(dirty_bytes, stats.sectors[S_DIRTY] << 9);
- sysfs_print(dirty_buckets, stats.buckets[S_DIRTY]);
- sysfs_hprint(cached_data, stats.sectors_cached << 9);
- sysfs_print(cached_bytes, stats.sectors_cached << 9);
- sysfs_print(cached_buckets, stats.buckets_cached);
- sysfs_print(meta_buckets, stats.buckets[S_META]);
- sysfs_print(alloc_buckets, stats.buckets_alloc);
- sysfs_print(available_buckets, __dev_buckets_available(ca, stats));
- sysfs_print(free_buckets, __dev_buckets_free(ca, stats));
+ if (attr == &sysfs_group) {
+ struct bch_sb_field_disk_groups *groups;
+ struct bch_disk_group *g;
+ unsigned len;
+
+ if (!ca->mi.group)
+ return scnprintf(out, end - out, "none\n");
+
+ mutex_lock(&c->sb_lock);
+ groups = bch2_sb_get_disk_groups(c->disk_sb);
+
+ g = &groups->entries[ca->mi.group - 1];
+ len = strnlen(g->label, sizeof(g->label));
+ memcpy(buf, g->label, len);
+ mutex_unlock(&c->sb_lock);
+
+ buf[len++] = '\n';
+ return len;
+ }
if (attr == &sysfs_has_data) {
out += bch2_scnprint_flag_list(out, end - out,
return out - buf;
}
- sysfs_print(tier, ca->mi.tier);
-
if (attr == &sysfs_state_rw) {
out += bch2_scnprint_string_list(out, end - out,
bch2_dev_state,
mutex_unlock(&c->sb_lock);
}
- if (attr == &sysfs_tier) {
- unsigned prev_tier;
- unsigned v = strtoul_restrict_or_return(buf,
- 0, BCH_TIER_MAX - 1);
-
- mutex_lock(&c->sb_lock);
- prev_tier = ca->mi.tier;
-
- if (v == ca->mi.tier) {
- mutex_unlock(&c->sb_lock);
- return size;
- }
-
- mi = &bch2_sb_get_members(c->disk_sb)->members[ca->dev_idx];
- SET_BCH_MEMBER_TIER(mi, v);
- bch2_write_super(c);
+ if (attr == &sysfs_group) {
+ char *tmp;
+ int ret;
- clear_bit(ca->dev_idx, c->tiers[prev_tier].devs.d);
- set_bit(ca->dev_idx, c->tiers[ca->mi.tier].devs.d);
- mutex_unlock(&c->sb_lock);
+ tmp = kstrdup(buf, GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
- bch2_recalc_capacity(c);
- bch2_tiering_start(c);
+ ret = bch2_dev_group_set(c, ca, strim(tmp));
+ kfree(tmp);
+ if (ret)
+ return ret;
}
if (attr == &sysfs_wake_allocator)
&sysfs_block_size,
&sysfs_first_bucket,
&sysfs_nbuckets,
+ &sysfs_durability,
/* settings: */
&sysfs_discard,
&sysfs_cache_replacement_policy,
- &sysfs_tier,
&sysfs_state_rw,
+ &sysfs_group,
&sysfs_has_data,
&sysfs_iostats,
- /* alloc info - data: */
- &sysfs_dirty_data,
- &sysfs_dirty_bytes,
- &sysfs_cached_data,
- &sysfs_cached_bytes,
-
- /* alloc info - buckets: */
- &sysfs_available_buckets,
- &sysfs_free_buckets,
- &sysfs_dirty_buckets,
- &sysfs_cached_buckets,
- &sysfs_meta_buckets,
- &sysfs_alloc_buckets,
-
/* alloc info - other stats: */
&sysfs_read_priority_stats,
&sysfs_write_priority_stats,