On 03/15/2013 12:32 PM, Daniel P. Berrange wrote: > From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> > > Add a virFileNBDDeviceAssociate method, which given a filename > will setup a NBD device, using qemu-nbd as the server. > > Signed-off-by: Daniel P. Berrange <berrange@xxxxxxxxxx> > --- > src/libvirt_private.syms | 1 + > src/util/virfile.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++ > src/util/virfile.h | 4 ++ > 3 files changed, 129 insertions(+) > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index 5cad990..0607bae 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -1253,6 +1253,7 @@ virFileDirectFdFlag; > virFileFclose; > virFileFdopen; > virFileLoopDeviceAssociate; > +virFileNBDDeviceAssociate; > virFileRewrite; > virFileTouch; > virFileUpdatePerm; > diff --git a/src/util/virfile.c b/src/util/virfile.c > index 4a9fa81..095559e 100644 > --- a/src/util/virfile.c > +++ b/src/util/virfile.c > @@ -631,6 +631,119 @@ cleanup: > return lofd; > } > > + > +# define SYSFS_BLOCK_DIR "/sys/block" > + > + > +static int > +virFileNBDDeviceIsBusy(const char *devname) > +{ > + char *path; > + int ret = -1; > + > + if (virAsprintf(&path, SYSFS_BLOCK_DIR "/%s/pid", > + devname) < 0) { > + virReportOOMError(); > + return -1; > + } > + > + if (access(path, F_OK) < 0) { > + if (errno == ENOENT) > + ret = 0; > + else > + virReportSystemError(errno, > + _("Cannot check NBD device %s pid"), > + devname); > + goto cleanup; > + } > + ret = 1; > + > +cleanup: > + VIR_FREE(path); > + return ret; > +} > + > + > +static char * > +virFileNBDDeviceFindUnused(void) > +{ > + DIR *dh; > + char *ret = NULL; > + struct dirent *de; > + > + if (!(dh = opendir(SYSFS_BLOCK_DIR))) { > + virReportSystemError(errno, > + _("Cannot read directory %s"), > + SYSFS_BLOCK_DIR); > + return NULL; > + } > + > + while ((de = readdir(dh)) != NULL) { > + if (STRPREFIX(de->d_name, "nbd")) { > + int rv = virFileNBDDeviceIsBusy(de->d_name); > + if (rv < 0) > + goto cleanup; > + if (rv == 0) { > + if (virAsprintf(&ret, "/dev/%s", de->d_name) < 0) { > + virReportOOMError(); > + goto cleanup; > + } > + goto cleanup; > + } > + } > + } > + > + virReportSystemError(EBUSY, "%s", > + _("No free NBD devices")); > + > +cleanup: > + closedir(dh); > + return ret; > +} > + > + > +int virFileNBDDeviceAssociate(const char *file, > + char **dev, > + bool readonly) > +{ > + char *nbddev; > + char *qemunbd; > + virCommandPtr cmd = NULL; > + int ret = -1; > + > + if (!(nbddev = virFileNBDDeviceFindUnused())) > + goto cleanup; > + > + if (!(qemunbd = virFindFileInPath("qemu-nbd"))) { > + virReportSystemError(ENOENT, "%s", > + _("Unable to find 'qemu-nbd' binary in $PATH")); > + goto cleanup; > + } > + > + cmd = virCommandNew(qemunbd); > + if (readonly) > + virCommandAddArg(cmd, "-r"); > + virCommandAddArgList(cmd, > + "-n", /* Don't cache in qemu-nbd layer */ > + "-c", nbddev, > + file, NULL); > + > + /* qemu-nbd will daemonize itself */ > + > + if (virCommandRun(cmd, NULL) < 0) > + goto cleanup; > + > + *dev = nbddev; > + nbddev = NULL; > + ret = 0; > + > +cleanup: > + VIR_FREE(nbddev); > + VIR_FREE(qemunbd); > + virCommandFree(cmd); > + return ret; > +} > + > #else /* __linux__ */ > > int virFileLoopDeviceAssociate(const char *file, > @@ -643,4 +756,15 @@ int virFileLoopDeviceAssociate(const char *file, > return -1; > } > > +int virFileNBDDeviceAssociate(const char *file, > + char **dev ATTRIBUTE_UNUSED, > + bool readonly ATTRIBUTE_UNUSED) > +{ > + virReportSystemError(ENOSYS, > + _("Unable to associate file %s with NBD device"), > + file); > + *dev = NULL; Since this is done - should this still be UNUSED in the header? > + return -1; > +} > + > #endif /* __linux__ */ > diff --git a/src/util/virfile.h b/src/util/virfile.h > index c885b73..6c9179b 100644 > --- a/src/util/virfile.h > +++ b/src/util/virfile.h > @@ -108,4 +108,8 @@ int virFileUpdatePerm(const char *path, > int virFileLoopDeviceAssociate(const char *file, > char **dev); > > +int virFileNBDDeviceAssociate(const char *file, > + char **dev, > + bool readonly); > + > #endif /* __VIR_FILES_H */ > ACK in any case. -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list