[3/4] mount: add support for external block devices (v3)

Submitted by Andrei Vagin on April 22, 2016, 6:12 a.m.

Details

Message ID 1461305565-29198-1-git-send-email-avagin@openvz.org
State Rejected
Series "Series without cover letter"
Headers show

Patch hide | download patch | download mbox

diff --git a/Documentation/criu.txt b/Documentation/criu.txt
index 1982f5d..07da757 100644
--- a/Documentation/criu.txt
+++ b/Documentation/criu.txt
@@ -176,9 +176,9 @@  In other words, do not use it until really needed.
     where locks are not holed by someone outside of it.
 
 *-M*, *--ext-mount-map* '<KEY>'*:*'<VAL>'::
-    Setup mapping for external mounts. '<KEY>' is a mountpoint inside container
-    and corresponding '<VAL>' is a string that will be written into the image
-    as mountpoint\'s root value.
+    Setup mapping for external mounts. '<KEY>' is a mountpoint or a device
+    (dev[maj:min]]) inside container and corresponding '<VAL>' is a string
+    that will be written into the image as mountpoint\'s root or source value.
 
 *--link-remap*::
     Allow one to link unlinked files back when possible (modifies FS till *restore*).
diff --git a/criu/mount.c b/criu/mount.c
index f57b10c..f8d0cc2 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;
@@ -487,15 +489,31 @@  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) {
+		em = ext_mount_lookup(devstr);
+		if (em) {
+			info->fstype = &fstypes[1];
+			BUG_ON(info->fstype->code != FSTYPE__AUTO);
+			xfree(info->source);
+			info->source = xstrdup(em->val);
+			return 0;
+		}
+	}
+
+	return -ENOTSUP;
 }
 
 static struct mount_info *find_widest_shared(struct mount_info *m)
@@ -2091,6 +2109,11 @@  static char *resolve_source(struct mount_info *mi)
 
 	if (mi->fstype->code == FSTYPE__AUTO) {
 		struct stat st;
+		struct ext_mount *key;
+
+		key = ext_mount_lookup(mi->source);
+		if (key)
+			return key->val;
 
 		if (!stat(mi->source, &st) && S_ISBLK(st.st_mode) &&
 		    major(st.st_rdev) == kdev_major(mi->s_dev) &&

Comments

Pavel Emelianov April 22, 2016, 1:49 p.m.
On 04/22/2016 09:12 AM, Andrey Vagin wrote:
> From: Andrew Vagin <avagin@virtuozzo.com>
> 
> The idea is to allow to dump and restore mounts of
> a specified block device.
> 
> Options:
> dump:		--ext-mount-map dev[MAJOR:MINOR]:VAL

Why dev[MAJOR:MINOR]? Isn't just path (which is a mountpoint) enough?

> restore:	--ext-mount-map 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
> 
> Signed-off-by: Andrew Vagin <avagin@virtuozzo.com>
> ---
>  Documentation/criu.txt |  6 +++---
>  criu/mount.c           | 35 +++++++++++++++++++++++++++++------
>  2 files changed, 32 insertions(+), 9 deletions(-)
> 
> diff --git a/Documentation/criu.txt b/Documentation/criu.txt
> index 1982f5d..07da757 100644
> --- a/Documentation/criu.txt
> +++ b/Documentation/criu.txt
> @@ -176,9 +176,9 @@ In other words, do not use it until really needed.
>      where locks are not holed by someone outside of it.
>  
>  *-M*, *--ext-mount-map* '<KEY>'*:*'<VAL>'::
> -    Setup mapping for external mounts. '<KEY>' is a mountpoint inside container
> -    and corresponding '<VAL>' is a string that will be written into the image
> -    as mountpoint\'s root value.
> +    Setup mapping for external mounts. '<KEY>' is a mountpoint or a device
> +    (dev[maj:min]]) inside container and corresponding '<VAL>' is a string
> +    that will be written into the image as mountpoint\'s root or source value.
>  
>  *--link-remap*::
>      Allow one to link unlinked files back when possible (modifies FS till *restore*).
> diff --git a/criu/mount.c b/criu/mount.c
> index f57b10c..f8d0cc2 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;
> @@ -487,15 +489,31 @@ 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) {
> +		em = ext_mount_lookup(devstr);
> +		if (em) {
> +			info->fstype = &fstypes[1];
> +			BUG_ON(info->fstype->code != FSTYPE__AUTO);
> +			xfree(info->source);
> +			info->source = xstrdup(em->val);
> +			return 0;
> +		}
> +	}
> +
> +	return -ENOTSUP;
>  }
>  
>  static struct mount_info *find_widest_shared(struct mount_info *m)
> @@ -2091,6 +2109,11 @@ static char *resolve_source(struct mount_info *mi)
>  
>  	if (mi->fstype->code == FSTYPE__AUTO) {
>  		struct stat st;
> +		struct ext_mount *key;
> +
> +		key = ext_mount_lookup(mi->source);
> +		if (key)
> +			return key->val;
>  
>  		if (!stat(mi->source, &st) && S_ISBLK(st.st_mode) &&
>  		    major(st.st_rdev) == kdev_major(mi->s_dev) &&
>
Andrey Vagin April 22, 2016, 3:48 p.m.
On Fri, Apr 22, 2016 at 04:49:48PM +0300, Pavel Emelyanov wrote:
> On 04/22/2016 09:12 AM, Andrey Vagin wrote:
> > From: Andrew Vagin <avagin@virtuozzo.com>
> > 
> > The idea is to allow to dump and restore mounts of
> > a specified block device.
> > 
> > Options:
> > dump:		--ext-mount-map dev[MAJOR:MINOR]:VAL
> 
> Why dev[MAJOR:MINOR]? Isn't just path (which is a mountpoint) enough?

We don't know where this device is mounted, we know that this device
may be mounted somewhere in a container.

In OpenVZ we can grant permissions to mount a block device in a
container. And a user of CT decides where to mount this device.

> 
> > restore:	--ext-mount-map 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
> > 
> > Signed-off-by: Andrew Vagin <avagin@virtuozzo.com>
> > ---
> >  Documentation/criu.txt |  6 +++---
> >  criu/mount.c           | 35 +++++++++++++++++++++++++++++------
> >  2 files changed, 32 insertions(+), 9 deletions(-)
> > 
> > diff --git a/Documentation/criu.txt b/Documentation/criu.txt
> > index 1982f5d..07da757 100644
> > --- a/Documentation/criu.txt
> > +++ b/Documentation/criu.txt
> > @@ -176,9 +176,9 @@ In other words, do not use it until really needed.
> >      where locks are not holed by someone outside of it.
> >  
> >  *-M*, *--ext-mount-map* '<KEY>'*:*'<VAL>'::
> > -    Setup mapping for external mounts. '<KEY>' is a mountpoint inside container
> > -    and corresponding '<VAL>' is a string that will be written into the image
> > -    as mountpoint\'s root value.
> > +    Setup mapping for external mounts. '<KEY>' is a mountpoint or a device
> > +    (dev[maj:min]]) inside container and corresponding '<VAL>' is a string
> > +    that will be written into the image as mountpoint\'s root or source value.
> >  
> >  *--link-remap*::
> >      Allow one to link unlinked files back when possible (modifies FS till *restore*).
> > diff --git a/criu/mount.c b/criu/mount.c
> > index f57b10c..f8d0cc2 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;
> > @@ -487,15 +489,31 @@ 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) {
> > +		em = ext_mount_lookup(devstr);
> > +		if (em) {
> > +			info->fstype = &fstypes[1];
> > +			BUG_ON(info->fstype->code != FSTYPE__AUTO);
> > +			xfree(info->source);
> > +			info->source = xstrdup(em->val);
> > +			return 0;
> > +		}
> > +	}
> > +
> > +	return -ENOTSUP;
> >  }
> >  
> >  static struct mount_info *find_widest_shared(struct mount_info *m)
> > @@ -2091,6 +2109,11 @@ static char *resolve_source(struct mount_info *mi)
> >  
> >  	if (mi->fstype->code == FSTYPE__AUTO) {
> >  		struct stat st;
> > +		struct ext_mount *key;
> > +
> > +		key = ext_mount_lookup(mi->source);
> > +		if (key)
> > +			return key->val;
> >  
> >  		if (!stat(mi->source, &st) && S_ISBLK(st.st_mode) &&
> >  		    major(st.st_rdev) == kdev_major(mi->s_dev) &&
> > 
>
Pavel Emelianov April 22, 2016, 4:01 p.m.
On 04/22/2016 06:48 PM, Andrew Vagin wrote:
> On Fri, Apr 22, 2016 at 04:49:48PM +0300, Pavel Emelyanov wrote:
>> On 04/22/2016 09:12 AM, Andrey Vagin wrote:
>>> From: Andrew Vagin <avagin@virtuozzo.com>
>>>
>>> The idea is to allow to dump and restore mounts of
>>> a specified block device.
>>>
>>> Options:
>>> dump:		--ext-mount-map dev[MAJOR:MINOR]:VAL
>>
>> Why dev[MAJOR:MINOR]? Isn't just path (which is a mountpoint) enough?
> 
> We don't know where this device is mounted, we know that this device
> may be mounted somewhere in a container.

OK, then this is not the case for --ext-mount-map option :(
Let's step back a little. Which error do we hit when dumping this mount option?

> In OpenVZ we can grant permissions to mount a block device in a
> container. And a user of CT decides where to mount this device.
> 
>>
>>> restore:	--ext-mount-map 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
>>>
>>> Signed-off-by: Andrew Vagin <avagin@virtuozzo.com>
>>> ---
>>>  Documentation/criu.txt |  6 +++---
>>>  criu/mount.c           | 35 +++++++++++++++++++++++++++++------
>>>  2 files changed, 32 insertions(+), 9 deletions(-)
>>>
>>> diff --git a/Documentation/criu.txt b/Documentation/criu.txt
>>> index 1982f5d..07da757 100644
>>> --- a/Documentation/criu.txt
>>> +++ b/Documentation/criu.txt
>>> @@ -176,9 +176,9 @@ In other words, do not use it until really needed.
>>>      where locks are not holed by someone outside of it.
>>>  
>>>  *-M*, *--ext-mount-map* '<KEY>'*:*'<VAL>'::
>>> -    Setup mapping for external mounts. '<KEY>' is a mountpoint inside container
>>> -    and corresponding '<VAL>' is a string that will be written into the image
>>> -    as mountpoint\'s root value.
>>> +    Setup mapping for external mounts. '<KEY>' is a mountpoint or a device
>>> +    (dev[maj:min]]) inside container and corresponding '<VAL>' is a string
>>> +    that will be written into the image as mountpoint\'s root or source value.
>>>  
>>>  *--link-remap*::
>>>      Allow one to link unlinked files back when possible (modifies FS till *restore*).
>>> diff --git a/criu/mount.c b/criu/mount.c
>>> index f57b10c..f8d0cc2 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;
>>> @@ -487,15 +489,31 @@ 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) {
>>> +		em = ext_mount_lookup(devstr);
>>> +		if (em) {
>>> +			info->fstype = &fstypes[1];
>>> +			BUG_ON(info->fstype->code != FSTYPE__AUTO);
>>> +			xfree(info->source);
>>> +			info->source = xstrdup(em->val);
>>> +			return 0;
>>> +		}
>>> +	}
>>> +
>>> +	return -ENOTSUP;
>>>  }
>>>  
>>>  static struct mount_info *find_widest_shared(struct mount_info *m)
>>> @@ -2091,6 +2109,11 @@ static char *resolve_source(struct mount_info *mi)
>>>  
>>>  	if (mi->fstype->code == FSTYPE__AUTO) {
>>>  		struct stat st;
>>> +		struct ext_mount *key;
>>> +
>>> +		key = ext_mount_lookup(mi->source);
>>> +		if (key)
>>> +			return key->val;
>>>  
>>>  		if (!stat(mi->source, &st) && S_ISBLK(st.st_mode) &&
>>>  		    major(st.st_rdev) == kdev_major(mi->s_dev) &&
>>>
>>
> .
>
Andrey Vagin April 22, 2016, 5:23 p.m.
On Fri, Apr 22, 2016 at 07:01:22PM +0300, Pavel Emelyanov wrote:
> On 04/22/2016 06:48 PM, Andrew Vagin wrote:
> > On Fri, Apr 22, 2016 at 04:49:48PM +0300, Pavel Emelyanov wrote:
> >> On 04/22/2016 09:12 AM, Andrey Vagin wrote:
> >>> From: Andrew Vagin <avagin@virtuozzo.com>
> >>>
> >>> The idea is to allow to dump and restore mounts of
> >>> a specified block device.
> >>>
> >>> Options:
> >>> dump:		--ext-mount-map dev[MAJOR:MINOR]:VAL
> >>
> >> Why dev[MAJOR:MINOR]? Isn't just path (which is a mountpoint) enough?
> > 
> > We don't know where this device is mounted, we know that this device
> > may be mounted somewhere in a container.
> 
> OK, then this is not the case for --ext-mount-map option :(
> Let's step back a little. Which error do we hit when dumping this mount option?

[root@fc22-vm ~]# cat /proc/25743/mountinfo 
152 117 252:2 /root/git/criu/test / rw,relatime - ext4 /dev/vda2 rw,data=ordered
153 152 0:46 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw
118 152 0:47 / /dev/pts rw,relatime - devpts pts rw,mode=666,ptmxmode=666
119 152 7:1 / /zdtm/static/mnt_ext_dev.test rw,relatime - ext4 /dev/loop1 rw,data=ordered
120 119 7:1 /test_dir /zdtm/static/mnt_ext_dev.test/test_dir2 rw,relatime - ext4 /dev/loop1 rw,data=ordered


(00.004858) Error (mount.c:731): mnt: FS mnt ./zdtm/static/mnt_ext_dev.test dev 0x700001 root / unsupported id 119

> 
> > In OpenVZ we can grant permissions to mount a block device in a
> > container. And a user of CT decides where to mount this device.
> > 
> >>
> >>> restore:	--ext-mount-map 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
> >>>
> >>> Signed-off-by: Andrew Vagin <avagin@virtuozzo.com>
> >>> ---
> >>>  Documentation/criu.txt |  6 +++---
> >>>  criu/mount.c           | 35 +++++++++++++++++++++++++++++------
> >>>  2 files changed, 32 insertions(+), 9 deletions(-)
> >>>
> >>> diff --git a/Documentation/criu.txt b/Documentation/criu.txt
> >>> index 1982f5d..07da757 100644
> >>> --- a/Documentation/criu.txt
> >>> +++ b/Documentation/criu.txt
> >>> @@ -176,9 +176,9 @@ In other words, do not use it until really needed.
> >>>      where locks are not holed by someone outside of it.
> >>>  
> >>>  *-M*, *--ext-mount-map* '<KEY>'*:*'<VAL>'::
> >>> -    Setup mapping for external mounts. '<KEY>' is a mountpoint inside container
> >>> -    and corresponding '<VAL>' is a string that will be written into the image
> >>> -    as mountpoint\'s root value.
> >>> +    Setup mapping for external mounts. '<KEY>' is a mountpoint or a device
> >>> +    (dev[maj:min]]) inside container and corresponding '<VAL>' is a string
> >>> +    that will be written into the image as mountpoint\'s root or source value.
> >>>  
> >>>  *--link-remap*::
> >>>      Allow one to link unlinked files back when possible (modifies FS till *restore*).
> >>> diff --git a/criu/mount.c b/criu/mount.c
> >>> index f57b10c..f8d0cc2 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;
> >>> @@ -487,15 +489,31 @@ 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) {
> >>> +		em = ext_mount_lookup(devstr);
> >>> +		if (em) {
> >>> +			info->fstype = &fstypes[1];
> >>> +			BUG_ON(info->fstype->code != FSTYPE__AUTO);
> >>> +			xfree(info->source);
> >>> +			info->source = xstrdup(em->val);
> >>> +			return 0;
> >>> +		}
> >>> +	}
> >>> +
> >>> +	return -ENOTSUP;
> >>>  }
> >>>  
> >>>  static struct mount_info *find_widest_shared(struct mount_info *m)
> >>> @@ -2091,6 +2109,11 @@ static char *resolve_source(struct mount_info *mi)
> >>>  
> >>>  	if (mi->fstype->code == FSTYPE__AUTO) {
> >>>  		struct stat st;
> >>> +		struct ext_mount *key;
> >>> +
> >>> +		key = ext_mount_lookup(mi->source);
> >>> +		if (key)
> >>> +			return key->val;
> >>>  
> >>>  		if (!stat(mi->source, &st) && S_ISBLK(st.st_mode) &&
> >>>  		    major(st.st_rdev) == kdev_major(mi->s_dev) &&
> >>>
> >>
> > .
> > 
>
Pavel Emelianov April 25, 2016, 9:09 a.m.
On 04/22/2016 08:23 PM, Andrew Vagin wrote:
> On Fri, Apr 22, 2016 at 07:01:22PM +0300, Pavel Emelyanov wrote:
>> On 04/22/2016 06:48 PM, Andrew Vagin wrote:
>>> On Fri, Apr 22, 2016 at 04:49:48PM +0300, Pavel Emelyanov wrote:
>>>> On 04/22/2016 09:12 AM, Andrey Vagin wrote:
>>>>> From: Andrew Vagin <avagin@virtuozzo.com>
>>>>>
>>>>> The idea is to allow to dump and restore mounts of
>>>>> a specified block device.
>>>>>
>>>>> Options:
>>>>> dump:		--ext-mount-map dev[MAJOR:MINOR]:VAL
>>>>
>>>> Why dev[MAJOR:MINOR]? Isn't just path (which is a mountpoint) enough?
>>>
>>> We don't know where this device is mounted, we know that this device
>>> may be mounted somewhere in a container.
>>
>> OK, then this is not the case for --ext-mount-map option :(
>> Let's step back a little. Which error do we hit when dumping this mount option?
> 
> [root@fc22-vm ~]# cat /proc/25743/mountinfo 
> 152 117 252:2 /root/git/criu/test / rw,relatime - ext4 /dev/vda2 rw,data=ordered
> 153 152 0:46 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw
> 118 152 0:47 / /dev/pts rw,relatime - devpts pts rw,mode=666,ptmxmode=666
> 119 152 7:1 / /zdtm/static/mnt_ext_dev.test rw,relatime - ext4 /dev/loop1 rw,data=ordered
> 120 119 7:1 /test_dir /zdtm/static/mnt_ext_dev.test/test_dir2 rw,relatime - ext4 /dev/loop1 rw,data=ordered
> 
> 
> (00.004858) Error (mount.c:731): mnt: FS mnt ./zdtm/static/mnt_ext_dev.test dev 0x700001 root / unsupported id 119

OK. Since v1.8 we can make --ext-mount-map work on fsroot mounts. If without applying your patch you
say --ext-mount-map /zdtm/static/mnt_ext_dev.test:ABC, will this unblock the dump?

>>
>>> In OpenVZ we can grant permissions to mount a block device in a
>>> container. And a user of CT decides where to mount this device.
>>>
>>>>
>>>>> restore:	--ext-mount-map 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
>>>>>
>>>>> Signed-off-by: Andrew Vagin <avagin@virtuozzo.com>
>>>>> ---
>>>>>  Documentation/criu.txt |  6 +++---
>>>>>  criu/mount.c           | 35 +++++++++++++++++++++++++++++------
>>>>>  2 files changed, 32 insertions(+), 9 deletions(-)
>>>>>
>>>>> diff --git a/Documentation/criu.txt b/Documentation/criu.txt
>>>>> index 1982f5d..07da757 100644
>>>>> --- a/Documentation/criu.txt
>>>>> +++ b/Documentation/criu.txt
>>>>> @@ -176,9 +176,9 @@ In other words, do not use it until really needed.
>>>>>      where locks are not holed by someone outside of it.
>>>>>  
>>>>>  *-M*, *--ext-mount-map* '<KEY>'*:*'<VAL>'::
>>>>> -    Setup mapping for external mounts. '<KEY>' is a mountpoint inside container
>>>>> -    and corresponding '<VAL>' is a string that will be written into the image
>>>>> -    as mountpoint\'s root value.
>>>>> +    Setup mapping for external mounts. '<KEY>' is a mountpoint or a device
>>>>> +    (dev[maj:min]]) inside container and corresponding '<VAL>' is a string
>>>>> +    that will be written into the image as mountpoint\'s root or source value.
>>>>>  
>>>>>  *--link-remap*::
>>>>>      Allow one to link unlinked files back when possible (modifies FS till *restore*).
>>>>> diff --git a/criu/mount.c b/criu/mount.c
>>>>> index f57b10c..f8d0cc2 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;
>>>>> @@ -487,15 +489,31 @@ 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) {
>>>>> +		em = ext_mount_lookup(devstr);
>>>>> +		if (em) {
>>>>> +			info->fstype = &fstypes[1];
>>>>> +			BUG_ON(info->fstype->code != FSTYPE__AUTO);
>>>>> +			xfree(info->source);
>>>>> +			info->source = xstrdup(em->val);
>>>>> +			return 0;
>>>>> +		}
>>>>> +	}
>>>>> +
>>>>> +	return -ENOTSUP;
>>>>>  }
>>>>>  
>>>>>  static struct mount_info *find_widest_shared(struct mount_info *m)
>>>>> @@ -2091,6 +2109,11 @@ static char *resolve_source(struct mount_info *mi)
>>>>>  
>>>>>  	if (mi->fstype->code == FSTYPE__AUTO) {
>>>>>  		struct stat st;
>>>>> +		struct ext_mount *key;
>>>>> +
>>>>> +		key = ext_mount_lookup(mi->source);
>>>>> +		if (key)
>>>>> +			return key->val;
>>>>>  
>>>>>  		if (!stat(mi->source, &st) && S_ISBLK(st.st_mode) &&
>>>>>  		    major(st.st_rdev) == kdev_major(mi->s_dev) &&
>>>>>
>>>>
>>> .
>>>
>>
> .
>