From a48b8d90d96667482d0fd8a747f1f0280c4fc2f2 Mon Sep 17 00:00:00 2001 From: Lucian Petrut Date: Thu, 24 Aug 2023 11:41:01 +0000 Subject: [PATCH] rbd-wnbd: wait for disks to become available After a WNBD mapping is created, the driver informs Storport that the bus changed, expecting it to rescan the bus and expose the disk. This is an asynchronous process and it usually takes a matter of milliseconds, up to a few seconds under significant load. The fsx librbd test ocasionally fails to open the disk as it isn't ready yet. Unlike the Python rbd-wnbd test, it doesn't perform any polling. For convenience, WNBD now includes a helper function called WnbdPollDiskNumber. We're going to use it to wait for the new disk attachments to become available. Signed-off-by: Lucian Petrut --- src/tools/rbd_wnbd/rbd_wnbd.cc | 43 +++++++++++++++++++++++++++++++++- src/tools/rbd_wnbd/rbd_wnbd.h | 1 + 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/tools/rbd_wnbd/rbd_wnbd.cc b/src/tools/rbd_wnbd/rbd_wnbd.cc index e7d5ecea0665e..bb899e022bda8 100644 --- a/src/tools/rbd_wnbd/rbd_wnbd.cc +++ b/src/tools/rbd_wnbd/rbd_wnbd.cc @@ -482,6 +482,13 @@ int map_device_using_suprocess(std::string arguments, int timeout_ms) clean_process: if (!is_process_running(pi.dwProcessId)) { GetExitCodeProcess(pi.hProcess, (PDWORD)&exit_code); + if (!exit_code) { + // Child terminated unexpectedly. + exit_code = -ECHILD; + } else if (exit_code > 0) { + // Make sure to return a negative error code. + exit_code = -exit_code; + } derr << "Daemon failed with: " << cpp_strerror(exit_code) << dendl; } else { // The process closed the pipe without notifying us or exiting. @@ -1197,6 +1204,28 @@ boost::intrusive_ptr do_global_init( return cct; } +// Wait for the mapped disk to become available. +static int wait_mapped_disk(Config *cfg) +{ + DWORD status = WnbdPollDiskNumber( + cfg->devpath.c_str(), + TRUE, // ExpectMapped + TRUE, // TryOpen + cfg->image_map_timeout, + DISK_STATUS_POLLING_INTERVAL_MS, + (PDWORD) &cfg->disk_number); + if (status) { + derr << "WNBD disk unavailable, error: " + << win32_strerror(status) << dendl; + return -EINVAL; + } + dout(0) << "Successfully mapped image: " << cfg->devpath + << ". Windows disk path: " + << "\\\\.\\PhysicalDrive" + std::to_string(cfg->disk_number) + << dendl; + return 0; +} + static int do_map(Config *cfg) { int r; @@ -1210,7 +1239,12 @@ static int do_map(Config *cfg) int err = 0; if (g_conf()->daemonize && cfg->parent_pipe.empty()) { - return send_map_request(get_cli_args()); + r = send_map_request(get_cli_args()); + if (r < 0) { + return r; + } + + return wait_mapped_disk(cfg); } dout(0) << "Mapping RBD image: " << cfg->devpath << dendl; @@ -1296,6 +1330,13 @@ static int do_map(Config *cfg) goto close_ret; } + // TODO: consider substracting the time it took to perform the + // above operations from cfg->image_map_timeout in wait_mapped_disk(). + r = wait_mapped_disk(cfg); + if (r < 0) { + goto close_ret; + } + // We're informing the parent processes that the initialization // was successful. if (!cfg->parent_pipe.empty()) { diff --git a/src/tools/rbd_wnbd/rbd_wnbd.h b/src/tools/rbd_wnbd/rbd_wnbd.h index ac298e3180f1d..5cb3301fb7c13 100644 --- a/src/tools/rbd_wnbd/rbd_wnbd.h +++ b/src/tools/rbd_wnbd/rbd_wnbd.h @@ -33,6 +33,7 @@ #define DEFAULT_SERVICE_START_TIMEOUT 120 #define DEFAULT_IMAGE_MAP_TIMEOUT 20 +#define DISK_STATUS_POLLING_INTERVAL_MS 500 #define HELP_INFO 1 #define VERSION_INFO 2 -- 2.39.5