mail archive of the rauc mailing list
 help / color / mirror / Atom feed
* [RAUC] Failed to mount seed slot
@ 2019-05-06 17:44 Ladislav Michl
  2019-05-07  7:31 ` Ladislav Michl
  0 siblings, 1 reply; 7+ messages in thread
From: Ladislav Michl @ 2019-05-06 17:44 UTC (permalink / raw)
  To: rauc

Hi there,

I'm using rauc with casync to update target system - it is symmetric rootfsA,
rootfsB, scenario, so slots are defined as:
[slot.rootfs.0]
device=/dev/ubi0_0
type=ubifs
bootname=system0

[slot.rootfs.1]
device=/dev/ubi0_1
type=ubifs
bootname=system1

Now system is booted with rootfs mounted read only which makes mounting seed
slot fail:
rauc[871]: Mounting /dev/ubi0_0 to use as seed
rauc[871]: launching subprocess: mount -t ubifs /dev/ubi0_0 /run/rauc/rootfs.0
rauc[871]: posix_spawn avoided (fd close requested) (child_setup specified) 
rauc[871]: mount: /run/rauc/rootfs.0: /dev/ubi0_0 already mounted or mount point busy.

Here adding '-o ro' would quick fix it up (but break rw case, as options have to
match), so it seems better to use bind mount as comment casync_extract_image
function suggests, but do not see it code.

Am I missing anything?

Thank you,
	ladis

_______________________________________________
RAUC mailing list

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RAUC] Failed to mount seed slot
  2019-05-06 17:44 [RAUC] Failed to mount seed slot Ladislav Michl
@ 2019-05-07  7:31 ` Ladislav Michl
  2019-05-07 15:49   ` Ladislav Michl
  0 siblings, 1 reply; 7+ messages in thread
From: Ladislav Michl @ 2019-05-07  7:31 UTC (permalink / raw)
  To: rauc

On Mon, May 06, 2019 at 07:44:09PM +0200, Ladislav Michl wrote:
> Hi there,
> 
> I'm using rauc with casync to update target system - it is symmetric rootfsA,
> rootfsB, scenario, so slots are defined as:
> [slot.rootfs.0]
> device=/dev/ubi0_0
> type=ubifs
> bootname=system0
> 
> [slot.rootfs.1]
> device=/dev/ubi0_1
> type=ubifs
> bootname=system1
> 
> Now system is booted with rootfs mounted read only which makes mounting seed
> slot fail:
> rauc[871]: Mounting /dev/ubi0_0 to use as seed
> rauc[871]: launching subprocess: mount -t ubifs /dev/ubi0_0 /run/rauc/rootfs.0
> rauc[871]: posix_spawn avoided (fd close requested) (child_setup specified) 
> rauc[871]: mount: /run/rauc/rootfs.0: /dev/ubi0_0 already mounted or mount point busy.
> 
> Here adding '-o ro' would quick fix it up (but break rw case, as options have to
> match), so it seems better to use bind mount as comment casync_extract_image
> function suggests, but do not see it code.
> 
> Am I missing anything?

So, whats still missing is a review of pull request #406 (Normalize device names
to find mounted slots) :)

Then determine_slot_states should properly fill slot's ext_mount_point and
casync_extract_image would then use it to bind mount seed slot.

And here's the tricky part. For device-less mount, volume to mount is specified
for example using ubiX_Y or ubiX:NAME syntax, so fix in #406 will fail in this
case.

A workaround is to add support to bootloader which will try to guess UBI
volume character device as seen by kernel.

Now it is time to make design decision: if rauc is going to suppport device-less
mounts this should be fixed (read: I'll provide a patch for review). Otherwise
I'll change a way bootloader passes root= option.

Thank you,
	ladis

_______________________________________________
RAUC mailing list

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RAUC] Failed to mount seed slot
  2019-05-07  7:31 ` Ladislav Michl
@ 2019-05-07 15:49   ` Ladislav Michl
  2019-05-07 17:59     ` Trent Piepho
  0 siblings, 1 reply; 7+ messages in thread
From: Ladislav Michl @ 2019-05-07 15:49 UTC (permalink / raw)
  To: rauc; +Cc: Trent Piepho, Enrico Jorns, Jan Luebbe

On Tue, May 07, 2019 at 09:31:28AM +0200, Ladislav Michl wrote:
> On Mon, May 06, 2019 at 07:44:09PM +0200, Ladislav Michl wrote:
> > Hi there,
> > 
> > I'm using rauc with casync to update target system - it is symmetric rootfsA,
> > rootfsB, scenario, so slots are defined as:
> > [slot.rootfs.0]
> > device=/dev/ubi0_0
> > type=ubifs
> > bootname=system0
> > 
> > [slot.rootfs.1]
> > device=/dev/ubi0_1
> > type=ubifs
> > bootname=system1
> > 
> > Now system is booted with rootfs mounted read only which makes mounting seed
> > slot fail:
> > rauc[871]: Mounting /dev/ubi0_0 to use as seed
> > rauc[871]: launching subprocess: mount -t ubifs /dev/ubi0_0 /run/rauc/rootfs.0
> > rauc[871]: posix_spawn avoided (fd close requested) (child_setup specified) 
> > rauc[871]: mount: /run/rauc/rootfs.0: /dev/ubi0_0 already mounted or mount point busy.
> > 
> > Here adding '-o ro' would quick fix it up (but break rw case, as options have to
> > match), so it seems better to use bind mount as comment casync_extract_image
> > function suggests, but do not see it code.
> > 
> > Am I missing anything?
> 
> So, whats still missing is a review of pull request #406 (Normalize device names
> to find mounted slots) :)

It feels really strange talking to myself, so let's hope someone else joins as
well, hence Cc list.

Problem is similar to that one solved by #406 and #388, however it needs to be
extended to ubi<X> and possibly mtd<X> case. For now let's start with fixing
pull request #406 to:
- use C comments
- avoid unneded allocations
- also allow character devices (for example /dev/ubi0_0)

> Then determine_slot_states should properly fill slot's ext_mount_point and
> casync_extract_image would then use it to bind mount seed slot.
> 
> And here's the tricky part. For device-less mount, volume to mount is specified
> for example using ubiX_Y or ubiX:NAME syntax, so fix in #406 will fail in this
> case.

This one was fixed by extending normalize_mountable_object from #406 and
adjusting casync_extract_image, but lets first get #406 revieved and merged :)
Trent, in case you want to merge following additional patch to your PR here's my
Signed-off-by: Ladislav Michl <ladis@linux-mips.org>

diff --git a/src/config_file.c b/src/config_file.c
index 875e0ee..e592d15 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -494,27 +494,25 @@ free:
 	return res;
 }
 
-// Something that is, or can be, mounted onto a mount point
+/* Something that is, or can be, mounted onto a mount point */
 typedef struct {
-	gboolean is_device;  // vs being a loop mounted file
-	dev_t dev;  // the device, or for a file, the device the file is on
-	ino_t inode;  // inode of file for a non-device
+	gboolean is_device;	/* vs being a loop mounted file */
+	dev_t dev;		/* the device, or for a file, the device the file is on */
+	ino_t inode;		/* inode of file for a non-device */
 } MountableObj;
 
-// Take a device (or file) path and normalize it
-static MountableObj *normalize_mountable_object(const gchar *devicepath)
+/* Take a device (or file) path or name and normalize it */
+static gboolean normalize_mountable_object(const gchar *devicename, MountableObj *obj)
 {
-	MountableObj *obj;
 	GStatBuf st;
 
-	if (g_stat(devicepath, &st) == -1) {
+	if (g_stat(devicename, &st) == -1) {
 		/* Virtual filesystems like devpts trigger case */
-		g_debug("Can't stat '%s', assuming unmountable: %s", devicepath, g_strerror(errno));
-		return NULL;
+		g_debug("Can't stat '%s', assuming unmountable: %s", devicename, g_strerror(errno));
+		return FALSE;
 	}
 
-	obj = g_new0(MountableObj, 1);
-	if (S_ISBLK(st.st_mode)) {
+	if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) {
 		obj->is_device = TRUE;
 		obj->dev = st.st_rdev;
 	} else if (S_ISREG(st.st_mode)) {
@@ -522,10 +520,10 @@ static MountableObj *normalize_mountable_object(const gchar *devicepath)
 		obj->dev = st.st_dev;
 		obj->inode = st.st_ino;
 	} else {
-		g_debug("Device '%s' is not something which is mountable", devicepath);
-		g_clear_pointer(&obj, g_free);
+		g_debug("Device '%s' is not something which is mountable", devicename);
+		return FALSE;
 	}
-	return obj;
+	return TRUE;
 }
 
 /* Compare two MountableObj for equality */
@@ -546,24 +544,24 @@ RaucSlot *find_slot_by_device(GHashTable *slots, const gchar *device)
 {
 	GHashTableIter iter;
 	RaucSlot *slot;
-	g_autofree MountableObj *obj = NULL;
+	MountableObj obj;
+	gboolean normalized;
 
 	g_return_val_if_fail(slots, NULL);
 	g_return_val_if_fail(device, NULL);
 
-	obj = normalize_mountable_object(device);
+	normalized = normalize_mountable_object(device, &obj);
 
 	g_hash_table_iter_init(&iter, slots);
 	while (g_hash_table_iter_next(&iter, NULL, (gpointer*) &slot)) {
 		if (g_strcmp0(slot->device, device) == 0)
 			goto out;
 
-		// Path doesn't match, but maybe device is same?
-		if (obj) {
-			g_autofree MountableObj *slot_obj =
-				normalize_mountable_object(slot->device);
-
-			if (slot_obj && is_same_mountable_object(obj, slot_obj))
+		/* Path doesn't match, but maybe device is the same? */
+		if (normalized) {
+			MountableObj slot_obj;
+			if (normalize_mountable_object(slot->device, &slot_obj) &&
+			    is_same_mountable_object(&obj, &slot_obj))
 				goto out;
 		}
 	}

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RAUC] Failed to mount seed slot
  2019-05-07 15:49   ` Ladislav Michl
@ 2019-05-07 17:59     ` Trent Piepho
  2019-05-07 20:33       ` Ladislav Michl
  2019-05-08  5:44       ` Ladislav Michl
  0 siblings, 2 replies; 7+ messages in thread
From: Trent Piepho @ 2019-05-07 17:59 UTC (permalink / raw)
  To: ladis, rauc; +Cc: ejo, jlu

On Tue, 2019-05-07 at 17:49 +0200, Ladislav Michl wrote:
> On Tue, May 07, 2019 at 09:31:28AM +0200, Ladislav Michl wrote:
> > On Mon, May 06, 2019 at 07:44:09PM +0200, Ladislav Michl wrote:
> > > [slot.rootfs.0]
> > > device=/dev/ubi0_0
> > > type=ubifs
> > > bootname=system0
> > > 
> > > Now system is booted with rootfs mounted read only which makes mounting seed
> > > slot fail:
> > > rauc[871]: Mounting /dev/ubi0_0 to use as seed
> > > rauc[871]: launching subprocess: mount -t ubifs /dev/ubi0_0 /run/rauc/rootfs.0
> > > rauc[871]: posix_spawn avoided (fd close requested) (child_setup specified) 
> > > rauc[871]: mount: /run/rauc/rootfs.0: /dev/ubi0_0 already mounted or mount point busy.

What does the kernel show in /proc/mounts in this case?  If it's
"/dev/ubi0_0", then it should match based on the simple path compare.

> Problem is similar to that one solved by #406 and #388, however it needs to be
> extended to ubi<X> and possibly mtd<X> case. For now let's start with fixing
> pull request #406 to:

Is there a way to mount a /dev/mtd<X> device directly, and not through
/dev/mtdblock<X>?  I was under the impression that yaffs1/2 and jffs2
used mtdblock, but I haven't used raw nand (what a PITA it is) in
while.

> - use C comments

Is this a requirement for rauc?  I see other // comments in rauc, they
are part of the C standard since C99, and rauc's extensive github
commit checking doesn't flag it.

> - avoid unneded allocations

Perhaps this is better, since none of the allocations need to live.

> - also allow character devices (for example /dev/ubi0_0)

Seems reasonable to fix that case.  This would work for /dev/mtd too,
if there is a way to mount those.

> > Then determine_slot_states should properly fill slot's ext_mount_point and
> > casync_extract_image would then use it to bind mount seed slot.
> > 
> > And here's the tricky part. For device-less mount, volume to mount is specified
> > for example using ubiX_Y or ubiX:NAME syntax, so fix in #406 will fail in this
> > case.

If the mount call uses ubiX:NAME, what does /proc/mounts report?  That
really the issue: matching the config file device string to the string
reported by the kernel when the device is mounted.

> This one was fixed by extending normalize_mountable_object from #406 and
> adjusting casync_extract_image, but lets first get #406 revieved and merged :)
> Trent, in case you want to merge following additional patch to your PR here's my
> Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
> 
> diff --git a/src/config_file.c b/src/config_file.c
> index 875e0ee..e592d15 100644
> --- a/src/config_file.c
> +++ b/src/config_file.c
> @@ -494,27 +494,25 @@ free:
>  	return res;
>  }
>  
> -// Something that is, or can be, mounted onto a mount point
> +/* Something that is, or can be, mounted onto a mount point */
>  typedef struct {
> -	gboolean is_device;  // vs being a loop mounted file
> -	dev_t dev;  // the device, or for a file, the device the file is on
> -	ino_t inode;  // inode of file for a non-device
> +	gboolean is_device;	/* vs being a loop mounted file */
> +	dev_t dev;		/* the device, or for a file, the device the file is on */
> +	ino_t inode;		/* inode of file for a non-device */
>  } MountableObj;

There would also need to be another bool to indicate if the device is a
 block dev or char dev, since the major:minor could match between
different device types.  That could be part of a union with inode since
the two are mutually exclusive.

>  
> -// Take a device (or file) path and normalize it
> -static MountableObj *normalize_mountable_object(const gchar *devicepath)
> +/* Take a device (or file) path or name and normalize it */
> +static gboolean normalize_mountable_object(const gchar *devicename, MountableObj *obj)
>  {
> -	MountableObj *obj;
>  	GStatBuf st;
>  
> -	if (g_stat(devicepath, &st) == -1) {
> +	if (g_stat(devicename, &st) == -1) {
>  		/* Virtual filesystems like devpts trigger case */
> -		g_debug("Can't stat '%s', assuming unmountable: %s", devicepath, g_strerror(errno));
> -		return NULL;
> +		g_debug("Can't stat '%s', assuming unmountable: %s", devicename, g_strerror(errno));
> +		return FALSE;
>  	}
>  
> -	obj = g_new0(MountableObj, 1);
> -	if (S_ISBLK(st.st_mode)) {
> +	if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) {
>  		obj->is_device = TRUE;
>  		obj->dev = st.st_rdev;
>  	} else if (S_ISREG(st.st_mode)) {
> @@ -522,10 +520,10 @@ static MountableObj *normalize_mountable_object(const gchar *devicepath)
>  		obj->dev = st.st_dev;
>  		obj->inode = st.st_ino;
>  	} else {
> -		g_debug("Device '%s' is not something which is mountable", devicepath);
> -		g_clear_pointer(&obj, g_free);
> +		g_debug("Device '%s' is not something which is mountable", devicename);
> +		return FALSE;
>  	}
> -	return obj;
> +	return TRUE;
>  }
>  
>  /* Compare two MountableObj for equality */
> @@ -546,24 +544,24 @@ RaucSlot *find_slot_by_device(GHashTable *slots, const gchar *device)
>  {
>  	GHashTableIter iter;
>  	RaucSlot *slot;
> -	g_autofree MountableObj *obj = NULL;
> +	MountableObj obj;
> +	gboolean normalized;
>  
>  	g_return_val_if_fail(slots, NULL);
>  	g_return_val_if_fail(device, NULL);
>  
> -	obj = normalize_mountable_object(device);
> +	normalized = normalize_mountable_object(device, &obj);
>  
>  	g_hash_table_iter_init(&iter, slots);
>  	while (g_hash_table_iter_next(&iter, NULL, (gpointer*) &slot)) {
>  		if (g_strcmp0(slot->device, device) == 0)
>  			goto out;
>  
> -		// Path doesn't match, but maybe device is same?
> -		if (obj) {
> -			g_autofree MountableObj *slot_obj =
> -				normalize_mountable_object(slot->device);
> -
> -			if (slot_obj && is_same_mountable_object(obj, slot_obj))
> +		/* Path doesn't match, but maybe device is the same? */
> +		if (normalized) {
> +			MountableObj slot_obj;
> +			if (normalize_mountable_object(slot->device, &slot_obj) &&
> +			    is_same_mountable_object(&obj, &slot_obj))
>  				goto out;
>  		}
>  	}

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RAUC] Failed to mount seed slot
  2019-05-07 17:59     ` Trent Piepho
@ 2019-05-07 20:33       ` Ladislav Michl
  2019-05-09 11:32         ` Ladislav Michl
  2019-05-08  5:44       ` Ladislav Michl
  1 sibling, 1 reply; 7+ messages in thread
From: Ladislav Michl @ 2019-05-07 20:33 UTC (permalink / raw)
  To: Trent Piepho; +Cc: ejo, rauc, jlu

On Tue, May 07, 2019 at 05:59:36PM +0000, Trent Piepho wrote:
> On Tue, 2019-05-07 at 17:49 +0200, Ladislav Michl wrote:
> > On Tue, May 07, 2019 at 09:31:28AM +0200, Ladislav Michl wrote:
> > > On Mon, May 06, 2019 at 07:44:09PM +0200, Ladislav Michl wrote:
> > > > [slot.rootfs.0]
> > > > device=/dev/ubi0_0
> > > > type=ubifs
> > > > bootname=system0
> > > > 
> > > > Now system is booted with rootfs mounted read only which makes mounting seed
> > > > slot fail:
> > > > rauc[871]: Mounting /dev/ubi0_0 to use as seed
> > > > rauc[871]: launching subprocess: mount -t ubifs /dev/ubi0_0 /run/rauc/rootfs.0
> > > > rauc[871]: posix_spawn avoided (fd close requested) (child_setup specified) 
> > > > rauc[871]: mount: /run/rauc/rootfs.0: /dev/ubi0_0 already mounted or mount point busy.
> 
> What does the kernel show in /proc/mounts in this case?  If it's
> "/dev/ubi0_0", then it should match based on the simple path compare.

System is using barebox' bootchooser with boot loader specification. Here
device is ubi0:rootfs0. And yes, device name could be changed in rauc's
slot configuration to be ubi0:rootfs0 allowing path compare succeed.
But see bellow why it is worth changing code a bit.

> > Problem is similar to that one solved by #406 and #388, however it needs to be
> > extended to ubi<X> and possibly mtd<X> case. For now let's start with fixing
> > pull request #406 to:
> 
> Is there a way to mount a /dev/mtd<X> device directly, and not through
> /dev/mtdblock<X>?  I was under the impression that yaffs1/2 and jffs2
> used mtdblock, but I haven't used raw nand (what a PITA it is) in
> while.

I guess mtd layer does not need block device to mount for over a decade,
but haven't bothered to found that commit :)

> > - use C comments
> 
> Is this a requirement for rauc?  I see other // comments in rauc, they
> are part of the C standard since C99, and rauc's extensive github
> commit checking doesn't flag it.

I have no strong opinion here, just made it consistent with the rest
of file.

> > - avoid unneded allocations
> 
> Perhaps this is better, since none of the allocations need to live.
> 
> > - also allow character devices (for example /dev/ubi0_0)
> 
> Seems reasonable to fix that case.  This would work for /dev/mtd too,
> if there is a way to mount those.

Please see http://www.linux-mtd.infradead.org/faq/jffs2.html#L_mtdblock

> > > Then determine_slot_states should properly fill slot's ext_mount_point and
> > > casync_extract_image would then use it to bind mount seed slot.
> > > 
> > > And here's the tricky part. For device-less mount, volume to mount is specified
> > > for example using ubiX_Y or ubiX:NAME syntax, so fix in #406 will fail in this
> > > case.
> 
> If the mount call uses ubiX:NAME, what does /proc/mounts report?  That
> really the issue: matching the config file device string to the string
> reported by the kernel when the device is mounted.

/proc/mounts reports whatever was used as mount argument.

> > This one was fixed by extending normalize_mountable_object from #406 and
> > adjusting casync_extract_image, but lets first get #406 revieved and merged :)
> > Trent, in case you want to merge following additional patch to your PR here's my
> > Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
> > 
> > diff --git a/src/config_file.c b/src/config_file.c
> > index 875e0ee..e592d15 100644
> > --- a/src/config_file.c
> > +++ b/src/config_file.c
> > @@ -494,27 +494,25 @@ free:
> >  	return res;
> >  }
> >  
> > -// Something that is, or can be, mounted onto a mount point
> > +/* Something that is, or can be, mounted onto a mount point */
> >  typedef struct {
> > -	gboolean is_device;  // vs being a loop mounted file
> > -	dev_t dev;  // the device, or for a file, the device the file is on
> > -	ino_t inode;  // inode of file for a non-device
> > +	gboolean is_device;	/* vs being a loop mounted file */
> > +	dev_t dev;		/* the device, or for a file, the device the file is on */
> > +	ino_t inode;		/* inode of file for a non-device */
> >  } MountableObj;
> 
> There would also need to be another bool to indicate if the device is a
>  block dev or char dev, since the major:minor could match between
> different device types.  That could be part of a union with inode since
> the two are mutually exclusive.

Ah, will fix that. Eventually it is possible to walk /sys/dev using major:minor
and find corresponding uevent file which is holding DEVNAME key, but I like
your approach a lot more as it will also allow us to move all logic which is
now scattered over different places to find_slot_by_device. The loop in
determine_slot_states then boils down to:

	/* Determine active slot mount points */
	mountlist = g_unix_mounts_get(NULL);
	for (GList *l = mountlist; l != NULL; l = l->next) {
		GUnixMountEntry *m = (GUnixMountEntry*)l->data;
		RaucSlot *s = find_config_slot_by_device(r_context()->config, g_unix_mount_get_device_path(m));
		if (!s || s->ext_mount_point)
			continue;

		s->ext_mount_point = g_strdup(g_unix_mount_get_mount_path(m));
		g_debug("Found external mountpoint for slot %s at %s",
				s->name, s->ext_mount_point);
	}
	g_list_free_full(mountlist, (GDestroyNotify)g_unix_mount_free);

Then we can remove resolve_loop_device as your match code should cover
that special case too and with normalize_mountable_object first checking
for "special" device names and then stating path if it is starting with
'/' all quirks elsewhere are gone.

So here's the last remaining piece to puzzle:
--- a/src/update_handler.c
+++ b/src/update_handler.c
@@ -253,11 +253,29 @@ static gboolean casync_extract_image(RaucImage *image, gchar *dest, GError **err
 		 * file systems, additional mounts, etc. */
 		if (!seedslot->mount_point) {
 			g_debug("Mounting %s to use as seed", seedslot->device);
-			res = r_mount_slot(seedslot, &ierror);
-			if (!res) {
-				g_warning("Failed mounting for seeding: %s", ierror->message);
-				g_clear_error(&ierror);
-				goto extract;
+			if (seedslot->ext_mount_point) {
+				gchar *mount_point = r_create_mount_point(seedslot->name, &ierror);
+				if (!mount_point) {
+					g_warning("Failed creating bind mount point for seeding: %s", ierror->message);
+					g_clear_error(&ierror);
+					goto extract;
+				}
+				res = r_mount_full(seedslot->ext_mount_point, mount_point, NULL, 0, "bind", &ierror);
+				if (!res) {
+					g_warning("Failed bind mounting for seeding: %s", ierror->message);
+					g_clear_error(&ierror);
+					g_rmdir(mount_point);
+					g_free(mount_point);
+					goto extract;
+				}
+				seedslot->mount_point = mount_point;
+			} else {
+				res = r_mount_slot(seedslot, &ierror);
+				if (!res) {
+					g_warning("Failed mounting for seeding: %s", ierror->message);
+					g_clear_error(&ierror);
+					goto extract;
+				}
 			}
 			seed_mounted = TRUE;
 		}

Above change would actually bind mount slot for seeding...

> > -// Take a device (or file) path and normalize it
> > -static MountableObj *normalize_mountable_object(const gchar *devicepath)
> > +/* Take a device (or file) path or name and normalize it */
> > +static gboolean normalize_mountable_object(const gchar *devicename, MountableObj *obj)
> >  {
> > -	MountableObj *obj;
> >  	GStatBuf st;
> >  
> > -	if (g_stat(devicepath, &st) == -1) {
> > +	if (g_stat(devicename, &st) == -1) {
> >  		/* Virtual filesystems like devpts trigger case */
> > -		g_debug("Can't stat '%s', assuming unmountable: %s", devicepath, g_strerror(errno));
> > -		return NULL;
> > +		g_debug("Can't stat '%s', assuming unmountable: %s", devicename, g_strerror(errno));
> > +		return FALSE;
> >  	}
> >  
> > -	obj = g_new0(MountableObj, 1);
> > -	if (S_ISBLK(st.st_mode)) {
> > +	if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) {
> >  		obj->is_device = TRUE;
> >  		obj->dev = st.st_rdev;
> >  	} else if (S_ISREG(st.st_mode)) {
> > @@ -522,10 +520,10 @@ static MountableObj *normalize_mountable_object(const gchar *devicepath)
> >  		obj->dev = st.st_dev;
> >  		obj->inode = st.st_ino;
> >  	} else {
> > -		g_debug("Device '%s' is not something which is mountable", devicepath);
> > -		g_clear_pointer(&obj, g_free);
> > +		g_debug("Device '%s' is not something which is mountable", devicename);
> > +		return FALSE;
> >  	}
> > -	return obj;
> > +	return TRUE;
> >  }
> >  
> >  /* Compare two MountableObj for equality */
> > @@ -546,24 +544,24 @@ RaucSlot *find_slot_by_device(GHashTable *slots, const gchar *device)
> >  {
> >  	GHashTableIter iter;
> >  	RaucSlot *slot;
> > -	g_autofree MountableObj *obj = NULL;
> > +	MountableObj obj;
> > +	gboolean normalized;
> >  
> >  	g_return_val_if_fail(slots, NULL);
> >  	g_return_val_if_fail(device, NULL);
> >  
> > -	obj = normalize_mountable_object(device);
> > +	normalized = normalize_mountable_object(device, &obj);
> >  
> >  	g_hash_table_iter_init(&iter, slots);
> >  	while (g_hash_table_iter_next(&iter, NULL, (gpointer*) &slot)) {
> >  		if (g_strcmp0(slot->device, device) == 0)
> >  			goto out;
> >  
> > -		// Path doesn't match, but maybe device is same?
> > -		if (obj) {
> > -			g_autofree MountableObj *slot_obj =
> > -				normalize_mountable_object(slot->device);
> > -
> > -			if (slot_obj && is_same_mountable_object(obj, slot_obj))
> > +		/* Path doesn't match, but maybe device is the same? */
> > +		if (normalized) {
> > +			MountableObj slot_obj;
> > +			if (normalize_mountable_object(slot->device, &slot_obj) &&
> > +			    is_same_mountable_object(&obj, &slot_obj))
> >  				goto out;
> >  		}
> >  	}

_______________________________________________
RAUC mailing list

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RAUC] Failed to mount seed slot
  2019-05-07 17:59     ` Trent Piepho
  2019-05-07 20:33       ` Ladislav Michl
@ 2019-05-08  5:44       ` Ladislav Michl
  1 sibling, 0 replies; 7+ messages in thread
From: Ladislav Michl @ 2019-05-08  5:44 UTC (permalink / raw)
  To: Trent Piepho; +Cc: rauc, Enrico Jorns, Jan Luebbe

On Tue, May 07, 2019 at 05:59:36PM +0000, Trent Piepho wrote:
> On Tue, 2019-05-07 at 17:49 +0200, Ladislav Michl wrote:
> > On Tue, May 07, 2019 at 09:31:28AM +0200, Ladislav Michl wrote:
> >  typedef struct {
> > -	gboolean is_device;  // vs being a loop mounted file
> > -	dev_t dev;  // the device, or for a file, the device the file is on
> > -	ino_t inode;  // inode of file for a non-device
> > +	gboolean is_device;	/* vs being a loop mounted file */
> > +	dev_t dev;		/* the device, or for a file, the device the file is on */
> > +	ino_t inode;		/* inode of file for a non-device */
> >  } MountableObj;
> 
> There would also need to be another bool to indicate if the device is a
>  block dev or char dev, since the major:minor could match between
> different device types.  That could be part of a union with inode since
> the two are mutually exclusive.

As those functions are close to each other I didn't bothered with creating
an union and simply used 1 and 2 for is_device :)
Also directory can be a bind mount, so added that as well, however it is not
yet tested.

---
 src/config_file.c | 60 ++++++++++++++++++++++++++---------------------
 1 file changed, 33 insertions(+), 27 deletions(-)

diff --git a/src/config_file.c b/src/config_file.c
index 875e0ee..d966533 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -494,38 +494,44 @@ free:
 	return res;
 }
 
-// Something that is, or can be, mounted onto a mount point
+/* Something that is, or can be, mounted onto a mount point */
 typedef struct {
-	gboolean is_device;  // vs being a loop mounted file
-	dev_t dev;  // the device, or for a file, the device the file is on
-	ino_t inode;  // inode of file for a non-device
+	dev_t dev;		/* the device, or for a file, the device the file is on */
+	ino_t inode;		/* inode of file for a non-device */
+	gchar is_device;	/* vs being a loop mounted file */
 } MountableObj;
 
-// Take a device (or file) path and normalize it
-static MountableObj *normalize_mountable_object(const gchar *devicepath)
+/* Take a device (or file) path or name and normalize it */
+static gboolean normalize_mountable_object(const gchar *name, MountableObj *obj)
 {
-	MountableObj *obj;
 	GStatBuf st;
 
-	if (g_stat(devicepath, &st) == -1) {
+	if (g_stat(name, &st) == -1) {
 		/* Virtual filesystems like devpts trigger case */
-		g_debug("Can't stat '%s', assuming unmountable: %s", devicepath, g_strerror(errno));
-		return NULL;
+		g_debug("Can't stat '%s', assuming unmountable: %s", name, g_strerror(errno));
+		return FALSE;
 	}
 
-	obj = g_new0(MountableObj, 1);
-	if (S_ISBLK(st.st_mode)) {
-		obj->is_device = TRUE;
+	switch (st.st_mode & S_IFMT) {
+	case S_IFCHR:
+		obj->is_device = 1;
 		obj->dev = st.st_rdev;
-	} else if (S_ISREG(st.st_mode)) {
-		obj->is_device = FALSE;
+		break;
+	case S_IFBLK:
+		obj->is_device = 2;
+		obj->dev = st.st_rdev;
+		break;
+	case S_IFDIR:
+	case S_IFREG:
+		obj->is_device = 0;
 		obj->dev = st.st_dev;
 		obj->inode = st.st_ino;
-	} else {
-		g_debug("Device '%s' is not something which is mountable", devicepath);
-		g_clear_pointer(&obj, g_free);
+		break;
+	default:
+		g_debug("Device '%s' is unmountable", name);
+		return FALSE;
 	}
-	return obj;
+	return TRUE;
 }
 
 /* Compare two MountableObj for equality */
@@ -546,24 +552,24 @@ RaucSlot *find_slot_by_device(GHashTable *slots, const gchar *device)
 {
 	GHashTableIter iter;
 	RaucSlot *slot;
-	g_autofree MountableObj *obj = NULL;
+	MountableObj obj;
+	gboolean normalized;
 
 	g_return_val_if_fail(slots, NULL);
 	g_return_val_if_fail(device, NULL);
 
-	obj = normalize_mountable_object(device);
+	normalized = normalize_mountable_object(device, &obj);
 
 	g_hash_table_iter_init(&iter, slots);
 	while (g_hash_table_iter_next(&iter, NULL, (gpointer*) &slot)) {
 		if (g_strcmp0(slot->device, device) == 0)
 			goto out;
 
-		// Path doesn't match, but maybe device is same?
-		if (obj) {
-			g_autofree MountableObj *slot_obj =
-				normalize_mountable_object(slot->device);
-
-			if (slot_obj && is_same_mountable_object(obj, slot_obj))
+		/* Path doesn't match, but maybe device is the same? */
+		if (normalized) {
+			MountableObj slot_obj;
+			if (normalize_mountable_object(slot->device, &slot_obj) &&
+			    is_same_mountable_object(&obj, &slot_obj))
 				goto out;
 		}
 	}
-- 
2.20.1

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RAUC] Failed to mount seed slot
  2019-05-07 20:33       ` Ladislav Michl
@ 2019-05-09 11:32         ` Ladislav Michl
  0 siblings, 0 replies; 7+ messages in thread
From: Ladislav Michl @ 2019-05-09 11:32 UTC (permalink / raw)
  To: Trent Piepho; +Cc: ejo, rauc, jlu

On Tue, May 07, 2019 at 10:33:48PM +0200, Ladislav Michl wrote:
> On Tue, May 07, 2019 at 05:59:36PM +0000, Trent Piepho wrote:
> > On Tue, 2019-05-07 at 17:49 +0200, Ladislav Michl wrote:
> > > On Tue, May 07, 2019 at 09:31:28AM +0200, Ladislav Michl wrote:
> > > > On Mon, May 06, 2019 at 07:44:09PM +0200, Ladislav Michl wrote:
> > > > > [slot.rootfs.0]
> > > > > device=/dev/ubi0_0
> > > > > type=ubifs
> > > > > bootname=system0
> > > > > 
> > > > > Now system is booted with rootfs mounted read only which makes mounting seed
> > > > > slot fail:
> > > > > rauc[871]: Mounting /dev/ubi0_0 to use as seed
> > > > > rauc[871]: launching subprocess: mount -t ubifs /dev/ubi0_0 /run/rauc/rootfs.0
> > > > > rauc[871]: posix_spawn avoided (fd close requested) (child_setup specified) 
> > > > > rauc[871]: mount: /run/rauc/rootfs.0: /dev/ubi0_0 already mounted or mount point busy.
> > 
> > What does the kernel show in /proc/mounts in this case?  If it's
> > "/dev/ubi0_0", then it should match based on the simple path compare.
> 
> System is using barebox' bootchooser with boot loader specification. Here
> device is ubi0:rootfs0. And yes, device name could be changed in rauc's
> slot configuration to be ubi0:rootfs0 allowing path compare succeed.

Well, that is actually not true, with
[slot.rootfs.0]
device=ubi0:rootfs0
type=ubifs
bootname=system0

rauc will try to be smart here:
$ rauc status
Compatible:  Foomatic System
Variant:     
Booted from: system0
Activated:   rootfs.0 (system0)
slot states:
  rootfs.1: class=rootfs, device=/etc/rauc/ubi0:rootfs1, type=ubifs, bootname=system1
      state=inactive, description=, parent=(none), mountpoint=(none)
      boot status=good
  rootfs.0: class=rootfs, device=/etc/rauc/ubi0:rootfs0, type=ubifs, bootname=system0
      state=booted, description=, parent=(none), mountpoint=(none)
      boot status=good

> But see bellow why it is worth changing code a bit.

The only way to make it work now is to use /dev/ubi0_0 and fix barebox to use
the same naming scheme.

Also, there are more problems with mtd:<name> (those are passed to flash_erase) or
ubi:<volume> (passed to mkfs.ubifs) schemes, so some kind of normalizing device
names is required anyway. Either that or making each kind (block devices (ext4,
vfat), mtd, ubi..) of slot type to be descendants of common slot ancestor and
let them handle all those quirks on their own [*].

[patch stripped]

...and instead of my previous patch to bind mount seed slot, r_mount_slot
should be modified to do just that if ext_mount_point is assigned as
all remaining code logic suggests it is right thing to do.

Btw, it looks like development nad review is done on github using web
interface. Would that explain low volume of this very mailing list?

I would really appreciate some brief review of suggested solutions to
problems with using rauc with barebox bootchooser and ubi volumes.
They do work for me (quick hacked), but I'm new to rauc codebase
and it is easy to break somene else usecase.

Thank you,
	ladis

As a side note, why does rauc depend on glib? Does not seem to be intended
to be portable and if it just for all those hash or list containers, isn't
that exactly what STL is for? Also imagine it to be OOP ;-) Common slot
object with all those specialities encapsulated on its descendants. Not
that it cannot be done in C even with glib, but...

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-05-09 11:32 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-06 17:44 [RAUC] Failed to mount seed slot Ladislav Michl
2019-05-07  7:31 ` Ladislav Michl
2019-05-07 15:49   ` Ladislav Michl
2019-05-07 17:59     ` Trent Piepho
2019-05-07 20:33       ` Ladislav Michl
2019-05-09 11:32         ` Ladislav Michl
2019-05-08  5:44       ` Ladislav Michl

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox