Skip to content

Commit d21262d

Browse files
author
Kent Overstreet
committed
bcachefs: bch2_dev_journal_bucket_delete()
Recover from "journal and btree in same bucket". Signed-off-by: Kent Overstreet <[email protected]>
1 parent 0224d17 commit d21262d

File tree

4 files changed

+82
-5
lines changed

4 files changed

+82
-5
lines changed

fs/bcachefs/buckets.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,20 @@ static int bch2_check_fix_ptr(struct btree_trans *trans,
221221
bch2_bkey_val_to_text(&buf, c, k), buf.buf))) {
222222
if (!p.ptr.cached &&
223223
data_type == BCH_DATA_btree) {
224+
switch (g->data_type) {
225+
case BCH_DATA_sb:
226+
bch_err(c, "btree and superblock in the same bucket - cannot repair");
227+
ret = -BCH_ERR_fsck_repair_unimplemented;
228+
goto out;
229+
case BCH_DATA_journal:
230+
ret = bch2_dev_journal_bucket_delete(ca, PTR_BUCKET_NR(ca, &p.ptr));
231+
bch_err_msg(c, ret, "error deleting journal bucket %zu",
232+
PTR_BUCKET_NR(ca, &p.ptr));
233+
if (ret)
234+
goto out;
235+
break;
236+
}
237+
224238
g->data_type = data_type;
225239
g->stripe_sectors = 0;
226240
g->dirty_sectors = 0;

fs/bcachefs/journal.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,6 +1304,66 @@ int bch2_set_nr_journal_buckets(struct bch_fs *c, struct bch_dev *ca,
13041304
return ret;
13051305
}
13061306

1307+
int bch2_dev_journal_bucket_delete(struct bch_dev *ca, u64 b)
1308+
{
1309+
struct bch_fs *c = ca->fs;
1310+
struct journal *j = &c->journal;
1311+
struct journal_device *ja = &ca->journal;
1312+
1313+
guard(mutex)(&c->sb_lock);
1314+
unsigned pos;
1315+
for (pos = 0; pos < ja->nr; pos++)
1316+
if (ja->buckets[pos] == b)
1317+
break;
1318+
1319+
if (pos == ja->nr) {
1320+
bch_err(ca, "journal bucket %llu not found when deleting", b);
1321+
return -EINVAL;
1322+
}
1323+
1324+
u64 *new_buckets = kcalloc(ja->nr, sizeof(u64), GFP_KERNEL);;
1325+
if (!new_buckets)
1326+
return -BCH_ERR_ENOMEM_set_nr_journal_buckets;
1327+
1328+
memcpy(new_buckets, ja->buckets, ja->nr * sizeof(u64));
1329+
memmove(&new_buckets[pos],
1330+
&new_buckets[pos + 1],
1331+
(ja->nr - 1 - pos) * sizeof(new_buckets[0]));
1332+
1333+
int ret = bch2_journal_buckets_to_sb(c, ca, ja->buckets, ja->nr - 1) ?:
1334+
bch2_write_super(c);
1335+
if (ret) {
1336+
kfree(new_buckets);
1337+
return ret;
1338+
}
1339+
1340+
scoped_guard(spinlock, &j->lock) {
1341+
if (pos < ja->discard_idx)
1342+
--ja->discard_idx;
1343+
if (pos < ja->dirty_idx_ondisk)
1344+
--ja->dirty_idx_ondisk;
1345+
if (pos < ja->dirty_idx)
1346+
--ja->dirty_idx;
1347+
if (pos < ja->cur_idx)
1348+
--ja->cur_idx;
1349+
1350+
ja->nr--;
1351+
1352+
memmove(&ja->buckets[pos],
1353+
&ja->buckets[pos + 1],
1354+
(ja->nr - pos) * sizeof(ja->buckets[0]));
1355+
1356+
memmove(&ja->bucket_seq[pos],
1357+
&ja->bucket_seq[pos + 1],
1358+
(ja->nr - pos) * sizeof(ja->bucket_seq[0]));
1359+
1360+
bch2_journal_space_available(j);
1361+
}
1362+
1363+
kfree(new_buckets);
1364+
return 0;
1365+
}
1366+
13071367
int bch2_dev_journal_alloc(struct bch_dev *ca, bool new_fs)
13081368
{
13091369
struct bch_fs *c = ca->fs;

fs/bcachefs/journal.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -444,8 +444,9 @@ struct journal_buf *bch2_next_write_buffer_flush_journal_buf(struct journal *, u
444444
void __bch2_journal_debug_to_text(struct printbuf *, struct journal *);
445445
void bch2_journal_debug_to_text(struct printbuf *, struct journal *);
446446

447-
int bch2_set_nr_journal_buckets(struct bch_fs *, struct bch_dev *,
448-
unsigned nr);
447+
int bch2_set_nr_journal_buckets(struct bch_fs *, struct bch_dev *, unsigned);
448+
int bch2_dev_journal_bucket_delete(struct bch_dev *, u64);
449+
449450
int bch2_dev_journal_alloc(struct bch_dev *, bool);
450451
int bch2_fs_journal_alloc(struct bch_fs *);
451452

fs/bcachefs/str_hash.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,8 @@ int __bch2_str_hash_check_key(struct btree_trans *trans,
239239

240240
for_each_btree_key_norestart(trans, iter, desc->btree_id,
241241
SPOS(hash_k.k->p.inode, hash, hash_k.k->p.snapshot),
242-
BTREE_ITER_slots, k, ret) {
242+
BTREE_ITER_slots|
243+
BTREE_ITER_with_updates, k, ret) {
243244
if (bkey_eq(k.k->p, hash_k.k->p))
244245
break;
245246

@@ -286,10 +287,11 @@ int __bch2_str_hash_check_key(struct btree_trans *trans,
286287
goto duplicate_entries;
287288

288289
ret = bch2_hash_delete_at(trans, *desc, hash_info, k_iter,
290+
BTREE_ITER_with_updates|
289291
BTREE_UPDATE_internal_snapshot_node) ?:
290292
bch2_fsck_update_backpointers(trans, s, *desc, hash_info, new) ?:
291293
bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc) ?:
292-
-BCH_ERR_transaction_restart_nested;
294+
-BCH_ERR_transaction_restart_commit;
293295
goto out;
294296
}
295297
fsck_err:
@@ -323,6 +325,6 @@ int __bch2_str_hash_check_key(struct btree_trans *trans,
323325
}
324326

325327
ret = bch2_trans_commit(trans, NULL, NULL, 0) ?:
326-
-BCH_ERR_transaction_restart_nested;
328+
-BCH_ERR_transaction_restart_commit;
327329
goto out;
328330
}

0 commit comments

Comments
 (0)