diff options
author | Alex Elder <elder@inktank.com> | 2013-04-19 16:34:50 -0400 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2013-05-02 00:19:11 -0400 |
commit | f1a4739f333b519fe041e1ad81d9b31c94b9d6a3 (patch) | |
tree | c86ebedf87940ce47adfb79e1370c85d41da1d8d | |
parent | b9434c5b43d1a90e762fe64169862fb198746935 (diff) |
rbd: support page array image requests
This patch adds the ability to build an image request whose data
will be written from or read into memory described by a page array.
(Previously only bio lists were supported.)
Originally this was going to define a new function for this purpose
but it was largely identical to the rbd_img_request_fill_bio(). So
instead, rbd_img_request_fill_bio() has been generalized to handle
both types of image request.
For the moment we still only fill image requests with bio data.
Signed-off-by: Alex Elder <elder@inktank.com>
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
-rw-r--r-- | drivers/block/rbd.c | 86 |
1 files changed, 66 insertions, 20 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 06bbd55c0ea1..8a7216d784d7 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
@@ -1780,6 +1780,13 @@ static bool rbd_img_obj_end_request(struct rbd_obj_request *obj_request) | |||
1780 | img_request->result = result; | 1780 | img_request->result = result; |
1781 | } | 1781 | } |
1782 | 1782 | ||
1783 | /* Image object requests don't own their page array */ | ||
1784 | |||
1785 | if (obj_request->type == OBJ_REQUEST_PAGES) { | ||
1786 | obj_request->pages = NULL; | ||
1787 | obj_request->page_count = 0; | ||
1788 | } | ||
1789 | |||
1783 | if (img_request_child_test(img_request)) { | 1790 | if (img_request_child_test(img_request)) { |
1784 | rbd_assert(img_request->obj_request != NULL); | 1791 | rbd_assert(img_request->obj_request != NULL); |
1785 | more = obj_request->which < img_request->obj_request_count - 1; | 1792 | more = obj_request->which < img_request->obj_request_count - 1; |
@@ -1830,30 +1837,48 @@ out: | |||
1830 | rbd_img_request_complete(img_request); | 1837 | rbd_img_request_complete(img_request); |
1831 | } | 1838 | } |
1832 | 1839 | ||
1833 | static int rbd_img_request_fill_bio(struct rbd_img_request *img_request, | 1840 | /* |
1834 | struct bio *bio_list) | 1841 | * Split up an image request into one or more object requests, each |
1842 | * to a different object. The "type" parameter indicates whether | ||
1843 | * "data_desc" is the pointer to the head of a list of bio | ||
1844 | * structures, or the base of a page array. In either case this | ||
1845 | * function assumes data_desc describes memory sufficient to hold | ||
1846 | * all data described by the image request. | ||
1847 | */ | ||
1848 | static int rbd_img_request_fill(struct rbd_img_request *img_request, | ||
1849 | enum obj_request_type type, | ||
1850 | void *data_desc) | ||
1835 | { | 1851 | { |
1836 | struct rbd_device *rbd_dev = img_request->rbd_dev; | 1852 | struct rbd_device *rbd_dev = img_request->rbd_dev; |
1837 | struct rbd_obj_request *obj_request = NULL; | 1853 | struct rbd_obj_request *obj_request = NULL; |
1838 | struct rbd_obj_request *next_obj_request; | 1854 | struct rbd_obj_request *next_obj_request; |
1839 | bool write_request = img_request_write_test(img_request); | 1855 | bool write_request = img_request_write_test(img_request); |
1840 | unsigned int bio_offset; | 1856 | struct bio *bio_list; |
1857 | unsigned int bio_offset = 0; | ||
1858 | struct page **pages; | ||
1841 | u64 img_offset; | 1859 | u64 img_offset; |
1842 | u64 resid; | 1860 | u64 resid; |
1843 | u16 opcode; | 1861 | u16 opcode; |
1844 | 1862 | ||
1845 | dout("%s: img %p bio %p\n", __func__, img_request, bio_list); | 1863 | dout("%s: img %p type %d data_desc %p\n", __func__, img_request, |
1864 | (int)type, data_desc); | ||
1846 | 1865 | ||
1847 | opcode = write_request ? CEPH_OSD_OP_WRITE : CEPH_OSD_OP_READ; | 1866 | opcode = write_request ? CEPH_OSD_OP_WRITE : CEPH_OSD_OP_READ; |
1848 | bio_offset = 0; | ||
1849 | img_offset = img_request->offset; | 1867 | img_offset = img_request->offset; |
1850 | rbd_assert(img_offset == bio_list->bi_sector << SECTOR_SHIFT); | ||
1851 | resid = img_request->length; | 1868 | resid = img_request->length; |
1852 | rbd_assert(resid > 0); | 1869 | rbd_assert(resid > 0); |
1870 | |||
1871 | if (type == OBJ_REQUEST_BIO) { | ||
1872 | bio_list = data_desc; | ||
1873 | rbd_assert(img_offset == bio_list->bi_sector << SECTOR_SHIFT); | ||
1874 | } else { | ||
1875 | rbd_assert(type == OBJ_REQUEST_PAGES); | ||
1876 | pages = data_desc; | ||
1877 | } | ||
1878 | |||
1853 | while (resid) { | 1879 | while (resid) { |
1854 | struct ceph_osd_request *osd_req; | 1880 | struct ceph_osd_request *osd_req; |
1855 | const char *object_name; | 1881 | const char *object_name; |
1856 | unsigned int clone_size; | ||
1857 | u64 offset; | 1882 | u64 offset; |
1858 | u64 length; | 1883 | u64 length; |
1859 | 1884 | ||
@@ -1863,19 +1888,33 @@ static int rbd_img_request_fill_bio(struct rbd_img_request *img_request, | |||
1863 | offset = rbd_segment_offset(rbd_dev, img_offset); | 1888 | offset = rbd_segment_offset(rbd_dev, img_offset); |
1864 | length = rbd_segment_length(rbd_dev, img_offset, resid); | 1889 | length = rbd_segment_length(rbd_dev, img_offset, resid); |
1865 | obj_request = rbd_obj_request_create(object_name, | 1890 | obj_request = rbd_obj_request_create(object_name, |
1866 | offset, length, | 1891 | offset, length, type); |
1867 | OBJ_REQUEST_BIO); | ||
1868 | kfree(object_name); /* object request has its own copy */ | 1892 | kfree(object_name); /* object request has its own copy */ |
1869 | if (!obj_request) | 1893 | if (!obj_request) |
1870 | goto out_unwind; | 1894 | goto out_unwind; |
1871 | 1895 | ||
1872 | rbd_assert(length <= (u64) UINT_MAX); | 1896 | if (type == OBJ_REQUEST_BIO) { |
1873 | clone_size = (unsigned int) length; | 1897 | unsigned int clone_size; |
1874 | obj_request->bio_list = bio_chain_clone_range(&bio_list, | 1898 | |
1875 | &bio_offset, clone_size, | 1899 | rbd_assert(length <= (u64)UINT_MAX); |
1876 | GFP_ATOMIC); | 1900 | clone_size = (unsigned int)length; |
1877 | if (!obj_request->bio_list) | 1901 | obj_request->bio_list = |
1878 | goto out_partial; | 1902 | bio_chain_clone_range(&bio_list, |
1903 | &bio_offset, | ||
1904 | clone_size, | ||
1905 | GFP_ATOMIC); | ||
1906 | if (!obj_request->bio_list) | ||
1907 | goto out_partial; | ||
1908 | } else { | ||
1909 | unsigned int page_count; | ||
1910 | |||
1911 | obj_request->pages = pages; | ||
1912 | page_count = (u32)calc_pages_for(offset, length); | ||
1913 | obj_request->page_count = page_count; | ||
1914 | if ((offset + length) & ~PAGE_MASK) | ||
1915 | page_count--; /* more on last page */ | ||
1916 | pages += page_count; | ||
1917 | } | ||
1879 | 1918 | ||
1880 | osd_req = rbd_osd_req_create(rbd_dev, write_request, | 1919 | osd_req = rbd_osd_req_create(rbd_dev, write_request, |
1881 | obj_request); | 1920 | obj_request); |
@@ -1886,8 +1925,13 @@ static int rbd_img_request_fill_bio(struct rbd_img_request *img_request, | |||
1886 | 1925 | ||
1887 | osd_req_op_extent_init(osd_req, 0, opcode, offset, length, | 1926 | osd_req_op_extent_init(osd_req, 0, opcode, offset, length, |
1888 | 0, 0); | 1927 | 0, 0); |
1889 | osd_req_op_extent_osd_data_bio(osd_req, 0, | 1928 | if (type == OBJ_REQUEST_BIO) |
1890 | obj_request->bio_list, obj_request->length); | 1929 | osd_req_op_extent_osd_data_bio(osd_req, 0, |
1930 | obj_request->bio_list, length); | ||
1931 | else | ||
1932 | osd_req_op_extent_osd_data_pages(osd_req, 0, | ||
1933 | obj_request->pages, length, | ||
1934 | offset & ~PAGE_MASK, false, false); | ||
1891 | 1935 | ||
1892 | if (write_request) | 1936 | if (write_request) |
1893 | rbd_osd_req_format_write(obj_request); | 1937 | rbd_osd_req_format_write(obj_request); |
@@ -2120,7 +2164,8 @@ static void rbd_img_parent_read(struct rbd_obj_request *obj_request) | |||
2120 | rbd_obj_request_get(obj_request); | 2164 | rbd_obj_request_get(obj_request); |
2121 | img_request->obj_request = obj_request; | 2165 | img_request->obj_request = obj_request; |
2122 | 2166 | ||
2123 | result = rbd_img_request_fill_bio(img_request, obj_request->bio_list); | 2167 | result = rbd_img_request_fill(img_request, OBJ_REQUEST_BIO, |
2168 | obj_request->bio_list); | ||
2124 | if (result) | 2169 | if (result) |
2125 | goto out_err; | 2170 | goto out_err; |
2126 | 2171 | ||
@@ -2425,7 +2470,8 @@ static void rbd_request_fn(struct request_queue *q) | |||
2425 | 2470 | ||
2426 | img_request->rq = rq; | 2471 | img_request->rq = rq; |
2427 | 2472 | ||
2428 | result = rbd_img_request_fill_bio(img_request, rq->bio); | 2473 | result = rbd_img_request_fill(img_request, OBJ_REQUEST_BIO, |
2474 | rq->bio); | ||
2429 | if (!result) | 2475 | if (!result) |
2430 | result = rbd_img_request_submit(img_request); | 2476 | result = rbd_img_request_submit(img_request); |
2431 | if (result) | 2477 | if (result) |