rbd-nbd: fix ebusy when do map

When doing rbd-nbd map, if the Ceph service is not available,
the codes will wait on rados.connect(), unless killing the process.
In that case, the close_nbd logic is skipped with NBD_CLEAR_SOCK ioctl
not called. On the CentOS 7 kernel, it leaves nbd->file not cleared, which
causes the subsequent map requests return EBUSY, this patch fixes it
by connecting Ceph first prior to calling NBD_SET_SOCK ioctl

Fixes: http://tracker.ceph.com/issues/23528

Signed-off-by: Li Wang <laurence.liwang@gmail.com>
This commit is contained in:
Li Wang 2017-12-07 22:03:45 +08:00
parent 9e8af3e243
commit ab77dcc017

View File

@ -695,6 +695,41 @@ static int do_map(int argc, const char *argv[], Config *cfg)
goto close_ret;
}
r = rados.init_with_context(g_ceph_context);
if (r < 0)
goto close_fd;
r = rados.connect();
if (r < 0)
goto close_fd;
r = rados.ioctx_create(cfg->poolname.c_str(), io_ctx);
if (r < 0)
goto close_fd;
r = rbd.open(io_ctx, image, cfg->imgname.c_str());
if (r < 0)
goto close_fd;
if (cfg->exclusive) {
r = image.lock_acquire(RBD_LOCK_MODE_EXCLUSIVE);
if (r < 0) {
cerr << "rbd-nbd: failed to acquire exclusive lock: " << cpp_strerror(r)
<< std::endl;
goto close_fd;
}
}
if (!cfg->snapname.empty()) {
r = image.snap_set(cfg->snapname.c_str());
if (r < 0)
goto close_fd;
}
r = image.stat(info, sizeof(info));
if (r < 0)
goto close_fd;
if (cfg->devpath.empty()) {
char dev[64];
bool try_load_module = true;
@ -763,41 +798,6 @@ static int do_map(int argc, const char *argv[], Config *cfg)
read_only = 1;
}
r = rados.init_with_context(g_ceph_context);
if (r < 0)
goto close_nbd;
r = rados.connect();
if (r < 0)
goto close_nbd;
r = rados.ioctx_create(cfg->poolname.c_str(), io_ctx);
if (r < 0)
goto close_nbd;
r = rbd.open(io_ctx, image, cfg->imgname.c_str());
if (r < 0)
goto close_nbd;
if (cfg->exclusive) {
r = image.lock_acquire(RBD_LOCK_MODE_EXCLUSIVE);
if (r < 0) {
cerr << "rbd-nbd: failed to acquire exclusive lock: " << cpp_strerror(r)
<< std::endl;
goto close_nbd;
}
}
if (!cfg->snapname.empty()) {
r = image.snap_set(cfg->snapname.c_str());
if (r < 0)
goto close_nbd;
}
r = image.stat(info, sizeof(info));
if (r < 0)
goto close_nbd;
r = ioctl(nbd, NBD_SET_BLKSIZE, RBD_NBD_BLKSIZE);
if (r < 0) {
r = -errno;