lxc/0033-support-mount-squashfs-in-mount-entry.patch
LiFeng c1c967d9bc lxc: make lxc-libs package
Signed-off-by: LiFeng <lifeng68@huawei.com>
2020-02-14 06:13:22 -05:00

370 lines
10 KiB
Diff

From af999d8da16a36ff541d27d84d40bcf97f62e581 Mon Sep 17 00:00:00 2001
From: tanyifeng <tanyifeng1@huawei.com>
Date: Tue, 15 Jan 2019 19:54:13 +0800
Subject: [PATCH 033/139] support mount squashfs in mount entry
Signed-off-by: LiFeng <lifeng68@huawei.com>
---
src/lxc/conf.c | 88 +++++++++++++++++++++++++++++++++++++++--
src/lxc/storage/loop.c | 36 ++++++++++++++---
src/lxc/storage/storage_utils.c | 36 ++++++++++++++++-
src/lxc/utils.c | 33 ++++++++++++++--
src/lxc/utils.h | 1 +
5 files changed, 181 insertions(+), 13 deletions(-)
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 54b967b..fea0f59 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -78,6 +78,7 @@
#include "storage/overlay.h"
#include "syscall_wrappers.h"
#include "terminal.h"
+#include "loop.h"
#include "path.h"
#include "utils.h"
@@ -2444,6 +2445,82 @@ static int mount_entry_create_dir_file(const struct mntent *mntent,
return 0;
}
+static int mount_entry_with_loop_dev(const char *src, const char *dest, const char *fstype,
+ char *mnt_opts, const char *rootfs)
+{
+ int srcfd = -1, destfd, ret, saved_errno;
+ char srcbuf[50], destbuf[50]; // only needs enough for /proc/self/fd/<fd>
+ const char *mntsrc = src;
+ int max_retry = 5;
+ struct lxc_storage loop;
+
+ if (!rootfs)
+ rootfs = "";
+
+ /* todo - allow symlinks for relative paths if 'allowsymlinks' option is passed */
+ if (src && src[0] != '/') {
+ INFO("this is a relative mount");
+ srcfd = open_without_symlink(src, NULL);
+ if (srcfd < 0)
+ return srcfd;
+ ret = snprintf(srcbuf, sizeof(srcbuf), "/proc/self/fd/%d", srcfd);
+ if (ret < 0 || ret > sizeof(srcbuf)) {
+ close(srcfd);
+ ERROR("Failed to print string");
+ return -EINVAL;
+ }
+ mntsrc = srcbuf;
+ }
+
+ destfd = open_without_symlink(dest, rootfs);
+ if (destfd < 0) {
+ if (srcfd != -1) {
+ saved_errno = errno;
+ close(srcfd);
+ errno = saved_errno;
+ }
+ return destfd;
+ }
+
+ ret = snprintf(destbuf, sizeof(destbuf), "/proc/self/fd/%d", destfd);
+ if (ret < 0 || ret > sizeof(destbuf)) {
+ if (srcfd != -1)
+ close(srcfd);
+ close(destfd);
+ ERROR("Out of memory");
+ return -EINVAL;
+ }
+
+retry:
+ loop.src = (char *)mntsrc;
+ loop.dest = destbuf;
+ loop.mntopts = mnt_opts;
+ loop.type = "loop";
+ loop.lofd = -1;
+ ret = loop_mount(&loop);
+ if (ret < 0) {
+ /* If loop is used by other program, mount may fail. So
+ * we do retry to ensure mount ok */
+ if (max_retry > 0) {
+ max_retry--;
+ DEBUG("mount entry with loop dev failed, retry mount."
+ "retry count left %d", max_retry);
+ goto retry;
+ }
+ }
+ if (loop.lofd != -1)
+ close(loop.lofd);
+ if (srcfd != -1)
+ close(srcfd);
+ close(destfd);
+ if (ret < 0) {
+ SYSERROR("Failed to mount %s onto %s", src, dest);
+ return ret;
+ }
+
+ return 0;
+}
+
/* rootfs, lxc_name, and lxc_path can be NULL when the container is created
* without a rootfs. */
static inline int mount_entry_on_generic(struct mntent *mntent,
@@ -2502,8 +2579,14 @@ static inline int mount_entry_on_generic(struct mntent *mntent,
return -1;
}
- ret = mount_entry(mntent->mnt_fsname, dest, mntent->mnt_type, mntflags,
- pflags, mntdata, optional, dev, relative, rootfs_path);
+ // isulad: support squashfs
+ if (strcmp(mntent->mnt_type, "squashfs") == 0) {
+ ret = mount_entry_with_loop_dev(mntent->mnt_fsname, dest, mntent->mnt_type,
+ mntent->mnt_opts, rootfs_path);
+ } else {
+ ret = mount_entry(mntent->mnt_fsname, dest, mntent->mnt_type, mntflags,
+ pflags, mntdata, optional, dev, relative, rootfs_path);
+ }
free(mntdata);
free(rpath);
@@ -3897,7 +3980,6 @@ static int setup_rootfs_mountopts(const struct lxc_rootfs *rootfs)
return 0;
}
-
int lxc_setup(struct lxc_handler *handler)
{
int ret;
diff --git a/src/lxc/storage/loop.c b/src/lxc/storage/loop.c
index 35cb13e..760def8 100644
--- a/src/lxc/storage/loop.c
+++ b/src/lxc/storage/loop.c
@@ -41,6 +41,7 @@
#include "loop.h"
#include "storage.h"
#include "storage_utils.h"
+#include "lxclock.h"
#include "utils.h"
lxc_log_define(loop, lxc);
@@ -236,9 +237,11 @@ bool loop_detect(const char *path)
int loop_mount(struct lxc_storage *bdev)
{
- int ret, loopfd;
+ int ret = 0;
+ int loopfd, lret;
char loname[PATH_MAX];
const char *src;
+ struct lxc_lock *l = NULL;
if (strcmp(bdev->type, "loop"))
return -22;
@@ -246,13 +249,29 @@ int loop_mount(struct lxc_storage *bdev)
if (!bdev->src || !bdev->dest)
return -22;
+ /* isulad: do lock before mount, so we can avoid use loop which is used by
+ * other starting contianers */
+ l = lxc_newlock("mount_lock", "mount_lock");
+ if (!l) {
+ SYSERROR("create file lock error when mount fs");
+ return -1;
+ }
+
+ lret = lxclock(l, 0);
+ if (lret) {
+ SYSERROR("try to lock failed when mount fs");
+ ret = -1;
+ goto out;
+ }
+
/* skip prefix */
src = lxc_storage_get_path(bdev->src, bdev->type);
loopfd = lxc_prepare_loop_dev(src, loname, LO_FLAGS_AUTOCLEAR);
if (loopfd < 0) {
ERROR("Failed to prepare loop device for loop file \"%s\"", src);
- return -1;
+ ret = -1;
+ goto out;
}
DEBUG("Prepared loop device \"%s\"", loname);
@@ -261,14 +280,21 @@ int loop_mount(struct lxc_storage *bdev)
ERROR("Failed to mount rootfs \"%s\" on \"%s\" via loop device \"%s\"",
bdev->src, bdev->dest, loname);
close(loopfd);
- return -1;
+ ret = -1;
+ goto out;
}
bdev->lofd = loopfd;
DEBUG("Mounted rootfs \"%s\" on \"%s\" via loop device \"%s\"",
bdev->src, bdev->dest, loname);
-
- return 0;
+out:
+ lret = lxcunlock(l);
+ if (lret) {
+ SYSERROR("try to unlock failed when mount fs");
+ ret = -1;
+ }
+ lxc_putlock(l);
+ return ret;
}
int loop_umount(struct lxc_storage *bdev)
diff --git a/src/lxc/storage/storage_utils.c b/src/lxc/storage/storage_utils.c
index b4dcb57..0a87778 100644
--- a/src/lxc/storage/storage_utils.c
+++ b/src/lxc/storage/storage_utils.c
@@ -339,10 +339,14 @@ int is_blktype(struct lxc_storage *b)
return 0;
}
+// isulad: recored error
+static char **mount_errors = NULL;
+
int mount_unknown_fs(const char *rootfs, const char *target,
const char *options)
{
size_t i;
+ char *errs = NULL;
int ret;
struct cbarg {
const char *rootfs;
@@ -371,15 +375,30 @@ int mount_unknown_fs(const char *rootfs, const char *target,
ret = lxc_file_for_each_line(fsfile[i], find_fstype_cb, &cbarg);
if (ret < 0) {
ERROR("Failed to parse \"%s\"", fsfile[i]);
+ lxc_free_array((void**)mount_errors, free);
+ mount_errors = NULL;
return -1;
}
- if (ret)
+ if (ret) {
+ lxc_free_array((void**)mount_errors, free);
+ mount_errors = NULL;
return 0;
+ }
+ }
+
+ if (mount_errors != NULL) {
+ errs = lxc_string_join("\n", (const char **)mount_errors, false);
+ if (errs == NULL) {
+ ERROR("failed to join mount errors");
+ }
}
- ERROR("Failed to determine FSType for \"%s\"", rootfs);
+ ERROR("Failed to determine FSType for \"%s\": %s", rootfs, errs ? errs : "unknown reason");
+ free(errs);
+ lxc_free_array((void**)mount_errors, free);
+ mount_errors = NULL;
return -1;
}
@@ -399,6 +418,8 @@ int find_fstype_cb(char *buffer, void *data)
unsigned long mntflags, pflags;
char *mntdata;
char *fstype;
+ char mount_err[BUFSIZ] = {0};
+ int ret;
/* we don't try 'nodev' entries */
if (strstr(buffer, "nodev"))
@@ -419,6 +440,17 @@ int find_fstype_cb(char *buffer, void *data)
if (mount(cbarg->rootfs, cbarg->target, fstype, (mntflags & ~MS_RDONLY), mntdata)) {
SYSDEBUG("Failed to mount");
free(mntdata);
+ // isulad: recored error
+ ret = snprintf(mount_err, BUFSIZ, "\t\tmount %s onto %s with FSType %s failed: %s",
+ cbarg->rootfs, cbarg->target, fstype, strerror(errno));
+ if (ret < 0 || (size_t)ret >= BUFSIZ) {
+ ERROR("failed to format output mount error");
+ return 0;
+ }
+
+ if (lxc_append_string(&mount_errors, mount_err) < 0) {
+ ERROR("failed to append mount error");
+ }
return 0;
}
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index d1a22f7..120a13d 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -1053,7 +1053,7 @@ static int open_if_safe(int dirfd, const char *nextpath)
*
* Return an open fd for the path, or <0 on error.
*/
-static int open_without_symlink(const char *target, const char *prefix_skip)
+int open_without_symlink(const char *target, const char *prefix_skip)
{
int curlen = 0, dirfd, fulllen, i;
char *dup;
@@ -1473,6 +1473,9 @@ static int lxc_get_unused_loop_dev(char *name_loop)
{
int loop_nr, ret;
int fd_ctl = -1, fd_tmp = -1;
+ // isulad: retry and try mknod
+ int max_retry = 200;
+ bool try_mknod = true;
fd_ctl = open("/dev/loop-control", O_RDWR | O_CLOEXEC);
if (fd_ctl < 0) {
@@ -1489,10 +1492,34 @@ static int lxc_get_unused_loop_dev(char *name_loop)
ret = snprintf(name_loop, LO_NAME_SIZE, "/dev/loop%d", loop_nr);
if (ret < 0 || ret >= LO_NAME_SIZE)
goto on_error;
-
+retry:
fd_tmp = open(name_loop, O_RDWR | O_CLOEXEC);
- if (fd_tmp < 0)
+ if (fd_tmp < 0) {
+ /* Success of LOOP_CTL_GET_FREE doesn't mean /dev/loop$i is ready,
+ * we try to make node by ourself to avoid wait. */
+ if (try_mknod) {
+ /* Do not check result of mknod because LOOP_CTL_GET_FREE
+ * alse do mknod, so this mknod may fail as node already
+ * exist. If we can open the node without error, we can
+ * say that it's be created successfully.
+ *
+ * note: 7 is the major device number of loopback devices
+ * in kernel.
+ */
+ mknod(name_loop, S_IFBLK | 0640, makedev(7, loop_nr));
+ try_mknod = false;
+ goto retry;
+ }
+ /* we need to wait some time to make sure it's ready for open if
+ * it can't open even if we have already try to make node by ourself. */
+ if (max_retry > 0) {
+ max_retry--;
+ usleep(5000); /* 5 millisecond */
+ goto retry;
+ }
SYSERROR("Failed to open loop \"%s\"", name_loop);
+ goto on_error;
+ }
on_error:
close(fd_ctl);
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index abc88ca..4313942 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -224,6 +224,7 @@ extern bool cgns_supported(void);
extern char *choose_init(const char *rootfs);
extern bool switch_to_ns(pid_t pid, const char *ns);
extern char *get_template_path(const char *t);
+extern int open_without_symlink(const char *target, const char *prefix_skip);
extern int safe_mount(const char *src, const char *dest, const char *fstype,
unsigned long flags, const void *data,
const char *rootfs);
--
1.8.3.1