diff options
author | Alex Elder <elder@inktank.com> | 2013-02-14 13:16:43 -0500 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2013-05-02 00:16:25 -0400 |
commit | 2ac2b7a6d4976bd6b5dc0751aa77d12d48d3ac4c (patch) | |
tree | af95ff579ab1719871e8678ef530db46514c0eb7 | |
parent | 2794a82a11cfeae0890741b18b0049ddb55ce646 (diff) |
libceph: distinguish page and bio requests
An osd request uses either pages or a bio list for its data. Use a
union to record information about the two, and add a data type
tag to select between them.
Signed-off-by: Alex Elder <elder@inktank.com>
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
-rw-r--r-- | drivers/block/rbd.c | 4 | ||||
-rw-r--r-- | fs/ceph/addr.c | 4 | ||||
-rw-r--r-- | fs/ceph/file.c | 1 | ||||
-rw-r--r-- | include/linux/ceph/osd_client.h | 11 | ||||
-rw-r--r-- | net/ceph/osd_client.c | 56 |
5 files changed, 55 insertions, 21 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 0e814dfda48e..f189bc2909b0 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
@@ -1425,12 +1425,16 @@ static struct ceph_osd_request *rbd_osd_req_create( | |||
1425 | break; /* Nothing to do */ | 1425 | break; /* Nothing to do */ |
1426 | case OBJ_REQUEST_BIO: | 1426 | case OBJ_REQUEST_BIO: |
1427 | rbd_assert(obj_request->bio_list != NULL); | 1427 | rbd_assert(obj_request->bio_list != NULL); |
1428 | osd_req->r_data.type = CEPH_OSD_DATA_TYPE_BIO; | ||
1428 | osd_req->r_data.bio = obj_request->bio_list; | 1429 | osd_req->r_data.bio = obj_request->bio_list; |
1429 | break; | 1430 | break; |
1430 | case OBJ_REQUEST_PAGES: | 1431 | case OBJ_REQUEST_PAGES: |
1432 | osd_req->r_data.type = CEPH_OSD_DATA_TYPE_PAGES; | ||
1431 | osd_req->r_data.pages = obj_request->pages; | 1433 | osd_req->r_data.pages = obj_request->pages; |
1432 | osd_req->r_data.num_pages = obj_request->page_count; | 1434 | osd_req->r_data.num_pages = obj_request->page_count; |
1433 | osd_req->r_data.alignment = offset & ~PAGE_MASK; | 1435 | osd_req->r_data.alignment = offset & ~PAGE_MASK; |
1436 | osd_req->r_data.pages_from_pool = false; | ||
1437 | osd_req->r_data.own_pages = false; | ||
1434 | break; | 1438 | break; |
1435 | } | 1439 | } |
1436 | 1440 | ||
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 3a1a77b0ae9f..276fe96f12e3 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c | |||
@@ -243,6 +243,7 @@ static void finish_read(struct ceph_osd_request *req, struct ceph_msg *msg) | |||
243 | dout("finish_read %p req %p rc %d bytes %d\n", inode, req, rc, bytes); | 243 | dout("finish_read %p req %p rc %d bytes %d\n", inode, req, rc, bytes); |
244 | 244 | ||
245 | /* unlock all pages, zeroing any data we didn't read */ | 245 | /* unlock all pages, zeroing any data we didn't read */ |
246 | BUG_ON(req->r_data.type != CEPH_OSD_DATA_TYPE_PAGES); | ||
246 | for (i = 0; i < req->r_data.num_pages; i++, bytes -= PAGE_CACHE_SIZE) { | 247 | for (i = 0; i < req->r_data.num_pages; i++, bytes -= PAGE_CACHE_SIZE) { |
247 | struct page *page = req->r_data.pages[i]; | 248 | struct page *page = req->r_data.pages[i]; |
248 | 249 | ||
@@ -336,6 +337,7 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max) | |||
336 | } | 337 | } |
337 | pages[i] = page; | 338 | pages[i] = page; |
338 | } | 339 | } |
340 | req->r_data.type = CEPH_OSD_DATA_TYPE_PAGES; | ||
339 | req->r_data.pages = pages; | 341 | req->r_data.pages = pages; |
340 | req->r_data.num_pages = nr_pages; | 342 | req->r_data.num_pages = nr_pages; |
341 | req->r_data.alignment = 0; | 343 | req->r_data.alignment = 0; |
@@ -561,6 +563,7 @@ static void writepages_finish(struct ceph_osd_request *req, | |||
561 | long writeback_stat; | 563 | long writeback_stat; |
562 | unsigned issued = ceph_caps_issued(ci); | 564 | unsigned issued = ceph_caps_issued(ci); |
563 | 565 | ||
566 | BUG_ON(req->r_data.type != CEPH_OSD_DATA_TYPE_PAGES); | ||
564 | if (rc >= 0) { | 567 | if (rc >= 0) { |
565 | /* | 568 | /* |
566 | * Assume we wrote the pages we originally sent. The | 569 | * Assume we wrote the pages we originally sent. The |
@@ -830,6 +833,7 @@ get_more_pages: | |||
830 | break; | 833 | break; |
831 | } | 834 | } |
832 | 835 | ||
836 | req->r_data.type = CEPH_OSD_DATA_TYPE_PAGES; | ||
833 | req->r_data.num_pages = calc_pages_for(0, len); | 837 | req->r_data.num_pages = calc_pages_for(0, len); |
834 | req->r_data.alignment = 0; | 838 | req->r_data.alignment = 0; |
835 | max_pages = req->r_data.num_pages; | 839 | max_pages = req->r_data.num_pages; |
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index d35fc05af06f..3643a386ab23 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
@@ -571,6 +571,7 @@ more: | |||
571 | req->r_data.own_pages = 1; | 571 | req->r_data.own_pages = 1; |
572 | } | 572 | } |
573 | } | 573 | } |
574 | req->r_data.type = CEPH_OSD_DATA_TYPE_PAGES; | ||
574 | req->r_data.pages = pages; | 575 | req->r_data.pages = pages; |
575 | req->r_data.num_pages = num_pages; | 576 | req->r_data.num_pages = num_pages; |
576 | req->r_data.alignment = page_align; | 577 | req->r_data.alignment = page_align; |
diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h index 600b8278d11e..56604b33dc3c 100644 --- a/include/linux/ceph/osd_client.h +++ b/include/linux/ceph/osd_client.h | |||
@@ -50,8 +50,17 @@ struct ceph_osd { | |||
50 | 50 | ||
51 | #define CEPH_OSD_MAX_OP 10 | 51 | #define CEPH_OSD_MAX_OP 10 |
52 | 52 | ||
53 | enum ceph_osd_data_type { | ||
54 | CEPH_OSD_DATA_TYPE_NONE, | ||
55 | CEPH_OSD_DATA_TYPE_PAGES, | ||
56 | #ifdef CONFIG_BLOCK | ||
57 | CEPH_OSD_DATA_TYPE_BIO, | ||
58 | #endif /* CONFIG_BLOCK */ | ||
59 | }; | ||
60 | |||
53 | struct ceph_osd_data { | 61 | struct ceph_osd_data { |
54 | struct { | 62 | enum ceph_osd_data_type type; |
63 | union { | ||
55 | struct { | 64 | struct { |
56 | struct page **pages; | 65 | struct page **pages; |
57 | u32 num_pages; | 66 | u32 num_pages; |
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 1f8c7a7c203b..591e1b0cccbe 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c | |||
@@ -122,7 +122,8 @@ void ceph_osdc_release_request(struct kref *kref) | |||
122 | } | 122 | } |
123 | if (req->r_reply) | 123 | if (req->r_reply) |
124 | ceph_msg_put(req->r_reply); | 124 | ceph_msg_put(req->r_reply); |
125 | if (req->r_data.own_pages) | 125 | if (req->r_data.type == CEPH_OSD_DATA_TYPE_PAGES && |
126 | req->r_data.own_pages) | ||
126 | ceph_release_page_vector(req->r_data.pages, | 127 | ceph_release_page_vector(req->r_data.pages, |
127 | req->r_data.num_pages); | 128 | req->r_data.num_pages); |
128 | ceph_put_snap_context(req->r_snapc); | 129 | ceph_put_snap_context(req->r_snapc); |
@@ -188,6 +189,7 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, | |||
188 | } | 189 | } |
189 | req->r_reply = msg; | 190 | req->r_reply = msg; |
190 | 191 | ||
192 | req->r_data.type = CEPH_OSD_DATA_TYPE_NONE; | ||
191 | ceph_pagelist_init(&req->r_trail); | 193 | ceph_pagelist_init(&req->r_trail); |
192 | 194 | ||
193 | /* create request message; allow space for oid */ | 195 | /* create request message; allow space for oid */ |
@@ -1739,12 +1741,17 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc, | |||
1739 | { | 1741 | { |
1740 | int rc = 0; | 1742 | int rc = 0; |
1741 | 1743 | ||
1742 | req->r_request->pages = req->r_data.pages; | 1744 | if (req->r_data.type == CEPH_OSD_DATA_TYPE_PAGES) { |
1743 | req->r_request->page_count = req->r_data.num_pages; | 1745 | req->r_request->pages = req->r_data.pages; |
1744 | req->r_request->page_alignment = req->r_data.alignment; | 1746 | req->r_request->page_count = req->r_data.num_pages; |
1747 | req->r_request->page_alignment = req->r_data.alignment; | ||
1745 | #ifdef CONFIG_BLOCK | 1748 | #ifdef CONFIG_BLOCK |
1746 | req->r_request->bio = req->r_data.bio; | 1749 | } else if (req->r_data.type == CEPH_OSD_DATA_TYPE_BIO) { |
1750 | req->r_request->bio = req->r_data.bio; | ||
1747 | #endif | 1751 | #endif |
1752 | } else { | ||
1753 | pr_err("unknown request data type %d\n", req->r_data.type); | ||
1754 | } | ||
1748 | req->r_request->trail = &req->r_trail; | 1755 | req->r_request->trail = &req->r_trail; |
1749 | 1756 | ||
1750 | register_request(osdc, req); | 1757 | register_request(osdc, req); |
@@ -1944,6 +1951,7 @@ int ceph_osdc_readpages(struct ceph_osd_client *osdc, | |||
1944 | return PTR_ERR(req); | 1951 | return PTR_ERR(req); |
1945 | 1952 | ||
1946 | /* it may be a short read due to an object boundary */ | 1953 | /* it may be a short read due to an object boundary */ |
1954 | req->r_data.type = CEPH_OSD_DATA_TYPE_PAGES; | ||
1947 | req->r_data.pages = pages; | 1955 | req->r_data.pages = pages; |
1948 | req->r_data.num_pages = calc_pages_for(page_align, *plen); | 1956 | req->r_data.num_pages = calc_pages_for(page_align, *plen); |
1949 | req->r_data.alignment = page_align; | 1957 | req->r_data.alignment = page_align; |
@@ -1987,6 +1995,7 @@ int ceph_osdc_writepages(struct ceph_osd_client *osdc, struct ceph_vino vino, | |||
1987 | return PTR_ERR(req); | 1995 | return PTR_ERR(req); |
1988 | 1996 | ||
1989 | /* it may be a short write due to an object boundary */ | 1997 | /* it may be a short write due to an object boundary */ |
1998 | req->r_data.type = CEPH_OSD_DATA_TYPE_PAGES; | ||
1990 | req->r_data.pages = pages; | 1999 | req->r_data.pages = pages; |
1991 | req->r_data.num_pages = calc_pages_for(page_align, len); | 2000 | req->r_data.num_pages = calc_pages_for(page_align, len); |
1992 | req->r_data.alignment = page_align; | 2001 | req->r_data.alignment = page_align; |
@@ -2083,23 +2092,30 @@ static struct ceph_msg *get_reply(struct ceph_connection *con, | |||
2083 | m = ceph_msg_get(req->r_reply); | 2092 | m = ceph_msg_get(req->r_reply); |
2084 | 2093 | ||
2085 | if (data_len > 0) { | 2094 | if (data_len > 0) { |
2086 | int want = calc_pages_for(req->r_data.alignment, data_len); | 2095 | if (req->r_data.type == CEPH_OSD_DATA_TYPE_PAGES) { |
2087 | 2096 | int want; | |
2088 | if (req->r_data.pages && unlikely(req->r_data.num_pages < want)) { | 2097 | |
2089 | pr_warning("tid %lld reply has %d bytes %d pages, we" | 2098 | want = calc_pages_for(req->r_data.alignment, data_len); |
2090 | " had only %d pages ready\n", tid, data_len, | 2099 | if (req->r_data.pages && |
2091 | want, req->r_data.num_pages); | 2100 | unlikely(req->r_data.num_pages < want)) { |
2092 | *skip = 1; | 2101 | |
2093 | ceph_msg_put(m); | 2102 | pr_warning("tid %lld reply has %d bytes %d " |
2094 | m = NULL; | 2103 | "pages, we had only %d pages ready\n", |
2095 | goto out; | 2104 | tid, data_len, want, |
2096 | } | 2105 | req->r_data.num_pages); |
2097 | m->pages = req->r_data.pages; | 2106 | *skip = 1; |
2098 | m->page_count = req->r_data.num_pages; | 2107 | ceph_msg_put(m); |
2099 | m->page_alignment = req->r_data.alignment; | 2108 | m = NULL; |
2109 | goto out; | ||
2110 | } | ||
2111 | m->pages = req->r_data.pages; | ||
2112 | m->page_count = req->r_data.num_pages; | ||
2113 | m->page_alignment = req->r_data.alignment; | ||
2100 | #ifdef CONFIG_BLOCK | 2114 | #ifdef CONFIG_BLOCK |
2101 | m->bio = req->r_data.bio; | 2115 | } else if (req->r_data.type == CEPH_OSD_DATA_TYPE_BIO) { |
2116 | m->bio = req->r_data.bio; | ||
2102 | #endif | 2117 | #endif |
2118 | } | ||
2103 | } | 2119 | } |
2104 | *skip = 0; | 2120 | *skip = 0; |
2105 | req->r_con_filling_msg = con->ops->get(con); | 2121 | req->r_con_filling_msg = con->ops->get(con); |