Disk labels used to be called groups - not all uses had been converted.
This renames --group to --label, and --label to --fs_label
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-50d6a25d9c0090d84ad9aadd29f76bc0abff5423
+069e88fae5fdce2aea08c9e192cf6ac5c7ed492d
" -S, --fs_size=size Size of filesystem on device\n"
" -B, --bucket=size Bucket size\n"
" -D, --discard Enable discards\n"
- " -g, --group=group Disk group\n"
+ " -l, --label=label Disk label\n"
" -f, --force Use device even if it appears to already be formatted\n"
" -h, --help Display this help and exit\n"
"\n"
{ "fs_size", required_argument, NULL, 'S' },
{ "bucket", required_argument, NULL, 'B' },
{ "discard", no_argument, NULL, 'D' },
- { "group", required_argument, NULL, 'g' },
+ { "label", required_argument, NULL, 'l' },
{ "force", no_argument, NULL, 'f' },
{ "help", no_argument, NULL, 'h' },
{ NULL }
dev_opts.discard = true;
break;
case 'g':
- dev_opts.group = strdup(optarg);
+ dev_opts.label = strdup(optarg);
break;
case 'f':
force = true;
x(0, replicas, required_argument) \
x(0, encrypted, no_argument) \
x(0, no_passphrase, no_argument) \
-x('L', label, required_argument) \
+x('L', fs_label, required_argument) \
x('U', uuid, required_argument) \
x(0, fs_size, required_argument) \
x(0, superblock_size, required_argument) \
x(0, bucket_size, required_argument) \
-x('g', group, required_argument) \
+x('l', label, required_argument) \
x(0, discard, no_argument) \
x(0, data_allowed, required_argument) \
x(0, durability, required_argument) \
" --replicas=# Sets both data and metadata replicas\n"
" --encrypted Enable whole filesystem encryption (chacha20/poly1305)\n"
" --no_passphrase Don't encrypt master encryption key\n"
- " -L, --label=label\n"
+ " -L, --fs_label=label\n"
" -U, --uuid=uuid\n"
" --superblock_size=size\n"
"\n"
bch2_opts_usage(OPT_DEVICE);
- puts(" -g, --group=label Disk group\n"
+ puts(" -l, --label=label Disk label\n"
"\n"
" -f, --force\n"
" -q, --quiet Only print errors\n"
" -h, --help Display this help and exit\n"
"\n"
"Device specific options must come before corresponding devices, e.g.\n"
- " bcachefs format --group cache /dev/sdb /dev/sdc\n"
+ " bcachefs format --label cache /dev/sdb /dev/sdc\n"
"\n"
"Report bugs to <linux-bcache@vger.kernel.org>");
}
case O_no_passphrase:
no_passphrase = true;
break;
- case O_label:
+ case O_fs_label:
case 'L':
opts.label = optarg;
break;
dev_opts.bucket_size =
hatoi_validate(optarg, "bucket size");
break;
- case O_group:
- case 'g':
- dev_opts.group = optarg;
+ case O_label:
+ case 'l':
+ dev_opts.label = optarg;
break;
case O_discard:
dev_opts.discard = true;
SET_BCH_MEMBER_DURABILITY(m, i->durability + 1);
}
- /* Disk groups */
+ /* Disk labels*/
for (i = devs; i < devs + nr_devs; i++) {
struct bch_member *m = mi->members + (i - devs);
int idx;
- if (!i->group)
+ if (!i->label)
continue;
- idx = bch2_disk_path_find_or_create(&sb, i->group);
+ idx = bch2_disk_path_find_or_create(&sb, i->label);
if (idx < 0)
die("error creating disk path: %s", idx);
char *path;
u64 size; /* 512 byte sectors */
unsigned bucket_size;
- const char *group;
+ const char *label;
unsigned data_allowed;
unsigned durability;
bool discard;
struct mutex data_progress_lock;
/* STRIPES: */
- GENRADIX(struct stripe) stripes[2];
+ GENRADIX(struct stripe) stripes;
+ GENRADIX(struct gc_stripe) gc_stripes;
ec_stripes_heap ec_stripes_heap;
spinlock_t ec_stripes_heap_lock;
LE64_BITMASK(BCH_SB_METADATA_TARGET, struct bch_sb, flags[3], 16, 28);
LE64_BITMASK(BCH_SB_SHARD_INUMS, struct bch_sb, flags[3], 28, 29);
LE64_BITMASK(BCH_SB_INODES_USE_KEY_CACHE,struct bch_sb, flags[3], 29, 30);
+LE64_BITMASK(BCH_SB_JOURNAL_FLUSH_DELAY,struct bch_sb, flags[3], 30, 62);
+LE64_BITMASK(BCH_SB_JOURNAL_FLUSH_DISABLED,struct bch_sb, flags[3], 62, 63);
+LE64_BITMASK(BCH_SB_JOURNAL_RECLAIM_DELAY,struct bch_sb, flags[4], 0, 32);
/*
* Features:
}
if (p.has_ec) {
- struct stripe *m = genradix_ptr(&c->stripes[true], p.ec.idx);
+ struct gc_stripe *m = genradix_ptr(&c->gc_stripes, p.ec.idx);
if (fsck_err_on(!m || !m->alive, c,
"pointer to nonexistent stripe %llu\n"
ptrs = bch2_bkey_ptrs(bkey_i_to_s(new));
bkey_extent_entry_for_each(ptrs, entry) {
if (extent_entry_type(entry) == BCH_EXTENT_ENTRY_stripe_ptr) {
- struct stripe *m = genradix_ptr(&c->stripes[true],
+ struct gc_stripe *m = genradix_ptr(&c->gc_stripes,
entry->stripe_ptr.idx);
union bch_extent_entry *next_ptr;
struct bch_dev *ca;
unsigned i;
- genradix_free(&c->stripes[1]);
+ genradix_free(&c->reflink_gc_table);
+ genradix_free(&c->gc_stripes);
for_each_member_device(ca, c, i) {
kvpfree(rcu_dereference_protected(ca->buckets[1], 1),
#define copy_fs_field(_f, _msg, ...) \
copy_field(_f, "fs has wrong " _msg, ##__VA_ARGS__)
- if (!metadata_only) {
- struct genradix_iter iter = genradix_iter_init(&c->stripes[1], 0);
- struct stripe *dst, *src;
-
- while ((src = genradix_iter_peek(&iter, &c->stripes[1]))) {
- dst = genradix_ptr_alloc(&c->stripes[0], iter.pos, GFP_KERNEL);
-
- if (dst->alive != src->alive ||
- dst->sectors != src->sectors ||
- dst->algorithm != src->algorithm ||
- dst->nr_blocks != src->nr_blocks ||
- dst->nr_redundant != src->nr_redundant) {
- bch_err(c, "unexpected stripe inconsistency at bch2_gc_done, confused");
- ret = -EINVAL;
- goto fsck_err;
- }
-
- for (i = 0; i < ARRAY_SIZE(dst->block_sectors); i++)
- copy_stripe_field(block_sectors[i],
- "block_sectors[%u]", i);
-
- dst->blocks_nonempty = 0;
- for (i = 0; i < dst->nr_blocks; i++)
- dst->blocks_nonempty += dst->block_sectors[i] != 0;
-
- genradix_iter_advance(&iter, &c->stripes[1]);
- }
- }
-
for (i = 0; i < ARRAY_SIZE(c->usage); i++)
bch2_fs_usage_acc_to_base(c, i);
fsck_err:
bch2_trans_iter_exit(&trans, &iter);
out:
- genradix_free(&c->reflink_gc_table);
c->reflink_gc_nr = 0;
bch2_trans_exit(&trans);
return ret;
}
+static int bch2_gc_stripes_done_initial_fn(struct btree_trans *trans,
+ struct bkey_s_c k)
+{
+ struct bch_fs *c = trans->c;
+ struct gc_stripe *m;
+ const struct bch_stripe *s;
+ char buf[200];
+ unsigned i;
+ int ret = 0;
+
+ if (k.k->type != KEY_TYPE_stripe)
+ return 0;
+
+ s = bkey_s_c_to_stripe(k).v;
+
+ m = genradix_ptr(&c->gc_stripes, k.k->p.offset);
+
+ for (i = 0; i < s->nr_blocks; i++)
+ if (stripe_blockcount_get(s, i) != (m ? m->block_sectors[i] : 0))
+ goto inconsistent;
+ return 0;
+inconsistent:
+ if (fsck_err_on(true, c,
+ "stripe has wrong block sector count %u:\n"
+ " %s\n"
+ " should be %u", i,
+ (bch2_bkey_val_to_text(&PBUF(buf), c, k), buf),
+ m ? m->block_sectors[i] : 0)) {
+ struct bkey_i_stripe *new;
+
+ new = kmalloc(bkey_bytes(k.k), GFP_KERNEL);
+ if (!new) {
+ ret = -ENOMEM;
+ goto fsck_err;
+ }
+
+ bkey_reassemble(&new->k_i, k);
+
+ for (i = 0; i < new->v.nr_blocks; i++)
+ stripe_blockcount_set(&new->v, i, m ? m->block_sectors[i] : 0);
+
+ ret = bch2_journal_key_insert(c, BTREE_ID_stripes, 0, &new->k_i);
+ if (ret)
+ kfree(new);
+ }
+fsck_err:
+ return ret;
+}
+
+static int bch2_gc_stripes_done(struct bch_fs *c, bool initial,
+ bool metadata_only)
+{
+ struct btree_trans trans;
+ int ret = 0;
+
+ if (metadata_only)
+ return 0;
+
+ bch2_trans_init(&trans, c, 0, 0);
+
+ if (initial) {
+ ret = bch2_btree_and_journal_walk(&trans, BTREE_ID_stripes,
+ bch2_gc_stripes_done_initial_fn);
+ } else {
+ BUG();
+ }
+
+ bch2_trans_exit(&trans);
+ return ret;
+}
+
static int bch2_gc_reflink_start_initial_fn(struct btree_trans *trans,
struct bkey_s_c k)
{
return 0;
bch2_trans_init(&trans, c, 0, 0);
- genradix_free(&c->reflink_gc_table);
c->reflink_gc_nr = 0;
if (initial) {
percpu_down_write(&c->mark_lock);
ret = bch2_gc_reflink_done(c, initial, metadata_only) ?:
+ bch2_gc_stripes_done(c, initial, metadata_only) ?:
bch2_gc_done(c, initial, metadata_only);
bch2_journal_unblock(&c->journal);
int bch2_btree_node_update_key_get_iter(struct btree_trans *,
struct btree *, struct bkey_i *, bool);
-int bch2_trans_update(struct btree_trans *, struct btree_iter *,
- struct bkey_i *, enum btree_update_flags);
+int __must_check bch2_trans_update(struct btree_trans *, struct btree_iter *,
+ struct bkey_i *, enum btree_update_flags);
void bch2_trans_commit_hook(struct btree_trans *,
struct btree_trans_commit_hook *);
int __bch2_trans_commit(struct btree_trans *);
return ret;
}
-int bch2_trans_update(struct btree_trans *trans, struct btree_iter *iter,
- struct bkey_i *k, enum btree_update_flags flags)
+int __must_check bch2_trans_update(struct btree_trans *trans, struct btree_iter *iter,
+ struct bkey_i *k, enum btree_update_flags flags)
{
struct btree_insert_entry *i, n;
.ip_allocated = _RET_IP_,
};
- __btree_path_get(n.path, true);
-
#ifdef CONFIG_BCACHEFS_DEBUG
trans_for_each_update(trans, i)
BUG_ON(i != trans->updates &&
if (n.cached && !i->cached) {
i->k = n.k;
i->flags = n.flags;
-
- __btree_path_get(n.path, false);
- } else {
- bch2_path_put(trans, i->path, true);
- *i = n;
+ return 0;
}
+
+ bch2_path_put(trans, i->path, true);
+ *i = n;
} else
array_insert_item(trans->updates, trans->nr_updates,
i - trans->updates, n);
+ __btree_path_get(n.path, true);
+
return 0;
}
bool gc = flags & BTREE_TRIGGER_GC;
struct bch_fs *c = trans->c;
struct bch_replicas_padded r;
- struct stripe *m;
- unsigned i, blocks_nonempty = 0;
- m = genradix_ptr(&c->stripes[gc], p.idx);
+ if (!gc) {
+ BUG();
+ } else {
+ struct gc_stripe *m = genradix_ptr_alloc(&c->gc_stripes, p.idx, GFP_KERNEL);
- spin_lock(&c->ec_stripes_heap_lock);
+ if (!m)
+ return -ENOMEM;
- if (!m || !m->alive) {
- spin_unlock(&c->ec_stripes_heap_lock);
- bch_err_ratelimited(c, "pointer to nonexistent stripe %llu",
- (u64) p.idx);
- bch2_inconsistent_error(c);
- return -EIO;
- }
+ spin_lock(&c->ec_stripes_heap_lock);
- m->block_sectors[p.block] += sectors;
+ if (!m || !m->alive) {
+ spin_unlock(&c->ec_stripes_heap_lock);
+ bch_err_ratelimited(c, "pointer to nonexistent stripe %llu",
+ (u64) p.idx);
+ bch2_inconsistent_error(c);
+ return -EIO;
+ }
- r = m->r;
+ m->block_sectors[p.block] += sectors;
- for (i = 0; i < m->nr_blocks; i++)
- blocks_nonempty += m->block_sectors[i] != 0;
+ r = m->r;
+ spin_unlock(&c->ec_stripes_heap_lock);
- if (m->blocks_nonempty != blocks_nonempty) {
- m->blocks_nonempty = blocks_nonempty;
- if (!gc)
- bch2_stripes_heap_update(c, m, p.idx);
+ r.e.data_type = data_type;
+ update_replicas(c, k, &r.e, sectors, trans->journal_res.seq, gc);
}
- spin_unlock(&c->ec_stripes_heap_lock);
-
- r.e.data_type = data_type;
- update_replicas(c, k, &r.e, sectors, trans->journal_res.seq, gc);
return 0;
}
? bkey_s_c_to_stripe(old).v : NULL;
const struct bch_stripe *new_s = new.k->type == KEY_TYPE_stripe
? bkey_s_c_to_stripe(new).v : NULL;
- struct stripe *m = genradix_ptr(&c->stripes[gc], idx);
unsigned i;
int ret;
BUG_ON(gc && old_s);
- if (!m || (old_s && !m->alive)) {
- char buf1[200], buf2[200];
-
- bch2_bkey_val_to_text(&PBUF(buf1), c, old);
- bch2_bkey_val_to_text(&PBUF(buf2), c, new);
- bch_err_ratelimited(c, "error marking nonexistent stripe %zu while marking\n"
- "old %s\n"
- "new %s", idx, buf1, buf2);
- bch2_inconsistent_error(c);
- return -1;
- }
+ if (!gc) {
+ struct stripe *m = genradix_ptr(&c->stripes, idx);
- if (!new_s) {
- spin_lock(&c->ec_stripes_heap_lock);
- bch2_stripes_heap_del(c, m, idx);
- spin_unlock(&c->ec_stripes_heap_lock);
+ if (!m || (old_s && !m->alive)) {
+ char buf1[200], buf2[200];
- memset(m, 0, sizeof(*m));
- } else {
- m->alive = true;
- m->sectors = le16_to_cpu(new_s->sectors);
- m->algorithm = new_s->algorithm;
- m->nr_blocks = new_s->nr_blocks;
- m->nr_redundant = new_s->nr_redundant;
- m->blocks_nonempty = 0;
+ bch2_bkey_val_to_text(&PBUF(buf1), c, old);
+ bch2_bkey_val_to_text(&PBUF(buf2), c, new);
+ bch_err_ratelimited(c, "error marking nonexistent stripe %zu while marking\n"
+ "old %s\n"
+ "new %s", idx, buf1, buf2);
+ bch2_inconsistent_error(c);
+ return -1;
+ }
- for (i = 0; i < new_s->nr_blocks; i++) {
- m->block_sectors[i] =
- stripe_blockcount_get(new_s, i);
- m->blocks_nonempty += !!m->block_sectors[i];
+ if (!new_s) {
+ spin_lock(&c->ec_stripes_heap_lock);
+ bch2_stripes_heap_del(c, m, idx);
+ spin_unlock(&c->ec_stripes_heap_lock);
- m->ptrs[i] = new_s->ptrs[i];
- }
+ memset(m, 0, sizeof(*m));
+ } else {
+ m->alive = true;
+ m->sectors = le16_to_cpu(new_s->sectors);
+ m->algorithm = new_s->algorithm;
+ m->nr_blocks = new_s->nr_blocks;
+ m->nr_redundant = new_s->nr_redundant;
+ m->blocks_nonempty = 0;
- bch2_bkey_to_replicas(&m->r.e, new);
+ for (i = 0; i < new_s->nr_blocks; i++)
+ m->blocks_nonempty += !!stripe_blockcount_get(new_s, i);
- if (!gc) {
spin_lock(&c->ec_stripes_heap_lock);
bch2_stripes_heap_update(c, m, idx);
spin_unlock(&c->ec_stripes_heap_lock);
}
- }
+ } else {
+ struct gc_stripe *m = genradix_ptr(&c->gc_stripes, idx);
- if (gc) {
/*
* This will be wrong when we bring back runtime gc: we should
* be unmarking the old key and then marking the new key
*/
+ m->alive = true;
+ m->sectors = le16_to_cpu(new_s->sectors);
+ m->algorithm = new_s->algorithm;
+ m->nr_blocks = new_s->nr_blocks;
+ m->nr_redundant = new_s->nr_redundant;
+
+ for (i = 0; i < new_s->nr_blocks; i++)
+ m->ptrs[i] = new_s->ptrs[i];
+
+ bch2_bkey_to_replicas(&m->r.e, new);
/*
* gc recalculates this field from stripe ptr
* references:
*/
memset(m->block_sectors, 0, sizeof(m->block_sectors));
- m->blocks_nonempty = 0;
for (i = 0; i < new_s->nr_blocks; i++) {
ret = mark_stripe_bucket(trans, new, i, journal_seq, flags);
goto out;
bch2_alloc_pack(c, a, u);
- bch2_trans_update(trans, &iter, &a->k, 0);
+ ret = bch2_trans_update(trans, &iter, &a->k, 0);
+ if (ret)
+ goto out;
out:
bch2_trans_iter_exit(trans, &iter);
return ret;
stripe_blockcount_set(&s->v, p.ec.block,
stripe_blockcount_get(&s->v, p.ec.block) +
sectors);
- bch2_trans_update(trans, &iter, &s->k_i, 0);
+
+ ret = bch2_trans_update(trans, &iter, &s->k_i, 0);
+ if (ret)
+ goto err;
bch2_bkey_to_replicas(&r.e, bkey_i_to_s_c(&s->k_i));
r.e.data_type = data_type;
u.data_type = !deleting ? data_type : 0;
bch2_alloc_pack(c, a, u);
- bch2_trans_update(trans, &iter, &a->k, 0);
+ ret = bch2_trans_update(trans, &iter, &a->k, 0);
+ if (ret)
+ goto err;
err:
bch2_trans_iter_exit(trans, &iter);
return ret;
u.dirty_sectors = sectors;
bch2_alloc_pack(c, a, u);
- bch2_trans_update(trans, &iter, &a->k, 0);
+ ret = bch2_trans_update(trans, &iter, &a->k, 0);
+ if (ret)
+ goto out;
out:
bch2_trans_iter_exit(trans, &iter);
return ret;
}
}
- bch2_trans_update(trans, &dst_iter, &new_dst->k_i, 0);
+ ret = bch2_trans_update(trans, &dst_iter, &new_dst->k_i, 0);
+ if (ret)
+ goto out;
out_set_src:
/*
src_update_flags |= BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE;
}
- bch2_trans_update(trans, &src_iter, &new_src->k_i, src_update_flags);
+ ret = bch2_trans_update(trans, &src_iter, &new_src->k_i, src_update_flags);
+ if (ret)
+ goto out;
if (mode == BCH_RENAME_EXCHANGE)
*src_offset = new_src->k.p.offset;
free_heap(&n);
}
- if (!genradix_ptr_alloc(&c->stripes[0], idx, gfp))
+ if (!genradix_ptr_alloc(&c->stripes, idx, gfp))
return -ENOMEM;
if (c->gc_pos.phase != GC_PHASE_NOT_RUNNING &&
- !genradix_ptr_alloc(&c->stripes[1], idx, gfp))
+ !genradix_ptr_alloc(&c->gc_stripes, idx, gfp))
return -ENOMEM;
return 0;
{
struct bch_fs *c = container_of(h, struct bch_fs, ec_stripes_heap);
- genradix_ptr(&c->stripes[0], h->data[i].idx)->heap_idx = i;
+ genradix_ptr(&c->stripes, h->data[i].idx)->heap_idx = i;
}
static void heap_verify_backpointer(struct bch_fs *c, size_t idx)
{
ec_stripes_heap *h = &c->ec_stripes_heap;
- struct stripe *m = genradix_ptr(&c->stripes[0], idx);
+ struct stripe *m = genradix_ptr(&c->stripes, idx);
BUG_ON(!m->alive);
BUG_ON(m->heap_idx >= h->used);
break;
}
- bch2_stripes_heap_del(c, genradix_ptr(&c->stripes[0], idx), idx);
+ bch2_stripes_heap_del(c, genradix_ptr(&c->stripes, idx), idx);
spin_unlock(&c->ec_stripes_heap_lock);
if (ec_stripe_delete(c, idx))
/* stripe creation: */
-static int ec_stripe_bkey_insert(struct bch_fs *c,
+static int ec_stripe_bkey_insert(struct btree_trans *trans,
struct bkey_i_stripe *stripe,
struct disk_reservation *res)
{
- struct btree_trans trans;
+ struct bch_fs *c = trans->c;
struct btree_iter iter;
struct bkey_s_c k;
struct bpos min_pos = POS(0, 1);
struct bpos start_pos = bpos_max(min_pos, POS(0, c->ec_stripe_hint));
int ret;
- bch2_trans_init(&trans, c, 0, 0);
-retry:
- bch2_trans_begin(&trans);
-
- for_each_btree_key(&trans, iter, BTREE_ID_stripes, start_pos,
+ for_each_btree_key(trans, iter, BTREE_ID_stripes, start_pos,
BTREE_ITER_SLOTS|BTREE_ITER_INTENT, k, ret) {
if (bkey_cmp(k.k->p, POS(0, U32_MAX)) > 0) {
if (start_pos.offset) {
found_slot:
start_pos = iter.pos;
- ret = ec_stripe_mem_alloc(&trans, &iter);
+ ret = ec_stripe_mem_alloc(trans, &iter);
if (ret)
goto err;
stripe->k.p = iter.pos;
- ret = bch2_trans_update(&trans, &iter, &stripe->k_i, 0) ?:
- bch2_trans_commit(&trans, res, NULL,
- BTREE_INSERT_NOFAIL);
-err:
- bch2_trans_iter_exit(&trans, &iter);
+ ret = bch2_trans_update(trans, &iter, &stripe->k_i, 0);
- if (ret == -EINTR)
- goto retry;
-
- c->ec_stripe_hint = ret ? start_pos.offset : start_pos.offset + 1;
- bch2_trans_exit(&trans);
+ c->ec_stripe_hint = start_pos.offset;
+err:
+ bch2_trans_iter_exit(trans, &iter);
return ret;
}
static int ec_stripe_bkey_update(struct btree_trans *trans,
- struct bkey_i_stripe *new)
+ struct bkey_i_stripe *new,
+ struct disk_reservation *res)
{
struct btree_iter iter;
struct bkey_s_c k;
goto err_put_writes;
}
- ret = s->have_existing_stripe
- ? bch2_trans_do(c, &s->res, NULL, BTREE_INSERT_NOFAIL,
- ec_stripe_bkey_update(&trans, &s->new_stripe.key))
- : ec_stripe_bkey_insert(c, &s->new_stripe.key, &s->res);
+ ret = bch2_trans_do(c, &s->res, NULL, BTREE_INSERT_NOFAIL,
+ s->have_existing_stripe
+ ? ec_stripe_bkey_update(&trans, &s->new_stripe.key, &s->res)
+ : ec_stripe_bkey_insert(&trans, &s->new_stripe.key, &s->res));
if (ret) {
bch_err(c, "error creating stripe: error creating stripe key");
goto err_put_writes;
}
spin_lock(&c->ec_stripes_heap_lock);
- m = genradix_ptr(&c->stripes[0], s->new_stripe.key.k.p.offset);
+ m = genradix_ptr(&c->stripes, s->new_stripe.key.k.p.offset);
BUG_ON(m->on_heap);
bch2_stripes_heap_insert(c, m, s->new_stripe.key.k.p.offset);
continue;
stripe_idx = h->data[heap_idx].idx;
- m = genradix_ptr(&c->stripes[0], stripe_idx);
+ m = genradix_ptr(&c->stripes, stripe_idx);
if (m->algorithm == head->algo &&
m->nr_redundant == head->redundancy &&
struct genradix_iter iter;
struct stripe *m;
- genradix_for_each(&c->stripes[0], iter, m)
+ genradix_for_each(&c->stripes, iter, m)
if (m->alive)
bch2_stripes_heap_insert(c, m, iter.pos);
}
-static int __bch2_stripe_write_key(struct btree_trans *trans,
- struct btree_iter *iter,
- struct stripe *m,
- size_t idx,
- struct bkey_i_stripe *new_key)
-{
- const struct bch_stripe *v;
- struct bkey_s_c k;
- unsigned i;
- int ret;
-
- bch2_btree_iter_set_pos(iter, POS(0, idx));
-
- k = bch2_btree_iter_peek_slot(iter);
- ret = bkey_err(k);
- if (ret)
- return ret;
-
- if (k.k->type != KEY_TYPE_stripe)
- return -EIO;
-
- v = bkey_s_c_to_stripe(k).v;
- for (i = 0; i < v->nr_blocks; i++)
- if (m->block_sectors[i] != stripe_blockcount_get(v, i))
- goto write;
- return 0;
-write:
- bkey_reassemble(&new_key->k_i, k);
-
- for (i = 0; i < new_key->v.nr_blocks; i++)
- stripe_blockcount_set(&new_key->v, i,
- m->block_sectors[i]);
-
- return bch2_trans_update(trans, iter, &new_key->k_i, 0);
-}
-
-int bch2_stripes_write(struct bch_fs *c, unsigned flags)
-{
- struct btree_trans trans;
- struct btree_iter iter;
- struct genradix_iter giter;
- struct bkey_i_stripe *new_key;
- struct stripe *m;
- int ret = 0;
-
- new_key = kmalloc(255 * sizeof(u64), GFP_KERNEL);
- BUG_ON(!new_key);
-
- bch2_trans_init(&trans, c, 0, 0);
-
- bch2_trans_iter_init(&trans, &iter, BTREE_ID_stripes, POS_MIN,
- BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
-
- genradix_for_each(&c->stripes[0], giter, m) {
- if (!m->alive)
- continue;
-
- ret = __bch2_trans_do(&trans, NULL, NULL,
- BTREE_INSERT_NOFAIL|flags,
- __bch2_stripe_write_key(&trans, &iter, m,
- giter.pos, new_key));
-
- if (ret)
- break;
- }
- bch2_trans_iter_exit(&trans, &iter);
-
- bch2_trans_exit(&trans);
-
- kfree(new_key);
-
- return ret;
-}
-
static int bch2_stripes_read_fn(struct btree_trans *trans, struct bkey_s_c k)
{
const struct bch_stripe *s;
s = bkey_s_c_to_stripe(k).v;
- m = genradix_ptr(&c->stripes[0], k.k->p.offset);
+ m = genradix_ptr(&c->stripes, k.k->p.offset);
m->alive = true;
m->sectors = le16_to_cpu(s->sectors);
m->algorithm = s->algorithm;
m->nr_redundant = s->nr_redundant;
m->blocks_nonempty = 0;
- for (i = 0; i < s->nr_blocks; i++) {
- m->block_sectors[i] =
- stripe_blockcount_get(s, i);
- m->blocks_nonempty += !!m->block_sectors[i];
- m->ptrs[i] = s->ptrs[i];
- }
-
- bch2_bkey_to_replicas(&m->r.e, k);
+ for (i = 0; i < s->nr_blocks; i++)
+ m->blocks_nonempty += !!stripe_blockcount_get(s, i);
spin_lock(&c->ec_stripes_heap_lock);
bch2_stripes_heap_update(c, m, k.k->p.offset);
ret = genradix_prealloc(&c->stripes[gc], idx, GFP_KERNEL);
#else
for (i = 0; i < idx; i++)
- if (!genradix_ptr_alloc(&c->stripes[gc], i, GFP_KERNEL))
+ if (!gc
+ ? !genradix_ptr_alloc(&c->stripes, i, GFP_KERNEL)
+ : !genradix_ptr_alloc(&c->gc_stripes, i, GFP_KERNEL))
return -ENOMEM;
#endif
return 0;
spin_lock(&c->ec_stripes_heap_lock);
for (i = 0; i < min_t(size_t, h->used, 20); i++) {
- m = genradix_ptr(&c->stripes[0], h->data[i].idx);
+ m = genradix_ptr(&c->stripes, h->data[i].idx);
pr_buf(out, "%zu %u/%u+%u\n", h->data[i].idx,
h->data[i].blocks_nonempty,
BUG_ON(!list_empty(&c->ec_stripe_new_list));
free_heap(&c->ec_stripes_heap);
- genradix_free(&c->stripes[0]);
+ genradix_free(&c->stripes);
bioset_exit(&c->ec_bioset);
}
le16_to_cpu(s->sectors));
}
-static inline bool bch2_ptr_matches_stripe_m(const struct stripe *m,
+static inline bool bch2_ptr_matches_stripe_m(const struct gc_stripe *m,
struct extent_ptr_decoded p)
{
unsigned nr_data = m->nr_blocks - m->nr_redundant;
void bch2_stripes_heap_start(struct bch_fs *);
int bch2_stripes_read(struct bch_fs *);
-int bch2_stripes_write(struct bch_fs *, unsigned);
int bch2_ec_mem_alloc(struct bch_fs *, bool);
unsigned alive:1; /* does a corresponding key exist in stripes btree? */
unsigned on_heap:1;
u8 blocks_nonempty;
+};
+
+struct gc_stripe {
+ u16 sectors;
+ u8 algorithm;
+
+ u8 nr_blocks;
+ u8 nr_redundant;
+
+ unsigned alive:1; /* does a corresponding key exist in stripes btree? */
u16 block_sectors[BCH_BKEY_PTRS_MAX];
struct bch_extent_ptr ptrs[BCH_BKEY_PTRS_MAX];
mod_delayed_work(c->io_complete_wq,
&j->write_work,
- msecs_to_jiffies(j->write_delay_ms));
+ msecs_to_jiffies(c->opts.journal_flush_delay));
journal_wake(j);
return 0;
}
lockdep_init_map(&j->res_map, "journal res", &res_key, 0);
- j->write_delay_ms = 1000;
- j->reclaim_delay_ms = 100;
-
atomic64_set(&j->reservations.counter,
((union journal_res_state)
{ .cur_entry_offset = JOURNAL_ENTRY_CLOSED_VAL }).v);
struct bch_fs *c = container_of(j, struct bch_fs, journal);
union journal_res_state s;
struct bch_dev *ca;
+ unsigned long now = jiffies;
unsigned i;
rcu_read_lock();
s = READ_ONCE(j->reservations);
- pr_buf(out,
- "active journal entries:\t%llu\n"
- "seq:\t\t\t%llu\n"
- "last_seq:\t\t%llu\n"
- "last_seq_ondisk:\t%llu\n"
- "flushed_seq_ondisk:\t%llu\n"
- "prereserved:\t\t%u/%u\n"
- "each entry reserved:\t%u\n"
- "nr flush writes:\t%llu\n"
- "nr noflush writes:\t%llu\n"
- "nr direct reclaim:\t%llu\n"
- "nr background reclaim:\t%llu\n"
- "reclaim kicked:\t\t%u\n"
- "reclaim runs in:\t%u ms\n"
- "current entry sectors:\t%u\n"
- "current entry error:\t%u\n"
- "current entry:\t\t",
- fifo_used(&j->pin),
- journal_cur_seq(j),
- journal_last_seq(j),
- j->last_seq_ondisk,
- j->flushed_seq_ondisk,
- j->prereserved.reserved,
- j->prereserved.remaining,
- j->entry_u64s_reserved,
- j->nr_flush_writes,
- j->nr_noflush_writes,
- j->nr_direct_reclaim,
- j->nr_background_reclaim,
- j->reclaim_kicked,
- jiffies_to_msecs(j->next_reclaim - jiffies),
- j->cur_entry_sectors,
- j->cur_entry_error);
+ pr_buf(out, "active journal entries:\t%llu\n", fifo_used(&j->pin));
+ pr_buf(out, "seq:\t\t\t%llu\n", journal_cur_seq(j));
+ pr_buf(out, "last_seq:\t\t%llu\n", journal_last_seq(j));
+ pr_buf(out, "last_seq_ondisk:\t%llu\n", j->last_seq_ondisk);
+ pr_buf(out, "flushed_seq_ondisk:\t%llu\n", j->flushed_seq_ondisk);
+ pr_buf(out, "prereserved:\t\t%u/%u\n", j->prereserved.reserved, j->prereserved.remaining);
+ pr_buf(out, "each entry reserved:\t%u\n", j->entry_u64s_reserved);
+ pr_buf(out, "nr flush writes:\t%llu\n", j->nr_flush_writes);
+ pr_buf(out, "nr noflush writes:\t%llu\n", j->nr_noflush_writes);
+ pr_buf(out, "nr direct reclaim:\t%llu\n", j->nr_direct_reclaim);
+ pr_buf(out, "nr background reclaim:\t%llu\n", j->nr_background_reclaim);
+ pr_buf(out, "reclaim kicked:\t\t%u\n", j->reclaim_kicked);
+ pr_buf(out, "reclaim runs in:\t%u ms\n", time_after(j->next_reclaim, now)
+ ? jiffies_to_msecs(j->next_reclaim - jiffies) : 0);
+ pr_buf(out, "current entry sectors:\t%u\n", j->cur_entry_sectors);
+ pr_buf(out, "current entry error:\t%u\n", j->cur_entry_error);
+ pr_buf(out, "current entry:\t\t");
switch (s.cur_entry_offset) {
case JOURNAL_ENTRY_ERROR_VAL:
pr_buf(out, "closed\n");
break;
default:
- pr_buf(out, "%u/%u\n",
- s.cur_entry_offset,
- j->cur_entry_u64s);
+ pr_buf(out, "%u/%u\n", s.cur_entry_offset, j->cur_entry_u64s);
break;
}
- pr_buf(out,
- "current entry:\t\tidx %u refcount %u\n",
- s.idx, journal_state_count(s, s.idx));
+ pr_buf(out, "current entry:\t\tidx %u refcount %u\n", s.idx, journal_state_count(s, s.idx));
i = s.idx;
while (i != s.unwritten_idx) {
if (!ja->nr)
continue;
- pr_buf(out,
- "dev %u:\n"
- "\tnr\t\t%u\n"
- "\tbucket size\t%u\n"
- "\tavailable\t%u:%u\n"
- "\tdiscard_idx\t%u\n"
- "\tdirty_ondisk\t%u (seq %llu)\n"
- "\tdirty_idx\t%u (seq %llu)\n"
- "\tcur_idx\t\t%u (seq %llu)\n",
- i, ja->nr, ca->mi.bucket_size,
- bch2_journal_dev_buckets_available(j, ja, journal_space_discarded),
- ja->sectors_free,
- ja->discard_idx,
- ja->dirty_idx_ondisk, ja->bucket_seq[ja->dirty_idx_ondisk],
- ja->dirty_idx, ja->bucket_seq[ja->dirty_idx],
- ja->cur_idx, ja->bucket_seq[ja->cur_idx]);
+ pr_buf(out, "dev %u:\n", i);
+ pr_buf(out, "\tnr\t\t%u\n", ja->nr);
+ pr_buf(out, "\tbucket size\t%u\n", ca->mi.bucket_size);
+ pr_buf(out, "\tavailable\t%u:%u\n", bch2_journal_dev_buckets_available(j, ja, journal_space_discarded), ja->sectors_free);
+ pr_buf(out, "\tdiscard_idx\t%u\n", ja->discard_idx);
+ pr_buf(out, "\tdirty_ondisk\t%u (seq %llu)\n", ja->dirty_idx_ondisk, ja->bucket_seq[ja->dirty_idx_ondisk]);
+ pr_buf(out, "\tdirty_idx\t%u (seq %llu)\n", ja->dirty_idx, ja->bucket_seq[ja->dirty_idx]);
+ pr_buf(out, "\tcur_idx\t\t%u (seq %llu)\n", ja->cur_idx, ja->bucket_seq[ja->cur_idx]);
}
rcu_read_unlock();
spin_lock(&j->lock);
if (c->sb.features & (1ULL << BCH_FEATURE_journal_no_flush) &&
!w->must_flush &&
- (jiffies - j->last_flush_write) < msecs_to_jiffies(j->write_delay_ms) &&
+ (jiffies - j->last_flush_write) < msecs_to_jiffies(c->opts.journal_flush_delay) &&
test_bit(JOURNAL_MAY_SKIP_FLUSH, &j->flags)) {
w->noflush = true;
SET_JSET_NO_FLUSH(jset, true);
* make sure to flush at least one journal pin:
*/
if (time_after(jiffies, j->last_flushed +
- msecs_to_jiffies(j->reclaim_delay_ms)))
+ msecs_to_jiffies(c->opts.journal_reclaim_delay)))
min_nr = 1;
if (j->prereserved.reserved * 4 > j->prereserved.remaining)
static int bch2_journal_reclaim_thread(void *arg)
{
struct journal *j = arg;
+ struct bch_fs *c = container_of(j, struct bch_fs, journal);
unsigned long delay, now;
int ret = 0;
mutex_unlock(&j->reclaim_lock);
now = jiffies;
- delay = msecs_to_jiffies(j->reclaim_delay_ms);
+ delay = msecs_to_jiffies(c->opts.journal_reclaim_delay);
j->next_reclaim = j->last_flushed + delay;
if (!time_in_range(j->next_reclaim, now, now + delay))
struct mutex discard_lock;
bool can_discard;
- unsigned write_delay_ms;
- unsigned reclaim_delay_ms;
unsigned long last_flush_write;
u64 res_get_blocked_start;
if (rate)
bch2_ratelimit_increment(rate, k.k->size);
next:
- atomic64_add(k.k->size * bch2_bkey_nr_ptrs_allocated(k),
- &stats->sectors_seen);
+ atomic64_add(k.k->size, &stats->sectors_seen);
next_nondata:
bch2_btree_iter_advance(&iter);
}
struct copygc_heap_entry e, *i;
struct bucket_array *buckets;
struct bch_move_stats move_stats;
- u64 sectors_to_move = 0, sectors_not_moved = 0;
+ u64 sectors_to_move = 0, sectors_to_write = 0, sectors_not_moved = 0;
u64 sectors_reserved = 0;
u64 buckets_to_move, buckets_not_moved = 0;
struct bch_dev *ca;
up_read(&ca->bucket_lock);
}
+ /*
+ * Our btree node allocations also come out of RESERVE_MOVINGGC:
+ */
+ sectors_reserved = (sectors_reserved * 3) / 4;
if (!sectors_reserved) {
bch2_fs_fatal_error(c, "stuck, ran out of copygc reserve!");
return -1;
}
- /*
- * Our btree node allocations also come out of RESERVE_MOVINGGC:
- */
- sectors_to_move = (sectors_to_move * 3) / 4;
-
- for (i = h->data; i < h->data + h->used; i++)
- sectors_to_move += i->sectors * i->replicas;
+ for (i = h->data; i < h->data + h->used; i++) {
+ sectors_to_move += i->sectors;
+ sectors_to_write += i->sectors * i->replicas;
+ }
- while (sectors_to_move > sectors_reserved) {
+ while (sectors_to_write > sectors_reserved) {
BUG_ON(!heap_pop(h, e, -fragmentation_cmp, NULL));
- sectors_to_move -= e.sectors * e.replicas;
+ sectors_to_write -= e.sectors * e.replicas;
}
buckets_to_move = h->used;
/* When can be set: */
enum opt_mode {
- OPT_FORMAT = (1 << 0),
- OPT_MOUNT = (1 << 1),
- OPT_RUNTIME = (1 << 2),
- OPT_INODE = (1 << 3),
- OPT_DEVICE = (1 << 4),
+ OPT_FS = (1 << 0), /* Filesystem option */
+ OPT_DEVICE = (1 << 1), /* Device option */
+ OPT_INODE = (1 << 2), /* Inode option */
+ OPT_FORMAT = (1 << 3), /* May be specified at format time */
+ OPT_MOUNT = (1 << 4), /* May be specified at mount time */
+ OPT_RUNTIME = (1 << 5), /* May be specified at runtime */
};
enum opt_type {
#define BCH_OPTS() \
x(block_size, u16, \
- OPT_FORMAT, \
+ OPT_FS|OPT_FORMAT, \
OPT_SECTORS(1, 128), \
BCH_SB_BLOCK_SIZE, 8, \
"size", NULL) \
x(btree_node_size, u16, \
- OPT_FORMAT, \
+ OPT_FS|OPT_FORMAT, \
OPT_SECTORS(1, 512), \
BCH_SB_BTREE_NODE_SIZE, 512, \
"size", "Btree node size, default 256k") \
x(errors, u8, \
- OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
+ OPT_FS|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
OPT_STR(bch2_error_actions), \
BCH_SB_ERROR_ACTION, BCH_ON_ERROR_ro, \
NULL, "Action to take on filesystem error") \
x(metadata_replicas, u8, \
- OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
+ OPT_FS|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
OPT_UINT(1, BCH_REPLICAS_MAX), \
BCH_SB_META_REPLICAS_WANT, 1, \
"#", "Number of metadata replicas") \
x(data_replicas, u8, \
- OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME|OPT_INODE, \
+ OPT_FS|OPT_INODE|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
OPT_UINT(1, BCH_REPLICAS_MAX), \
BCH_SB_DATA_REPLICAS_WANT, 1, \
"#", "Number of data replicas") \
x(metadata_replicas_required, u8, \
- OPT_FORMAT|OPT_MOUNT, \
+ OPT_FS|OPT_FORMAT|OPT_MOUNT, \
OPT_UINT(1, BCH_REPLICAS_MAX), \
BCH_SB_META_REPLICAS_REQ, 1, \
"#", NULL) \
x(data_replicas_required, u8, \
- OPT_FORMAT|OPT_MOUNT, \
+ OPT_FS|OPT_FORMAT|OPT_MOUNT, \
OPT_UINT(1, BCH_REPLICAS_MAX), \
BCH_SB_DATA_REPLICAS_REQ, 1, \
"#", NULL) \
x(metadata_checksum, u8, \
- OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
+ OPT_FS|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
OPT_STR(bch2_csum_opts), \
BCH_SB_META_CSUM_TYPE, BCH_CSUM_OPT_crc32c, \
NULL, NULL) \
x(data_checksum, u8, \
- OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME|OPT_INODE, \
+ OPT_FS|OPT_INODE|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
OPT_STR(bch2_csum_opts), \
BCH_SB_DATA_CSUM_TYPE, BCH_CSUM_OPT_crc32c, \
NULL, NULL) \
x(compression, u8, \
- OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME|OPT_INODE, \
+ OPT_FS|OPT_INODE|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
OPT_STR(bch2_compression_opts), \
BCH_SB_COMPRESSION_TYPE, BCH_COMPRESSION_OPT_none, \
NULL, NULL) \
x(background_compression, u8, \
- OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME|OPT_INODE, \
+ OPT_FS|OPT_INODE|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
OPT_STR(bch2_compression_opts), \
BCH_SB_BACKGROUND_COMPRESSION_TYPE,BCH_COMPRESSION_OPT_none, \
NULL, NULL) \
x(str_hash, u8, \
- OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
+ OPT_FS|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
OPT_STR(bch2_str_hash_opts), \
BCH_SB_STR_HASH_TYPE, BCH_STR_HASH_OPT_siphash, \
NULL, "Hash function for directory entries and xattrs")\
x(metadata_target, u16, \
- OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME|OPT_INODE, \
+ OPT_FS|OPT_INODE|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
OPT_FN(bch2_opt_target), \
BCH_SB_METADATA_TARGET, 0, \
"(target)", "Device or disk group for metadata writes") \
x(foreground_target, u16, \
- OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME|OPT_INODE, \
+ OPT_FS|OPT_INODE|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
OPT_FN(bch2_opt_target), \
BCH_SB_FOREGROUND_TARGET, 0, \
"(target)", "Device or disk group for foreground writes") \
x(background_target, u16, \
- OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME|OPT_INODE, \
+ OPT_FS|OPT_INODE|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
OPT_FN(bch2_opt_target), \
BCH_SB_BACKGROUND_TARGET, 0, \
"(target)", "Device or disk group to move data to in the background")\
x(promote_target, u16, \
- OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME|OPT_INODE, \
+ OPT_FS|OPT_INODE|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
OPT_FN(bch2_opt_target), \
BCH_SB_PROMOTE_TARGET, 0, \
"(target)", "Device or disk group to promote data to on read")\
x(erasure_code, u16, \
- OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME|OPT_INODE, \
+ OPT_FS|OPT_INODE|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
OPT_BOOL(), \
BCH_SB_ERASURE_CODE, false, \
NULL, "Enable erasure coding (DO NOT USE YET)") \
x(inodes_32bit, u8, \
- OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
+ OPT_FS|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
OPT_BOOL(), \
BCH_SB_INODE_32BIT, true, \
NULL, "Constrain inode numbers to 32 bits") \
x(shard_inode_numbers, u8, \
- OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
+ OPT_FS|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
OPT_BOOL(), \
BCH_SB_SHARD_INUMS, true, \
NULL, "Shard new inode numbers by CPU id") \
x(inodes_use_key_cache, u8, \
- OPT_FORMAT|OPT_MOUNT, \
+ OPT_FS|OPT_FORMAT|OPT_MOUNT, \
OPT_BOOL(), \
BCH_SB_INODES_USE_KEY_CACHE, true, \
NULL, "Use the btree key cache for the inodes btree") \
x(btree_node_mem_ptr_optimization, u8, \
- OPT_MOUNT|OPT_RUNTIME, \
+ OPT_FS|OPT_MOUNT|OPT_RUNTIME, \
OPT_BOOL(), \
NO_SB_OPT, true, \
NULL, "Stash pointer to in memory btree node in btree ptr")\
x(gc_reserve_percent, u8, \
- OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
+ OPT_FS|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
OPT_UINT(5, 21), \
BCH_SB_GC_RESERVE, 8, \
"%", "Percentage of disk space to reserve for copygc")\
x(gc_reserve_bytes, u64, \
- OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
+ OPT_FS|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
OPT_SECTORS(0, U64_MAX), \
BCH_SB_GC_RESERVE_BYTES, 0, \
"%", "Amount of disk space to reserve for copygc\n" \
"Takes precedence over gc_reserve_percent if set")\
x(root_reserve_percent, u8, \
- OPT_FORMAT|OPT_MOUNT, \
+ OPT_FS|OPT_FORMAT|OPT_MOUNT, \
OPT_UINT(0, 100), \
BCH_SB_ROOT_RESERVE, 0, \
"%", "Percentage of disk space to reserve for superuser")\
x(wide_macs, u8, \
- OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
+ OPT_FS|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
OPT_BOOL(), \
BCH_SB_128_BIT_MACS, false, \
NULL, "Store full 128 bits of cryptographic MACs, instead of 80")\
x(inline_data, u8, \
- OPT_MOUNT|OPT_RUNTIME, \
+ OPT_FS|OPT_MOUNT|OPT_RUNTIME, \
OPT_BOOL(), \
NO_SB_OPT, true, \
NULL, "Enable inline data extents") \
x(acl, u8, \
- OPT_FORMAT|OPT_MOUNT, \
+ OPT_FS|OPT_FORMAT|OPT_MOUNT, \
OPT_BOOL(), \
BCH_SB_POSIX_ACL, true, \
NULL, "Enable POSIX acls") \
x(usrquota, u8, \
- OPT_FORMAT|OPT_MOUNT, \
+ OPT_FS|OPT_FORMAT|OPT_MOUNT, \
OPT_BOOL(), \
BCH_SB_USRQUOTA, false, \
NULL, "Enable user quotas") \
x(grpquota, u8, \
- OPT_FORMAT|OPT_MOUNT, \
+ OPT_FS|OPT_FORMAT|OPT_MOUNT, \
OPT_BOOL(), \
BCH_SB_GRPQUOTA, false, \
NULL, "Enable group quotas") \
x(prjquota, u8, \
- OPT_FORMAT|OPT_MOUNT, \
+ OPT_FS|OPT_FORMAT|OPT_MOUNT, \
OPT_BOOL(), \
BCH_SB_PRJQUOTA, false, \
NULL, "Enable project quotas") \
x(degraded, u8, \
- OPT_MOUNT, \
+ OPT_FS|OPT_MOUNT, \
OPT_BOOL(), \
NO_SB_OPT, false, \
NULL, "Allow mounting in degraded mode") \
x(very_degraded, u8, \
- OPT_MOUNT, \
+ OPT_FS|OPT_MOUNT, \
OPT_BOOL(), \
NO_SB_OPT, false, \
NULL, "Allow mounting in when data will be missing") \
x(discard, u8, \
- OPT_MOUNT|OPT_DEVICE, \
+ OPT_FS|OPT_MOUNT|OPT_DEVICE, \
OPT_BOOL(), \
NO_SB_OPT, false, \
NULL, "Enable discard/TRIM support") \
x(verbose, u8, \
- OPT_MOUNT, \
+ OPT_FS|OPT_MOUNT, \
OPT_BOOL(), \
NO_SB_OPT, false, \
NULL, "Extra debugging information during mount/recovery")\
+ x(journal_flush_delay, u32, \
+ OPT_FS|OPT_MOUNT|OPT_RUNTIME, \
+ OPT_UINT(0, U32_MAX), \
+ BCH_SB_JOURNAL_FLUSH_DELAY, 1000, \
+ NULL, "Delay in milliseconds before automatic journal commits")\
x(journal_flush_disabled, u8, \
- OPT_MOUNT|OPT_RUNTIME, \
+ OPT_FS|OPT_MOUNT|OPT_RUNTIME, \
OPT_BOOL(), \
- NO_SB_OPT, false, \
+ BCH_SB_JOURNAL_FLUSH_DISABLED,false, \
NULL, "Disable journal flush on sync/fsync\n" \
"If enabled, writes can be lost, but only since the\n"\
"last journal write (default 1 second)") \
+ x(journal_reclaim_delay, u32, \
+ OPT_FS|OPT_MOUNT|OPT_RUNTIME, \
+ OPT_UINT(0, U32_MAX), \
+ BCH_SB_JOURNAL_RECLAIM_DELAY, 100, \
+ NULL, "Delay in milliseconds before automatic journal reclaim")\
x(fsck, u8, \
- OPT_MOUNT, \
+ OPT_FS|OPT_MOUNT, \
OPT_BOOL(), \
NO_SB_OPT, false, \
NULL, "Run fsck on mount") \
x(fix_errors, u8, \
- OPT_MOUNT, \
+ OPT_FS|OPT_MOUNT, \
OPT_BOOL(), \
NO_SB_OPT, false, \
NULL, "Fix errors during fsck without asking") \
x(ratelimit_errors, u8, \
- OPT_MOUNT, \
+ OPT_FS|OPT_MOUNT, \
OPT_BOOL(), \
NO_SB_OPT, RATELIMIT_ERRORS, \
NULL, "Ratelimit error messages during fsck") \
x(nochanges, u8, \
- OPT_MOUNT, \
+ OPT_FS|OPT_MOUNT, \
OPT_BOOL(), \
NO_SB_OPT, false, \
NULL, "Super read only mode - no writes at all will be issued,\n"\
"even if we have to replay the journal") \
x(norecovery, u8, \
- OPT_MOUNT, \
+ OPT_FS|OPT_MOUNT, \
OPT_BOOL(), \
NO_SB_OPT, false, \
NULL, "Don't replay the journal") \
x(rebuild_replicas, u8, \
- OPT_MOUNT, \
+ OPT_FS|OPT_MOUNT, \
OPT_BOOL(), \
NO_SB_OPT, false, \
NULL, "Rebuild the superblock replicas section") \
x(keep_journal, u8, \
- OPT_MOUNT, \
+ 0, \
OPT_BOOL(), \
NO_SB_OPT, false, \
NULL, "Don't free journal entries/keys after startup")\
NO_SB_OPT, false, \
NULL, "Read all journal entries, not just dirty ones")\
x(noexcl, u8, \
- OPT_MOUNT, \
+ OPT_FS|OPT_MOUNT, \
OPT_BOOL(), \
NO_SB_OPT, false, \
NULL, "Don't open device in exclusive mode") \
NO_SB_OPT, BCH_SB_SECTOR, \
"offset", "Sector offset of superblock") \
x(read_only, u8, \
- 0, \
+ OPT_FS, \
OPT_BOOL(), \
NO_SB_OPT, false, \
NULL, NULL) \
NO_SB_OPT, false, \
NULL, "Don\'t start filesystem, only open devices") \
x(reconstruct_alloc, u8, \
- OPT_MOUNT, \
+ OPT_FS|OPT_MOUNT, \
OPT_BOOL(), \
NO_SB_OPT, false, \
NULL, "Reconstruct alloc btree") \
x(version_upgrade, u8, \
- OPT_MOUNT, \
+ OPT_FS|OPT_MOUNT, \
OPT_BOOL(), \
NO_SB_OPT, false, \
NULL, "Set superblock to latest version,\n" \
*/
bch_verbose(c, "writing allocation info");
err = "error writing out alloc info";
- ret = bch2_stripes_write(c, BTREE_INSERT_LAZY_RW) ?:
- bch2_alloc_write(c, BTREE_INSERT_LAZY_RW);
+ ret = bch2_alloc_write(c, BTREE_INSERT_LAZY_RW);
if (ret) {
bch_err(c, "error writing alloc info");
goto err;
n = bch2_trans_kmalloc(trans, sizeof(*n));
ret = PTR_ERR_OR_ZERO(n);
if (ret)
- return ret;
+ goto err;
bkey_snapshot_init(&n->k_i);
n->k.p = iter.pos;
n->v.pad = 0;
SET_BCH_SNAPSHOT_SUBVOL(&n->v, true);
- bch2_trans_update(trans, &iter, &n->k_i, 0);
-
- ret = bch2_mark_snapshot(trans, bkey_s_c_null, bkey_i_to_s_c(&n->k_i), 0);
+ ret = bch2_trans_update(trans, &iter, &n->k_i, 0) ?:
+ bch2_mark_snapshot(trans, bkey_s_c_null, bkey_i_to_s_c(&n->k_i), 0);
if (ret)
- break;
+ goto err;
new_snapids[i] = iter.pos.offset;
}
n->v.children[0] = cpu_to_le32(new_snapids[0]);
n->v.children[1] = cpu_to_le32(new_snapids[1]);
SET_BCH_SNAPSHOT_SUBVOL(&n->v, false);
- bch2_trans_update(trans, &iter, &n->k_i, 0);
+ ret = bch2_trans_update(trans, &iter, &n->k_i, 0);
+ if (ret)
+ goto err;
}
err:
bch2_trans_iter_exit(trans, &iter);
if (src_subvolid) {
src_subvol->v.snapshot = cpu_to_le32(new_nodes[1]);
- bch2_trans_update(trans, &src_iter, &src_subvol->k_i, 0);
+ ret = bch2_trans_update(trans, &src_iter, &src_subvol->k_i, 0);
+ if (ret)
+ goto err;
}
new_subvol = bch2_trans_kmalloc(trans, sizeof(*new_subvol));
SET_BCH_SUBVOLUME_RO(&new_subvol->v, ro);
SET_BCH_SUBVOLUME_SNAP(&new_subvol->v, src_subvolid != 0);
new_subvol->k.p = dst_iter.pos;
- bch2_trans_update(trans, &dst_iter, &new_subvol->k_i, 0);
+ ret = bch2_trans_update(trans, &dst_iter, &new_subvol->k_i, 0);
+ if (ret)
+ goto err;
*new_subvolid = new_subvol->k.p.offset;
*new_snapshotid = new_nodes[0];
scnprintf(c->name, sizeof(c->name), "%pU", &c->sb.user_uuid);
+ /* Compat: */
+ if (sb->version <= bcachefs_metadata_version_inode_v2 &&
+ !BCH_SB_JOURNAL_FLUSH_DELAY(sb))
+ SET_BCH_SB_JOURNAL_FLUSH_DELAY(sb, 1000);
+
+ if (sb->version <= bcachefs_metadata_version_inode_v2 &&
+ !BCH_SB_JOURNAL_RECLAIM_DELAY(sb))
+ SET_BCH_SB_JOURNAL_RECLAIM_DELAY(sb, 100);
+
c->opts = bch2_opts_default;
bch2_opts_apply(&c->opts, bch2_opts_from_sb(sb));
bch2_opts_apply(&c->opts, opts);
read_attribute(uuid);
read_attribute(minor);
read_attribute(bucket_size);
-read_attribute(block_size);
-read_attribute(btree_node_size);
read_attribute(first_bucket);
read_attribute(nbuckets);
read_attribute(durability);
read_attribute(extent_migrate_done);
read_attribute(extent_migrate_raced);
-rw_attribute(journal_write_delay_ms);
-rw_attribute(journal_reclaim_delay_ms);
-
rw_attribute(discard);
rw_attribute(cache_replacement_policy);
rw_attribute(label);
sysfs_print(minor, c->minor);
sysfs_printf(internal_uuid, "%pU", c->sb.uuid.b);
- sysfs_print(journal_write_delay_ms, c->journal.write_delay_ms);
- sysfs_print(journal_reclaim_delay_ms, c->journal.reclaim_delay_ms);
-
- sysfs_print(block_size, block_bytes(c));
- sysfs_print(btree_node_size, btree_bytes(c));
sysfs_hprint(btree_cache_size, bch2_btree_cache_size(c));
sysfs_hprint(btree_avg_write_size, bch2_btree_avg_write_size(c));
{
struct bch_fs *c = container_of(kobj, struct bch_fs, kobj);
- sysfs_strtoul(journal_write_delay_ms, c->journal.write_delay_ms);
- sysfs_strtoul(journal_reclaim_delay_ms, c->journal.reclaim_delay_ms);
-
if (attr == &sysfs_btree_gc_periodic) {
ssize_t ret = strtoul_safe(buf, c->btree_gc_periodic)
?: (ssize_t) size;
struct attribute *bch2_fs_files[] = {
&sysfs_minor,
- &sysfs_block_size,
- &sysfs_btree_node_size,
&sysfs_btree_cache_size,
&sysfs_btree_avg_write_size,
- &sysfs_journal_write_delay_ms,
- &sysfs_journal_reclaim_delay_ms,
-
&sysfs_promote_whole_extents,
&sysfs_compression_stats,
for (i = bch2_opt_table;
i < bch2_opt_table + bch2_opts_nr;
i++) {
- if (!(i->mode & (OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME)))
+ if (!(i->mode & OPT_FS))
continue;
ret = sysfs_create_file(kobj, &i->attr);
sysfs_printf(uuid, "%pU\n", ca->uuid.b);
sysfs_print(bucket_size, bucket_bytes(ca));
- 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);
struct attribute *bch2_dev_files[] = {
&sysfs_uuid,
&sysfs_bucket_size,
- &sysfs_block_size,
&sysfs_first_bucket,
&sysfs_nbuckets,
&sysfs_durability,
if (!(i & 3) && k.k) {
bkey_cookie_init(&cookie->k_i);
cookie->k.p = iter->pos;
- bch2_trans_update(trans, iter, &cookie->k_i, 0);
+ ret = bch2_trans_update(trans, iter, &cookie->k_i, 0);
}
- return 0;
+ return ret;
}
static int rand_mixed(struct bch_fs *c, u64 nr)