summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bcachefs_revision2
-rw-r--r--libbcachefs/alloc_foreground.c1
-rw-r--r--libbcachefs/bkey_buf.h6
-rw-r--r--libbcachefs/btree_iter.c10
-rw-r--r--libbcachefs/btree_journal_iter.h2
-rw-r--r--libbcachefs/buckets.c30
-rw-r--r--libbcachefs/buckets_types.h2
-rw-r--r--libbcachefs/data_update.c8
-rw-r--r--libbcachefs/disk_accounting.c36
-rw-r--r--libbcachefs/extents.c12
-rw-r--r--libbcachefs/fs-io-buffered.c13
-rw-r--r--libbcachefs/fs.c8
-rw-r--r--libbcachefs/journal_io.c31
-rw-r--r--libbcachefs/opts.h2
-rw-r--r--libbcachefs/rebalance.c21
-rw-r--r--libbcachefs/sb-counters_format.h3
-rw-r--r--libbcachefs/sb-errors_format.h3
-rw-r--r--libbcachefs/super.c40
-rw-r--r--libbcachefs/sysfs.c1
-rw-r--r--libbcachefs/vstructs.h3
20 files changed, 160 insertions, 74 deletions
diff --git a/.bcachefs_revision b/.bcachefs_revision
index b3f04e2b..d21b55fa 100644
--- a/.bcachefs_revision
+++ b/.bcachefs_revision
@@ -1 +1 @@
-bd062cbcd84d5e7b007561be6e972fcdd283c7aa
+753b29cc79897dd7f776fa09654196f5b25f8b96
diff --git a/libbcachefs/alloc_foreground.c b/libbcachefs/alloc_foreground.c
index 0a5b3d31..f6ea4a82 100644
--- a/libbcachefs/alloc_foreground.c
+++ b/libbcachefs/alloc_foreground.c
@@ -1537,7 +1537,6 @@ void bch2_fs_alloc_debug_to_text(struct printbuf *out, struct bch_fs *c)
prt_printf(out, "cached\t%llu\n", percpu_u64_get(&c->usage->cached));
prt_printf(out, "reserved\t%llu\n", percpu_u64_get(&c->usage->reserved));
prt_printf(out, "online_reserved\t%llu\n", percpu_u64_get(c->online_reserved));
- prt_printf(out, "nr_inodes\t%llu\n", percpu_u64_get(&c->usage->nr_inodes));
prt_newline(out);
prt_printf(out, "freelist_wait\t%s\n", c->freelist_wait.list.first ? "waiting" : "empty");
diff --git a/libbcachefs/bkey_buf.h b/libbcachefs/bkey_buf.h
index 0a1fc582..05a01bf8 100644
--- a/libbcachefs/bkey_buf.h
+++ b/libbcachefs/bkey_buf.h
@@ -29,7 +29,7 @@ static inline int bch2_bkey_buf_reassemble_noprof(struct bkey_buf *s,
struct bch_fs *c,
struct bkey_s_c k)
{
- bch2_bkey_buf_realloc(s, c, k.k->u64s);
+ bch2_bkey_buf_realloc_noprof(s, c, k.k->u64s);
bkey_reassemble(s->k, k);
return 0;
}
@@ -39,7 +39,7 @@ static inline int bch2_bkey_buf_copy_noprof(struct bkey_buf *s,
struct bch_fs *c,
struct bkey_i *src)
{
- bch2_bkey_buf_realloc(s, c, src->k.u64s);
+ bch2_bkey_buf_realloc_noprof(s, c, src->k.u64s);
bkey_copy(s->k, src);
return 0;
}
@@ -50,7 +50,7 @@ static inline int bch2_bkey_buf_unpack_noprof(struct bkey_buf *s,
struct btree *b,
struct bkey_packed *src)
{
- bch2_bkey_buf_realloc(s, c, BKEY_U64s + bkeyp_val_u64s(&b->format, src));
+ bch2_bkey_buf_realloc_noprof(s, c, BKEY_U64s + bkeyp_val_u64s(&b->format, src));
bch2_bkey_unpack(b, s->k, src);
return 0;
}
diff --git a/libbcachefs/btree_iter.c b/libbcachefs/btree_iter.c
index 76f430f9..1e152c67 100644
--- a/libbcachefs/btree_iter.c
+++ b/libbcachefs/btree_iter.c
@@ -3271,9 +3271,10 @@ void *__bch2_trans_kmalloc(struct btree_trans *trans, size_t size, unsigned long
EBUG_ON(trans->mem_bytes);
EBUG_ON(trans->mem_top);
EBUG_ON(new_bytes > BTREE_TRANS_MEM_MAX);
-
+
bool lock_dropped = false;
- new_mem = allocate_dropping_locks_norelock(trans, lock_dropped, kmalloc(new_bytes, _gfp));
+ new_mem = allocate_dropping_locks_norelock(trans, lock_dropped,
+ kmalloc(new_bytes, _gfp|__GFP_NOWARN));
if (!new_mem) {
new_mem = mempool_alloc(&c->btree_trans_mem_pool, GFP_KERNEL);
new_bytes = BTREE_TRANS_MEM_MAX;
@@ -3525,7 +3526,7 @@ got_trans:
if (s->max_mem) {
unsigned expected_mem_bytes = roundup_pow_of_two(s->max_mem);
- trans->mem = kmalloc(expected_mem_bytes, GFP_KERNEL);
+ trans->mem = kmalloc(expected_mem_bytes, GFP_KERNEL|__GFP_NOWARN);
if (likely(trans->mem))
trans->mem_bytes = expected_mem_bytes;
}
@@ -3696,6 +3697,9 @@ void bch2_btree_trans_to_text(struct printbuf *out, struct btree_trans *trans)
prt_printf(out, "%i %s\n", task ? task->pid : 0, trans->fn);
+ if (trans->journal_replay_not_finished)
+ prt_printf(out, "has journal_keys ref\n");
+
/* trans->paths is rcu protected vs. freeing */
guard(rcu)();
guard(printbuf_atomic)(out);
diff --git a/libbcachefs/btree_journal_iter.h b/libbcachefs/btree_journal_iter.h
index 8dc8e778..85d6969f 100644
--- a/libbcachefs/btree_journal_iter.h
+++ b/libbcachefs/btree_journal_iter.h
@@ -31,7 +31,7 @@ struct btree_and_journal_iter {
static inline u32 journal_entry_radix_idx(struct bch_fs *c, u64 seq)
{
- return (seq - c->journal_entries_base_seq) & (~0U >> 1);
+ return seq - c->journal_entries_base_seq;
}
static inline struct bkey_i *journal_key_k(struct bch_fs *c,
diff --git a/libbcachefs/buckets.c b/libbcachefs/buckets.c
index 280b169e..021f5cb7 100644
--- a/libbcachefs/buckets.c
+++ b/libbcachefs/buckets.c
@@ -63,8 +63,6 @@ __bch2_fs_usage_read_short(struct bch_fs *c)
ret.used = min(ret.capacity, data + reserve_factor(reserved));
ret.free = ret.capacity - ret.used;
- ret.nr_inodes = percpu_u64_get(&c->usage->nr_inodes);
-
return ret;
}
@@ -113,14 +111,26 @@ static int bch2_check_fix_ptr(struct btree_trans *trans,
CLASS(bch2_dev_tryget_noerror, ca)(c, p.ptr.dev);
if (!ca) {
- if (fsck_err_on(p.ptr.dev != BCH_SB_MEMBER_INVALID,
- trans, ptr_to_invalid_device,
- "pointer to missing device %u\n"
- "while marking %s",
- p.ptr.dev,
- (printbuf_reset(&buf),
- bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
- *do_update = true;
+ if (p.ptr.dev == BCH_SB_MEMBER_INVALID)
+ return 0;
+
+ if (test_bit(p.ptr.dev, c->devs_removed.d)) {
+ if (fsck_err(trans, ptr_to_removed_device,
+ "pointer to removed device %u\n"
+ "while marking %s",
+ p.ptr.dev,
+ (printbuf_reset(&buf),
+ bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
+ *do_update = true;
+ } else {
+ if (fsck_err(trans, ptr_to_invalid_device,
+ "pointer to missing device %u\n"
+ "while marking %s",
+ p.ptr.dev,
+ (printbuf_reset(&buf),
+ bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
+ *do_update = true;
+ }
return 0;
}
diff --git a/libbcachefs/buckets_types.h b/libbcachefs/buckets_types.h
index 0aed2500..7c726e90 100644
--- a/libbcachefs/buckets_types.h
+++ b/libbcachefs/buckets_types.h
@@ -78,14 +78,12 @@ struct bch_fs_usage_base {
u64 data;
u64 cached;
u64 reserved;
- u64 nr_inodes;
};
struct bch_fs_usage_short {
u64 capacity;
u64 used;
u64 free;
- u64 nr_inodes;
};
/*
diff --git a/libbcachefs/data_update.c b/libbcachefs/data_update.c
index a314d70c..2c997fdd 100644
--- a/libbcachefs/data_update.c
+++ b/libbcachefs/data_update.c
@@ -812,10 +812,14 @@ static int can_write_extent(struct bch_fs *c, struct data_update *m)
break;
}
- if (!nr_replicas) {
+ if (nr_replicas < m->op.nr_replicas) {
+ prt_printf(&buf, "\nnr_replicas %u < %u", nr_replicas, m->op.nr_replicas);
trace_data_update_done_no_rw_devs(c, buf.buf);
- return bch_err_throw(c, data_update_done_no_rw_devs);
}
+
+ if (!nr_replicas)
+ return bch_err_throw(c, data_update_done_no_rw_devs);
+
if (nr_replicas < m->op.nr_replicas)
return bch_err_throw(c, insufficient_devices);
return 0;
diff --git a/libbcachefs/disk_accounting.c b/libbcachefs/disk_accounting.c
index 809c76b6..d6c91abc 100644
--- a/libbcachefs/disk_accounting.c
+++ b/libbcachefs/disk_accounting.c
@@ -11,6 +11,7 @@
#include "disk_accounting.h"
#include "error.h"
#include "journal_io.h"
+#include "recovery_passes.h"
#include "replicas.h"
/*
@@ -910,6 +911,40 @@ int bch2_accounting_read(struct bch_fs *c)
u64 v[BCH_ACCOUNTING_MAX_COUNTERS];
bch2_accounting_mem_read_counters(acc, i, v, ARRAY_SIZE(v), false);
+ /*
+ * Check for underflow, schedule check_allocations
+ * necessary:
+ *
+ * XXX - see if we can factor this out to run on a bkey
+ * so we can check everything lazily, right now we don't
+ * check the non in-mem counters at all
+ */
+ bool underflow = false;
+ for (unsigned j = 0; j < acc->k.data[i].nr_counters; j++)
+ underflow |= (s64) v[j] < 0;
+
+ if (underflow) {
+ CLASS(printbuf, buf)();
+ bch2_log_msg_start(c, &buf);
+
+ prt_printf(&buf, "Accounting underflow for\n");
+ bch2_accounting_key_to_text(&buf, &k);
+
+ for (unsigned j = 0; j < acc->k.data[i].nr_counters; j++)
+ prt_printf(&buf, " %lli", v[j]);
+
+ bool print = bch2_count_fsck_err(c, accounting_key_underflow, &buf);
+ unsigned pos = buf.pos;
+ ret = bch2_run_explicit_recovery_pass(c, &buf,
+ BCH_RECOVERY_PASS_check_allocations, 0);
+ print |= buf.pos != pos;
+
+ if (print)
+ bch2_print_str(c, KERN_ERR, buf.buf);
+ if (ret)
+ return ret;
+ }
+
switch (k.type) {
case BCH_DISK_ACCOUNTING_persistent_reserved:
usage->reserved += v[0] * k.persistent_reserved.nr_replicas;
@@ -1063,7 +1098,6 @@ void bch2_verify_accounting_clean(struct bch_fs *c)
check(data);
check(cached);
check(reserved);
- check(nr_inodes);
WARN_ON(mismatch);
}
diff --git a/libbcachefs/extents.c b/libbcachefs/extents.c
index 7ab03987..68a61f7b 100644
--- a/libbcachefs/extents.c
+++ b/libbcachefs/extents.c
@@ -157,7 +157,7 @@ static inline bool ptr_better(struct bch_fs *c,
const struct extent_ptr_decoded p2,
u64 p2_latency)
{
- struct bch_dev *ca2 = bch2_dev_rcu(c, p2.ptr.dev);
+ struct bch_dev *ca2 = bch2_dev_rcu_noerror(c, p2.ptr.dev);
int failed_delta = dev_failed(ca1) - dev_failed(ca2);
if (unlikely(failed_delta))
@@ -419,7 +419,7 @@ bool bch2_extent_merge(struct bch_fs *c, struct bkey_s l, struct bkey_s_c r)
return false;
/* Extents may not straddle buckets: */
- struct bch_dev *ca = bch2_dev_rcu(c, lp.ptr.dev);
+ struct bch_dev *ca = bch2_dev_rcu_noerror(c, lp.ptr.dev);
bool same_bucket = ca && PTR_BUCKET_NR(ca, &lp.ptr) == PTR_BUCKET_NR(ca, &rp.ptr);
if (!same_bucket)
@@ -815,14 +815,14 @@ static inline unsigned __extent_ptr_durability(struct bch_dev *ca, struct extent
unsigned bch2_extent_ptr_desired_durability(struct bch_fs *c, struct extent_ptr_decoded *p)
{
- struct bch_dev *ca = bch2_dev_rcu(c, p->ptr.dev);
+ struct bch_dev *ca = bch2_dev_rcu_noerror(c, p->ptr.dev);
return ca ? __extent_ptr_durability(ca, p) : 0;
}
unsigned bch2_extent_ptr_durability(struct bch_fs *c, struct extent_ptr_decoded *p)
{
- struct bch_dev *ca = bch2_dev_rcu(c, p->ptr.dev);
+ struct bch_dev *ca = bch2_dev_rcu_noerror(c, p->ptr.dev);
if (!ca || ca->mi.state == BCH_MEMBER_STATE_failed)
return 0;
@@ -1044,7 +1044,7 @@ bool bch2_bkey_has_target(struct bch_fs *c, struct bkey_s_c k, unsigned target)
guard(rcu)();
bkey_for_each_ptr(ptrs, ptr)
if (bch2_dev_in_target(c, ptr->dev, target) &&
- (ca = bch2_dev_rcu(c, ptr->dev)) &&
+ (ca = bch2_dev_rcu_noerror(c, ptr->dev)) &&
(!ptr->cached ||
!dev_ptr_stale_rcu(ca, ptr)))
return true;
@@ -1228,7 +1228,7 @@ bool bch2_extent_normalize(struct bch_fs *c, struct bkey_s k)
guard(rcu)();
bch2_bkey_drop_ptrs(k, ptr,
ptr->cached &&
- (!(ca = bch2_dev_rcu(c, ptr->dev)) ||
+ (!(ca = bch2_dev_rcu_noerror(c, ptr->dev)) ||
dev_ptr_stale_rcu(ca, ptr) > 0));
return bkey_deleted(k.k);
diff --git a/libbcachefs/fs-io-buffered.c b/libbcachefs/fs-io-buffered.c
index fd8beb51..9532f1a7 100644
--- a/libbcachefs/fs-io-buffered.c
+++ b/libbcachefs/fs-io-buffered.c
@@ -667,6 +667,17 @@ do_io:
return 0;
}
+static int bch2_write_cache_pages(struct address_space *mapping,
+ struct writeback_control *wbc, void *data)
+{
+ struct folio *folio = NULL;
+ int error;
+
+ while ((folio = writeback_iter(mapping, wbc, folio, &error)))
+ error = __bch2_writepage(folio, wbc, data);
+ return error;
+}
+
int bch2_writepages(struct address_space *mapping, struct writeback_control *wbc)
{
struct bch_fs *c = mapping->host->i_sb->s_fs_info;
@@ -675,7 +686,7 @@ int bch2_writepages(struct address_space *mapping, struct writeback_control *wbc
bch2_inode_opts_get(&w->opts, c, &to_bch_ei(mapping->host)->ei_inode);
blk_start_plug(&w->plug);
- int ret = write_cache_pages(mapping, wbc, __bch2_writepage, w);
+ int ret = bch2_write_cache_pages(mapping, wbc, w);
if (w->io)
bch2_writepage_do_io(w);
blk_finish_plug(&w->plug);
diff --git a/libbcachefs/fs.c b/libbcachefs/fs.c
index 0425238a..39ebcab1 100644
--- a/libbcachefs/fs.c
+++ b/libbcachefs/fs.c
@@ -8,6 +8,7 @@
#include "buckets.h"
#include "chardev.h"
#include "dirent.h"
+#include "disk_accounting.h"
#include "errcode.h"
#include "extents.h"
#include "fs.h"
@@ -2247,7 +2248,12 @@ static int bch2_statfs(struct dentry *dentry, struct kstatfs *buf)
buf->f_bfree = usage.free >> shift;
buf->f_bavail = avail_factor(usage.free) >> shift;
- buf->f_files = usage.nr_inodes + avail_inodes;
+ u64 nr_inodes = 0;
+ struct disk_accounting_pos k;
+ disk_accounting_key_init(k, nr_inodes);
+ bch2_accounting_mem_read(c, disk_accounting_pos_to_bpos(&k), &nr_inodes, 1);
+
+ buf->f_files = nr_inodes + avail_inodes;
buf->f_ffree = avail_inodes;
buf->f_fsid = uuid_to_fsid(c->sb.user_uuid.b);
diff --git a/libbcachefs/journal_io.c b/libbcachefs/journal_io.c
index c5458c61..0a9fbc76 100644
--- a/libbcachefs/journal_io.c
+++ b/libbcachefs/journal_io.c
@@ -152,6 +152,7 @@ static int journal_entry_add(struct bch_fs *c, struct bch_dev *ca,
struct journal_replay **_i, *i, *dup;
size_t bytes = vstruct_bytes(j);
u64 last_seq = !JSET_NO_FLUSH(j) ? le64_to_cpu(j->last_seq) : 0;
+ u64 seq = le64_to_cpu(j->seq);
CLASS(printbuf, buf)();
int ret = JOURNAL_ENTRY_ADD_OK;
@@ -159,12 +160,11 @@ static int journal_entry_add(struct bch_fs *c, struct bch_dev *ca,
last_seq = min(last_seq, c->opts.journal_rewind);
if (!c->journal.oldest_seq_found_ondisk ||
- le64_to_cpu(j->seq) < c->journal.oldest_seq_found_ondisk)
- c->journal.oldest_seq_found_ondisk = le64_to_cpu(j->seq);
+ seq < c->journal.oldest_seq_found_ondisk)
+ c->journal.oldest_seq_found_ondisk = seq;
/* Is this entry older than the range we need? */
- if (!c->opts.read_entire_journal &&
- le64_to_cpu(j->seq) < jlist->last_seq)
+ if (!c->opts.read_entire_journal && seq < jlist->last_seq)
return JOURNAL_ENTRY_ADD_OUT_OF_RANGE;
/*
@@ -173,7 +173,7 @@ static int journal_entry_add(struct bch_fs *c, struct bch_dev *ca,
* within the range of +-2billion of the filrst one we find.
*/
if (!c->journal_entries_base_seq)
- c->journal_entries_base_seq = max_t(s64, 1, le64_to_cpu(j->seq) - S32_MAX);
+ c->journal_entries_base_seq = max_t(s64, 1, seq - S32_MAX);
/* Drop entries we don't need anymore */
if (last_seq > jlist->last_seq && !c->opts.read_entire_journal) {
@@ -194,25 +194,33 @@ static int journal_entry_add(struct bch_fs *c, struct bch_dev *ca,
/* Drop overwrites, log entries if we don't need them: */
if (!c->opts.retain_recovery_info &&
!c->opts.journal_rewind) {
+ vstruct_for_each_safe(j, src)
+ if (vstruct_end(src) > vstruct_end(j))
+ goto nocompact;
+
struct jset_entry *dst = j->start;
vstruct_for_each_safe(j, src) {
if (src->type == BCH_JSET_ENTRY_log ||
src->type == BCH_JSET_ENTRY_overwrite)
continue;
- memcpy(dst, src, vstruct_bytes(src));
+ memmove_u64s_down(dst, src, vstruct_u64s(src));
dst = vstruct_next(dst);
}
j->u64s = cpu_to_le32((u64 *) dst - j->_data);
bytes = vstruct_bytes(j);
}
-
+nocompact:
jlist->last_seq = max(jlist->last_seq, last_seq);
- _i = genradix_ptr_alloc(&c->journal_entries,
- journal_entry_radix_idx(c, le64_to_cpu(j->seq)),
- GFP_KERNEL);
+ if (seq < c->journal_entries_base_seq ||
+ seq >= c->journal_entries_base_seq + U32_MAX) {
+ bch_err(c, "journal entry sequence numbers span too large a range: cannot reply, contact developers");
+ return bch_err_throw(c, ENOMEM_journal_entry_add);
+ }
+
+ _i = genradix_ptr_alloc(&c->journal_entries, journal_entry_radix_idx(c, seq), GFP_KERNEL);
if (!_i)
return bch_err_throw(c, ENOMEM_journal_entry_add);
@@ -222,8 +230,6 @@ static int journal_entry_add(struct bch_fs *c, struct bch_dev *ca,
*/
dup = *_i;
if (dup) {
- BUG_ON(dup->j.seq != j->seq);
-
bool identical = bytes == vstruct_bytes(&dup->j) &&
!memcmp(j, &dup->j, bytes);
bool not_identical = !identical &&
@@ -254,7 +260,6 @@ static int journal_entry_add(struct bch_fs *c, struct bch_dev *ca,
if (entry_ptr.csum_good && !identical)
goto replace;
- BUG_ON(dup->j.seq != j->seq);
return ret;
}
replace:
diff --git a/libbcachefs/opts.h b/libbcachefs/opts.h
index 31a3abcb..f8828f46 100644
--- a/libbcachefs/opts.h
+++ b/libbcachefs/opts.h
@@ -539,7 +539,7 @@ enum fsck_err_opts {
"n", "Data written to this device will be considered\n"\
"to have already been replicated n times") \
x(data_allowed, u8, \
- OPT_DEVICE, \
+ OPT_DEVICE|OPT_FORMAT, \
OPT_BITFIELD(__bch2_data_types), \
BCH_MEMBER_DATA_ALLOWED, BIT(BCH_DATA_journal)|BIT(BCH_DATA_btree)|BIT(BCH_DATA_user),\
"types", "Allowed data types for this device: journal, btree, and/or user")\
diff --git a/libbcachefs/rebalance.c b/libbcachefs/rebalance.c
index e1db63d7..25bf72dc 100644
--- a/libbcachefs/rebalance.c
+++ b/libbcachefs/rebalance.c
@@ -421,6 +421,7 @@ static struct bkey_s_c next_rebalance_extent(struct btree_trans *trans,
trace_rebalance_extent(c, buf.buf);
}
+ count_event(c, rebalance_extent);
return k;
}
@@ -478,11 +479,12 @@ out:
return ret;
}
-static int do_rebalance_scan(struct moving_context *ctxt, u64 inum, u64 cookie)
+static int do_rebalance_scan(struct moving_context *ctxt,
+ u64 inum, u64 cookie, u64 *sectors_scanned)
{
struct btree_trans *trans = ctxt->trans;
struct bch_fs *c = trans->c;
- struct bch_fs_rebalance *r = &trans->c->rebalance;
+ struct bch_fs_rebalance *r = &c->rebalance;
bch2_move_stats_init(&r->scan_stats, "rebalance_scan");
ctxt->stats = &r->scan_stats;
@@ -514,14 +516,16 @@ static int do_rebalance_scan(struct moving_context *ctxt, u64 inum, u64 cookie)
bch2_clear_rebalance_needs_scan(trans, inum, cookie));
per_snapshot_io_opts_exit(&snapshot_io_opts);
- bch2_move_stats_exit(&r->scan_stats, trans->c);
+ *sectors_scanned += atomic64_read(&r->scan_stats.sectors_seen);
+ bch2_move_stats_exit(&r->scan_stats, c);
/*
* Ensure that the rebalance_work entries we created are seen by the
* next iteration of do_rebalance(), so we don't end up stuck in
* rebalance_wait():
*/
- atomic64_inc(&r->scan_stats.sectors_seen);
+ *sectors_scanned += 1;
+
bch2_btree_write_buffer_flush_sync(trans);
return ret;
@@ -561,6 +565,7 @@ static int do_rebalance(struct moving_context *ctxt)
struct bch_fs *c = trans->c;
struct bch_fs_rebalance *r = &c->rebalance;
struct btree_iter extent_iter = {};
+ u64 sectors_scanned = 0;
u32 kick = r->kick;
struct bpos work_pos = POS_MIN;
@@ -570,7 +575,6 @@ static int do_rebalance(struct moving_context *ctxt)
return ret;
bch2_move_stats_init(&r->work_stats, "rebalance_work");
- bch2_move_stats_init(&r->scan_stats, "rebalance_scan");
while (!bch2_move_ratelimit(ctxt)) {
if (!bch2_rebalance_enabled(c)) {
@@ -587,19 +591,20 @@ static int do_rebalance(struct moving_context *ctxt)
ret = k->k.type == KEY_TYPE_cookie
? do_rebalance_scan(ctxt, k->k.p.inode,
- le64_to_cpu(bkey_i_to_cookie(k)->v.cookie))
+ le64_to_cpu(bkey_i_to_cookie(k)->v.cookie),
+ &sectors_scanned)
: do_rebalance_extent(ctxt, k->k.p, &extent_iter);
if (ret)
break;
}
bch2_trans_iter_exit(&extent_iter);
- bch2_move_stats_exit(&r->scan_stats, c);
+ bch2_move_stats_exit(&r->work_stats, c);
if (!ret &&
!kthread_should_stop() &&
!atomic64_read(&r->work_stats.sectors_seen) &&
- !atomic64_read(&r->scan_stats.sectors_seen) &&
+ !sectors_scanned &&
kick == r->kick) {
bch2_moving_ctxt_flush_all(ctxt);
bch2_trans_unlock_long(trans);
diff --git a/libbcachefs/sb-counters_format.h b/libbcachefs/sb-counters_format.h
index 96ad6492..17cd6176 100644
--- a/libbcachefs/sb-counters_format.h
+++ b/libbcachefs/sb-counters_format.h
@@ -35,6 +35,7 @@ enum counters_flags {
x(io_move_noop, 92, TYPE_COUNTER) \
x(io_move_created_rebalance, 83, TYPE_COUNTER) \
x(io_move_evacuate_bucket, 84, TYPE_COUNTER) \
+ x(rebalance_extent, 96, TYPE_COUNTER) \
x(bucket_invalidate, 3, TYPE_COUNTER) \
x(bucket_discard, 4, TYPE_COUNTER) \
x(bucket_discard_fast, 79, TYPE_COUNTER) \
@@ -127,7 +128,7 @@ struct bch_sb_field_counters {
static inline void __maybe_unused check_bch_counter_ids_unique(void) {
switch(0){
#define x(t, n, ...) case (n):
- BCH_PERSISTENT_COUNTERS()
+ BCH_PERSISTENT_COUNTERS();
#undef x
;
}
diff --git a/libbcachefs/sb-errors_format.h b/libbcachefs/sb-errors_format.h
index 5317b1bf..aa0ea1ec 100644
--- a/libbcachefs/sb-errors_format.h
+++ b/libbcachefs/sb-errors_format.h
@@ -328,6 +328,7 @@ enum bch_fsck_flags {
x(accounting_key_replicas_devs_unsorted, 280, FSCK_AUTOFIX) \
x(accounting_key_version_0, 282, FSCK_AUTOFIX) \
x(accounting_key_nr_counters_wrong, 307, FSCK_AUTOFIX) \
+ x(accounting_key_underflow, 325, FSCK_AUTOFIX) \
x(logged_op_but_clean, 283, FSCK_AUTOFIX) \
x(compression_opt_not_marked_in_sb, 295, FSCK_AUTOFIX) \
x(compression_type_not_marked_in_sb, 296, FSCK_AUTOFIX) \
@@ -336,7 +337,7 @@ enum bch_fsck_flags {
x(dirent_stray_data_after_cf_name, 305, 0) \
x(rebalance_work_incorrectly_set, 309, FSCK_AUTOFIX) \
x(rebalance_work_incorrectly_unset, 310, FSCK_AUTOFIX) \
- x(MAX, 325, 0)
+ x(MAX, 326, 0)
enum bch_sb_error_id {
#define x(t, n, ...) BCH_FSCK_ERR_##t = n,
diff --git a/libbcachefs/super.c b/libbcachefs/super.c
index cc9d00e1..793c16fa 100644
--- a/libbcachefs/super.c
+++ b/libbcachefs/super.c
@@ -237,6 +237,7 @@ static int bch2_dev_alloc(struct bch_fs *, unsigned);
static int bch2_dev_sysfs_online(struct bch_fs *, struct bch_dev *);
static void bch2_dev_io_ref_stop(struct bch_dev *, int);
static void __bch2_dev_read_only(struct bch_fs *, struct bch_dev *);
+static int bch2_dev_attach_bdev(struct bch_fs *, struct bch_sb_handle *, struct printbuf *);
struct bch_fs *bch2_dev_to_fs(dev_t dev)
{
@@ -988,11 +989,7 @@ static int bch2_fs_opt_version_init(struct bch_fs *c)
}
}
- if (c->cf_encoding)
- prt_printf(&p, "\nUsing encoding defined by superblock: utf8-%u.%u.%u",
- unicode_major(BCH_FS_DEFAULT_UTF8_ENCODING),
- unicode_minor(BCH_FS_DEFAULT_UTF8_ENCODING),
- unicode_rev(BCH_FS_DEFAULT_UTF8_ENCODING));
+ /* cf_encoding log message should be here, but it breaks xfstests - sigh */
if (c->opts.journal_rewind)
prt_printf(&p, "\nrewinding journal, fsck required");
@@ -1008,8 +1005,9 @@ static int bch2_fs_opt_version_init(struct bch_fs *c)
return ret;
__le64 now = cpu_to_le64(ktime_get_real_seconds());
- for_each_online_member_rcu(c, ca)
- bch2_members_v2_get_mut(c->disk_sb.sb, ca->dev_idx)->last_mount = now;
+ scoped_guard(rcu)
+ for_each_online_member_rcu(c, ca)
+ bch2_members_v2_get_mut(c->disk_sb.sb, ca->dev_idx)->last_mount = now;
if (BCH_SB_HAS_TOPOLOGY_ERRORS(c->disk_sb.sb))
ext->recovery_passes_required[0] |=
@@ -1060,6 +1058,14 @@ static int bch2_fs_opt_version_init(struct bch_fs *c)
bch2_print_str(c, KERN_INFO, p.buf);
+ /* this really should be part of our one multi line mount message, but -
+ * xfstests... */
+ if (c->cf_encoding)
+ bch_info(c, "Using encoding defined by superblock: utf8-%u.%u.%u",
+ unicode_major(BCH_FS_DEFAULT_UTF8_ENCODING),
+ unicode_minor(BCH_FS_DEFAULT_UTF8_ENCODING),
+ unicode_rev(BCH_FS_DEFAULT_UTF8_ENCODING));
+
if (BCH_SB_INITIALIZED(c->disk_sb.sb)) {
if (!(c->sb.features & (1ULL << BCH_FEATURE_new_extent_overwrite))) {
bch_err(c, "feature new_extent_overwrite not set, filesystem no longer supported");
@@ -1313,6 +1319,16 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts *opts,
&c->clock_journal_res,
(sizeof(struct jset_entry_clock) / sizeof(u64)) * 2);
+ scoped_guard(rwsem_write, &c->state_lock)
+ darray_for_each(*sbs, sb) {
+ CLASS(printbuf, err)();
+ ret = bch2_dev_attach_bdev(c, sb, &err);
+ if (ret) {
+ bch_err(bch2_dev_locked(c, sb->sb->dev_idx), "%s", err.buf);
+ goto err;
+ }
+ }
+
ret = bch2_fs_opt_version_init(c);
if (ret)
goto err;
@@ -2604,16 +2620,6 @@ struct bch_fs *bch2_fs_open(darray_const_str *devices,
if (ret)
goto err;
- scoped_guard(rwsem_write, &c->state_lock)
- darray_for_each(sbs, sb) {
- CLASS(printbuf, err)();
- ret = bch2_dev_attach_bdev(c, sb, &err);
- if (ret) {
- bch_err(bch2_dev_locked(c, sb->sb->dev_idx), "%s", err.buf);
- goto err;
- }
- }
-
if (!c->opts.nostart) {
ret = bch2_fs_start(c);
if (ret)
diff --git a/libbcachefs/sysfs.c b/libbcachefs/sysfs.c
index bd3fa9c3..6b071dcc 100644
--- a/libbcachefs/sysfs.c
+++ b/libbcachefs/sysfs.c
@@ -304,7 +304,6 @@ static void bch2_fs_usage_base_to_text(struct printbuf *out, struct bch_fs *c)
prt_printf(out, "data:\t\t%llu\n", b.data);
prt_printf(out, "cached:\t%llu\n", b.cached);
prt_printf(out, "reserved:\t\t%llu\n", b.reserved);
- prt_printf(out, "nr_inodes:\t%llu\n", b.nr_inodes);
}
static int bch2_read_fua_test(struct printbuf *out, struct bch_dev *ca)
diff --git a/libbcachefs/vstructs.h b/libbcachefs/vstructs.h
index 2ad338e2..446770ec 100644
--- a/libbcachefs/vstructs.h
+++ b/libbcachefs/vstructs.h
@@ -23,6 +23,9 @@
(size_t) (offsetof(_type, _data) + (_u64s) * sizeof(u64)); \
})
+#define vstruct_u64s(_s) \
+ (offsetof(typeof(*(_s)), _data) / sizeof(u64) + __vstruct_u64s(_s))
+
#define vstruct_bytes(_s) \
__vstruct_bytes(typeof(*(_s)), __vstruct_u64s(_s))