[prev in list] [next in list] [prev in thread] [next in thread] 

List:       busybox
Subject:    [PATCH 2/2] mount: use volume_id for fstype detection
From:       "Alex Xu (Hello71)" <alex_y_xu () yahoo ! ca>
Date:       2021-11-25 23:22:50
Message-ID: 20211125232250.87522-2-alex_y_xu () yahoo ! ca
[Download RAW message or body]

This allows filesystems to be mounted even if the module is not
currently loaded and the type is not listed in /etc/filesystems. This
was semi-rejected back in 2005 on the basis that it would be impractical
to add a database of all filesystem types into busybox, but that has
since been added in the form of volume_id. The benefits of using
volume_id instead of adding all filesystems to /etc/filesystems or
listing modaliases are:

1. it is faster since it doesn't call mount (or worse, modprobe) N times
   for each filesystem
2. it doesn't require loading all filesystems into kernel memory
3. it doesn't require the distributor/sysadmin to maintain
   /etc/filesystems

function                                             old     new   delta
resolve_mount_spec                                   107     266    +159
singlemount                                         1053    1150     +97
uuidcache_init                                        64      67      +3
swap_enable_disable                                  245     247      +2
findfs_main                                           82      84      +2
devices_scanned                                        -       1      +1
mount_main                                          1275    1255     -20
get_devname_from_uuid                                 63       -     -63
get_devname_from_label                                68       -     -68
------------------------------------------------------------------------------
(add/remove: 1/2 grow/shrink: 5/1 up/down: 264/-151)          Total: 113 bytes
---
 include/volume_id.h                |  4 +-
 util-linux/findfs.c                |  2 +-
 util-linux/mount.c                 | 54 ++++++++++++-----------
 util-linux/swaponoff.c             |  4 +-
 util-linux/volume_id/get_devname.c | 69 +++++++++++++-----------------
 5 files changed, 64 insertions(+), 69 deletions(-)

diff --git a/include/volume_id.h b/include/volume_id.h
index a83da899e..6e6d7aef9 100644
--- a/include/volume_id.h
+++ b/include/volume_id.h
@@ -18,8 +18,6 @@
  *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
-char *get_devname_from_label(const char *spec);
-char *get_devname_from_uuid(const char *spec);
 void display_uuid_cache(int scan_devices);
 
 /* Returns:
@@ -27,5 +25,5 @@ void display_uuid_cache(int scan_devices);
  * 1: UUID= or LABEL= prefix found. In this case,
  *    *fsname is replaced if device with such UUID or LABEL is found
  */
-int resolve_mount_spec(char **fsname);
+int resolve_mount_spec(char **fsname, char **fstype);
 int add_to_uuid_cache(const char *device);
diff --git a/util-linux/findfs.c b/util-linux/findfs.c
index f5621a1fa..3a5f442a9 100644
--- a/util-linux/findfs.c
+++ b/util-linux/findfs.c
@@ -46,7 +46,7 @@ int findfs_main(int argc UNUSED_PARAM, char **argv)
 	} else {
 		/* Otherwise, handle LABEL=xxx and UUID=xxx,
 		 * fail on anything else */
-		if (!resolve_mount_spec(argv))
+		if (!resolve_mount_spec(argv, NULL))
 			bb_show_usage();
 	}
 
diff --git a/util-linux/mount.c b/util-linux/mount.c
index 4e65b6b46..2a94ca759 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -55,8 +55,8 @@
 //config:	"sometype [-o opts] fs /mnt" if simple mount syscall fails.
 //config:	The idea is to use such virtual filesystems in /etc/fstab.
 //config:
-//config:config FEATURE_MOUNT_LABEL
-//config:	bool "Support specifying devices by label or UUID"
+//config:config FEATURE_MOUNT_VOLUMEID
+//config:	bool "Support auto-detecting type and searching by label or UUID"
 //config:	default y
 //config:	depends on MOUNT
 //config:	select VOLUMEID
@@ -234,10 +234,10 @@
 
 #include "libbb.h"
 #include "common_bufsiz.h"
-#if ENABLE_FEATURE_MOUNT_LABEL
+#if ENABLE_FEATURE_MOUNT_VOLUMEID
 # include "volume_id.h"
 #else
-# define resolve_mount_spec(fsname) ((void)0)
+# define resolve_mount_spec(fsname, fstype) ((void)0)
 #endif
 
 // Needed for nfs support only
@@ -1972,7 +1972,7 @@ static int singlemount(struct mntent *mp, int ignore_busy)
 	int loopfd = -1;
 	int rc = -1;
 	unsigned long vfsflags;
-	char *loopFile = NULL, *filteropts = NULL;
+	char *loopFile = NULL, *filteropts = NULL, *guess_type = NULL;
 	llist_t *fl = NULL;
 	struct stat st;
 
@@ -2103,6 +2103,8 @@ static int singlemount(struct mntent *mp, int ignore_busy)
 		}
 	}
 
+	resolve_mount_spec(&mp->mnt_fsname, mp->mnt_type ? NULL : &guess_type);
+
 	// Look at the file.  (Not found isn't a failure for remount, or for
 	// a synthetic filesystem like proc or sysfs.)
 	// (We use stat, not lstat, in order to allow
@@ -2162,23 +2164,31 @@ static int singlemount(struct mntent *mp, int ignore_busy)
 			mp->mnt_type = next + 1;
 		}
 	} else {
-		// Loop through filesystem types until mount succeeds
-		// or we run out
-
-		// Initialize list of block backed filesystems.
-		// This has to be done here so that during "mount -a",
-		// mounts after /proc shows up can autodetect.
-		if (!fslist) {
-			fslist = get_block_backed_filesystems();
-			if (ENABLE_FEATURE_CLEAN_UP && fslist)
-				atexit(delete_block_backed_filesystems);
+		// Try the guessed type if one is available
+		if (guess_type) {
+			mp->mnt_type = guess_type;
+			rc = mount_it_now(mp, vfsflags, filteropts);
 		}
 
-		for (fl = fslist; fl; fl = fl->link) {
-			mp->mnt_type = fl->data;
-			rc = mount_it_now(mp, vfsflags, filteropts);
-			if (rc == 0)
-				break;
+		if (rc != 0) {
+			// Loop through filesystem types until mount succeeds
+			// or we run out
+
+			// Initialize list of block backed filesystems.
+			// This has to be done here so that during "mount -a",
+			// mounts after /proc shows up can autodetect.
+			if (!fslist) {
+				fslist = get_block_backed_filesystems();
+				if (ENABLE_FEATURE_CLEAN_UP && fslist)
+					atexit(delete_block_backed_filesystems);
+			}
+
+			for (fl = fslist; fl; fl = fl->link) {
+				mp->mnt_type = fl->data;
+				rc = mount_it_now(mp, vfsflags, filteropts);
+				if (rc == 0)
+					break;
+			}
 		}
 	}
 
@@ -2350,7 +2360,6 @@ int mount_main(int argc UNUSED_PARAM, char **argv)
 			mtpair->mnt_dir = argv[1];
 			mtpair->mnt_type = fstype;
 			mtpair->mnt_opts = cmdopts;
-			resolve_mount_spec(&mtpair->mnt_fsname);
 			rc = singlemount(mtpair, /*ignore_busy:*/ 0);
 			return rc;
 		}
@@ -2446,8 +2455,6 @@ int mount_main(int argc UNUSED_PARAM, char **argv)
 			if (!match_opt(mtcur->mnt_opts, O_optmatch))
 				continue;
 
-			resolve_mount_spec(&mtcur->mnt_fsname);
-
 			// NFS mounts want this to be xrealloc-able
 			mtcur->mnt_opts = xstrdup(mtcur->mnt_opts);
 
@@ -2523,7 +2530,6 @@ int mount_main(int argc UNUSED_PARAM, char **argv)
 			// ...mount the last thing we found
 			mtcur->mnt_opts = xstrdup(mtcur->mnt_opts);
 			append_mount_options(&(mtcur->mnt_opts), cmdopts);
-			resolve_mount_spec(&mtpair->mnt_fsname);
 			rc = singlemount(mtcur, /*ignore_busy:*/ 0);
 			if (ENABLE_FEATURE_CLEAN_UP)
 				free(mtcur->mnt_opts);
diff --git a/util-linux/swaponoff.c b/util-linux/swaponoff.c
index e2ff4b5cc..540faa042 100644
--- a/util-linux/swaponoff.c
+++ b/util-linux/swaponoff.c
@@ -82,7 +82,7 @@
 #if ENABLE_FEATURE_SWAPONOFF_LABEL
 # include "volume_id.h"
 #else
-# define resolve_mount_spec(fsname) ((void)0)
+# define resolve_mount_spec(fsname, fstype) ((void)0)
 #endif
 
 #ifndef MNTTYPE_SWAP
@@ -151,7 +151,7 @@ static int swap_enable_disable(char *device)
 	int err = 0;
 	int quiet = 0;
 
-	resolve_mount_spec(&device);
+	resolve_mount_spec(&device, NULL);
 
 	if (do_swapoff) {
 		err = swapoff(device);
diff --git a/util-linux/volume_id/get_devname.c b/util-linux/volume_id/get_devname.c
index 9a5f6abce..007d2b737 100644
--- a/util-linux/volume_id/get_devname.c
+++ b/util-linux/volume_id/get_devname.c
@@ -28,6 +28,8 @@ static struct uuidCache_s {
 	const char *type;
 } *uuidCache;
 
+static unsigned char devices_scanned;
+
 /* Returns !0 on error.
  * Otherwise, returns malloc'ed strings for label and uuid
  * (and they can't be NULL, although they can be "").
@@ -116,8 +118,6 @@ static struct uuidCache_s*
 uuidcache_init(int scan_devices)
 {
 	dbg("DBG: uuidCache=%x, uuidCache");
-	if (uuidCache)
-		return uuidCache;
 
 	/* We were scanning /proc/partitions
 	 * and /proc/sys/dev/cdrom/info here.
@@ -129,21 +129,22 @@ uuidcache_init(int scan_devices)
 	 * This is unacceptably complex. Let's just scan /dev.
 	 * (Maybe add scanning of /sys/block/XXX/dev for devices
 	 * somehow not having their /dev/XXX entries created?) */
-	if (scan_devices) {
+	if (scan_devices && !devices_scanned) {
 		recursive_action("/dev", ACTION_RECURSE,
 			uuidcache_check_device, /* file_action */
 			NULL, /* dir_action */
 			NULL /* userData */
 		);
+		devices_scanned = 1;
 	}
 
 	return uuidCache;
 }
 
+#ifdef UNUSED
 #define UUID   1
 #define VOL    2
 
-#ifdef UNUSED
 static char *
 get_spec_by_x(int n, const char *t, int *majorPtr, int *minorPtr)
 {
@@ -254,49 +255,39 @@ int add_to_uuid_cache(const char *device)
 
 
 /* Used by mount and findfs */
-
-char *get_devname_from_label(const char *spec)
+int resolve_mount_spec(char **fsname, char **fstype)
 {
-	struct uuidCache_s *uc;
+	struct uuidCache_s *uc = NULL;
+	enum { NONE = 0, UUID, LABEL } nametype =
+		is_prefixed_with(*fsname, "UUID=") ? UUID :
+		is_prefixed_with(*fsname, "LABEL=") ? LABEL :
+		NONE;
 
-	uc = uuidcache_init(/*scan_devices:*/ 1);
-	while (uc) {
-		if (uc->label[0] && strcmp(spec, uc->label) == 0) {
-			return xstrdup(uc->device);
-		}
-		uc = uc->next;
+	if (nametype) {
+		uc = uuidcache_init(/*scan_devices:*/ 1);
+	} else if (fstype) {
+		uc = uuidcache_init(/*scan_devices:*/ 0);
+		add_to_uuid_cache(*fsname);
 	}
-	return NULL;
-}
-
-char *get_devname_from_uuid(const char *spec)
-{
-	struct uuidCache_s *uc;
-
-	uc = uuidcache_init(/*scan_devices:*/ 1);
-	while (uc) {
-		/* case of hex numbers doesn't matter */
-		if (strcasecmp(spec, uc->uc_uuid) == 0) {
-			return xstrdup(uc->device);
+	if (nametype || fstype) {
+		while (uc) {
+			if ((nametype == NONE && strcmp(*fsname, uc->device) == 0) ||
+				(nametype == UUID && strcasecmp(*fsname + 5, uc->uc_uuid) == 0) ||
+				(nametype == LABEL && uc->label[0] && strcmp(*fsname + 6, uc->label) == 0)) {
+				break;
+			}
+			uc = uc->next;
 		}
-		uc = uc->next;
 	}
-	return NULL;
-}
 
-int resolve_mount_spec(char **fsname)
-{
-	char *tmp = *fsname;
+	if (!uc)
+		return 0;
 
-	if (is_prefixed_with(*fsname, "UUID="))
-		tmp = get_devname_from_uuid(*fsname + 5);
-	else if (is_prefixed_with(*fsname, "LABEL="))
-		tmp = get_devname_from_label(*fsname + 6);
+	if (nametype)
+		*fsname = xstrdup(uc->device);
 
-	if (tmp == *fsname)
-		return 0; /* no UUID= or LABEL= prefix found */
+	if (fstype)
+		*fstype = xstrdup(uc->type);
 
-	if (tmp)
-		*fsname = tmp;
 	return 1;
 }
-- 
2.34.1

_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic