Skip to content

Commit dcffc3b

Browse files
author
Kent Overstreet
committed
bcachefs: Split up bch_dev.io_ref
We now have separate per device io_refs for read and write access. This fixes a device removal bug where the discard workers were still running while we're removing alloc info for that device. It's also a bit of hardening; we no longer allow writes to devices that are read-only. Signed-off-by: Kent Overstreet <[email protected]>
1 parent f1350c2 commit dcffc3b

19 files changed

+142
-87
lines changed

fs/bcachefs/alloc_background.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1950,7 +1950,7 @@ static void bch2_do_discards_work(struct work_struct *work)
19501950
trace_discard_buckets(c, s.seen, s.open, s.need_journal_commit, s.discarded,
19511951
bch2_err_str(ret));
19521952

1953-
percpu_ref_put(&ca->io_ref);
1953+
percpu_ref_put(&ca->io_ref[WRITE]);
19541954
bch2_write_ref_put(c, BCH_WRITE_REF_discard);
19551955
}
19561956

@@ -1967,7 +1967,7 @@ void bch2_dev_do_discards(struct bch_dev *ca)
19671967
if (queue_work(c->write_ref_wq, &ca->discard_work))
19681968
return;
19691969

1970-
percpu_ref_put(&ca->io_ref);
1970+
percpu_ref_put(&ca->io_ref[WRITE]);
19711971
put_write_ref:
19721972
bch2_write_ref_put(c, BCH_WRITE_REF_discard);
19731973
}
@@ -2045,7 +2045,7 @@ static void bch2_do_discards_fast_work(struct work_struct *work)
20452045
trace_discard_buckets_fast(c, s.seen, s.open, s.need_journal_commit, s.discarded, bch2_err_str(ret));
20462046

20472047
bch2_trans_put(trans);
2048-
percpu_ref_put(&ca->io_ref);
2048+
percpu_ref_put(&ca->io_ref[WRITE]);
20492049
bch2_write_ref_put(c, BCH_WRITE_REF_discard_fast);
20502050
}
20512051

@@ -2065,7 +2065,7 @@ static void bch2_discard_one_bucket_fast(struct bch_dev *ca, u64 bucket)
20652065
if (queue_work(c->write_ref_wq, &ca->discard_fast_work))
20662066
return;
20672067

2068-
percpu_ref_put(&ca->io_ref);
2068+
percpu_ref_put(&ca->io_ref[WRITE]);
20692069
put_ref:
20702070
bch2_write_ref_put(c, BCH_WRITE_REF_discard_fast);
20712071
}
@@ -2256,7 +2256,7 @@ static void bch2_do_invalidates_work(struct work_struct *work)
22562256
bch2_trans_iter_exit(trans, &iter);
22572257
err:
22582258
bch2_trans_put(trans);
2259-
percpu_ref_put(&ca->io_ref);
2259+
percpu_ref_put(&ca->io_ref[WRITE]);
22602260
bch2_bkey_buf_exit(&last_flushed, c);
22612261
bch2_write_ref_put(c, BCH_WRITE_REF_invalidate);
22622262
}
@@ -2274,7 +2274,7 @@ void bch2_dev_do_invalidates(struct bch_dev *ca)
22742274
if (queue_work(c->write_ref_wq, &ca->invalidate_work))
22752275
return;
22762276

2277-
percpu_ref_put(&ca->io_ref);
2277+
percpu_ref_put(&ca->io_ref[WRITE]);
22782278
put_ref:
22792279
bch2_write_ref_put(c, BCH_WRITE_REF_invalidate);
22802280
}
@@ -2506,7 +2506,7 @@ void bch2_recalc_capacity(struct bch_fs *c)
25062506

25072507
bch2_set_ra_pages(c, ra_pages);
25082508

2509-
for_each_rw_member(c, ca) {
2509+
__for_each_online_member(c, ca, BIT(BCH_MEMBER_STATE_rw), READ) {
25102510
u64 dev_reserve = 0;
25112511

25122512
/*

fs/bcachefs/backpointers.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ static int check_extent_checksum(struct btree_trans *trans,
462462
if (bio)
463463
bio_put(bio);
464464
kvfree(data_buf);
465-
percpu_ref_put(&ca->io_ref);
465+
percpu_ref_put(&ca->io_ref[READ]);
466466
printbuf_exit(&buf);
467467
return ret;
468468
}

fs/bcachefs/bcachefs.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -524,8 +524,8 @@ struct bch_dev {
524524
struct percpu_ref ref;
525525
#endif
526526
struct completion ref_completion;
527-
struct percpu_ref io_ref;
528-
struct completion io_ref_completion;
527+
struct percpu_ref io_ref[2];
528+
struct completion io_ref_completion[2];
529529

530530
struct bch_fs *fs;
531531

fs/bcachefs/btree_io.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,7 +1353,7 @@ static void btree_node_read_work(struct work_struct *work)
13531353
"btree read error %s for %s",
13541354
bch2_blk_status_to_str(bio->bi_status), buf.buf);
13551355
if (rb->have_ioref)
1356-
percpu_ref_put(&ca->io_ref);
1356+
percpu_ref_put(&ca->io_ref[READ]);
13571357
rb->have_ioref = false;
13581358

13591359
bch2_mark_io_failure(&failed, &rb->pick, false);
@@ -1609,7 +1609,7 @@ static void btree_node_read_all_replicas_endio(struct bio *bio)
16091609
struct bch_dev *ca = bch2_dev_have_ref(c, rb->pick.ptr.dev);
16101610

16111611
bch2_latency_acct(ca, rb->start_time, READ);
1612-
percpu_ref_put(&ca->io_ref);
1612+
percpu_ref_put(&ca->io_ref[READ]);
16131613
}
16141614

16151615
ra->err[rb->idx] = bio->bi_status;
@@ -1928,7 +1928,7 @@ static void btree_node_scrub_work(struct work_struct *work)
19281928
printbuf_exit(&err);
19291929
bch2_bkey_buf_exit(&scrub->key, c);;
19301930
btree_bounce_free(c, c->opts.btree_node_size, scrub->used_mempool, scrub->buf);
1931-
percpu_ref_put(&scrub->ca->io_ref);
1931+
percpu_ref_put(&scrub->ca->io_ref[READ]);
19321932
kfree(scrub);
19331933
bch2_write_ref_put(c, BCH_WRITE_REF_btree_node_scrub);
19341934
}
@@ -1997,7 +1997,7 @@ int bch2_btree_node_scrub(struct btree_trans *trans,
19971997
return 0;
19981998
err_free:
19991999
btree_bounce_free(c, c->opts.btree_node_size, used_mempool, buf);
2000-
percpu_ref_put(&ca->io_ref);
2000+
percpu_ref_put(&ca->io_ref[READ]);
20012001
err:
20022002
bch2_write_ref_put(c, BCH_WRITE_REF_btree_node_scrub);
20032003
return ret;
@@ -2159,8 +2159,12 @@ static void btree_node_write_endio(struct bio *bio)
21592159
spin_unlock_irqrestore(&c->btree_write_error_lock, flags);
21602160
}
21612161

2162+
/*
2163+
* XXX: we should be using io_ref[WRITE], but we aren't retrying failed
2164+
* btree writes yet (due to device removal/ro):
2165+
*/
21622166
if (wbio->have_ioref)
2163-
percpu_ref_put(&ca->io_ref);
2167+
percpu_ref_put(&ca->io_ref[READ]);
21642168

21652169
if (parent) {
21662170
bio_put(bio);

fs/bcachefs/btree_node_scan.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ static int read_btree_nodes_worker(void *p)
271271
err:
272272
bio_put(bio);
273273
free_page((unsigned long) buf);
274-
percpu_ref_put(&ca->io_ref);
274+
percpu_ref_put(&ca->io_ref[READ]);
275275
closure_put(w->cl);
276276
kfree(w);
277277
return 0;
@@ -291,7 +291,7 @@ static int read_btree_nodes(struct find_btree_nodes *f)
291291

292292
struct find_btree_nodes_worker *w = kmalloc(sizeof(*w), GFP_KERNEL);
293293
if (!w) {
294-
percpu_ref_put(&ca->io_ref);
294+
percpu_ref_put(&ca->io_ref[READ]);
295295
ret = -ENOMEM;
296296
goto err;
297297
}
@@ -303,14 +303,14 @@ static int read_btree_nodes(struct find_btree_nodes *f)
303303
struct task_struct *t = kthread_create(read_btree_nodes_worker, w, "read_btree_nodes/%s", ca->name);
304304
ret = PTR_ERR_OR_ZERO(t);
305305
if (ret) {
306-
percpu_ref_put(&ca->io_ref);
306+
percpu_ref_put(&ca->io_ref[READ]);
307307
kfree(w);
308308
bch_err_msg(c, ret, "starting kthread");
309309
break;
310310
}
311311

312312
closure_get(&cl);
313-
percpu_ref_get(&ca->io_ref);
313+
percpu_ref_get(&ca->io_ref[READ]);
314314
wake_up_process(t);
315315
}
316316
err:

fs/bcachefs/buckets.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1132,7 +1132,7 @@ int bch2_trans_mark_dev_sbs_flags(struct bch_fs *c,
11321132
for_each_online_member(c, ca) {
11331133
int ret = bch2_trans_mark_dev_sb(c, ca, flags);
11341134
if (ret) {
1135-
percpu_ref_put(&ca->io_ref);
1135+
percpu_ref_put(&ca->io_ref[READ]);
11361136
return ret;
11371137
}
11381138
}

fs/bcachefs/chardev.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,7 @@ static long bch2_ioctl_disk_get_idx(struct bch_fs *c,
615615

616616
for_each_online_member(c, ca)
617617
if (ca->dev == dev) {
618-
percpu_ref_put(&ca->io_ref);
618+
percpu_ref_put(&ca->io_ref[READ]);
619619
return ca->dev_idx;
620620
}
621621

fs/bcachefs/debug.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ static bool bch2_btree_verify_replica(struct bch_fs *c, struct btree *b,
5757
submit_bio_wait(bio);
5858

5959
bio_put(bio);
60-
percpu_ref_put(&ca->io_ref);
60+
percpu_ref_put(&ca->io_ref[READ]);
6161

6262
memcpy(n_ondisk, n_sorted, btree_buf_bytes(b));
6363

@@ -297,7 +297,7 @@ void bch2_btree_node_ondisk_to_text(struct printbuf *out, struct bch_fs *c,
297297
if (bio)
298298
bio_put(bio);
299299
kvfree(n_ondisk);
300-
percpu_ref_put(&ca->io_ref);
300+
percpu_ref_put(&ca->io_ref[READ]);
301301
}
302302

303303
#ifdef CONFIG_DEBUG_FS

fs/bcachefs/disk_groups.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,9 +555,9 @@ void bch2_target_to_text(struct printbuf *out, struct bch_fs *c, unsigned v)
555555
? rcu_dereference(c->devs[t.dev])
556556
: NULL;
557557

558-
if (ca && percpu_ref_tryget(&ca->io_ref)) {
558+
if (ca && percpu_ref_tryget(&ca->io_ref[READ])) {
559559
prt_printf(out, "/dev/%s", ca->name);
560-
percpu_ref_put(&ca->io_ref);
560+
percpu_ref_put(&ca->io_ref[READ]);
561561
} else if (ca) {
562562
prt_printf(out, "offline device %u", t.dev);
563563
} else {

fs/bcachefs/ec.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ struct ec_bio {
105105
struct bch_dev *ca;
106106
struct ec_stripe_buf *buf;
107107
size_t idx;
108+
int rw;
108109
u64 submit_time;
109110
struct bio bio;
110111
};
@@ -704,6 +705,7 @@ static void ec_block_endio(struct bio *bio)
704705
struct bch_extent_ptr *ptr = &v->ptrs[ec_bio->idx];
705706
struct bch_dev *ca = ec_bio->ca;
706707
struct closure *cl = bio->bi_private;
708+
int rw = ec_bio->rw;
707709

708710
bch2_account_io_completion(ca, bio_data_dir(bio),
709711
ec_bio->submit_time, !bio->bi_status);
@@ -725,7 +727,7 @@ static void ec_block_endio(struct bio *bio)
725727
}
726728

727729
bio_put(&ec_bio->bio);
728-
percpu_ref_put(&ca->io_ref);
730+
percpu_ref_put(&ca->io_ref[rw]);
729731
closure_put(cl);
730732
}
731733

@@ -776,6 +778,7 @@ static void ec_block_io(struct bch_fs *c, struct ec_stripe_buf *buf,
776778
ec_bio->ca = ca;
777779
ec_bio->buf = buf;
778780
ec_bio->idx = idx;
781+
ec_bio->rw = rw;
779782
ec_bio->submit_time = local_clock();
780783

781784
ec_bio->bio.bi_iter.bi_sector = ptr->offset + buf->offset + (offset >> 9);
@@ -785,14 +788,14 @@ static void ec_block_io(struct bch_fs *c, struct ec_stripe_buf *buf,
785788
bch2_bio_map(&ec_bio->bio, buf->data[idx] + offset, b);
786789

787790
closure_get(cl);
788-
percpu_ref_get(&ca->io_ref);
791+
percpu_ref_get(&ca->io_ref[rw]);
789792

790793
submit_bio(&ec_bio->bio);
791794

792795
offset += b;
793796
}
794797

795-
percpu_ref_put(&ca->io_ref);
798+
percpu_ref_put(&ca->io_ref[rw]);
796799
}
797800

798801
static int get_stripe_key_trans(struct btree_trans *trans, u64 idx,
@@ -1265,7 +1268,7 @@ static void zero_out_rest_of_ec_bucket(struct bch_fs *c,
12651268
ob->sectors_free,
12661269
GFP_KERNEL, 0);
12671270

1268-
percpu_ref_put(&ca->io_ref);
1271+
percpu_ref_put(&ca->io_ref[WRITE]);
12691272

12701273
if (ret)
12711274
s->err = ret;

0 commit comments

Comments
 (0)