From 465c055f4a3baa72f06c7677f2203d1002cb2520 Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Mon, 25 Jun 2012 10:53:39 +0100 Subject: [PATCH] Support bind mounting host files, as well as directories in LXC 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 --- src/lxc/lxc_container.c | 43 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index bf67ba11ab..071d8d1bf0 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -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) {