[libvirt] [PATCH 4/5] lxc: be more patient while resolving symlinks

Cédric Bosdonnat cbosdonnat at suse.com
Mon Nov 24 20:54:45 UTC 2014


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.
---
 src/conf/domain_conf.h  |  1 +
 src/lxc/lxc_container.c | 77 ++++++++++++++++++++++++++++++++++---------------
 2 files changed, 54 insertions(+), 24 deletions(-)

diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 0a609df..f56b8b1 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -821,6 +821,7 @@ struct _virDomainFSDef {
     virDomainDeviceInfo info;
     unsigned long long space_hard_limit; /* in bytes */
     unsigned long long space_soft_limit; /* in bytes */
+    bool symlinksResolved;
 };
 
 
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index db823d6..12f3a41 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -608,6 +608,48 @@ static int lxcContainerUnmountSubtree(const char *prefix,
     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,
                                    virDomainFSDefPtr root,
@@ -634,6 +676,9 @@ static int lxcContainerPrepareRoot(virDomainDefPtr def,
         return -1;
     }
 
+    if (lxcContainerResolveSymlinks(root, false) < 0)
+        return -1;
+
     if (virAsprintf(&dst, "%s/%s.root",
                     LXC_STATE_DIR, def->name) < 0)
         return -1;
@@ -1552,6 +1597,9 @@ static int lxcContainerMountAllFS(virDomainDefPtr vmDef,
         if (STREQ(vmDef->fss[i]->dst, "/"))
             continue;
 
+        if (lxcContainerResolveSymlinks(vmDef->fss[i], false) < 0)
+            return -1;
+
         if (lxcContainerUnmountSubtree(vmDef->fss[i]->dst,
                                        false) < 0)
             return -1;
@@ -1735,37 +1783,18 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
     return ret;
 }
 
-
-static int lxcContainerResolveSymlinks(virDomainDefPtr vmDef)
+static int lxcContainerResolveAllSymlinks(virDomainDefPtr vmDef)
 {
-    char *newroot;
     size_t i;
 
     VIR_DEBUG("Resolving symlinks");
 
     for (i = 0; i < vmDef->nfss; i++) {
         virDomainFSDefPtr fs = vmDef->fss[i];
-        if (!fs->src)
-            continue;
-
-        if (access(fs->src, F_OK)) {
-            virReportSystemError(errno,
-                                 _("Failed to access '%s'"), fs->src);
+        /* In the first pass, be gentle as some files may
+           depend on other filesystems to be mounted */
+        if (lxcContainerResolveSymlinks(fs, true) < 0)
             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");
 
@@ -2106,7 +2135,7 @@ static int lxcContainerChild(void *data)
         goto cleanup;
     }
 
-    if (lxcContainerResolveSymlinks(vmDef) < 0)
+    if (lxcContainerResolveAllSymlinks(vmDef) < 0)
         goto cleanup;
 
     VIR_DEBUG("Setting up pivot");
-- 
2.1.2




More information about the libvir-list mailing list