mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-22 04:25:18 +00:00
qemu_namespace: Be less aggressive in removing /dev nodes from namespace
When creating /dev nodes in a QEMU domain's namespace the first thing we simply do is unlink() the path and create it again. This aims to solve the case when a file changed type/major/minor in the host and thus we need to reflect this in the guest's namespace. Fair enough, except we can be a bit more clever about it: firstly check whether the path doesn't already exist or isn't already of the correct type/major/minor and do the unlink+creation only if needed. Currently, this is implemented only for symlinks and block/character devices. For regular files/directories (which are less common) this might be implemented one day, but not today. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
parent
9d749998b3
commit
22188790ca
@ -948,38 +948,55 @@ qemuNamespaceMknodOne(qemuNamespaceMknodItem *data)
|
||||
}
|
||||
|
||||
if (isLink) {
|
||||
VIR_DEBUG("Creating symlink %s -> %s", data->file, data->target);
|
||||
g_autoptr(GError) gerr = NULL;
|
||||
g_autofree char *target = NULL;
|
||||
|
||||
/* First, unlink the symlink target. Symlinks change and
|
||||
* therefore we have no guarantees that pre-existing
|
||||
* symlink is still valid. */
|
||||
if (unlink(data->file) < 0 &&
|
||||
errno != ENOENT) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to remove symlink %s"),
|
||||
data->file);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (symlink(data->target, data->file) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to create symlink %s (pointing to %s)"),
|
||||
data->file, data->target);
|
||||
goto cleanup;
|
||||
if ((target = g_file_read_link(data->file, &gerr)) &&
|
||||
STREQ(target, data->target)) {
|
||||
VIR_DEBUG("Skipping symlink %s -> %s which exists and points to correct target",
|
||||
data->file, data->target);
|
||||
} else {
|
||||
delDevice = true;
|
||||
VIR_DEBUG("Creating symlink %s -> %s", data->file, data->target);
|
||||
|
||||
/* First, unlink the symlink target. Symlinks change and
|
||||
* therefore we have no guarantees that pre-existing
|
||||
* symlink is still valid. */
|
||||
if (unlink(data->file) < 0 &&
|
||||
errno != ENOENT) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to remove symlink %s"),
|
||||
data->file);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (symlink(data->target, data->file) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to create symlink %s (pointing to %s)"),
|
||||
data->file, data->target);
|
||||
goto cleanup;
|
||||
} else {
|
||||
delDevice = true;
|
||||
}
|
||||
}
|
||||
} else if (isDev) {
|
||||
VIR_DEBUG("Creating dev %s (%d,%d)",
|
||||
data->file, major(data->sb.st_rdev), minor(data->sb.st_rdev));
|
||||
unlink(data->file);
|
||||
if (mknod(data->file, data->sb.st_mode, data->sb.st_rdev) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to create device %s"),
|
||||
data->file);
|
||||
goto cleanup;
|
||||
GStatBuf sb;
|
||||
|
||||
if (g_lstat(data->file, &sb) >= 0 &&
|
||||
sb.st_rdev == data->sb.st_rdev) {
|
||||
VIR_DEBUG("Skipping dev %s (%d,%d) which exists and has correct MAJ:MIN",
|
||||
data->file, major(data->sb.st_rdev), minor(data->sb.st_rdev));
|
||||
} else {
|
||||
delDevice = true;
|
||||
VIR_DEBUG("Creating dev %s (%d,%d)",
|
||||
data->file, major(data->sb.st_rdev), minor(data->sb.st_rdev));
|
||||
unlink(data->file);
|
||||
if (mknod(data->file, data->sb.st_mode, data->sb.st_rdev) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to create device %s"),
|
||||
data->file);
|
||||
goto cleanup;
|
||||
} else {
|
||||
delDevice = true;
|
||||
}
|
||||
}
|
||||
} else if (isReg || isDir) {
|
||||
/* We are not cleaning up disks on virDomainDetachDevice
|
||||
|
Loading…
x
Reference in New Issue
Block a user