aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Elder <elder@inktank.com>2013-02-14 13:16:43 -0500
committerSage Weil <sage@inktank.com>2013-05-02 00:16:25 -0400
commit2ac2b7a6d4976bd6b5dc0751aa77d12d48d3ac4c (patch)
treeaf95ff579ab1719871e8678ef530db46514c0eb7
parent2794a82a11cfeae0890741b18b0049ddb55ce646 (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.c4
-rw-r--r--fs/ceph/addr.c4
-rw-r--r--fs/ceph/file.c1
-rw-r--r--include/linux/ceph/osd_client.h11
-rw-r--r--net/ceph/osd_client.c56
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
53enum 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
53struct ceph_osd_data { 61struct 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);