diff options
author | Alex Elder <elder@inktank.com> | 2013-05-08 23:50:04 -0400 |
---|---|---|
committer | Alex Elder <elder@inktank.com> | 2013-05-13 16:06:44 -0400 |
commit | e93f3152357ca75284284bef8eeea7d45fe1bab1 (patch) | |
tree | 772595e38dcf482119c938228c2e4db699bcbaa3 /drivers/block | |
parent | fb65d2284c117cfc28d30217d25a14a8e7a75a94 (diff) |
rbd: define parent image request routines
Define rbd_parent_request_create() and rbd_parent_request_destroy()
to handle the creation of parent image requests submitted for
layered image objects. For simplicity, let rbd_img_request_put()
handle dropping the reference to any image request (parent or not),
and call whichever destructor is appropriate on the last put.
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 | 78 |
1 files changed, 55 insertions, 23 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 9c2b20a88be2..1ffdfbfbf3c4 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
@@ -1359,13 +1359,18 @@ static void rbd_obj_request_put(struct rbd_obj_request *obj_request) | |||
1359 | kref_put(&obj_request->kref, rbd_obj_request_destroy); | 1359 | kref_put(&obj_request->kref, rbd_obj_request_destroy); |
1360 | } | 1360 | } |
1361 | 1361 | ||
1362 | static bool img_request_child_test(struct rbd_img_request *img_request); | ||
1363 | static void rbd_parent_request_destroy(struct kref *kref); | ||
1362 | static void rbd_img_request_destroy(struct kref *kref); | 1364 | static void rbd_img_request_destroy(struct kref *kref); |
1363 | static void rbd_img_request_put(struct rbd_img_request *img_request) | 1365 | static void rbd_img_request_put(struct rbd_img_request *img_request) |
1364 | { | 1366 | { |
1365 | rbd_assert(img_request != NULL); | 1367 | rbd_assert(img_request != NULL); |
1366 | dout("%s: img %p (was %d)\n", __func__, img_request, | 1368 | dout("%s: img %p (was %d)\n", __func__, img_request, |
1367 | atomic_read(&img_request->kref.refcount)); | 1369 | atomic_read(&img_request->kref.refcount)); |
1368 | kref_put(&img_request->kref, rbd_img_request_destroy); | 1370 | if (img_request_child_test(img_request)) |
1371 | kref_put(&img_request->kref, rbd_parent_request_destroy); | ||
1372 | else | ||
1373 | kref_put(&img_request->kref, rbd_img_request_destroy); | ||
1369 | } | 1374 | } |
1370 | 1375 | ||
1371 | static inline void rbd_img_obj_request_add(struct rbd_img_request *img_request, | 1376 | static inline void rbd_img_obj_request_add(struct rbd_img_request *img_request, |
@@ -1482,6 +1487,12 @@ static void img_request_child_set(struct rbd_img_request *img_request) | |||
1482 | smp_mb(); | 1487 | smp_mb(); |
1483 | } | 1488 | } |
1484 | 1489 | ||
1490 | static void img_request_child_clear(struct rbd_img_request *img_request) | ||
1491 | { | ||
1492 | clear_bit(IMG_REQ_CHILD, &img_request->flags); | ||
1493 | smp_mb(); | ||
1494 | } | ||
1495 | |||
1485 | static bool img_request_child_test(struct rbd_img_request *img_request) | 1496 | static bool img_request_child_test(struct rbd_img_request *img_request) |
1486 | { | 1497 | { |
1487 | smp_mb(); | 1498 | smp_mb(); |
@@ -1856,8 +1867,7 @@ static void rbd_dev_unparent(struct rbd_device *rbd_dev) | |||
1856 | static struct rbd_img_request *rbd_img_request_create( | 1867 | static struct rbd_img_request *rbd_img_request_create( |
1857 | struct rbd_device *rbd_dev, | 1868 | struct rbd_device *rbd_dev, |
1858 | u64 offset, u64 length, | 1869 | u64 offset, u64 length, |
1859 | bool write_request, | 1870 | bool write_request) |
1860 | bool child_request) | ||
1861 | { | 1871 | { |
1862 | struct rbd_img_request *img_request; | 1872 | struct rbd_img_request *img_request; |
1863 | 1873 | ||
@@ -1882,8 +1892,6 @@ static struct rbd_img_request *rbd_img_request_create( | |||
1882 | } else { | 1892 | } else { |
1883 | img_request->snap_id = rbd_dev->spec->snap_id; | 1893 | img_request->snap_id = rbd_dev->spec->snap_id; |
1884 | } | 1894 | } |
1885 | if (child_request) | ||
1886 | img_request_child_set(img_request); | ||
1887 | if (rbd_dev->parent_overlap) | 1895 | if (rbd_dev->parent_overlap) |
1888 | img_request_layered_set(img_request); | 1896 | img_request_layered_set(img_request); |
1889 | spin_lock_init(&img_request->completion_lock); | 1897 | spin_lock_init(&img_request->completion_lock); |
@@ -1918,12 +1926,46 @@ static void rbd_img_request_destroy(struct kref *kref) | |||
1918 | if (img_request_write_test(img_request)) | 1926 | if (img_request_write_test(img_request)) |
1919 | ceph_put_snap_context(img_request->snapc); | 1927 | ceph_put_snap_context(img_request->snapc); |
1920 | 1928 | ||
1921 | if (img_request_child_test(img_request)) | ||
1922 | rbd_obj_request_put(img_request->obj_request); | ||
1923 | |||
1924 | kmem_cache_free(rbd_img_request_cache, img_request); | 1929 | kmem_cache_free(rbd_img_request_cache, img_request); |
1925 | } | 1930 | } |
1926 | 1931 | ||
1932 | static struct rbd_img_request *rbd_parent_request_create( | ||
1933 | struct rbd_obj_request *obj_request, | ||
1934 | u64 img_offset, u64 length) | ||
1935 | { | ||
1936 | struct rbd_img_request *parent_request; | ||
1937 | struct rbd_device *rbd_dev; | ||
1938 | |||
1939 | rbd_assert(obj_request->img_request); | ||
1940 | rbd_dev = obj_request->img_request->rbd_dev; | ||
1941 | |||
1942 | parent_request = rbd_img_request_create(rbd_dev->parent, | ||
1943 | img_offset, length, false); | ||
1944 | if (!parent_request) | ||
1945 | return NULL; | ||
1946 | |||
1947 | img_request_child_set(parent_request); | ||
1948 | rbd_obj_request_get(obj_request); | ||
1949 | parent_request->obj_request = obj_request; | ||
1950 | |||
1951 | return parent_request; | ||
1952 | } | ||
1953 | |||
1954 | static void rbd_parent_request_destroy(struct kref *kref) | ||
1955 | { | ||
1956 | struct rbd_img_request *parent_request; | ||
1957 | struct rbd_obj_request *orig_request; | ||
1958 | |||
1959 | parent_request = container_of(kref, struct rbd_img_request, kref); | ||
1960 | orig_request = parent_request->obj_request; | ||
1961 | |||
1962 | parent_request->obj_request = NULL; | ||
1963 | rbd_obj_request_put(orig_request); | ||
1964 | img_request_child_clear(parent_request); | ||
1965 | |||
1966 | rbd_img_request_destroy(kref); | ||
1967 | } | ||
1968 | |||
1927 | static bool rbd_img_obj_end_request(struct rbd_obj_request *obj_request) | 1969 | static bool rbd_img_obj_end_request(struct rbd_obj_request *obj_request) |
1928 | { | 1970 | { |
1929 | struct rbd_img_request *img_request; | 1971 | struct rbd_img_request *img_request; |
@@ -2321,13 +2363,10 @@ static int rbd_img_obj_parent_read_full(struct rbd_obj_request *obj_request) | |||
2321 | } | 2363 | } |
2322 | 2364 | ||
2323 | result = -ENOMEM; | 2365 | result = -ENOMEM; |
2324 | parent_request = rbd_img_request_create(rbd_dev->parent, | 2366 | parent_request = rbd_parent_request_create(obj_request, |
2325 | img_offset, length, | 2367 | img_offset, length); |
2326 | false, true); | ||
2327 | if (!parent_request) | 2368 | if (!parent_request) |
2328 | goto out_err; | 2369 | goto out_err; |
2329 | rbd_obj_request_get(obj_request); | ||
2330 | parent_request->obj_request = obj_request; | ||
2331 | 2370 | ||
2332 | result = rbd_img_request_fill(parent_request, OBJ_REQUEST_PAGES, pages); | 2371 | result = rbd_img_request_fill(parent_request, OBJ_REQUEST_PAGES, pages); |
2333 | if (result) | 2372 | if (result) |
@@ -2580,7 +2619,6 @@ out: | |||
2580 | 2619 | ||
2581 | static void rbd_img_parent_read(struct rbd_obj_request *obj_request) | 2620 | static void rbd_img_parent_read(struct rbd_obj_request *obj_request) |
2582 | { | 2621 | { |
2583 | struct rbd_device *rbd_dev; | ||
2584 | struct rbd_img_request *img_request; | 2622 | struct rbd_img_request *img_request; |
2585 | int result; | 2623 | int result; |
2586 | 2624 | ||
@@ -2589,20 +2627,14 @@ static void rbd_img_parent_read(struct rbd_obj_request *obj_request) | |||
2589 | rbd_assert(obj_request->result == (s32) -ENOENT); | 2627 | rbd_assert(obj_request->result == (s32) -ENOENT); |
2590 | rbd_assert(obj_request_type_valid(obj_request->type)); | 2628 | rbd_assert(obj_request_type_valid(obj_request->type)); |
2591 | 2629 | ||
2592 | rbd_dev = obj_request->img_request->rbd_dev; | ||
2593 | rbd_assert(rbd_dev->parent != NULL); | ||
2594 | /* rbd_read_finish(obj_request, obj_request->length); */ | 2630 | /* rbd_read_finish(obj_request, obj_request->length); */ |
2595 | img_request = rbd_img_request_create(rbd_dev->parent, | 2631 | img_request = rbd_parent_request_create(obj_request, |
2596 | obj_request->img_offset, | 2632 | obj_request->img_offset, |
2597 | obj_request->length, | 2633 | obj_request->length); |
2598 | false, true); | ||
2599 | result = -ENOMEM; | 2634 | result = -ENOMEM; |
2600 | if (!img_request) | 2635 | if (!img_request) |
2601 | goto out_err; | 2636 | goto out_err; |
2602 | 2637 | ||
2603 | rbd_obj_request_get(obj_request); | ||
2604 | img_request->obj_request = obj_request; | ||
2605 | |||
2606 | if (obj_request->type == OBJ_REQUEST_BIO) | 2638 | if (obj_request->type == OBJ_REQUEST_BIO) |
2607 | result = rbd_img_request_fill(img_request, OBJ_REQUEST_BIO, | 2639 | result = rbd_img_request_fill(img_request, OBJ_REQUEST_BIO, |
2608 | obj_request->bio_list); | 2640 | obj_request->bio_list); |
@@ -2913,7 +2945,7 @@ static void rbd_request_fn(struct request_queue *q) | |||
2913 | 2945 | ||
2914 | result = -ENOMEM; | 2946 | result = -ENOMEM; |
2915 | img_request = rbd_img_request_create(rbd_dev, offset, length, | 2947 | img_request = rbd_img_request_create(rbd_dev, offset, length, |
2916 | write_request, false); | 2948 | write_request); |
2917 | if (!img_request) | 2949 | if (!img_request) |
2918 | goto end_request; | 2950 | goto end_request; |
2919 | 2951 | ||