diff options
author | Kent Overstreet <kmo@daterainc.com> | 2013-08-07 17:31:11 -0400 |
---|---|---|
committer | Kent Overstreet <kmo@daterainc.com> | 2013-11-24 01:33:54 -0500 |
commit | 5341a6278bc5d10dbbb2ab6031b41d95c8db7a35 (patch) | |
tree | 5861afdd9264fc55f8e4ce5794fbe7c9db7fe35e /drivers/block/rbd.c | |
parent | 59d276fe02d7e887a4825ef05c80b8f8c54ba60a (diff) |
rbd: Refactor bio cloning
Now that we've got drivers converted to the new immutable bvec
primitives, bio splitting becomes much easier - this is how the new
bio_split() will work. (Someone more familiar with the ceph code could
probably use bio_clone_fast() instead of bio_clone() here).
Signed-off-by: Kent Overstreet <kmo@daterainc.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Yehuda Sadeh <yehuda@inktank.com>
Cc: Alex Elder <elder@inktank.com>
Cc: ceph-devel@vger.kernel.org
Diffstat (limited to 'drivers/block/rbd.c')
-rw-r--r-- | drivers/block/rbd.c | 64 |
1 files changed, 2 insertions, 62 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 20e8ab35736b..3624368b910d 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
@@ -1173,73 +1173,13 @@ static struct bio *bio_clone_range(struct bio *bio_src, | |||
1173 | unsigned int len, | 1173 | unsigned int len, |
1174 | gfp_t gfpmask) | 1174 | gfp_t gfpmask) |
1175 | { | 1175 | { |
1176 | struct bio_vec bv; | ||
1177 | struct bvec_iter iter; | ||
1178 | struct bvec_iter end_iter; | ||
1179 | unsigned int resid; | ||
1180 | unsigned int voff; | ||
1181 | unsigned short vcnt; | ||
1182 | struct bio *bio; | 1176 | struct bio *bio; |
1183 | 1177 | ||
1184 | /* Handle the easy case for the caller */ | 1178 | bio = bio_clone(bio_src, gfpmask); |
1185 | |||
1186 | if (!offset && len == bio_src->bi_iter.bi_size) | ||
1187 | return bio_clone(bio_src, gfpmask); | ||
1188 | |||
1189 | if (WARN_ON_ONCE(!len)) | ||
1190 | return NULL; | ||
1191 | if (WARN_ON_ONCE(len > bio_src->bi_iter.bi_size)) | ||
1192 | return NULL; | ||
1193 | if (WARN_ON_ONCE(offset > bio_src->bi_iter.bi_size - len)) | ||
1194 | return NULL; | ||
1195 | |||
1196 | /* Find first affected segment... */ | ||
1197 | |||
1198 | resid = offset; | ||
1199 | bio_for_each_segment(bv, bio_src, iter) { | ||
1200 | if (resid < bv.bv_len) | ||
1201 | break; | ||
1202 | resid -= bv.bv_len; | ||
1203 | } | ||
1204 | voff = resid; | ||
1205 | |||
1206 | /* ...and the last affected segment */ | ||
1207 | |||
1208 | resid += len; | ||
1209 | __bio_for_each_segment(bv, bio_src, end_iter, iter) { | ||
1210 | if (resid <= bv.bv_len) | ||
1211 | break; | ||
1212 | resid -= bv.bv_len; | ||
1213 | } | ||
1214 | vcnt = end_iter.bi_idx = iter.bi_idx + 1; | ||
1215 | |||
1216 | /* Build the clone */ | ||
1217 | |||
1218 | bio = bio_alloc(gfpmask, (unsigned int) vcnt); | ||
1219 | if (!bio) | 1179 | if (!bio) |
1220 | return NULL; /* ENOMEM */ | 1180 | return NULL; /* ENOMEM */ |
1221 | 1181 | ||
1222 | bio->bi_bdev = bio_src->bi_bdev; | 1182 | bio_advance(bio, offset); |
1223 | bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector + | ||
1224 | (offset >> SECTOR_SHIFT); | ||
1225 | bio->bi_rw = bio_src->bi_rw; | ||
1226 | bio->bi_flags |= 1 << BIO_CLONED; | ||
1227 | |||
1228 | /* | ||
1229 | * Copy over our part of the bio_vec, then update the first | ||
1230 | * and last (or only) entries. | ||
1231 | */ | ||
1232 | memcpy(&bio->bi_io_vec[0], &bio_src->bi_io_vec[iter.bi_idx], | ||
1233 | vcnt * sizeof (struct bio_vec)); | ||
1234 | bio->bi_io_vec[0].bv_offset += voff; | ||
1235 | if (vcnt > 1) { | ||
1236 | bio->bi_io_vec[0].bv_len -= voff; | ||
1237 | bio->bi_io_vec[vcnt - 1].bv_len = resid; | ||
1238 | } else { | ||
1239 | bio->bi_io_vec[0].bv_len = len; | ||
1240 | } | ||
1241 | |||
1242 | bio->bi_vcnt = vcnt; | ||
1243 | bio->bi_iter.bi_size = len; | 1183 | bio->bi_iter.bi_size = len; |
1244 | 1184 | ||
1245 | return bio; | 1185 | return bio; |