aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/rbd.c
diff options
context:
space:
mode:
authorKent Overstreet <kmo@daterainc.com>2013-08-07 17:31:11 -0400
committerKent Overstreet <kmo@daterainc.com>2013-11-24 01:33:54 -0500
commit5341a6278bc5d10dbbb2ab6031b41d95c8db7a35 (patch)
tree5861afdd9264fc55f8e4ce5794fbe7c9db7fe35e /drivers/block/rbd.c
parent59d276fe02d7e887a4825ef05c80b8f8c54ba60a (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.c64
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;