From: Mike Christie Date: Tue, 30 Apr 2019 06:54:49 +0000 (-0500) Subject: rbd nbd: move nbd map ioctls to new function X-Git-Tag: v14.2.5~167^2~10 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=eb0d0747fb5a9c2adc1733c28b3480974d804856;p=ceph.git rbd nbd: move nbd map ioctls to new function The next patches will add nbd map netlink support so this moves the ioctl code to a new function to keep things cleaner and not overloading do_map. Signed-off-by: Mike Christie (cherry picked from commit 7ad4b5000ce749f111d8e1f03db6763c5e1c28f4) --- diff --git a/src/tools/rbd_nbd/rbd-nbd.cc b/src/tools/rbd_nbd/rbd-nbd.cc index 5aa3ea1092d..90034b423c4 100644 --- a/src/tools/rbd_nbd/rbd-nbd.cc +++ b/src/tools/rbd_nbd/rbd-nbd.cc @@ -644,6 +644,113 @@ static int check_device_size(int nbd_index, unsigned long expected_size) return 0; } +static int try_ioctl_setup(Config *cfg, int fd, uint64_t size, int *nbd_index, + uint64_t flags) +{ + int index = 0, r; + + if (cfg->devpath.empty()) { + char dev[64]; + bool try_load_module = true; + const char *path = "/sys/module/nbd/parameters/nbds_max"; + int nbds_max = -1; + if (access(path, F_OK) == 0) { + std::ifstream ifs; + ifs.open(path, std::ifstream::in); + if (ifs.is_open()) { + ifs >> nbds_max; + ifs.close(); + } + } + + while (true) { + snprintf(dev, sizeof(dev), "/dev/nbd%d", index); + + nbd = open_device(dev, cfg, try_load_module); + try_load_module = false; + if (nbd < 0) { + if (nbd == -EPERM && nbds_max != -1 && index < (nbds_max-1)) { + ++index; + continue; + } + r = nbd; + cerr << "rbd-nbd: failed to find unused device" << std::endl; + goto done; + } + + r = ioctl(nbd, NBD_SET_SOCK, fd); + if (r < 0) { + close(nbd); + ++index; + continue; + } + + cfg->devpath = dev; + break; + } + } else { + r = sscanf(cfg->devpath.c_str(), "/dev/nbd%d", &index); + if (r <= 0) { + // mean an early matching failure. But some cases need a negative value. + if (r == 0) + r = -EINVAL; + cerr << "rbd-nbd: invalid device path: " << cfg->devpath + << " (expected /dev/nbd{num})" << std::endl; + goto done; + } + nbd = open_device(cfg->devpath.c_str(), cfg, true); + if (nbd < 0) { + r = nbd; + cerr << "rbd-nbd: failed to open device: " << cfg->devpath << std::endl; + goto done; + } + + r = ioctl(nbd, NBD_SET_SOCK, fd); + if (r < 0) { + r = -errno; + cerr << "rbd-nbd: the device " << cfg->devpath << " is busy" << std::endl; + close(nbd); + goto done; + } + } + + r = ioctl(nbd, NBD_SET_BLKSIZE, RBD_NBD_BLKSIZE); + if (r < 0) { + r = -errno; + goto close_nbd; + } + + r = ioctl(nbd, NBD_SET_SIZE, size); + if (r < 0) { + r = -errno; + goto close_nbd; + } + + ioctl(nbd, NBD_SET_FLAGS, flags); + + if (cfg->timeout >= 0) { + r = ioctl(nbd, NBD_SET_TIMEOUT, (unsigned long)cfg->timeout); + if (r < 0) { + r = -errno; + cerr << "rbd-nbd: failed to set timeout: " << cpp_strerror(r) + << std::endl; + goto close_nbd; + } + } + + *nbd_index = index; + return 0; + +close_nbd: + if (r < 0) { + ioctl(nbd, NBD_CLEAR_SOCK); + cerr << "rbd-nbd: failed to map, status: " << cpp_strerror(-r) << std::endl; + } + close(nbd); +done: + return r; +} + static int do_map(int argc, const char *argv[], Config *cfg) { int r; @@ -657,7 +764,7 @@ static int do_map(int argc, const char *argv[], Config *cfg) unsigned long flags; unsigned long size; - int index = 0; + int nbd_index; int fd[2]; librbd::image_info_t info; @@ -741,121 +848,36 @@ static int do_map(int argc, const char *argv[], Config *cfg) if (r < 0) goto close_fd; - if (cfg->devpath.empty()) { - char dev[64]; - bool try_load_module = true; - const char *path = "/sys/module/nbd/parameters/nbds_max"; - int nbds_max = -1; - if (access(path, F_OK) == 0) { - std::ifstream ifs; - ifs.open(path, std::ifstream::in); - if (ifs.is_open()) { - ifs >> nbds_max; - ifs.close(); - } - } - - while (true) { - snprintf(dev, sizeof(dev), "/dev/nbd%d", index); - - nbd = open_device(dev, cfg, try_load_module); - try_load_module = false; - if (nbd < 0) { - if (nbd == -EPERM && nbds_max != -1 && index < (nbds_max-1)) { - ++index; - continue; - } - r = nbd; - cerr << "rbd-nbd: failed to find unused device" << std::endl; - goto close_fd; - } - - r = ioctl(nbd, NBD_SET_SOCK, fd[0]); - if (r < 0) { - close(nbd); - ++index; - continue; - } - - cfg->devpath = dev; - break; - } - } else { - r = sscanf(cfg->devpath.c_str(), "/dev/nbd%d", &index); - if (r <= 0) { - // mean an early matching failure. But some cases need a negative value. - if (r == 0) - r = -EINVAL; - cerr << "rbd-nbd: invalid device path: " << cfg->devpath - << " (expected /dev/nbd{num})" << std::endl; - goto close_fd; - } - nbd = open_device(cfg->devpath.c_str(), cfg, true); - if (nbd < 0) { - r = nbd; - cerr << "rbd-nbd: failed to open device: " << cfg->devpath << std::endl; - goto close_fd; - } - - r = ioctl(nbd, NBD_SET_SOCK, fd[0]); - if (r < 0) { - r = -errno; - cerr << "rbd-nbd: the device " << cfg->devpath << " is busy" << std::endl; - close(nbd); - goto close_fd; - } - } - flags = NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_TRIM | NBD_FLAG_HAS_FLAGS; if (!cfg->snapname.empty() || cfg->readonly) { flags |= NBD_FLAG_READ_ONLY; read_only = 1; } - r = ioctl(nbd, NBD_SET_BLKSIZE, RBD_NBD_BLKSIZE); - if (r < 0) { - r = -errno; - goto close_nbd; - } - if (info.size > ULONG_MAX) { r = -EFBIG; cerr << "rbd-nbd: image is too large (" << byte_u_t(info.size) << ", max is " << byte_u_t(ULONG_MAX) << ")" << std::endl; - goto close_nbd; + goto close_fd; } size = info.size; - r = ioctl(nbd, NBD_SET_SIZE, size); - if (r < 0) { - r = -errno; - goto close_nbd; - } + r = try_ioctl_setup(cfg, fd[0], size, &nbd_index, flags); + if (r < 0) + goto close_fd; - r = check_device_size(index, size); + r = check_device_size(nbd_index, size); if (r < 0) { goto close_nbd; } - ioctl(nbd, NBD_SET_FLAGS, flags); - r = ioctl(nbd, BLKROSET, (unsigned long) &read_only); if (r < 0) { r = -errno; goto close_nbd; } - if (cfg->timeout >= 0) { - r = ioctl(nbd, NBD_SET_TIMEOUT, (unsigned long)cfg->timeout); - if (r < 0) { - r = -errno; - cerr << "rbd-nbd: failed to set timeout: " << cpp_strerror(r) - << std::endl; - goto close_nbd; - } - } - { uint64_t handle;