[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