History

bcache: use bio cloning for detached device requests

Previously, bcache hijacked the bi_end_io and bi_private fields of the incoming bio when the backing device was in a detached state. This is fragile and breaks if the bio is needed to be processed by other layers. This patch transitions to using a cloned bio embedded within a private structure. This ensures the original bio's metadata remains untouched.

Shida Zhang committed 9 months ago

Commit 3ef825d1 parent 046be7e3 files · +54 −46Browse files

Unified · Split

3 files
  1. drivers/md/bcache/bcache.h +9 −0
  2. drivers/md/bcache/request.c +35 −44
  3. drivers/md/bcache/super.c +10 −2
drivers/md/bcache/bcache.h+9−0
@@ -273,6 +273,8 @@ struct bcache_device { · 272 unmodified lines
273273
274274 struct bio_set bio_split;
275275
276+ struct bio_set bio_detached;
277+
276278 unsigned int data_csum:1;
277279
278280 int (*cache_miss)(struct btree *b, struct search *s,
@@ -753,6 +755,13 @@ struct bbio { · 474 unmodified lines
753755 struct bio bio;
754756 };
755757
758+struct detached_dev_io_private {
759+ struct bcache_device *d;
760+ unsigned long start_time;
761+ struct bio *orig_bio;
762+ struct bio bio;
763+};
764+
756765 #define BTREE_PRIO USHRT_MAX
757766 #define INITIAL_PRIO 32768U
758767
drivers/md/bcache/request.c+35−44
@@ -1077,68 +1077,58 @@ static CLOSURE_CALLBACK(cached_dev_nodata) · 1076 unmodified lines
10771077 continue_at(cl, cached_dev_bio_complete, NULL);
10781078 }
10791079
1080−struct detached_dev_io_private {
1081− struct bcache_device *d;
1082− unsigned long start_time;
1083− bio_end_io_t *bi_end_io;
1084− void *bi_private;
1085− struct block_device *orig_bdev;
1086−};
1087−
10881080 static void detached_dev_end_io(struct bio *bio)
10891081 {
1090− struct detached_dev_io_private *ddip;
1091−
1092− ddip = bio->bi_private;
1093− bio->bi_end_io = ddip->bi_end_io;
1094− bio->bi_private = ddip->bi_private;
1082+ struct detached_dev_io_private *ddip =
1083+ container_of(bio, struct detached_dev_io_private, bio);
1084+ struct bio *orig_bio = ddip->orig_bio;
10951085
10961086 /* Count on the bcache device */
1097− bio_end_io_acct_remapped(bio, ddip->start_time, ddip->orig_bdev);
1087+ bio_end_io_acct(orig_bio, ddip->start_time);
10981088
10991089 if (bio->bi_status) {
1100− struct cached_dev *dc = container_of(ddip->d,
1101− struct cached_dev, disk);
1090+ struct cached_dev *dc = bio->bi_private;
1091+
11021092 /* should count I/O error for backing device here */
11031093 bch_count_backing_io_errors(dc, bio);
1094+ orig_bio->bi_status = bio->bi_status;
11041095 }
11051096
1106− kfree(ddip);
1107− bio_endio(bio);
1097+ bio_put(bio);
1098+ bio_endio(orig_bio);
11081099 }
11091100
1110−static void detached_dev_do_request(struct bcache_device *d, struct bio *bio,
1111− struct block_device *orig_bdev, unsigned long start_time)
1101+static void detached_dev_do_request(struct bcache_device *d,
1102+ struct bio *orig_bio, unsigned long start_time)
11121103 {
11131104 struct detached_dev_io_private *ddip;
11141105 struct cached_dev *dc = container_of(d, struct cached_dev, disk);
1106+ struct bio *clone_bio;
11151107
1116− /*
1117− * no need to call closure_get(&dc->disk.cl),
1118− * because upper layer had already opened bcache device,
1119− * which would call closure_get(&dc->disk.cl)
1120− */
1121− ddip = kzalloc(sizeof(struct detached_dev_io_private), GFP_NOIO);
1122− if (!ddip) {
1123− bio->bi_status = BLK_STS_RESOURCE;
1124− bio_endio(bio);
1108+ if (bio_op(orig_bio) == REQ_OP_DISCARD &&
1109+ !bdev_max_discard_sectors(dc->bdev)) {
1110+ bio_endio(orig_bio);
11251111 return;
11261112 }
11271113
1128− ddip->d = d;
1114+ clone_bio = bio_alloc_clone(dc->bdev, orig_bio, GFP_NOIO,
1115+ &d->bio_detached);
1116+ if (!clone_bio) {
1117+ orig_bio->bi_status = BLK_STS_RESOURCE;
1118+ bio_endio(orig_bio);
1119+ return;
1120+ }
1121+
1122+ ddip = container_of(clone_bio, struct detached_dev_io_private, bio);
11291123 /* Count on the bcache device */
1130− ddip->orig_bdev = orig_bdev;
1124+ ddip->d = d;
11311125 ddip->start_time = start_time;
1132− ddip->bi_end_io = bio->bi_end_io;
1133− ddip->bi_private = bio->bi_private;
1134− bio->bi_end_io = detached_dev_end_io;
1135− bio->bi_private = ddip;
1136−
1137− if ((bio_op(bio) == REQ_OP_DISCARD) &&
1138− !bdev_max_discard_sectors(dc->bdev))
1139− detached_dev_end_io(bio);
1140− else
1141− submit_bio_noacct(bio);
1126+ ddip->orig_bio = orig_bio;
1127+
1128+ clone_bio->bi_end_io = detached_dev_end_io;
1129+ clone_bio->bi_private = dc;
1130+
1131+ submit_bio_noacct(clone_bio);
11421132 }
11431133
11441134 static void quit_max_writeback_rate(struct cache_set *c,
@@ -1214,10 +1204,10 @@ void cached_dev_submit_bio(struct bio *bio) · 69 unmodified lines
12141204
12151205 start_time = bio_start_io_acct(bio);
12161206
1217− bio_set_dev(bio, dc->bdev);
12181207 bio->bi_iter.bi_sector += dc->sb.data_offset;
12191208
12201209 if (cached_dev_get(dc)) {
1210+ bio_set_dev(bio, dc->bdev);
12211211 s = search_alloc(bio, d, orig_bdev, start_time);
12221212 trace_bcache_request_start(s->d, bio);
12231213
@@ -1237,9 +1227,10 @@ void cached_dev_submit_bio(struct bio *bio) · 13 unmodified lines
12371227 else
12381228 cached_dev_read(dc, s);
12391229 }
1240− } else
1230+ } else {
12411231 /* I/O request sent to backing device */
1242− detached_dev_do_request(d, bio, orig_bdev, start_time);
1232+ detached_dev_do_request(d, bio, start_time);
1233+ }
12431234 }
12441235
12451236 static int cached_dev_ioctl(struct bcache_device *d, blk_mode_t mode,
drivers/md/bcache/super.c+10−2
@@ -887,6 +887,7 @@ static void bcache_device_free(struct bcache_device *d) · 886 unmodified lines
887887 }
888888
889889 bioset_exit(&d->bio_split);
890+ bioset_exit(&d->bio_detached);
890891 kvfree(d->full_dirty_stripes);
891892 kvfree(d->stripe_sectors_dirty);
892893
@@ -949,6 +950,11 @@ static int bcache_device_init(struct bcache_device *d, unsigned int block_size, · 56 unmodified lines
949950 BIOSET_NEED_BVECS|BIOSET_NEED_RESCUER))
950951 goto out_ida_remove;
951952
953+ if (bioset_init(&d->bio_detached, 4,
954+ offsetof(struct detached_dev_io_private, bio),
955+ BIOSET_NEED_BVECS|BIOSET_NEED_RESCUER))
956+ goto out_bioset_split_exit;
957+
952958 if (lim.logical_block_size > PAGE_SIZE && cached_bdev) {
953959 /*
954960 * This should only happen with BCACHE_SB_VERSION_BDEV.
@@ -964,7 +970,7 @@ static int bcache_device_init(struct bcache_device *d, unsigned int block_size, · 9 unmodified lines
964970
965971 d->disk = blk_alloc_disk(&lim, NUMA_NO_NODE);
966972 if (IS_ERR(d->disk))
967− goto out_bioset_exit;
973+ goto out_bioset_detach_exit;
968974
969975 set_capacity(d->disk, sectors);
970976 snprintf(d->disk->disk_name, DISK_NAME_LEN, "bcache%i", idx);
@@ -976,7 +982,9 @@ static int bcache_device_init(struct bcache_device *d, unsigned int block_size, · 5 unmodified lines
976982 d->disk->private_data = d;
977983 return 0;
978984
979−out_bioset_exit:
985+out_bioset_detach_exit:
986+ bioset_exit(&d->bio_detached);
987+out_bioset_split_exit:
980988 bioset_exit(&d->bio_split);
981989 out_ida_remove:
982990 ida_free(&bcache_device_idx, idx);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t