Currently qemu-nbd does not support finding free nbd device for users like "losetup -f" and issuing "qemu-nbd -c /dev/nbdX disk.img" won't report error message when /dev/nbd is already in use. It makes things a little confusing. This patch adds "-f" option to qemu-nbd to support finding a free nbd device for users. Please review and share your comments. Thanks.
Signed-off-by: Chunyan Liu <cy...@suse.com> --- qemu-nbd.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 64 insertions(+), 1 deletions(-) diff --git a/qemu-nbd.c b/qemu-nbd.c index 291cba2..5c43a68 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -244,6 +244,60 @@ out: return (void *) EXIT_FAILURE; } +static int is_nbd_used(int minor) +{ + FILE *proc; + int NBDMAJOR = 43; + char buf[BUFSIZ]; + int find = 0; + + proc = fopen("/proc/partitions", "r"); + if (proc != NULL) { + while (fgets(buf, sizeof(buf), proc)) { + int m, n; + unsigned long long sz; + char name[16]; + char *pname = name; + char *end; + + if (sscanf(buf, " %d %d %llu %128[^\n ]", + &m, &n, &sz, name) != 4) + continue; + if (m != NBDMAJOR) + continue; + if (strncmp(name, "nbd", 3)) + continue; + pname += 3; + n = strtol(pname, &end, 10); + if (end && end != pname && *end == '\0' && n == minor) { + find = 1; + break; + } + } + fclose(proc); + } + + return find; +} + +static char *find_free_nbd_device(void) +{ + int i; + int nbds_max = 16; + char name[16]; + char *devname = NULL; + + for (i = 0; i < nbds_max; i++) { + if (!is_nbd_used(i)) { + snprintf(name, sizeof(name), "/dev/nbd%d", i); + devname = strdup(name); + break; + } + } + + return devname; +} + int main(int argc, char **argv) { BlockDriverState *bs; @@ -256,7 +310,7 @@ int main(int argc, char **argv) struct sockaddr_in addr; socklen_t addr_len = sizeof(addr); off_t fd_size; - const char *sopt = "hVb:o:p:rsnP:c:dvk:e:t"; + const char *sopt = "hVb:o:p:rsnP:c:dvk:e:tf"; struct option lopt[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'V' }, @@ -273,6 +327,7 @@ int main(int argc, char **argv) { "shared", 1, NULL, 'e' }, { "persistent", 0, NULL, 't' }, { "verbose", 0, NULL, 'v' }, + { "find", 0, NULL, 'f' }, { NULL, 0, NULL, 0 } }; int ch; @@ -292,6 +347,7 @@ int main(int argc, char **argv) int max_fd; int persistent = 0; pthread_t client_thread; + char *devname = NULL; /* The client thread uses SIGTERM to interrupt the server. A signal * handler ensures that "qemu-nbd -v -c" exits with a nice status code. @@ -374,6 +430,13 @@ int main(int argc, char **argv) case 'v': verbose = 1; break; + case 'f': + devname = find_free_nbd_device(); + if (devname) { + printf("%s\n", devname); + } + exit(0); + break; case 'V': version(argv[0]); exit(0); -- 1.7.3.4