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;
|
||||
virFileMakePathWithMode;
|
||||
virFileMatchesNameSuffix;
|
||||
virFileNBDDeviceAssociate;
|
||||
virFileOpenAs;
|
||||
virFileOpenTty;
|
||||
virFileReadAll;
|
||||
|
|
|
@ -653,6 +653,138 @@ 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;
|
||||
}
|
||||
|
||||
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__ */
|
||||
|
||||
int virFileLoopDeviceAssociate(const char *file,
|
||||
|
@ -665,6 +797,17 @@ int virFileLoopDeviceAssociate(const char *file,
|
|||
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__ */
|
||||
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
# include <stdio.h>
|
||||
|
||||
# include "internal.h"
|
||||
# include "virstoragefile.h"
|
||||
|
||||
typedef enum virFileCloseFlags {
|
||||
VIR_FILE_CLOSE_PRESERVE_ERRNO = 1 << 0,
|
||||
|
@ -114,6 +115,11 @@ int virFileUpdatePerm(const char *path,
|
|||
int virFileLoopDeviceAssociate(const char *file,
|
||||
char **dev);
|
||||
|
||||
int virFileNBDDeviceAssociate(const char *file,
|
||||
enum virStorageFileFormat fmt,
|
||||
bool readonly,
|
||||
char **dev);
|
||||
|
||||
int virFileDeleteTree(const char *dir);
|
||||
|
||||
int virFileReadLimFD(int fd, int maxlen, char **buf) ATTRIBUTE_RETURN_CHECK;
|
||||
|
|
Loading…
Reference in New Issue