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
273 273
274 struct bio_set bio_split;274 struct bio_set bio_split;
275 275
276 struct bio_set bio_detached;
277
276 unsigned int data_csum:1;278 unsigned int data_csum:1;
277 279
278 int (*cache_miss)(struct btree *b, struct search *s,280 int (*cache_miss)(struct btree *b, struct search *s,
@@ -753,6 +755,13 @@ struct bbio { · 474 unmodified lines
753 struct bio bio;755 struct bio bio;
754};756};
755 757
758struct 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
756#define BTREE_PRIO USHRT_MAX765#define BTREE_PRIO USHRT_MAX
757#define INITIAL_PRIO 32768U766#define INITIAL_PRIO 32768U
758 767
drivers/md/bcache/request.c+35−44
@@ -1077,68 +1077,58 @@ static CLOSURE_CALLBACK(cached_dev_nodata) · 1076 unmodified lines
1077 continue_at(cl, cached_dev_bio_complete, NULL);1077 continue_at(cl, cached_dev_bio_complete, NULL);
1078}1078}
1079 1079
1080struct 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
1088static void detached_dev_end_io(struct bio *bio)1080static void detached_dev_end_io(struct bio *bio)
1089{1081{
1090 struct detached_dev_io_private *ddip;1082 struct detached_dev_io_private *ddip =
1091 1083 container_of(bio, struct detached_dev_io_private, bio);
1092 ddip = bio->bi_private;1084 struct bio *orig_bio = ddip->orig_bio;
1093 bio->bi_end_io = ddip->bi_end_io;
1094 bio->bi_private = ddip->bi_private;
1095 1085
1096 /* Count on the bcache device */1086 /* 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);
1098 1088
1099 if (bio->bi_status) {1089 if (bio->bi_status) {
1100 struct cached_dev *dc = container_of(ddip->d,1090 struct cached_dev *dc = bio->bi_private;
1101 struct cached_dev, disk);1091
1102 /* should count I/O error for backing device here */1092 /* should count I/O error for backing device here */
1103 bch_count_backing_io_errors(dc, bio);1093 bch_count_backing_io_errors(dc, bio);
1094 orig_bio->bi_status = bio->bi_status;
1104 }1095 }
1105 1096
1106 kfree(ddip);1097 bio_put(bio);
1107 bio_endio(bio);1098 bio_endio(orig_bio);
1108}1099}
1109 1100
1110static void detached_dev_do_request(struct bcache_device *d, struct bio *bio,1101static void detached_dev_do_request(struct bcache_device *d,
1111 struct block_device *orig_bdev, unsigned long start_time)1102 struct bio *orig_bio, unsigned long start_time)
1112{1103{
1113 struct detached_dev_io_private *ddip;1104 struct detached_dev_io_private *ddip;
1114 struct cached_dev *dc = container_of(d, struct cached_dev, disk);1105 struct cached_dev *dc = container_of(d, struct cached_dev, disk);
1106 struct bio *clone_bio;
1115 1107
1116 /*1108 if (bio_op(orig_bio) == REQ_OP_DISCARD &&
1117 * no need to call closure_get(&dc->disk.cl),1109 !bdev_max_discard_sectors(dc->bdev)) {
1118 * because upper layer had already opened bcache device,1110 bio_endio(orig_bio);
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);
1125 return;1111 return;
1126 }1112 }
1127 1113
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);
1129 /* Count on the bcache device */1123 /* Count on the bcache device */
1130 ddip->orig_bdev = orig_bdev;1124 ddip->d = d;
1131 ddip->start_time = start_time;1125 ddip->start_time = start_time;
1132 ddip->bi_end_io = bio->bi_end_io;1126 ddip->orig_bio = orig_bio;
1133 ddip->bi_private = bio->bi_private;1127
1134 bio->bi_end_io = detached_dev_end_io;1128 clone_bio->bi_end_io = detached_dev_end_io;
1135 bio->bi_private = ddip;1129 clone_bio->bi_private = dc;
1136 1130
1137 if ((bio_op(bio) == REQ_OP_DISCARD) &&1131 submit_bio_noacct(clone_bio);
1138 !bdev_max_discard_sectors(dc->bdev))
1139 detached_dev_end_io(bio);
1140 else
1141 submit_bio_noacct(bio);
1142}1132}
1143 1133
1144static void quit_max_writeback_rate(struct cache_set *c,1134static void quit_max_writeback_rate(struct cache_set *c,
@@ -1214,10 +1204,10 @@ void cached_dev_submit_bio(struct bio *bio) · 69 unmodified lines
1214 1204
1215 start_time = bio_start_io_acct(bio);1205 start_time = bio_start_io_acct(bio);
1216 1206
1217 bio_set_dev(bio, dc->bdev);
1218 bio->bi_iter.bi_sector += dc->sb.data_offset;1207 bio->bi_iter.bi_sector += dc->sb.data_offset;
1219 1208
1220 if (cached_dev_get(dc)) {1209 if (cached_dev_get(dc)) {
1210 bio_set_dev(bio, dc->bdev);
1221 s = search_alloc(bio, d, orig_bdev, start_time);1211 s = search_alloc(bio, d, orig_bdev, start_time);
1222 trace_bcache_request_start(s->d, bio);1212 trace_bcache_request_start(s->d, bio);
1223 1213
@@ -1237,9 +1227,10 @@ void cached_dev_submit_bio(struct bio *bio) · 13 unmodified lines
1237 else1227 else
1238 cached_dev_read(dc, s);1228 cached_dev_read(dc, s);
1239 }1229 }
1240 } else1230 } else {
1241 /* I/O request sent to backing device */1231 /* 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 }
1243}1234}
1244 1235
1245static int cached_dev_ioctl(struct bcache_device *d, blk_mode_t mode,1236static 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
887 }887 }
888 888
889 bioset_exit(&d->bio_split);889 bioset_exit(&d->bio_split);
890 bioset_exit(&d->bio_detached);
890 kvfree(d->full_dirty_stripes);891 kvfree(d->full_dirty_stripes);
891 kvfree(d->stripe_sectors_dirty);892 kvfree(d->stripe_sectors_dirty);
892 893
@@ -949,6 +950,11 @@ static int bcache_device_init(struct bcache_device *d, unsigned int block_size, · 56 unmodified lines
949 BIOSET_NEED_BVECS|BIOSET_NEED_RESCUER))950 BIOSET_NEED_BVECS|BIOSET_NEED_RESCUER))
950 goto out_ida_remove;951 goto out_ida_remove;
951 952
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
952 if (lim.logical_block_size > PAGE_SIZE && cached_bdev) {958 if (lim.logical_block_size > PAGE_SIZE && cached_bdev) {
953 /*959 /*
954 * This should only happen with BCACHE_SB_VERSION_BDEV.960 * 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
964 970
965 d->disk = blk_alloc_disk(&lim, NUMA_NO_NODE);971 d->disk = blk_alloc_disk(&lim, NUMA_NO_NODE);
966 if (IS_ERR(d->disk))972 if (IS_ERR(d->disk))
967 goto out_bioset_exit;973 goto out_bioset_detach_exit;
968 974
969 set_capacity(d->disk, sectors);975 set_capacity(d->disk, sectors);
970 snprintf(d->disk->disk_name, DISK_NAME_LEN, "bcache%i", idx);976 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
976 d->disk->private_data = d;982 d->disk->private_data = d;
977 return 0;983 return 0;
978 984
979out_bioset_exit:985out_bioset_detach_exit:
986 bioset_exit(&d->bio_detached);
987out_bioset_split_exit:
980 bioset_exit(&d->bio_split);988 bioset_exit(&d->bio_split);
981out_ida_remove:989out_ida_remove:
982 ida_free(&bcache_device_idx, idx);990 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