[libvirt] [PATCH 4/7] Add a helper API for setting up a NBD device with qemu-nbd
John Ferlan
jferlan at redhat.com
Tue Mar 19 13:39:18 UTC 2013
On 03/15/2013 12:32 PM, Daniel P. Berrange wrote:
> From: "Daniel P. Berrange" <berrange at redhat.com>
>
> 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 at redhat.com>
> ---
> 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.
More information about the libvir-list
mailing list