diff options
author | Ilya Dryomov <ilya.dryomov@inktank.com> | 2014-06-20 10:29:20 -0400 |
---|---|---|
committer | Ilya Dryomov <ilya.dryomov@inktank.com> | 2014-07-08 07:08:45 -0400 |
commit | 76756a51e27984692fe0affa564e89ee8d323e66 (patch) | |
tree | 905f22e40bc4e2f7a95c8db69aac4d98feda068d | |
parent | bb040aa03ce870b0eff21ee75f7f324cd8cabe03 (diff) |
rbd: use rbd_obj_watch_request_helper() helper
Switch rbd_dev_header_{un,}watch_sync() to use the new helper and fix
rbd_dev_header_unwatch_sync() to destroy watch_request structures
before queuing watch-remove message while at it. This mistake slipped
into commit b30a01f2a307 ("rbd: fix osd_request memory leak in
__rbd_dev_header_watch_sync()") and could lead to "image still in use"
errors on image removal.
Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com>
Reviewed-by: Alex Elder <elder@linaro.org>
-rw-r--r-- | drivers/block/rbd.c | 115 |
1 files changed, 17 insertions, 98 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 02cf7aba7679..d99aa81774f8 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
@@ -3040,130 +3040,49 @@ static int rbd_dev_header_watch_sync(struct rbd_device *rbd_dev) | |||
3040 | if (ret < 0) | 3040 | if (ret < 0) |
3041 | return ret; | 3041 | return ret; |
3042 | 3042 | ||
3043 | rbd_assert(rbd_dev->watch_event); | 3043 | obj_request = rbd_obj_watch_request_helper(rbd_dev, true); |
3044 | 3044 | if (IS_ERR(obj_request)) { | |
3045 | obj_request = rbd_obj_request_create(rbd_dev->header_name, 0, 0, | 3045 | ceph_osdc_cancel_event(rbd_dev->watch_event); |
3046 | OBJ_REQUEST_NODATA); | 3046 | rbd_dev->watch_event = NULL; |
3047 | if (!obj_request) { | 3047 | return PTR_ERR(obj_request); |
3048 | ret = -ENOMEM; | ||
3049 | goto out_cancel; | ||
3050 | } | 3048 | } |
3051 | 3049 | ||
3052 | obj_request->osd_req = rbd_osd_req_create(rbd_dev, true, 1, | ||
3053 | obj_request); | ||
3054 | if (!obj_request->osd_req) { | ||
3055 | ret = -ENOMEM; | ||
3056 | goto out_put; | ||
3057 | } | ||
3058 | |||
3059 | ceph_osdc_set_request_linger(osdc, obj_request->osd_req); | ||
3060 | |||
3061 | osd_req_op_watch_init(obj_request->osd_req, 0, CEPH_OSD_OP_WATCH, | ||
3062 | rbd_dev->watch_event->cookie, 0, 1); | ||
3063 | rbd_osd_req_format_write(obj_request); | ||
3064 | |||
3065 | ret = rbd_obj_request_submit(osdc, obj_request); | ||
3066 | if (ret) | ||
3067 | goto out_linger; | ||
3068 | |||
3069 | ret = rbd_obj_request_wait(obj_request); | ||
3070 | if (ret) | ||
3071 | goto out_linger; | ||
3072 | |||
3073 | ret = obj_request->result; | ||
3074 | if (ret) | ||
3075 | goto out_linger; | ||
3076 | |||
3077 | /* | 3050 | /* |
3078 | * A watch request is set to linger, so the underlying osd | 3051 | * A watch request is set to linger, so the underlying osd |
3079 | * request won't go away until we unregister it. We retain | 3052 | * request won't go away until we unregister it. We retain |
3080 | * a pointer to the object request during that time (in | 3053 | * a pointer to the object request during that time (in |
3081 | * rbd_dev->watch_request), so we'll keep a reference to | 3054 | * rbd_dev->watch_request), so we'll keep a reference to it. |
3082 | * it. We'll drop that reference (below) after we've | 3055 | * We'll drop that reference after we've unregistered it in |
3083 | * unregistered it. | 3056 | * rbd_dev_header_unwatch_sync(). |
3084 | */ | 3057 | */ |
3085 | rbd_dev->watch_request = obj_request; | 3058 | rbd_dev->watch_request = obj_request; |
3086 | 3059 | ||
3087 | return 0; | 3060 | return 0; |
3088 | |||
3089 | out_linger: | ||
3090 | ceph_osdc_unregister_linger_request(osdc, obj_request->osd_req); | ||
3091 | out_put: | ||
3092 | rbd_obj_request_put(obj_request); | ||
3093 | out_cancel: | ||
3094 | ceph_osdc_cancel_event(rbd_dev->watch_event); | ||
3095 | rbd_dev->watch_event = NULL; | ||
3096 | |||
3097 | return ret; | ||
3098 | } | 3061 | } |
3099 | 3062 | ||
3100 | /* | 3063 | /* |
3101 | * Tear down a watch request, synchronously. | 3064 | * Tear down a watch request, synchronously. |
3102 | */ | 3065 | */ |
3103 | static int __rbd_dev_header_unwatch_sync(struct rbd_device *rbd_dev) | 3066 | static void rbd_dev_header_unwatch_sync(struct rbd_device *rbd_dev) |
3104 | { | 3067 | { |
3105 | struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc; | ||
3106 | struct rbd_obj_request *obj_request; | 3068 | struct rbd_obj_request *obj_request; |
3107 | int ret; | ||
3108 | 3069 | ||
3109 | rbd_assert(rbd_dev->watch_event); | 3070 | rbd_assert(rbd_dev->watch_event); |
3110 | rbd_assert(rbd_dev->watch_request); | 3071 | rbd_assert(rbd_dev->watch_request); |
3111 | 3072 | ||
3112 | obj_request = rbd_obj_request_create(rbd_dev->header_name, 0, 0, | 3073 | rbd_obj_request_end(rbd_dev->watch_request); |
3113 | OBJ_REQUEST_NODATA); | ||
3114 | if (!obj_request) { | ||
3115 | ret = -ENOMEM; | ||
3116 | goto out_cancel; | ||
3117 | } | ||
3118 | |||
3119 | obj_request->osd_req = rbd_osd_req_create(rbd_dev, true, 1, | ||
3120 | obj_request); | ||
3121 | if (!obj_request->osd_req) { | ||
3122 | ret = -ENOMEM; | ||
3123 | goto out_put; | ||
3124 | } | ||
3125 | |||
3126 | osd_req_op_watch_init(obj_request->osd_req, 0, CEPH_OSD_OP_WATCH, | ||
3127 | rbd_dev->watch_event->cookie, 0, 0); | ||
3128 | rbd_osd_req_format_write(obj_request); | ||
3129 | |||
3130 | ret = rbd_obj_request_submit(osdc, obj_request); | ||
3131 | if (ret) | ||
3132 | goto out_put; | ||
3133 | |||
3134 | ret = rbd_obj_request_wait(obj_request); | ||
3135 | if (ret) | ||
3136 | goto out_put; | ||
3137 | |||
3138 | ret = obj_request->result; | ||
3139 | if (ret) | ||
3140 | goto out_put; | ||
3141 | |||
3142 | /* We have successfully torn down the watch request */ | ||
3143 | |||
3144 | ceph_osdc_unregister_linger_request(osdc, | ||
3145 | rbd_dev->watch_request->osd_req); | ||
3146 | rbd_obj_request_put(rbd_dev->watch_request); | 3074 | rbd_obj_request_put(rbd_dev->watch_request); |
3147 | rbd_dev->watch_request = NULL; | 3075 | rbd_dev->watch_request = NULL; |
3148 | 3076 | ||
3149 | out_put: | 3077 | obj_request = rbd_obj_watch_request_helper(rbd_dev, false); |
3150 | rbd_obj_request_put(obj_request); | 3078 | if (!IS_ERR(obj_request)) |
3151 | out_cancel: | 3079 | rbd_obj_request_put(obj_request); |
3080 | else | ||
3081 | rbd_warn(rbd_dev, "unable to tear down watch request (%ld)", | ||
3082 | PTR_ERR(obj_request)); | ||
3083 | |||
3152 | ceph_osdc_cancel_event(rbd_dev->watch_event); | 3084 | ceph_osdc_cancel_event(rbd_dev->watch_event); |
3153 | rbd_dev->watch_event = NULL; | 3085 | rbd_dev->watch_event = NULL; |
3154 | |||
3155 | return ret; | ||
3156 | } | ||
3157 | |||
3158 | static void rbd_dev_header_unwatch_sync(struct rbd_device *rbd_dev) | ||
3159 | { | ||
3160 | int ret; | ||
3161 | |||
3162 | ret = __rbd_dev_header_unwatch_sync(rbd_dev); | ||
3163 | if (ret) { | ||
3164 | rbd_warn(rbd_dev, "unable to tear down watch request: %d\n", | ||
3165 | ret); | ||
3166 | } | ||
3167 | } | 3086 | } |
3168 | 3087 | ||
3169 | /* | 3088 | /* |