diff options
author | Alex Elder <elder@inktank.com> | 2013-01-18 13:31:10 -0500 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2013-02-13 21:29:08 -0500 |
commit | 9969ebc5af93028c21f2614621737f0d6ff6fc06 (patch) | |
tree | f65f331f36dc9bdc3f6d46b1e3b165f2202e60dc /drivers/block | |
parent | 86ea43bfcbeae61858b0fee4971e5b1e894d7174 (diff) |
rbd: implement watch/unwatch with new code
Implement a new function to set up or tear down a watch event
for an mapped rbd image header using the new request code.
Create a new object request type "nodata" to handle this. And
define rbd_osd_trivial_callback() which simply marks a request done.
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.c | 89 |
1 files changed, 86 insertions, 3 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 5e7110a50513..60b68512fa93 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
@@ -170,7 +170,9 @@ typedef void (*rbd_img_callback_t)(struct rbd_img_request *); | |||
170 | struct rbd_obj_request; | 170 | struct rbd_obj_request; |
171 | typedef void (*rbd_obj_callback_t)(struct rbd_obj_request *); | 171 | typedef void (*rbd_obj_callback_t)(struct rbd_obj_request *); |
172 | 172 | ||
173 | enum obj_request_type { OBJ_REQUEST_BIO, OBJ_REQUEST_PAGES }; | 173 | enum obj_request_type { |
174 | OBJ_REQUEST_NODATA, OBJ_REQUEST_BIO, OBJ_REQUEST_PAGES | ||
175 | }; | ||
174 | 176 | ||
175 | struct rbd_obj_request { | 177 | struct rbd_obj_request { |
176 | const char *object_name; | 178 | const char *object_name; |
@@ -1083,6 +1085,7 @@ static inline void rbd_img_obj_request_del(struct rbd_img_request *img_request, | |||
1083 | static bool obj_request_type_valid(enum obj_request_type type) | 1085 | static bool obj_request_type_valid(enum obj_request_type type) |
1084 | { | 1086 | { |
1085 | switch (type) { | 1087 | switch (type) { |
1088 | case OBJ_REQUEST_NODATA: | ||
1086 | case OBJ_REQUEST_BIO: | 1089 | case OBJ_REQUEST_BIO: |
1087 | case OBJ_REQUEST_PAGES: | 1090 | case OBJ_REQUEST_PAGES: |
1088 | return true; | 1091 | return true; |
@@ -1306,6 +1309,12 @@ static int rbd_obj_request_wait(struct rbd_obj_request *obj_request) | |||
1306 | return wait_for_completion_interruptible(&obj_request->completion); | 1309 | return wait_for_completion_interruptible(&obj_request->completion); |
1307 | } | 1310 | } |
1308 | 1311 | ||
1312 | static void rbd_osd_trivial_callback(struct rbd_obj_request *obj_request, | ||
1313 | struct ceph_osd_op *op) | ||
1314 | { | ||
1315 | atomic_set(&obj_request->done, 1); | ||
1316 | } | ||
1317 | |||
1309 | static void rbd_obj_request_complete(struct rbd_obj_request *obj_request) | 1318 | static void rbd_obj_request_complete(struct rbd_obj_request *obj_request) |
1310 | { | 1319 | { |
1311 | if (obj_request->callback) | 1320 | if (obj_request->callback) |
@@ -1500,6 +1509,9 @@ static void rbd_osd_req_callback(struct ceph_osd_request *osd_req, | |||
1500 | case CEPH_OSD_OP_WRITE: | 1509 | case CEPH_OSD_OP_WRITE: |
1501 | rbd_osd_write_callback(obj_request, op); | 1510 | rbd_osd_write_callback(obj_request, op); |
1502 | break; | 1511 | break; |
1512 | case CEPH_OSD_OP_WATCH: | ||
1513 | rbd_osd_trivial_callback(obj_request, op); | ||
1514 | break; | ||
1503 | default: | 1515 | default: |
1504 | rbd_warn(NULL, "%s: unsupported op %hu\n", | 1516 | rbd_warn(NULL, "%s: unsupported op %hu\n", |
1505 | obj_request->object_name, (unsigned short) opcode); | 1517 | obj_request->object_name, (unsigned short) opcode); |
@@ -1543,6 +1555,8 @@ static struct ceph_osd_request *rbd_osd_req_create( | |||
1543 | 1555 | ||
1544 | rbd_assert(obj_request_type_valid(obj_request->type)); | 1556 | rbd_assert(obj_request_type_valid(obj_request->type)); |
1545 | switch (obj_request->type) { | 1557 | switch (obj_request->type) { |
1558 | case OBJ_REQUEST_NODATA: | ||
1559 | break; /* Nothing to do */ | ||
1546 | case OBJ_REQUEST_BIO: | 1560 | case OBJ_REQUEST_BIO: |
1547 | rbd_assert(obj_request->bio_list != NULL); | 1561 | rbd_assert(obj_request->bio_list != NULL); |
1548 | osd_req->r_bio = obj_request->bio_list; | 1562 | osd_req->r_bio = obj_request->bio_list; |
@@ -1635,6 +1649,8 @@ static void rbd_obj_request_destroy(struct kref *kref) | |||
1635 | 1649 | ||
1636 | rbd_assert(obj_request_type_valid(obj_request->type)); | 1650 | rbd_assert(obj_request_type_valid(obj_request->type)); |
1637 | switch (obj_request->type) { | 1651 | switch (obj_request->type) { |
1652 | case OBJ_REQUEST_NODATA: | ||
1653 | break; /* Nothing to do */ | ||
1638 | case OBJ_REQUEST_BIO: | 1654 | case OBJ_REQUEST_BIO: |
1639 | if (obj_request->bio_list) | 1655 | if (obj_request->bio_list) |
1640 | bio_chain_put(obj_request->bio_list); | 1656 | bio_chain_put(obj_request->bio_list); |
@@ -1862,6 +1878,72 @@ static int rbd_img_request_submit(struct rbd_img_request *img_request) | |||
1862 | return 0; | 1878 | return 0; |
1863 | } | 1879 | } |
1864 | 1880 | ||
1881 | /* | ||
1882 | * Request sync osd watch/unwatch. The value of "start" determines | ||
1883 | * whether a watch request is being initiated or torn down. | ||
1884 | */ | ||
1885 | static int rbd_dev_header_watch_sync(struct rbd_device *rbd_dev, int start) | ||
1886 | { | ||
1887 | struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc; | ||
1888 | struct rbd_obj_request *obj_request; | ||
1889 | struct ceph_osd_req_op *op; | ||
1890 | int ret; | ||
1891 | |||
1892 | rbd_assert(start ^ !!rbd_dev->watch_event); | ||
1893 | rbd_assert(start ^ !!rbd_dev->watch_request); | ||
1894 | |||
1895 | if (start) { | ||
1896 | ret = ceph_osdc_create_event(osdc, rbd_watch_cb, 0, rbd_dev, | ||
1897 | &rbd_dev->watch_event); | ||
1898 | if (ret < 0) | ||
1899 | return ret; | ||
1900 | } | ||
1901 | |||
1902 | ret = -ENOMEM; | ||
1903 | obj_request = rbd_obj_request_create(rbd_dev->header_name, 0, 0, | ||
1904 | OBJ_REQUEST_NODATA); | ||
1905 | if (!obj_request) | ||
1906 | goto out_cancel; | ||
1907 | |||
1908 | op = rbd_osd_req_op_create(CEPH_OSD_OP_WATCH, | ||
1909 | rbd_dev->watch_event->cookie, | ||
1910 | rbd_dev->header.obj_version, start); | ||
1911 | if (!op) | ||
1912 | goto out_cancel; | ||
1913 | obj_request->osd_req = rbd_osd_req_create(rbd_dev, true, | ||
1914 | obj_request, op); | ||
1915 | rbd_osd_req_op_destroy(op); | ||
1916 | if (!obj_request->osd_req) | ||
1917 | goto out_cancel; | ||
1918 | |||
1919 | if (start) { | ||
1920 | rbd_dev->watch_request = obj_request->osd_req; | ||
1921 | ceph_osdc_set_request_linger(osdc, rbd_dev->watch_request); | ||
1922 | } | ||
1923 | ret = rbd_obj_request_submit(osdc, obj_request); | ||
1924 | if (ret) | ||
1925 | goto out_cancel; | ||
1926 | ret = rbd_obj_request_wait(obj_request); | ||
1927 | if (ret) | ||
1928 | goto out_cancel; | ||
1929 | |||
1930 | ret = obj_request->result; | ||
1931 | if (ret) | ||
1932 | goto out_cancel; | ||
1933 | |||
1934 | if (start) | ||
1935 | goto done; /* Done if setting up the watch request */ | ||
1936 | out_cancel: | ||
1937 | /* Cancel the event if we're tearing down, or on error */ | ||
1938 | ceph_osdc_cancel_event(rbd_dev->watch_event); | ||
1939 | rbd_dev->watch_event = NULL; | ||
1940 | done: | ||
1941 | if (obj_request) | ||
1942 | rbd_obj_request_put(obj_request); | ||
1943 | |||
1944 | return ret; | ||
1945 | } | ||
1946 | |||
1865 | static void rbd_request_fn(struct request_queue *q) | 1947 | static void rbd_request_fn(struct request_queue *q) |
1866 | { | 1948 | { |
1867 | struct rbd_device *rbd_dev = q->queuedata; | 1949 | struct rbd_device *rbd_dev = q->queuedata; |
@@ -3879,7 +3961,8 @@ static int rbd_dev_probe_finish(struct rbd_device *rbd_dev) | |||
3879 | if (ret) | 3961 | if (ret) |
3880 | goto err_out_bus; | 3962 | goto err_out_bus; |
3881 | 3963 | ||
3882 | ret = rbd_req_sync_watch(rbd_dev, 1); | 3964 | (void) rbd_req_sync_watch; /* avoid a warning */ |
3965 | ret = rbd_dev_header_watch_sync(rbd_dev, 1); | ||
3883 | if (ret) | 3966 | if (ret) |
3884 | goto err_out_bus; | 3967 | goto err_out_bus; |
3885 | 3968 | ||
@@ -4042,7 +4125,7 @@ static void rbd_dev_release(struct device *dev) | |||
4042 | rbd_dev->watch_request); | 4125 | rbd_dev->watch_request); |
4043 | } | 4126 | } |
4044 | if (rbd_dev->watch_event) | 4127 | if (rbd_dev->watch_event) |
4045 | rbd_req_sync_watch(rbd_dev, 0); | 4128 | rbd_dev_header_watch_sync(rbd_dev, 0); |
4046 | 4129 | ||
4047 | /* clean up and free blkdev */ | 4130 | /* clean up and free blkdev */ |
4048 | rbd_free_disk(rbd_dev); | 4131 | rbd_free_disk(rbd_dev); |