aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorAlex Elder <elder@inktank.com>2013-01-17 13:25:27 -0500
committerSage Weil <sage@inktank.com>2013-02-13 21:29:08 -0500
commit788e2df3b92e30f1fff74139bb53e68ec13fe2a5 (patch)
treee0386e011b2dd488bb55e1b2baef4677b11ad6b2 /drivers/block
parent7d250b949a33c8a658a2ad4ab390d8394b842224 (diff)
rbd: implement sync object read with new code
Reimplement the synchronous read operation used for reading a version 1 header using the new request tracking code. Name the resulting function rbd_obj_read_sync() to better reflect that it's a full object operation, not an object request. To do this, implement a new OBJ_REQUEST_PAGES object request type. This implements a new mechanism to allow the caller to wait for completion for an rbd_obj_request by calling rbd_obj_request_wait(). This partially resolves: http://tracker.newdream.net/issues/3755 Signed-off-by: Alex Elder <elder@inktank.com> Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/rbd.c96
1 files changed, 92 insertions, 4 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index c1bb649b4ad1..3f5eaea444a0 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -170,7 +170,7 @@ typedef void (*rbd_img_callback_t)(struct rbd_img_request *);
170struct rbd_obj_request; 170struct rbd_obj_request;
171typedef void (*rbd_obj_callback_t)(struct rbd_obj_request *); 171typedef void (*rbd_obj_callback_t)(struct rbd_obj_request *);
172 172
173enum obj_request_type { OBJ_REQUEST_BIO }; /* More types to come */ 173enum obj_request_type { OBJ_REQUEST_BIO, OBJ_REQUEST_PAGES };
174 174
175struct rbd_obj_request { 175struct rbd_obj_request {
176 const char *object_name; 176 const char *object_name;
@@ -182,7 +182,13 @@ struct rbd_obj_request {
182 u32 which; /* posn image request list */ 182 u32 which; /* posn image request list */
183 183
184 enum obj_request_type type; 184 enum obj_request_type type;
185 struct bio *bio_list; 185 union {
186 struct bio *bio_list;
187 struct {
188 struct page **pages;
189 u32 page_count;
190 };
191 };
186 192
187 struct ceph_osd_request *osd_req; 193 struct ceph_osd_request *osd_req;
188 194
@@ -192,6 +198,7 @@ struct rbd_obj_request {
192 atomic_t done; 198 atomic_t done;
193 199
194 rbd_obj_callback_t callback; 200 rbd_obj_callback_t callback;
201 struct completion completion;
195 202
196 struct kref kref; 203 struct kref kref;
197}; 204};
@@ -1077,6 +1084,7 @@ static bool obj_request_type_valid(enum obj_request_type type)
1077{ 1084{
1078 switch (type) { 1085 switch (type) {
1079 case OBJ_REQUEST_BIO: 1086 case OBJ_REQUEST_BIO:
1087 case OBJ_REQUEST_PAGES:
1080 return true; 1088 return true;
1081 default: 1089 default:
1082 return false; 1090 return false;
@@ -1291,14 +1299,23 @@ static void rbd_img_request_complete(struct rbd_img_request *img_request)
1291 rbd_img_request_put(img_request); 1299 rbd_img_request_put(img_request);
1292} 1300}
1293 1301
1302/* Caller is responsible for rbd_obj_request_destroy(obj_request) */
1303
1304static int rbd_obj_request_wait(struct rbd_obj_request *obj_request)
1305{
1306 return wait_for_completion_interruptible(&obj_request->completion);
1307}
1308
1294static void rbd_obj_request_complete(struct rbd_obj_request *obj_request) 1309static void rbd_obj_request_complete(struct rbd_obj_request *obj_request)
1295{ 1310{
1296 if (obj_request->callback) 1311 if (obj_request->callback)
1297 obj_request->callback(obj_request); 1312 obj_request->callback(obj_request);
1313 else
1314 complete_all(&obj_request->completion);
1298} 1315}
1299 1316
1300/* 1317/*
1301 * Request sync osd read 1318 * Synchronously read a range from an object into a provided buffer
1302 */ 1319 */
1303static int rbd_req_sync_read(struct rbd_device *rbd_dev, 1320static int rbd_req_sync_read(struct rbd_device *rbd_dev,
1304 const char *object_name, 1321 const char *object_name,
@@ -1556,6 +1573,11 @@ static struct ceph_osd_request *rbd_osd_req_create(
1556 /* osd client requires "num pages" even for bio */ 1573 /* osd client requires "num pages" even for bio */
1557 osd_req->r_num_pages = calc_pages_for(offset, length); 1574 osd_req->r_num_pages = calc_pages_for(offset, length);
1558 break; 1575 break;
1576 case OBJ_REQUEST_PAGES:
1577 osd_req->r_pages = obj_request->pages;
1578 osd_req->r_num_pages = obj_request->page_count;
1579 osd_req->r_page_alignment = offset & ~PAGE_MASK;
1580 break;
1559 } 1581 }
1560 1582
1561 if (write_request) { 1583 if (write_request) {
@@ -1616,6 +1638,7 @@ static struct rbd_obj_request *rbd_obj_request_create(const char *object_name,
1616 obj_request->type = type; 1638 obj_request->type = type;
1617 INIT_LIST_HEAD(&obj_request->links); 1639 INIT_LIST_HEAD(&obj_request->links);
1618 atomic_set(&obj_request->done, 0); 1640 atomic_set(&obj_request->done, 0);
1641 init_completion(&obj_request->completion);
1619 kref_init(&obj_request->kref); 1642 kref_init(&obj_request->kref);
1620 1643
1621 return obj_request; 1644 return obj_request;
@@ -1639,6 +1662,11 @@ static void rbd_obj_request_destroy(struct kref *kref)
1639 if (obj_request->bio_list) 1662 if (obj_request->bio_list)
1640 bio_chain_put(obj_request->bio_list); 1663 bio_chain_put(obj_request->bio_list);
1641 break; 1664 break;
1665 case OBJ_REQUEST_PAGES:
1666 if (obj_request->pages)
1667 ceph_release_page_vector(obj_request->pages,
1668 obj_request->page_count);
1669 break;
1642 } 1670 }
1643 1671
1644 kfree(obj_request); 1672 kfree(obj_request);
@@ -1987,6 +2015,65 @@ static void rbd_free_disk(struct rbd_device *rbd_dev)
1987 put_disk(disk); 2015 put_disk(disk);
1988} 2016}
1989 2017
2018static int rbd_obj_read_sync(struct rbd_device *rbd_dev,
2019 const char *object_name,
2020 u64 offset, u64 length,
2021 char *buf, u64 *version)
2022
2023{
2024 struct ceph_osd_req_op *op;
2025 struct rbd_obj_request *obj_request;
2026 struct ceph_osd_client *osdc;
2027 struct page **pages = NULL;
2028 u32 page_count;
2029 int ret;
2030
2031 page_count = (u32) calc_pages_for(offset, length);
2032 pages = ceph_alloc_page_vector(page_count, GFP_KERNEL);
2033 if (IS_ERR(pages))
2034 ret = PTR_ERR(pages);
2035
2036 ret = -ENOMEM;
2037 obj_request = rbd_obj_request_create(object_name, offset, length,
2038 OBJ_REQUEST_PAGES);
2039 if (!obj_request)
2040 goto out;
2041
2042 obj_request->pages = pages;
2043 obj_request->page_count = page_count;
2044
2045 op = rbd_osd_req_op_create(CEPH_OSD_OP_READ, offset, length);
2046 if (!op)
2047 goto out;
2048 obj_request->osd_req = rbd_osd_req_create(rbd_dev, false,
2049 obj_request, op);
2050 rbd_osd_req_op_destroy(op);
2051 if (!obj_request->osd_req)
2052 goto out;
2053
2054 osdc = &rbd_dev->rbd_client->client->osdc;
2055 ret = rbd_obj_request_submit(osdc, obj_request);
2056 if (ret)
2057 goto out;
2058 ret = rbd_obj_request_wait(obj_request);
2059 if (ret)
2060 goto out;
2061
2062 ret = obj_request->result;
2063 if (ret < 0)
2064 goto out;
2065 ret = ceph_copy_from_page_vector(pages, buf, 0, obj_request->xferred);
2066 if (version)
2067 *version = obj_request->version;
2068out:
2069 if (obj_request)
2070 rbd_obj_request_put(obj_request);
2071 else
2072 ceph_release_page_vector(pages, page_count);
2073
2074 return ret;
2075}
2076
1990/* 2077/*
1991 * Read the complete header for the given rbd device. 2078 * Read the complete header for the given rbd device.
1992 * 2079 *
@@ -2025,7 +2112,8 @@ rbd_dev_v1_header_read(struct rbd_device *rbd_dev, u64 *version)
2025 if (!ondisk) 2112 if (!ondisk)
2026 return ERR_PTR(-ENOMEM); 2113 return ERR_PTR(-ENOMEM);
2027 2114
2028 ret = rbd_req_sync_read(rbd_dev, rbd_dev->header_name, 2115 (void) rbd_req_sync_read; /* avoid a warning */
2116 ret = rbd_obj_read_sync(rbd_dev, rbd_dev->header_name,
2029 0, size, 2117 0, size,
2030 (char *) ondisk, version); 2118 (char *) ondisk, version);
2031 2119