mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 21:55:25 +00:00
qemuDomainGetPreservedMounts: Fetch list of /dev/* mounts dynamically
With my namespace patches, we are spawning qemu in its own namespace so that we can manage /dev entries ourselves. However, some filesystems mounted under /dev needs to be preserved in order to be shared with the parent namespace (e.g. /dev/pts). Currently, the list of mount points to preserve is hardcoded which ain't right - on some systems there might be less or more items under real /dev that on our list. The solution is to parse /proc/mounts and fetch the list from there. Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
486fd7f700
commit
e08ee7cd34
@ -99,14 +99,8 @@ VIR_ENUM_IMPL(qemuDomainNamespace, QEMU_DOMAIN_NS_LAST,
|
|||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
static struct {
|
#define PROC_MOUNTS "/proc/mounts"
|
||||||
const char *path;
|
#define DEVPREFIX "/dev/"
|
||||||
const char *suffix;
|
|
||||||
} devPreserveMounts[] = {
|
|
||||||
{"/dev/pts", "devpts"},
|
|
||||||
{"/dev/shm", "devshm"},
|
|
||||||
{"/dev/mqueue", "mqueue"},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct _qemuDomainLogContext {
|
struct _qemuDomainLogContext {
|
||||||
@ -200,33 +194,73 @@ qemuDomainEnableNamespace(virDomainObjPtr vm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemuDomainGetPreservedMounts:
|
||||||
|
*
|
||||||
|
* Process list of mounted filesystems and:
|
||||||
|
* a) save all FSs mounted under /dev to @devPath
|
||||||
|
* b) generate backup path for all the entries in a)
|
||||||
|
*
|
||||||
|
* Any of the return pointers can be NULL.
|
||||||
|
*
|
||||||
|
* Returns 0 on success, -1 otherwise (with error reported)
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
qemuDomainGetPreservedMounts(virQEMUDriverPtr driver,
|
qemuDomainGetPreservedMounts(virQEMUDriverPtr driver,
|
||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
char ***devMountsPath,
|
char ***devPath,
|
||||||
size_t *ndevMountsPath)
|
char ***devSavePath,
|
||||||
|
size_t *ndevPath)
|
||||||
{
|
{
|
||||||
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
||||||
char **paths;
|
char **paths = NULL, **mounts = NULL;
|
||||||
size_t i;
|
size_t i, nmounts;
|
||||||
|
|
||||||
if (VIR_ALLOC_N(paths, ARRAY_CARDINALITY(devPreserveMounts)) < 0)
|
if (virFileGetMountSubtree(PROC_MOUNTS, "/dev",
|
||||||
|
&mounts, &nmounts) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_CARDINALITY(devPreserveMounts); i++) {
|
if (!nmounts) {
|
||||||
|
if (ndevPath)
|
||||||
|
*ndevPath = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Okay, this is crazy. But virFileGetMountSubtree() fetched us all the
|
||||||
|
* mount points under /dev including /dev itself. Fortunately, the paths
|
||||||
|
* are sorted based on their length so we skip the first one (/dev) as it
|
||||||
|
* is handled differently anyway. */
|
||||||
|
VIR_DELETE_ELEMENT(mounts, 0, nmounts);
|
||||||
|
|
||||||
|
if (VIR_ALLOC_N(paths, nmounts) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
for (i = 0; i < nmounts; i++) {
|
||||||
if (virAsprintf(&paths[i], "%s/%s.%s",
|
if (virAsprintf(&paths[i], "%s/%s.%s",
|
||||||
cfg->stateDir, vm->def->name,
|
cfg->stateDir, vm->def->name,
|
||||||
devPreserveMounts[i].suffix) < 0)
|
mounts[i] + strlen(DEVPREFIX)) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
*devMountsPath = paths;
|
if (devPath)
|
||||||
*ndevMountsPath = ARRAY_CARDINALITY(devPreserveMounts);
|
*devPath = mounts;
|
||||||
|
else
|
||||||
|
virStringListFreeCount(mounts, nmounts);
|
||||||
|
|
||||||
|
if (devSavePath)
|
||||||
|
*devSavePath = paths;
|
||||||
|
else
|
||||||
|
virStringListFreeCount(paths, nmounts);
|
||||||
|
|
||||||
|
if (ndevPath)
|
||||||
|
*ndevPath = nmounts;
|
||||||
|
|
||||||
virObjectUnref(cfg);
|
virObjectUnref(cfg);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
virStringListFreeCount(paths, ARRAY_CARDINALITY(devPreserveMounts));
|
virStringListFreeCount(mounts, nmounts);
|
||||||
|
virStringListFreeCount(paths, nmounts);
|
||||||
virObjectUnref(cfg);
|
virObjectUnref(cfg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -6917,8 +6951,6 @@ qemuDomainGetHostdevPath(virDomainHostdevDefPtr dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define DEVPREFIX "/dev/"
|
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
static int
|
static int
|
||||||
qemuDomainCreateDevice(const char *device,
|
qemuDomainCreateDevice(const char *device,
|
||||||
@ -7304,7 +7336,7 @@ qemuDomainBuildNamespace(virQEMUDriverPtr driver,
|
|||||||
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
||||||
const unsigned long mount_flags = MS_MOVE;
|
const unsigned long mount_flags = MS_MOVE;
|
||||||
char *devPath = NULL;
|
char *devPath = NULL;
|
||||||
char **devMountsPath = NULL;
|
char **devMountsPath = NULL, **devMountsSavePath = NULL;
|
||||||
size_t ndevMountsPath = 0, i;
|
size_t ndevMountsPath = 0, i;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
@ -7318,7 +7350,8 @@ qemuDomainBuildNamespace(virQEMUDriverPtr driver,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (qemuDomainGetPreservedMounts(driver, vm,
|
if (qemuDomainGetPreservedMounts(driver, vm,
|
||||||
&devMountsPath, &ndevMountsPath) < 0)
|
&devMountsPath, &devMountsSavePath,
|
||||||
|
&ndevMountsPath) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (qemuDomainSetupDev(driver, vm, devPath) < 0)
|
if (qemuDomainSetupDev(driver, vm, devPath) < 0)
|
||||||
@ -7326,11 +7359,11 @@ qemuDomainBuildNamespace(virQEMUDriverPtr driver,
|
|||||||
|
|
||||||
/* Save some mount points because we want to share them with the host */
|
/* Save some mount points because we want to share them with the host */
|
||||||
for (i = 0; i < ndevMountsPath; i++) {
|
for (i = 0; i < ndevMountsPath; i++) {
|
||||||
if (mount(devPreserveMounts[i].path, devMountsPath[i],
|
if (mount(devMountsPath[i], devMountsSavePath[i],
|
||||||
NULL, mount_flags, NULL) < 0) {
|
NULL, mount_flags, NULL) < 0) {
|
||||||
virReportSystemError(errno,
|
virReportSystemError(errno,
|
||||||
_("Unable to move %s mount"),
|
_("Unable to move %s mount"),
|
||||||
devPreserveMounts[i].path);
|
devMountsPath[i]);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7361,18 +7394,18 @@ qemuDomainBuildNamespace(virQEMUDriverPtr driver,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < ndevMountsPath; i++) {
|
for (i = 0; i < ndevMountsPath; i++) {
|
||||||
if (virFileMakePath(devPreserveMounts[i].path) < 0) {
|
if (virFileMakePath(devMountsPath[i]) < 0) {
|
||||||
virReportSystemError(errno, _("Cannot create %s"),
|
virReportSystemError(errno, _("Cannot create %s"),
|
||||||
devPreserveMounts[i].path);
|
devMountsPath[i]);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mount(devMountsPath[i], devPreserveMounts[i].path,
|
if (mount(devMountsSavePath[i], devMountsPath[i],
|
||||||
NULL, mount_flags, NULL) < 0) {
|
NULL, mount_flags, NULL) < 0) {
|
||||||
virReportSystemError(errno,
|
virReportSystemError(errno,
|
||||||
_("Failed to mount %s on %s"),
|
_("Failed to mount %s on %s"),
|
||||||
devMountsPath[i],
|
devMountsSavePath[i],
|
||||||
devPreserveMounts[i].path);
|
devMountsPath[i]);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7382,6 +7415,7 @@ qemuDomainBuildNamespace(virQEMUDriverPtr driver,
|
|||||||
virObjectUnref(cfg);
|
virObjectUnref(cfg);
|
||||||
VIR_FREE(devPath);
|
VIR_FREE(devPath);
|
||||||
virStringListFreeCount(devMountsPath, ndevMountsPath);
|
virStringListFreeCount(devMountsPath, ndevMountsPath);
|
||||||
|
virStringListFreeCount(devMountsSavePath, ndevMountsPath);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7393,8 +7427,8 @@ qemuDomainCreateNamespace(virQEMUDriverPtr driver,
|
|||||||
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
char *devPath = NULL;
|
char *devPath = NULL;
|
||||||
char **devMountsPath = NULL;
|
char **devMountsSavePath = NULL;
|
||||||
size_t ndevMountsPath = 0, i;
|
size_t ndevMountsSavePath = 0, i;
|
||||||
|
|
||||||
if (!virBitmapIsBitSet(cfg->namespaces, QEMU_DOMAIN_NS_MOUNT) ||
|
if (!virBitmapIsBitSet(cfg->namespaces, QEMU_DOMAIN_NS_MOUNT) ||
|
||||||
!virQEMUDriverIsPrivileged(driver)) {
|
!virQEMUDriverIsPrivileged(driver)) {
|
||||||
@ -7407,7 +7441,8 @@ qemuDomainCreateNamespace(virQEMUDriverPtr driver,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (qemuDomainGetPreservedMounts(driver, vm,
|
if (qemuDomainGetPreservedMounts(driver, vm,
|
||||||
&devMountsPath, &ndevMountsPath) < 0)
|
NULL, &devMountsSavePath,
|
||||||
|
&ndevMountsSavePath) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (virFileMakePath(devPath) < 0) {
|
if (virFileMakePath(devPath) < 0) {
|
||||||
@ -7417,11 +7452,11 @@ qemuDomainCreateNamespace(virQEMUDriverPtr driver,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < ndevMountsPath; i++) {
|
for (i = 0; i < ndevMountsSavePath; i++) {
|
||||||
if (virFileMakePath(devMountsPath[i]) < 0) {
|
if (virFileMakePath(devMountsSavePath[i]) < 0) {
|
||||||
virReportSystemError(errno,
|
virReportSystemError(errno,
|
||||||
_("Failed to create %s"),
|
_("Failed to create %s"),
|
||||||
devMountsPath[i]);
|
devMountsSavePath[i]);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7434,10 +7469,10 @@ qemuDomainCreateNamespace(virQEMUDriverPtr driver,
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (devPath)
|
if (devPath)
|
||||||
unlink(devPath);
|
unlink(devPath);
|
||||||
for (i = 0; i < ndevMountsPath; i++)
|
for (i = 0; i < ndevMountsSavePath; i++)
|
||||||
unlink(devMountsPath[i]);
|
unlink(devMountsSavePath[i]);
|
||||||
}
|
}
|
||||||
virStringListFreeCount(devMountsPath, ndevMountsPath);
|
virStringListFreeCount(devMountsSavePath, ndevMountsSavePath);
|
||||||
VIR_FREE(devPath);
|
VIR_FREE(devPath);
|
||||||
virObjectUnref(cfg);
|
virObjectUnref(cfg);
|
||||||
return ret;
|
return ret;
|
||||||
@ -7472,8 +7507,8 @@ qemuDomainDeleteNamespace(virQEMUDriverPtr driver,
|
|||||||
{
|
{
|
||||||
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
||||||
char *devPath = NULL;
|
char *devPath = NULL;
|
||||||
char **devMountsPath = NULL;
|
char **devMountsSavePath = NULL;
|
||||||
size_t ndevMountsPath = 0, i;
|
size_t ndevMountsSavePath = 0, i;
|
||||||
|
|
||||||
|
|
||||||
if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT))
|
if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT))
|
||||||
@ -7484,7 +7519,8 @@ qemuDomainDeleteNamespace(virQEMUDriverPtr driver,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (qemuDomainGetPreservedMounts(driver, vm,
|
if (qemuDomainGetPreservedMounts(driver, vm,
|
||||||
&devMountsPath, &ndevMountsPath) < 0)
|
NULL, &devMountsSavePath,
|
||||||
|
&ndevMountsSavePath) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (rmdir(devPath) < 0) {
|
if (rmdir(devPath) < 0) {
|
||||||
@ -7494,17 +7530,17 @@ qemuDomainDeleteNamespace(virQEMUDriverPtr driver,
|
|||||||
/* Bet effort. Fall through. */
|
/* Bet effort. Fall through. */
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < ndevMountsPath; i++) {
|
for (i = 0; i < ndevMountsSavePath; i++) {
|
||||||
if (rmdir(devMountsPath[i]) < 0) {
|
if (rmdir(devMountsSavePath[i]) < 0) {
|
||||||
virReportSystemError(errno,
|
virReportSystemError(errno,
|
||||||
_("Unable to remove %s"),
|
_("Unable to remove %s"),
|
||||||
devMountsPath[i]);
|
devMountsSavePath[i]);
|
||||||
/* Bet effort. Fall through. */
|
/* Bet effort. Fall through. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cleanup:
|
cleanup:
|
||||||
virObjectUnref(cfg);
|
virObjectUnref(cfg);
|
||||||
virStringListFreeCount(devMountsPath, ndevMountsPath);
|
virStringListFreeCount(devMountsSavePath, ndevMountsSavePath);
|
||||||
VIR_FREE(devPath);
|
VIR_FREE(devPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user