aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIlya Dryomov <ilya.dryomov@inktank.com>2014-06-20 10:29:20 -0400
committerIlya Dryomov <ilya.dryomov@inktank.com>2014-07-08 07:08:45 -0400
commit76756a51e27984692fe0affa564e89ee8d323e66 (patch)
tree905f22e40bc4e2f7a95c8db69aac4d98feda068d
parentbb040aa03ce870b0eff21ee75f7f324cd8cabe03 (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.c115
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
3089out_linger:
3090 ceph_osdc_unregister_linger_request(osdc, obj_request->osd_req);
3091out_put:
3092 rbd_obj_request_put(obj_request);
3093out_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 */
3103static int __rbd_dev_header_unwatch_sync(struct rbd_device *rbd_dev) 3066static 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
3149out_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))
3151out_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
3158static 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/*