mirror of https://gitee.com/openkylin/libvirt.git
Add a helper API for setting up a NBD device with qemu-nbd
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@redhat.com>
This commit is contained in:
parent
1eeff53d7d
commit
8aabd597b3
|
@ -1298,6 +1298,7 @@ virFileLoopDeviceAssociate;
|
||||||
virFileMakePath;
|
virFileMakePath;
|
||||||
virFileMakePathWithMode;
|
virFileMakePathWithMode;
|
||||||
virFileMatchesNameSuffix;
|
virFileMatchesNameSuffix;
|
||||||
|
virFileNBDDeviceAssociate;
|
||||||
virFileOpenAs;
|
virFileOpenAs;
|
||||||
virFileOpenTty;
|
virFileOpenTty;
|
||||||
virFileReadAll;
|
virFileReadAll;
|
||||||
|
|
|
@ -653,6 +653,138 @@ cleanup:
|
||||||
return lofd;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errno = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errno != 0)
|
||||||
|
virReportSystemError(errno, "%s",
|
||||||
|
_("Unable to iterate over NBD devices"));
|
||||||
|
else
|
||||||
|
virReportSystemError(EBUSY, "%s",
|
||||||
|
_("No free NBD devices"));
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
closedir(dh);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int virFileNBDDeviceAssociate(const char *file,
|
||||||
|
enum virStorageFileFormat fmt,
|
||||||
|
bool readonly,
|
||||||
|
char **dev)
|
||||||
|
{
|
||||||
|
char *nbddev;
|
||||||
|
char *qemunbd;
|
||||||
|
virCommandPtr cmd = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
const char *fmtstr = NULL;
|
||||||
|
|
||||||
|
if (!(nbddev = virFileNBDDeviceFindUnused()))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!(qemunbd = virFindFileInPath("qemu-nbd"))) {
|
||||||
|
virReportSystemError(ENOENT, "%s",
|
||||||
|
_("Unable to find 'qemu-nbd' binary in $PATH"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fmt > 0)
|
||||||
|
fmtstr = virStorageFileFormatTypeToString(fmt);
|
||||||
|
|
||||||
|
cmd = virCommandNew(qemunbd);
|
||||||
|
|
||||||
|
/* Explicitly not trying to cope with old qemu-nbd which
|
||||||
|
* lacked --format. We want to see a fatal error in that
|
||||||
|
* case since it would be security flaw to continue */
|
||||||
|
if (fmtstr)
|
||||||
|
virCommandAddArgList(cmd, "--format", fmtstr, NULL);
|
||||||
|
|
||||||
|
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__ */
|
#else /* __linux__ */
|
||||||
|
|
||||||
int virFileLoopDeviceAssociate(const char *file,
|
int virFileLoopDeviceAssociate(const char *file,
|
||||||
|
@ -665,6 +797,17 @@ int virFileLoopDeviceAssociate(const char *file,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int virFileNBDDeviceAssociate(const char *file,
|
||||||
|
enum virStorageFileFormat fmt ATTRIBUTE_UNUSED,
|
||||||
|
bool readonly ATTRIBUTE_UNUSED,
|
||||||
|
char **dev ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
virReportSystemError(ENOSYS,
|
||||||
|
_("Unable to associate file %s with NBD device"),
|
||||||
|
file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* __linux__ */
|
#endif /* __linux__ */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
|
|
||||||
# include "internal.h"
|
# include "internal.h"
|
||||||
|
# include "virstoragefile.h"
|
||||||
|
|
||||||
typedef enum virFileCloseFlags {
|
typedef enum virFileCloseFlags {
|
||||||
VIR_FILE_CLOSE_PRESERVE_ERRNO = 1 << 0,
|
VIR_FILE_CLOSE_PRESERVE_ERRNO = 1 << 0,
|
||||||
|
@ -114,6 +115,11 @@ int virFileUpdatePerm(const char *path,
|
||||||
int virFileLoopDeviceAssociate(const char *file,
|
int virFileLoopDeviceAssociate(const char *file,
|
||||||
char **dev);
|
char **dev);
|
||||||
|
|
||||||
|
int virFileNBDDeviceAssociate(const char *file,
|
||||||
|
enum virStorageFileFormat fmt,
|
||||||
|
bool readonly,
|
||||||
|
char **dev);
|
||||||
|
|
||||||
int virFileDeleteTree(const char *dir);
|
int virFileDeleteTree(const char *dir);
|
||||||
|
|
||||||
int virFileReadLimFD(int fd, int maxlen, char **buf) ATTRIBUTE_RETURN_CHECK;
|
int virFileReadLimFD(int fd, int maxlen, char **buf) ATTRIBUTE_RETURN_CHECK;
|
||||||
|
|
Loading…
Reference in New Issue