]> xenbits.xensource.com Git - libvirt.git/commitdiff
Support bind mounting host files, as well as directories in LXC
authorDaniel J Walsh <dwalsh@redhat.com>
Mon, 25 Jun 2012 09:53:39 +0000 (10:53 +0100)
committerDaniel P. Berrange <berrange@redhat.com>
Mon, 25 Jun 2012 09:56:38 +0000 (10:56 +0100)
Currently libvirt-lxc checks to see if the destination exists and is a
directory.  If it is not a directory then the mount fails.  Since
libvirt-lxc can bind mount files on an inode, this patch is needed to
allow us to bind mount files on files.  Currently we want to bind mount
on top of /etc/machine-id, and /etc/adjtime

If the destination of the mount point does not exists, it checks if the
src is a directory and then attempts to create a directory, otherwise it
creates an empty file for the destination.  The code will then bind mount
over the destination.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
src/lxc/lxc_container.c

index bf67ba11abb1e4d45613e1fc49ff9d82687fa1b6..071d8d1bf09681309b0fb4d0bcdd14c248aabc69 100644 (file)
@@ -650,17 +650,50 @@ static int lxcContainerMountFSBind(virDomainFSDefPtr fs,
 {
     char *src = NULL;
     int ret = -1;
+    struct stat st;
 
     if (virAsprintf(&src, "%s%s", srcprefix, fs->src) < 0) {
         virReportOOMError();
         goto cleanup;
     }
 
-    if (virFileMakePath(fs->dst) < 0) {
-        virReportSystemError(errno,
-                             _("Failed to create %s"),
-                             fs->dst);
-        goto cleanup;
+    if (stat(fs->dst, &st) < 0) {
+        if (errno != ENOENT) {
+            virReportSystemError(errno, _("Unable to stat bind target %s"),
+                                 fs->dst);
+            goto cleanup;
+        }
+        /* ENOENT => create the target dir or file */
+        if (stat(src, &st) < 0) {
+            virReportSystemError(errno, _("Unable to stat bind source %s"),
+                                 src);
+            goto cleanup;
+        }
+        if (S_ISDIR(st.st_mode)) {
+            if (virFileMakePath(fs->dst) < 0) {
+                virReportSystemError(errno,
+                                     _("Failed to create %s"),
+                                     fs->dst);
+                goto cleanup;
+            }
+        } else {
+            /* Create Empty file for target mount point */
+            int fd = open(fs->dst, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, 0666);
+            if (fd < 0) {
+                if (errno != EEXIST) {
+                    virReportSystemError(errno,
+                                         _("Failed to create bind target %s"),
+                                         fs->dst);
+                    goto cleanup;
+                }
+            }
+            if (VIR_CLOSE(fd) < 0) {
+                virReportSystemError(errno,
+                                     _("Failed to close bind target %s"),
+                                     fs->dst);
+                goto cleanup;
+            }
+        }
     }
 
     if (mount(src, fs->dst, NULL, MS_BIND, NULL) < 0) {