|
@@ -1583,6 +1583,64 @@ static struct rbd_req_coll *rbd_alloc_coll(int num_reqs)
|
|
|
return coll;
|
|
|
}
|
|
|
|
|
|
+static int rbd_dev_do_request(struct request *rq,
|
|
|
+ struct rbd_device *rbd_dev,
|
|
|
+ struct ceph_snap_context *snapc,
|
|
|
+ u64 ofs, unsigned int size,
|
|
|
+ struct bio *bio_chain)
|
|
|
+{
|
|
|
+ int num_segs;
|
|
|
+ struct rbd_req_coll *coll;
|
|
|
+ unsigned int bio_offset;
|
|
|
+ int cur_seg = 0;
|
|
|
+
|
|
|
+ dout("%s 0x%x bytes at 0x%llx\n",
|
|
|
+ rq_data_dir(rq) == WRITE ? "write" : "read",
|
|
|
+ size, (unsigned long long) blk_rq_pos(rq) * SECTOR_SIZE);
|
|
|
+
|
|
|
+ num_segs = rbd_get_num_segments(&rbd_dev->header, ofs, size);
|
|
|
+ if (num_segs <= 0)
|
|
|
+ return num_segs;
|
|
|
+
|
|
|
+ coll = rbd_alloc_coll(num_segs);
|
|
|
+ if (!coll)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ bio_offset = 0;
|
|
|
+ do {
|
|
|
+ u64 limit = rbd_segment_length(rbd_dev, ofs, size);
|
|
|
+ unsigned int clone_size;
|
|
|
+ struct bio *bio_clone;
|
|
|
+
|
|
|
+ BUG_ON(limit > (u64)UINT_MAX);
|
|
|
+ clone_size = (unsigned int)limit;
|
|
|
+ dout("bio_chain->bi_vcnt=%hu\n", bio_chain->bi_vcnt);
|
|
|
+
|
|
|
+ kref_get(&coll->kref);
|
|
|
+
|
|
|
+ /* Pass a cloned bio chain via an osd request */
|
|
|
+
|
|
|
+ bio_clone = bio_chain_clone_range(&bio_chain,
|
|
|
+ &bio_offset, clone_size,
|
|
|
+ GFP_ATOMIC);
|
|
|
+ if (bio_clone)
|
|
|
+ (void)rbd_do_op(rq, rbd_dev, snapc,
|
|
|
+ ofs, clone_size,
|
|
|
+ bio_clone, coll, cur_seg);
|
|
|
+ else
|
|
|
+ rbd_coll_end_req_index(rq, coll, cur_seg,
|
|
|
+ (s32)-ENOMEM,
|
|
|
+ clone_size);
|
|
|
+ size -= clone_size;
|
|
|
+ ofs += clone_size;
|
|
|
+
|
|
|
+ cur_seg++;
|
|
|
+ } while (size > 0);
|
|
|
+ kref_put(&coll->kref, rbd_coll_release);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* block device queue callback
|
|
|
*/
|
|
@@ -1596,10 +1654,8 @@ static void rbd_rq_fn(struct request_queue *q)
|
|
|
bool do_write;
|
|
|
unsigned int size;
|
|
|
u64 ofs;
|
|
|
- int num_segs, cur_seg = 0;
|
|
|
- struct rbd_req_coll *coll;
|
|
|
struct ceph_snap_context *snapc;
|
|
|
- unsigned int bio_offset;
|
|
|
+ int result;
|
|
|
|
|
|
dout("fetched request\n");
|
|
|
|
|
@@ -1637,60 +1693,11 @@ static void rbd_rq_fn(struct request_queue *q)
|
|
|
ofs = blk_rq_pos(rq) * SECTOR_SIZE;
|
|
|
bio = rq->bio;
|
|
|
|
|
|
- dout("%s 0x%x bytes at 0x%llx\n",
|
|
|
- do_write ? "write" : "read",
|
|
|
- size, (unsigned long long) blk_rq_pos(rq) * SECTOR_SIZE);
|
|
|
-
|
|
|
- num_segs = rbd_get_num_segments(&rbd_dev->header, ofs, size);
|
|
|
- if (num_segs <= 0) {
|
|
|
- spin_lock_irq(q->queue_lock);
|
|
|
- __blk_end_request_all(rq, num_segs);
|
|
|
- ceph_put_snap_context(snapc);
|
|
|
- continue;
|
|
|
- }
|
|
|
- coll = rbd_alloc_coll(num_segs);
|
|
|
- if (!coll) {
|
|
|
- spin_lock_irq(q->queue_lock);
|
|
|
- __blk_end_request_all(rq, -ENOMEM);
|
|
|
- ceph_put_snap_context(snapc);
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- bio_offset = 0;
|
|
|
- do {
|
|
|
- u64 limit = rbd_segment_length(rbd_dev, ofs, size);
|
|
|
- unsigned int chain_size;
|
|
|
- struct bio *bio_chain;
|
|
|
-
|
|
|
- BUG_ON(limit > (u64) UINT_MAX);
|
|
|
- chain_size = (unsigned int) limit;
|
|
|
- dout("rq->bio->bi_vcnt=%hu\n", rq->bio->bi_vcnt);
|
|
|
-
|
|
|
- kref_get(&coll->kref);
|
|
|
-
|
|
|
- /* Pass a cloned bio chain via an osd request */
|
|
|
-
|
|
|
- bio_chain = bio_chain_clone_range(&bio,
|
|
|
- &bio_offset, chain_size,
|
|
|
- GFP_ATOMIC);
|
|
|
- if (bio_chain)
|
|
|
- (void) rbd_do_op(rq, rbd_dev, snapc,
|
|
|
- ofs, chain_size,
|
|
|
- bio_chain, coll, cur_seg);
|
|
|
- else
|
|
|
- rbd_coll_end_req_index(rq, coll, cur_seg,
|
|
|
- (s32)-ENOMEM,
|
|
|
- chain_size);
|
|
|
- size -= chain_size;
|
|
|
- ofs += chain_size;
|
|
|
-
|
|
|
- cur_seg++;
|
|
|
- } while (size > 0);
|
|
|
- kref_put(&coll->kref, rbd_coll_release);
|
|
|
-
|
|
|
- spin_lock_irq(q->queue_lock);
|
|
|
-
|
|
|
+ result = rbd_dev_do_request(rq, rbd_dev, snapc, ofs, size, bio);
|
|
|
ceph_put_snap_context(snapc);
|
|
|
+ spin_lock_irq(q->queue_lock);
|
|
|
+ if (!size || result < 0)
|
|
|
+ __blk_end_request_all(rq, result);
|
|
|
}
|
|
|
}
|
|
|
|