[1/2,v5] mount: add support for external block devices

Submitted by Andrei Vagin on May 7, 2016, 12:25 a.m.

Details

Message ID 1462580746-10683-1-git-send-email-avagin@openvz.org
State Accepted
Series "Series without cover letter"
Commit 85370471d568c903ae81bd43fd37f16749c222c0
Headers show

Commit Message

Andrei Vagin May 7, 2016, 12:25 a.m.
From: Andrew Vagin <avagin@virtuozzo.com>

The idea is to allow to dump and restore mounts of
a specified block device.

Options:
dump:      --external dev[MAJOR:MINOR]:VAL
restore:   --external dev[VAL]:DEVPATH

If we find a mount with a specified block device, we
set its type into FSTYPE__AUTO and write VAL into
the "source" field.

VAL is replaced on DEVPATH on restore.

https://jira.sw.ru/browse/PSBM-39381

v2: use --ext-mount-map instead of --external on dump
v3: clean up
v4: use --external on dump and on restore
v5: VAL:DEVPATH -> dev[VAL]:DEVPATH on restore

Signed-off-by: Andrew Vagin <avagin@virtuozzo.com>
---
 criu/crtools.c       | 10 ++++------
 criu/files.c         | 14 ++++++++++++++
 criu/include/files.h |  1 +
 criu/mount.c         | 46 ++++++++++++++++++++++++++++++++++++++++------
 4 files changed, 59 insertions(+), 12 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/crtools.c b/criu/crtools.c
index 7a0f977..9362dcf 100644
--- a/criu/crtools.c
+++ b/criu/crtools.c
@@ -698,11 +698,6 @@  int main(int argc, char *argv[], char *envp[])
 	if (log_init(opts.output))
 		return 1;
 
-	if (!list_empty(&opts.external) && strcmp(argv[optind], "dump")) {
-		pr_err("--external is dump-only option\n");
-		return 1;
-	}
-
 	if (!list_empty(&opts.inherit_fds)) {
 		if (strcmp(argv[optind], "restore")) {
 			pr_err("--inherit-fd is restore-only option\n");
@@ -878,9 +873,12 @@  usage:
 "                        force criu to (try to) dump/restore these filesystem's\n"
 "                        mountpoints even if fs is not supported.\n"
 "  --external RES        dump objects from this list as external resources:\n"
-"                        Formats of RES:\n"
+"                        Formats of RES on dump:\n"
 "                            tty[rdev:dev]\n"
 "                            file[mnt_id:inode]\n"
+"                            dev[maj:min]:VAL\n"
+"                        Formats of RES on restore:\n"
+"                            dev[VAL]:DEVPATH\n"
 "  --inherit-fd fd[<num>]:<existing>\n"
 "                        Inherit file descriptors. This allows to treat file descriptor\n"
 "                        <num> as being already opened via <existing> one and instead of\n"
diff --git a/criu/files.c b/criu/files.c
index d3ce116..dfa3603 100644
--- a/criu/files.c
+++ b/criu/files.c
@@ -1627,3 +1627,17 @@  bool external_lookup_id(char *id)
 			return true;
 	return false;
 }
+
+char *external_lookup_by_key(char *key)
+{
+	struct external *ext;
+	int len = strlen(key);
+
+	list_for_each_entry(ext, &opts.external, node) {
+		if (strncmp(ext->id, key, len))
+			continue;
+		if (ext->id[len] == ':')
+			return ext->id + len + 1;
+	}
+	return NULL;
+}
diff --git a/criu/include/files.h b/criu/include/files.h
index 363437b..1894f09 100644
--- a/criu/include/files.h
+++ b/criu/include/files.h
@@ -210,6 +210,7 @@  extern int inherit_fd_fini(void);
 
 extern bool external_lookup_id(char *id);
 extern int inherit_fd_lookup_id(char *id);
+extern char *external_lookup_by_key(char *id);
 
 extern bool inherited_fd(struct file_desc *, int *fdp);
 
diff --git a/criu/mount.c b/criu/mount.c
index fc584bf..03ad6e8 100644
--- a/criu/mount.c
+++ b/criu/mount.c
@@ -40,6 +40,8 @@ 
 #undef	LOG_PREFIX
 #define LOG_PREFIX "mnt: "
 
+static struct fstype fstypes[];
+
 int ext_mount_add(char *key, char *val)
 {
 	struct ext_mount *em;
@@ -485,15 +487,42 @@  static void mnt_tree_show(struct mount_info *tree, int off)
 static int try_resolve_ext_mount(struct mount_info *info)
 {
 	struct ext_mount *em;
+	char devstr[64];
 
 	em = ext_mount_lookup(info->mountpoint + 1 /* trim the . */);
-	if (em == NULL)
-		return -ENOTSUP;
+	if (em) {
+		pr_info("Found %s mapping for %s mountpoint\n",
+				em->val, info->mountpoint);
+		info->external = em;
+		return 0;
+	}
 
-	pr_info("Found %s mapping for %s mountpoint\n",
-			em->val, info->mountpoint);
-	info->external = em;
-	return 0;
+	snprintf(devstr, sizeof(devstr), "dev[%d/%d]",
+			kdev_major(info->s_dev),  kdev_minor(info->s_dev));
+
+	if (info->fstype->code == FSTYPE__UNSUPPORTED) {
+		char *val;
+
+		val = external_lookup_by_key(devstr);
+		if (val) {
+			char *source;
+			int len;
+
+			len = strlen(val) + sizeof("dev[]");
+			source = xmalloc(len);
+			if (source == NULL)
+				return -1;
+
+			snprintf(source, len, "dev[%s]", val);
+			info->fstype = &fstypes[1];
+			BUG_ON(info->fstype->code != FSTYPE__AUTO);
+			xfree(info->source);
+			info->source = source;
+			return 0;
+		}
+	}
+
+	return -ENOTSUP;
 }
 
 static struct mount_info *find_widest_shared(struct mount_info *m)
@@ -2092,6 +2121,11 @@  static char *resolve_source(struct mount_info *mi)
 
 	if (mi->fstype->code == FSTYPE__AUTO) {
 		struct stat st;
+		char *val;
+
+		val = external_lookup_by_key(mi->source);
+		if (val)
+			return val;
 
 		if (!stat(mi->source, &st) && S_ISBLK(st.st_mode) &&
 		    major(st.st_rdev) == kdev_major(mi->s_dev) &&