rbd: timeout watch teardown on unmap with mount_timeout
As part of unmap sequence, kernel client has to talk to the OSDs to teardown watch on the header object. If none of the OSDs are available it would hang forever, until interrupted by a signal - when that happens we follow through with the rest of unmap procedure (i.e. unregister the device and put all the data structures) and the unmap is still considired successful (rbd cli tool exits with 0). The watch on the userspace side should eventually timeout so that's fine. This isn't very nice, because various userspace tools (pacemaker rbd resource agent, for example) then have to worry about setting up their own timeouts. Timeout it with mount_timeout (60 seconds by default). Signed-off-by: Ilya Dryomov <idryomov@gmail.com> Reviewed-by: Alex Elder <elder@linaro.org> Reviewed-by: Sage Weil <sage@redhat.com>
This commit is contained in:
parent
5be7303477
commit
2894e1d769
1 changed files with 28 additions and 10 deletions
|
@ -1563,22 +1563,39 @@ static void rbd_obj_request_end(struct rbd_obj_request *obj_request)
|
||||||
/*
|
/*
|
||||||
* Wait for an object request to complete. If interrupted, cancel the
|
* Wait for an object request to complete. If interrupted, cancel the
|
||||||
* underlying osd request.
|
* underlying osd request.
|
||||||
|
*
|
||||||
|
* @timeout: in jiffies, 0 means "wait forever"
|
||||||
*/
|
*/
|
||||||
static int rbd_obj_request_wait(struct rbd_obj_request *obj_request)
|
static int __rbd_obj_request_wait(struct rbd_obj_request *obj_request,
|
||||||
|
unsigned long timeout)
|
||||||
{
|
{
|
||||||
int ret;
|
long ret;
|
||||||
|
|
||||||
dout("%s %p\n", __func__, obj_request);
|
dout("%s %p\n", __func__, obj_request);
|
||||||
|
ret = wait_for_completion_interruptible_timeout(
|
||||||
ret = wait_for_completion_interruptible(&obj_request->completion);
|
&obj_request->completion,
|
||||||
if (ret < 0) {
|
ceph_timeout_jiffies(timeout));
|
||||||
dout("%s %p interrupted\n", __func__, obj_request);
|
if (ret <= 0) {
|
||||||
|
if (ret == 0)
|
||||||
|
ret = -ETIMEDOUT;
|
||||||
rbd_obj_request_end(obj_request);
|
rbd_obj_request_end(obj_request);
|
||||||
return ret;
|
} else {
|
||||||
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
dout("%s %p done\n", __func__, obj_request);
|
dout("%s %p ret %d\n", __func__, obj_request, (int)ret);
|
||||||
return 0;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rbd_obj_request_wait(struct rbd_obj_request *obj_request)
|
||||||
|
{
|
||||||
|
return __rbd_obj_request_wait(obj_request, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rbd_obj_request_wait_timeout(struct rbd_obj_request *obj_request,
|
||||||
|
unsigned long timeout)
|
||||||
|
{
|
||||||
|
return __rbd_obj_request_wait(obj_request, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rbd_img_request_complete(struct rbd_img_request *img_request)
|
static void rbd_img_request_complete(struct rbd_img_request *img_request)
|
||||||
|
@ -3122,6 +3139,7 @@ static struct rbd_obj_request *rbd_obj_watch_request_helper(
|
||||||
bool watch)
|
bool watch)
|
||||||
{
|
{
|
||||||
struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
|
struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
|
||||||
|
struct ceph_options *opts = osdc->client->options;
|
||||||
struct rbd_obj_request *obj_request;
|
struct rbd_obj_request *obj_request;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -3148,7 +3166,7 @@ static struct rbd_obj_request *rbd_obj_watch_request_helper(
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = rbd_obj_request_wait(obj_request);
|
ret = rbd_obj_request_wait_timeout(obj_request, opts->mount_timeout);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue