lxc: be more patient while resolving symlinks
Resolving symlinks can fail before mounting any file system if one file system depends on another being mounted. Symlinks are now resolved in two passes: * Before any file system is mounted, but then we are more gentle if the source path can't be accessed * Right before mounting a file system, so that we are sure that we have the resolved path... but then if it can't be accessed we raise an error.
This commit is contained in:
parent
433b427ff8
commit
72fecf1813
@ -821,6 +821,7 @@ struct _virDomainFSDef {
|
|||||||
virDomainDeviceInfo info;
|
virDomainDeviceInfo info;
|
||||||
unsigned long long space_hard_limit; /* in bytes */
|
unsigned long long space_hard_limit; /* in bytes */
|
||||||
unsigned long long space_soft_limit; /* in bytes */
|
unsigned long long space_soft_limit; /* in bytes */
|
||||||
|
bool symlinksResolved;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -608,6 +608,48 @@ static int lxcContainerUnmountSubtree(const char *prefix,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lxcContainerResolveSymlinks(virDomainFSDefPtr fs, bool gentle)
|
||||||
|
{
|
||||||
|
char *newroot;
|
||||||
|
|
||||||
|
if (!fs->src || fs->symlinksResolved)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (access(fs->src, F_OK)) {
|
||||||
|
if (gentle) {
|
||||||
|
/* Just ignore the error for the while, we'll try again later */
|
||||||
|
VIR_DEBUG("Skipped unaccessible '%s'", fs->src);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
virReportSystemError(errno,
|
||||||
|
_("Failed to access '%s'"), fs->src);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VIR_DEBUG("Resolving '%s'", fs->src);
|
||||||
|
if (virFileResolveAllLinks(fs->src, &newroot) < 0) {
|
||||||
|
if (gentle) {
|
||||||
|
VIR_DEBUG("Skipped non-resolvable '%s'", fs->src);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
virReportSystemError(errno,
|
||||||
|
_("Failed to resolve symlink at %s"),
|
||||||
|
fs->src);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mark it resolved to skip it the next time */
|
||||||
|
fs->symlinksResolved = true;
|
||||||
|
|
||||||
|
VIR_DEBUG("Resolved '%s' to %s", fs->src, newroot);
|
||||||
|
|
||||||
|
VIR_FREE(fs->src);
|
||||||
|
fs->src = newroot;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int lxcContainerPrepareRoot(virDomainDefPtr def,
|
static int lxcContainerPrepareRoot(virDomainDefPtr def,
|
||||||
virDomainFSDefPtr root,
|
virDomainFSDefPtr root,
|
||||||
@ -634,6 +676,9 @@ static int lxcContainerPrepareRoot(virDomainDefPtr def,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lxcContainerResolveSymlinks(root, false) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (virAsprintf(&dst, "%s/%s.root",
|
if (virAsprintf(&dst, "%s/%s.root",
|
||||||
LXC_STATE_DIR, def->name) < 0)
|
LXC_STATE_DIR, def->name) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
@ -1552,6 +1597,9 @@ static int lxcContainerMountAllFS(virDomainDefPtr vmDef,
|
|||||||
if (STREQ(vmDef->fss[i]->dst, "/"))
|
if (STREQ(vmDef->fss[i]->dst, "/"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (lxcContainerResolveSymlinks(vmDef->fss[i], false) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (lxcContainerUnmountSubtree(vmDef->fss[i]->dst,
|
if (lxcContainerUnmountSubtree(vmDef->fss[i]->dst,
|
||||||
false) < 0)
|
false) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
@ -1735,37 +1783,18 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lxcContainerResolveAllSymlinks(virDomainDefPtr vmDef)
|
||||||
static int lxcContainerResolveSymlinks(virDomainDefPtr vmDef)
|
|
||||||
{
|
{
|
||||||
char *newroot;
|
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
VIR_DEBUG("Resolving symlinks");
|
VIR_DEBUG("Resolving symlinks");
|
||||||
|
|
||||||
for (i = 0; i < vmDef->nfss; i++) {
|
for (i = 0; i < vmDef->nfss; i++) {
|
||||||
virDomainFSDefPtr fs = vmDef->fss[i];
|
virDomainFSDefPtr fs = vmDef->fss[i];
|
||||||
if (!fs->src)
|
/* In the first pass, be gentle as some files may
|
||||||
continue;
|
depend on other filesystems to be mounted */
|
||||||
|
if (lxcContainerResolveSymlinks(fs, true) < 0)
|
||||||
if (access(fs->src, F_OK)) {
|
|
||||||
virReportSystemError(errno,
|
|
||||||
_("Failed to access '%s'"), fs->src);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
VIR_DEBUG("Resolving '%s'", fs->src);
|
|
||||||
if (virFileResolveAllLinks(fs->src, &newroot) < 0) {
|
|
||||||
virReportSystemError(errno,
|
|
||||||
_("Failed to resolve symlink at %s"),
|
|
||||||
fs->src);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
VIR_DEBUG("Resolved '%s' to %s", fs->src, newroot);
|
|
||||||
|
|
||||||
VIR_FREE(fs->src);
|
|
||||||
fs->src = newroot;
|
|
||||||
}
|
}
|
||||||
VIR_DEBUG("Resolved all filesystem symlinks");
|
VIR_DEBUG("Resolved all filesystem symlinks");
|
||||||
|
|
||||||
@ -2106,7 +2135,7 @@ static int lxcContainerChild(void *data)
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lxcContainerResolveSymlinks(vmDef) < 0)
|
if (lxcContainerResolveAllSymlinks(vmDef) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
VIR_DEBUG("Setting up pivot");
|
VIR_DEBUG("Setting up pivot");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user