Loading drivers/block/rbd.c +156 −21 Original line number Original line Diff line number Diff line Loading @@ -92,6 +92,8 @@ struct rbd_client { struct list_head node; struct list_head node; }; }; struct rbd_req_coll; /* /* * a single io request * a single io request */ */ Loading @@ -100,6 +102,24 @@ struct rbd_request { struct bio *bio; /* cloned bio */ struct bio *bio; /* cloned bio */ struct page **pages; /* list of used pages */ struct page **pages; /* list of used pages */ u64 len; u64 len; int coll_index; struct rbd_req_coll *coll; }; struct rbd_req_status { int done; int rc; u64 bytes; }; /* * a collection of requests */ struct rbd_req_coll { int total; int num_done; struct kref kref; struct rbd_req_status status[0]; }; }; struct rbd_snap { struct rbd_snap { Loading Loading @@ -416,6 +436,17 @@ static void rbd_put_client(struct rbd_device *rbd_dev) rbd_dev->client = NULL; rbd_dev->client = NULL; } } /* * Destroy requests collection */ static void rbd_coll_release(struct kref *kref) { struct rbd_req_coll *coll = container_of(kref, struct rbd_req_coll, kref); dout("rbd_coll_release %p\n", coll); kfree(coll); } /* /* * Create a new header structure, translate header format from the on-disk * Create a new header structure, translate header format from the on-disk Loading Loading @@ -590,6 +621,14 @@ static u64 rbd_get_segment(struct rbd_image_header *header, return len; return len; } } static int rbd_get_num_segments(struct rbd_image_header *header, u64 ofs, u64 len) { u64 start_seg = ofs >> header->obj_order; u64 end_seg = (ofs + len - 1) >> header->obj_order; return end_seg - start_seg + 1; } /* /* * bio helpers * bio helpers */ */ Loading Loading @@ -735,6 +774,50 @@ static void rbd_destroy_ops(struct ceph_osd_req_op *ops) kfree(ops); kfree(ops); } } static void rbd_coll_end_req_index(struct request *rq, struct rbd_req_coll *coll, int index, int ret, u64 len) { struct request_queue *q; int min, max, i; dout("rbd_coll_end_req_index %p index %d ret %d len %lld\n", coll, index, ret, len); if (!rq) return; if (!coll) { blk_end_request(rq, ret, len); return; } q = rq->q; spin_lock_irq(q->queue_lock); coll->status[index].done = 1; coll->status[index].rc = ret; coll->status[index].bytes = len; max = min = coll->num_done; while (max < coll->total && coll->status[max].done) max++; for (i = min; i<max; i++) { __blk_end_request(rq, coll->status[i].rc, coll->status[i].bytes); coll->num_done++; kref_put(&coll->kref, rbd_coll_release); } spin_unlock_irq(q->queue_lock); } static void rbd_coll_end_req(struct rbd_request *req, int ret, u64 len) { rbd_coll_end_req_index(req->rq, req->coll, req->coll_index, ret, len); } /* /* * Send ceph osd request * Send ceph osd request */ */ Loading @@ -749,6 +832,8 @@ static int rbd_do_request(struct request *rq, int flags, int flags, struct ceph_osd_req_op *ops, struct ceph_osd_req_op *ops, int num_reply, int num_reply, struct rbd_req_coll *coll, int coll_index, void (*rbd_cb)(struct ceph_osd_request *req, void (*rbd_cb)(struct ceph_osd_request *req, struct ceph_msg *msg), struct ceph_msg *msg), struct ceph_osd_request **linger_req, struct ceph_osd_request **linger_req, Loading @@ -763,12 +848,20 @@ static int rbd_do_request(struct request *rq, struct ceph_osd_request_head *reqhead; struct ceph_osd_request_head *reqhead; struct rbd_image_header *header = &dev->header; struct rbd_image_header *header = &dev->header; ret = -ENOMEM; req_data = kzalloc(sizeof(*req_data), GFP_NOIO); req_data = kzalloc(sizeof(*req_data), GFP_NOIO); if (!req_data) if (!req_data) { goto done; if (coll) rbd_coll_end_req_index(rq, coll, coll_index, -ENOMEM, len); return -ENOMEM; } if (coll) { req_data->coll = coll; req_data->coll_index = coll_index; } dout("rbd_do_request len=%lld ofs=%lld\n", len, ofs); dout("rbd_do_request obj=%s ofs=%lld len=%lld\n", obj, len, ofs); down_read(&header->snap_rwsem); down_read(&header->snap_rwsem); Loading Loading @@ -828,7 +921,8 @@ static int rbd_do_request(struct request *rq, ret = ceph_osdc_wait_request(&dev->client->osdc, req); ret = ceph_osdc_wait_request(&dev->client->osdc, req); if (ver) if (ver) *ver = le64_to_cpu(req->r_reassert_version.version); *ver = le64_to_cpu(req->r_reassert_version.version); dout("reassert_ver=%lld\n", le64_to_cpu(req->r_reassert_version.version)); dout("reassert_ver=%lld\n", le64_to_cpu(req->r_reassert_version.version)); ceph_osdc_put_request(req); ceph_osdc_put_request(req); } } return ret; return ret; Loading @@ -837,10 +931,8 @@ done_err: bio_chain_put(req_data->bio); bio_chain_put(req_data->bio); ceph_osdc_put_request(req); ceph_osdc_put_request(req); done_pages: done_pages: rbd_coll_end_req(req_data, ret, len); kfree(req_data); kfree(req_data); done: if (rq) blk_end_request(rq, ret, len); return ret; return ret; } } Loading Loading @@ -874,7 +966,7 @@ static void rbd_req_cb(struct ceph_osd_request *req, struct ceph_msg *msg) bytes = req_data->len; bytes = req_data->len; } } blk_end_request(req_data->rq, rc, bytes); rbd_coll_end_req(req_data, rc, bytes); if (req_data->bio) if (req_data->bio) bio_chain_put(req_data->bio); bio_chain_put(req_data->bio); Loading Loading @@ -934,6 +1026,7 @@ static int rbd_req_sync_op(struct rbd_device *dev, flags, flags, ops, ops, 2, 2, NULL, 0, NULL, NULL, linger_req, ver); linger_req, ver); if (ret < 0) if (ret < 0) Loading @@ -959,7 +1052,9 @@ static int rbd_do_op(struct request *rq, u64 snapid, u64 snapid, int opcode, int flags, int num_reply, int opcode, int flags, int num_reply, u64 ofs, u64 len, u64 ofs, u64 len, struct bio *bio) struct bio *bio, struct rbd_req_coll *coll, int coll_index) { { char *seg_name; char *seg_name; u64 seg_ofs; u64 seg_ofs; Loading Loading @@ -995,7 +1090,10 @@ static int rbd_do_op(struct request *rq, flags, flags, ops, ops, num_reply, num_reply, coll, coll_index, rbd_req_cb, 0, NULL); rbd_req_cb, 0, NULL); rbd_destroy_ops(ops); done: done: kfree(seg_name); kfree(seg_name); return ret; return ret; Loading @@ -1008,13 +1106,15 @@ static int rbd_req_write(struct request *rq, struct rbd_device *rbd_dev, struct rbd_device *rbd_dev, struct ceph_snap_context *snapc, struct ceph_snap_context *snapc, u64 ofs, u64 len, u64 ofs, u64 len, struct bio *bio) struct bio *bio, struct rbd_req_coll *coll, int coll_index) { { return rbd_do_op(rq, rbd_dev, snapc, CEPH_NOSNAP, return rbd_do_op(rq, rbd_dev, snapc, CEPH_NOSNAP, CEPH_OSD_OP_WRITE, CEPH_OSD_OP_WRITE, CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK, CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK, 2, 2, ofs, len, bio); ofs, len, bio, coll, coll_index); } } /* /* Loading @@ -1024,14 +1124,16 @@ static int rbd_req_read(struct request *rq, struct rbd_device *rbd_dev, struct rbd_device *rbd_dev, u64 snapid, u64 snapid, u64 ofs, u64 len, u64 ofs, u64 len, struct bio *bio) struct bio *bio, struct rbd_req_coll *coll, int coll_index) { { return rbd_do_op(rq, rbd_dev, NULL, return rbd_do_op(rq, rbd_dev, NULL, (snapid ? snapid : CEPH_NOSNAP), (snapid ? snapid : CEPH_NOSNAP), CEPH_OSD_OP_READ, CEPH_OSD_OP_READ, CEPH_OSD_FLAG_READ, CEPH_OSD_FLAG_READ, 2, 2, ofs, len, bio); ofs, len, bio, coll, coll_index); } } /* /* Loading Loading @@ -1063,7 +1165,9 @@ static int rbd_req_sync_notify_ack(struct rbd_device *dev, { { struct ceph_osd_req_op *ops; struct ceph_osd_req_op *ops; struct page **pages = NULL; struct page **pages = NULL; int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_NOTIFY_ACK, 0); int ret; ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_NOTIFY_ACK, 0); if (ret < 0) if (ret < 0) return ret; return ret; Loading @@ -1077,6 +1181,7 @@ static int rbd_req_sync_notify_ack(struct rbd_device *dev, CEPH_OSD_FLAG_READ, CEPH_OSD_FLAG_READ, ops, ops, 1, 1, NULL, 0, rbd_simple_req_cb, 0, NULL); rbd_simple_req_cb, 0, NULL); rbd_destroy_ops(ops); rbd_destroy_ops(ops); Loading Loading @@ -1274,6 +1379,20 @@ static int rbd_req_sync_exec(struct rbd_device *dev, return ret; return ret; } } static struct rbd_req_coll *rbd_alloc_coll(int num_reqs) { struct rbd_req_coll *coll = kzalloc(sizeof(struct rbd_req_coll) + sizeof(struct rbd_req_status) * num_reqs, GFP_ATOMIC); if (!coll) return NULL; coll->total = num_reqs; kref_init(&coll->kref); return coll; } /* /* * block device queue callback * block device queue callback */ */ Loading @@ -1291,6 +1410,8 @@ static void rbd_rq_fn(struct request_queue *q) bool do_write; bool do_write; int size, op_size = 0; int size, op_size = 0; u64 ofs; u64 ofs; int num_segs, cur_seg = 0; struct rbd_req_coll *coll; /* peek at request from block layer */ /* peek at request from block layer */ if (!rq) if (!rq) Loading Loading @@ -1321,6 +1442,14 @@ static void rbd_rq_fn(struct request_queue *q) do_write ? "write" : "read", do_write ? "write" : "read", size, blk_rq_pos(rq) * 512ULL); size, blk_rq_pos(rq) * 512ULL); num_segs = rbd_get_num_segments(&rbd_dev->header, ofs, size); coll = rbd_alloc_coll(num_segs); if (!coll) { spin_lock_irq(q->queue_lock); __blk_end_request_all(rq, -ENOMEM); goto next; } do { do { /* a bio clone to be passed down to OSD req */ /* a bio clone to be passed down to OSD req */ dout("rq->bio->bi_vcnt=%d\n", rq->bio->bi_vcnt); dout("rq->bio->bi_vcnt=%d\n", rq->bio->bi_vcnt); Loading @@ -1328,35 +1457,41 @@ static void rbd_rq_fn(struct request_queue *q) rbd_dev->header.block_name, rbd_dev->header.block_name, ofs, size, ofs, size, NULL, NULL); NULL, NULL); kref_get(&coll->kref); bio = bio_chain_clone(&rq_bio, &next_bio, &bp, bio = bio_chain_clone(&rq_bio, &next_bio, &bp, op_size, GFP_ATOMIC); op_size, GFP_ATOMIC); if (!bio) { if (!bio) { spin_lock_irq(q->queue_lock); rbd_coll_end_req_index(rq, coll, cur_seg, __blk_end_request_all(rq, -ENOMEM); -ENOMEM, op_size); goto next; goto next_seg; } } /* init OSD command: write or read */ /* init OSD command: write or read */ if (do_write) if (do_write) rbd_req_write(rq, rbd_dev, rbd_req_write(rq, rbd_dev, rbd_dev->header.snapc, rbd_dev->header.snapc, ofs, ofs, op_size, bio); op_size, bio, coll, cur_seg); else else rbd_req_read(rq, rbd_dev, rbd_req_read(rq, rbd_dev, cur_snap_id(rbd_dev), cur_snap_id(rbd_dev), ofs, ofs, op_size, bio); op_size, bio, coll, cur_seg); next_seg: size -= op_size; size -= op_size; ofs += op_size; ofs += op_size; cur_seg++; rq_bio = next_bio; rq_bio = next_bio; } while (size > 0); } while (size > 0); kref_put(&coll->kref, rbd_coll_release); if (bp) if (bp) bio_pair_release(bp); bio_pair_release(bp); spin_lock_irq(q->queue_lock); spin_lock_irq(q->queue_lock); next: next: rq = blk_fetch_request(q); rq = blk_fetch_request(q); Loading Loading
drivers/block/rbd.c +156 −21 Original line number Original line Diff line number Diff line Loading @@ -92,6 +92,8 @@ struct rbd_client { struct list_head node; struct list_head node; }; }; struct rbd_req_coll; /* /* * a single io request * a single io request */ */ Loading @@ -100,6 +102,24 @@ struct rbd_request { struct bio *bio; /* cloned bio */ struct bio *bio; /* cloned bio */ struct page **pages; /* list of used pages */ struct page **pages; /* list of used pages */ u64 len; u64 len; int coll_index; struct rbd_req_coll *coll; }; struct rbd_req_status { int done; int rc; u64 bytes; }; /* * a collection of requests */ struct rbd_req_coll { int total; int num_done; struct kref kref; struct rbd_req_status status[0]; }; }; struct rbd_snap { struct rbd_snap { Loading Loading @@ -416,6 +436,17 @@ static void rbd_put_client(struct rbd_device *rbd_dev) rbd_dev->client = NULL; rbd_dev->client = NULL; } } /* * Destroy requests collection */ static void rbd_coll_release(struct kref *kref) { struct rbd_req_coll *coll = container_of(kref, struct rbd_req_coll, kref); dout("rbd_coll_release %p\n", coll); kfree(coll); } /* /* * Create a new header structure, translate header format from the on-disk * Create a new header structure, translate header format from the on-disk Loading Loading @@ -590,6 +621,14 @@ static u64 rbd_get_segment(struct rbd_image_header *header, return len; return len; } } static int rbd_get_num_segments(struct rbd_image_header *header, u64 ofs, u64 len) { u64 start_seg = ofs >> header->obj_order; u64 end_seg = (ofs + len - 1) >> header->obj_order; return end_seg - start_seg + 1; } /* /* * bio helpers * bio helpers */ */ Loading Loading @@ -735,6 +774,50 @@ static void rbd_destroy_ops(struct ceph_osd_req_op *ops) kfree(ops); kfree(ops); } } static void rbd_coll_end_req_index(struct request *rq, struct rbd_req_coll *coll, int index, int ret, u64 len) { struct request_queue *q; int min, max, i; dout("rbd_coll_end_req_index %p index %d ret %d len %lld\n", coll, index, ret, len); if (!rq) return; if (!coll) { blk_end_request(rq, ret, len); return; } q = rq->q; spin_lock_irq(q->queue_lock); coll->status[index].done = 1; coll->status[index].rc = ret; coll->status[index].bytes = len; max = min = coll->num_done; while (max < coll->total && coll->status[max].done) max++; for (i = min; i<max; i++) { __blk_end_request(rq, coll->status[i].rc, coll->status[i].bytes); coll->num_done++; kref_put(&coll->kref, rbd_coll_release); } spin_unlock_irq(q->queue_lock); } static void rbd_coll_end_req(struct rbd_request *req, int ret, u64 len) { rbd_coll_end_req_index(req->rq, req->coll, req->coll_index, ret, len); } /* /* * Send ceph osd request * Send ceph osd request */ */ Loading @@ -749,6 +832,8 @@ static int rbd_do_request(struct request *rq, int flags, int flags, struct ceph_osd_req_op *ops, struct ceph_osd_req_op *ops, int num_reply, int num_reply, struct rbd_req_coll *coll, int coll_index, void (*rbd_cb)(struct ceph_osd_request *req, void (*rbd_cb)(struct ceph_osd_request *req, struct ceph_msg *msg), struct ceph_msg *msg), struct ceph_osd_request **linger_req, struct ceph_osd_request **linger_req, Loading @@ -763,12 +848,20 @@ static int rbd_do_request(struct request *rq, struct ceph_osd_request_head *reqhead; struct ceph_osd_request_head *reqhead; struct rbd_image_header *header = &dev->header; struct rbd_image_header *header = &dev->header; ret = -ENOMEM; req_data = kzalloc(sizeof(*req_data), GFP_NOIO); req_data = kzalloc(sizeof(*req_data), GFP_NOIO); if (!req_data) if (!req_data) { goto done; if (coll) rbd_coll_end_req_index(rq, coll, coll_index, -ENOMEM, len); return -ENOMEM; } if (coll) { req_data->coll = coll; req_data->coll_index = coll_index; } dout("rbd_do_request len=%lld ofs=%lld\n", len, ofs); dout("rbd_do_request obj=%s ofs=%lld len=%lld\n", obj, len, ofs); down_read(&header->snap_rwsem); down_read(&header->snap_rwsem); Loading Loading @@ -828,7 +921,8 @@ static int rbd_do_request(struct request *rq, ret = ceph_osdc_wait_request(&dev->client->osdc, req); ret = ceph_osdc_wait_request(&dev->client->osdc, req); if (ver) if (ver) *ver = le64_to_cpu(req->r_reassert_version.version); *ver = le64_to_cpu(req->r_reassert_version.version); dout("reassert_ver=%lld\n", le64_to_cpu(req->r_reassert_version.version)); dout("reassert_ver=%lld\n", le64_to_cpu(req->r_reassert_version.version)); ceph_osdc_put_request(req); ceph_osdc_put_request(req); } } return ret; return ret; Loading @@ -837,10 +931,8 @@ done_err: bio_chain_put(req_data->bio); bio_chain_put(req_data->bio); ceph_osdc_put_request(req); ceph_osdc_put_request(req); done_pages: done_pages: rbd_coll_end_req(req_data, ret, len); kfree(req_data); kfree(req_data); done: if (rq) blk_end_request(rq, ret, len); return ret; return ret; } } Loading Loading @@ -874,7 +966,7 @@ static void rbd_req_cb(struct ceph_osd_request *req, struct ceph_msg *msg) bytes = req_data->len; bytes = req_data->len; } } blk_end_request(req_data->rq, rc, bytes); rbd_coll_end_req(req_data, rc, bytes); if (req_data->bio) if (req_data->bio) bio_chain_put(req_data->bio); bio_chain_put(req_data->bio); Loading Loading @@ -934,6 +1026,7 @@ static int rbd_req_sync_op(struct rbd_device *dev, flags, flags, ops, ops, 2, 2, NULL, 0, NULL, NULL, linger_req, ver); linger_req, ver); if (ret < 0) if (ret < 0) Loading @@ -959,7 +1052,9 @@ static int rbd_do_op(struct request *rq, u64 snapid, u64 snapid, int opcode, int flags, int num_reply, int opcode, int flags, int num_reply, u64 ofs, u64 len, u64 ofs, u64 len, struct bio *bio) struct bio *bio, struct rbd_req_coll *coll, int coll_index) { { char *seg_name; char *seg_name; u64 seg_ofs; u64 seg_ofs; Loading Loading @@ -995,7 +1090,10 @@ static int rbd_do_op(struct request *rq, flags, flags, ops, ops, num_reply, num_reply, coll, coll_index, rbd_req_cb, 0, NULL); rbd_req_cb, 0, NULL); rbd_destroy_ops(ops); done: done: kfree(seg_name); kfree(seg_name); return ret; return ret; Loading @@ -1008,13 +1106,15 @@ static int rbd_req_write(struct request *rq, struct rbd_device *rbd_dev, struct rbd_device *rbd_dev, struct ceph_snap_context *snapc, struct ceph_snap_context *snapc, u64 ofs, u64 len, u64 ofs, u64 len, struct bio *bio) struct bio *bio, struct rbd_req_coll *coll, int coll_index) { { return rbd_do_op(rq, rbd_dev, snapc, CEPH_NOSNAP, return rbd_do_op(rq, rbd_dev, snapc, CEPH_NOSNAP, CEPH_OSD_OP_WRITE, CEPH_OSD_OP_WRITE, CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK, CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK, 2, 2, ofs, len, bio); ofs, len, bio, coll, coll_index); } } /* /* Loading @@ -1024,14 +1124,16 @@ static int rbd_req_read(struct request *rq, struct rbd_device *rbd_dev, struct rbd_device *rbd_dev, u64 snapid, u64 snapid, u64 ofs, u64 len, u64 ofs, u64 len, struct bio *bio) struct bio *bio, struct rbd_req_coll *coll, int coll_index) { { return rbd_do_op(rq, rbd_dev, NULL, return rbd_do_op(rq, rbd_dev, NULL, (snapid ? snapid : CEPH_NOSNAP), (snapid ? snapid : CEPH_NOSNAP), CEPH_OSD_OP_READ, CEPH_OSD_OP_READ, CEPH_OSD_FLAG_READ, CEPH_OSD_FLAG_READ, 2, 2, ofs, len, bio); ofs, len, bio, coll, coll_index); } } /* /* Loading Loading @@ -1063,7 +1165,9 @@ static int rbd_req_sync_notify_ack(struct rbd_device *dev, { { struct ceph_osd_req_op *ops; struct ceph_osd_req_op *ops; struct page **pages = NULL; struct page **pages = NULL; int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_NOTIFY_ACK, 0); int ret; ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_NOTIFY_ACK, 0); if (ret < 0) if (ret < 0) return ret; return ret; Loading @@ -1077,6 +1181,7 @@ static int rbd_req_sync_notify_ack(struct rbd_device *dev, CEPH_OSD_FLAG_READ, CEPH_OSD_FLAG_READ, ops, ops, 1, 1, NULL, 0, rbd_simple_req_cb, 0, NULL); rbd_simple_req_cb, 0, NULL); rbd_destroy_ops(ops); rbd_destroy_ops(ops); Loading Loading @@ -1274,6 +1379,20 @@ static int rbd_req_sync_exec(struct rbd_device *dev, return ret; return ret; } } static struct rbd_req_coll *rbd_alloc_coll(int num_reqs) { struct rbd_req_coll *coll = kzalloc(sizeof(struct rbd_req_coll) + sizeof(struct rbd_req_status) * num_reqs, GFP_ATOMIC); if (!coll) return NULL; coll->total = num_reqs; kref_init(&coll->kref); return coll; } /* /* * block device queue callback * block device queue callback */ */ Loading @@ -1291,6 +1410,8 @@ static void rbd_rq_fn(struct request_queue *q) bool do_write; bool do_write; int size, op_size = 0; int size, op_size = 0; u64 ofs; u64 ofs; int num_segs, cur_seg = 0; struct rbd_req_coll *coll; /* peek at request from block layer */ /* peek at request from block layer */ if (!rq) if (!rq) Loading Loading @@ -1321,6 +1442,14 @@ static void rbd_rq_fn(struct request_queue *q) do_write ? "write" : "read", do_write ? "write" : "read", size, blk_rq_pos(rq) * 512ULL); size, blk_rq_pos(rq) * 512ULL); num_segs = rbd_get_num_segments(&rbd_dev->header, ofs, size); coll = rbd_alloc_coll(num_segs); if (!coll) { spin_lock_irq(q->queue_lock); __blk_end_request_all(rq, -ENOMEM); goto next; } do { do { /* a bio clone to be passed down to OSD req */ /* a bio clone to be passed down to OSD req */ dout("rq->bio->bi_vcnt=%d\n", rq->bio->bi_vcnt); dout("rq->bio->bi_vcnt=%d\n", rq->bio->bi_vcnt); Loading @@ -1328,35 +1457,41 @@ static void rbd_rq_fn(struct request_queue *q) rbd_dev->header.block_name, rbd_dev->header.block_name, ofs, size, ofs, size, NULL, NULL); NULL, NULL); kref_get(&coll->kref); bio = bio_chain_clone(&rq_bio, &next_bio, &bp, bio = bio_chain_clone(&rq_bio, &next_bio, &bp, op_size, GFP_ATOMIC); op_size, GFP_ATOMIC); if (!bio) { if (!bio) { spin_lock_irq(q->queue_lock); rbd_coll_end_req_index(rq, coll, cur_seg, __blk_end_request_all(rq, -ENOMEM); -ENOMEM, op_size); goto next; goto next_seg; } } /* init OSD command: write or read */ /* init OSD command: write or read */ if (do_write) if (do_write) rbd_req_write(rq, rbd_dev, rbd_req_write(rq, rbd_dev, rbd_dev->header.snapc, rbd_dev->header.snapc, ofs, ofs, op_size, bio); op_size, bio, coll, cur_seg); else else rbd_req_read(rq, rbd_dev, rbd_req_read(rq, rbd_dev, cur_snap_id(rbd_dev), cur_snap_id(rbd_dev), ofs, ofs, op_size, bio); op_size, bio, coll, cur_seg); next_seg: size -= op_size; size -= op_size; ofs += op_size; ofs += op_size; cur_seg++; rq_bio = next_bio; rq_bio = next_bio; } while (size > 0); } while (size > 0); kref_put(&coll->kref, rbd_coll_release); if (bp) if (bp) bio_pair_release(bp); bio_pair_release(bp); spin_lock_irq(q->queue_lock); spin_lock_irq(q->queue_lock); next: next: rq = blk_fetch_request(q); rq = blk_fetch_request(q); Loading