diff --git a/backport-libblkid-improve-debug-for-proc-partitions.patch b/backport-libblkid-improve-debug-for-proc-partitions.patch new file mode 100644 index 0000000000000000000000000000000000000000..718444700b5f36c93c18249aa93be6dab4de4cda --- /dev/null +++ b/backport-libblkid-improve-debug-for-proc-partitions.patch @@ -0,0 +1,75 @@ +From e9131920485962f33bd32b492cb93078ee7a3c34 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Wed, 30 Sep 2020 11:37:09 +0200 +Subject: [PATCH] libblkid: improve debug for /proc/partitions + +Signed-off-by: Karel Zak +--- + libblkid/src/devname.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/libblkid/src/devname.c b/libblkid/src/devname.c +index c58b784..8f2d89a 100644 +--- a/libblkid/src/devname.c ++++ b/libblkid/src/devname.c +@@ -351,7 +351,7 @@ static void lvm_probe_all(blkid_cache cache, int only_if_new) + lv_name); + dev = lvm_get_devno(lvm_device); + sprintf(lvm_device, "%s/%s", vg_name, lv_name); +- DBG(DEVNAME, ul_debug("LVM dev %s: devno 0x%04X", ++ DBG(DEVNAME, ul_debug("Probe LVM dev %s: devno 0x%04X", + lvm_device, + (unsigned int) dev)); + probe_one(cache, lvm_device, dev, BLKID_PRI_LVM, +@@ -383,7 +383,7 @@ evms_probe_all(blkid_cache cache, int only_if_new) + &ma, &mi, &sz, device) != 4) + continue; + +- DBG(DEVNAME, ul_debug("Checking partition %s (%d, %d)", ++ DBG(DEVNAME, ul_debug("Probe EVMS partition %s (%d, %d)", + device, ma, mi)); + + probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS, +@@ -433,7 +433,7 @@ ubi_probe_all(blkid_cache cache, int only_if_new) + + if (!S_ISCHR(st.st_mode) || !minor(dev)) + continue; +- DBG(DEVNAME, ul_debug("UBI vol %s/%s: devno 0x%04X", ++ DBG(DEVNAME, ul_debug("Probe UBI vol %s/%s: devno 0x%04X", + *dirname, name, (int) dev)); + probe_one(cache, name, dev, BLKID_PRI_UBI, only_if_new, 0); + } +@@ -506,7 +506,7 @@ static int probe_all(blkid_cache cache, int only_if_new) + + /* probably partition, so check */ + if (!iswhole[which]) { +- DBG(DEVNAME, ul_debug(" partition dev %s, devno 0x%04X", ++ DBG(DEVNAME, ul_debug(" Probe partition dev %s, devno 0x%04X", + ptname, (unsigned int) devs[which])); + + if (sz > 1) +@@ -545,7 +545,7 @@ static int probe_all(blkid_cache cache, int only_if_new) + * check last as well. + */ + if (lens[last] && strncmp(ptnames[last], ptname, lens[last]) != 0) { +- DBG(DEVNAME, ul_debug(" whole dev %s, devno 0x%04X", ++ DBG(DEVNAME, ul_debug(" Probe whole dev %s, devno 0x%04X", + ptnames[last], (unsigned int) devs[last])); + probe_one(cache, ptnames[last], devs[last], 0, + only_if_new, 0); +@@ -555,8 +555,11 @@ static int probe_all(blkid_cache cache, int only_if_new) + } + + /* Handle the last device if it wasn't partitioned */ +- if (lens[which]) ++ if (lens[which]) { ++ DBG(DEVNAME, ul_debug(" Probe whole dev %s, devno 0x%04X", ++ ptname, (unsigned int) devs[which])); + probe_one(cache, ptname, devs[which], 0, only_if_new, 0); ++ } + + fclose(proc); + blkid_flush_cache(cache); +-- +1.8.3.1 + diff --git a/backport-libblkid-use-sys-to-read-all-block-devices.patch b/backport-libblkid-use-sys-to-read-all-block-devices.patch new file mode 100644 index 0000000000000000000000000000000000000000..4eea71c0b805131a5c179411895ccf71e236d7a7 --- /dev/null +++ b/backport-libblkid-use-sys-to-read-all-block-devices.patch @@ -0,0 +1,414 @@ +From 8d3f9430c59416e4c1eddc899578158a7a1ed414 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Wed, 7 Oct 2020 13:49:45 +0200 +Subject: [PATCH] libblkid: use /sys to read all block devices + +The old implementation uses /proc/partitions where devices are +filtered by kernel (missing devices with ext_range=1 and removable +devices). + +The problem with the old implementation is whole-disk heuristic based +on device name, order of devices, etc. + +The new implementation use the same code to read also removable +devices. + +Addresses: https://github.com/karelzak/util-linux/issues/1151 +Signed-off-by: Karel Zak +--- + lib/sysfs.c | 36 +++++--- + libblkid/src/blkidP.h | 2 +- + libblkid/src/devname.c | 235 +++++++++++++++++++++---------------------------- + 3 files changed, 128 insertions(+), 145 deletions(-) + +diff --git a/lib/sysfs.c b/lib/sysfs.c +index 5b4de2c..0c360ce 100644 +--- a/lib/sysfs.c ++++ b/lib/sysfs.c +@@ -874,7 +874,7 @@ int sysfs_devname_is_hidden(const char *prefix, const char *name) + dev_t __sysfs_devname_to_devno(const char *prefix, const char *name, const char *parent) + { + char buf[PATH_MAX]; +- char *_name = NULL; /* name as encoded in sysfs */ ++ char *_name = NULL, *_parent = NULL; /* name as encoded in sysfs */ + dev_t dev = 0; + int len; + +@@ -901,19 +901,20 @@ dev_t __sysfs_devname_to_devno(const char *prefix, const char *name, const char + goto done; + sysfs_devname_dev_to_sys(_name); + +- if (parent && strncmp("dm-", name, 3) != 0) { +- /* +- * Create path to /sys/block///dev +- */ +- char *_parent = strdup(parent); +- ++ if (parent) { ++ _parent = strdup(parent); + if (!_parent) + goto done; ++ } ++ ++ if (parent && strncmp("dm-", name, 3) != 0) { ++ /* ++ * Create path to /sys/block///dev ++ */ + sysfs_devname_dev_to_sys(_parent); + len = snprintf(buf, sizeof(buf), + "%s" _PATH_SYS_BLOCK "/%s/%s/dev", + prefix, _parent, _name); +- free(_parent); + if (len < 0 || (size_t) len >= sizeof(buf)) + goto done; + +@@ -934,10 +935,22 @@ dev_t __sysfs_devname_to_devno(const char *prefix, const char *name, const char + goto done; + dev = read_devno(buf); + ++ /* ++ * Read from /sys/block///dev ++ */ ++ if (!dev && parent && startswith(name, parent)) { ++ len = snprintf(buf, sizeof(buf), ++ "%s" _PATH_SYS_BLOCK "/%s/%s/dev", ++ prefix, _parent, _name); ++ if (len < 0 || (size_t) len >= sizeof(buf)) ++ goto done; ++ dev = read_devno(buf); ++ } ++ ++ /* ++ * Read from /sys/block//device/dev ++ */ + if (!dev) { +- /* +- * Read from /sys/block//device/dev +- */ + len = snprintf(buf, sizeof(buf), + "%s" _PATH_SYS_BLOCK "/%s/device/dev", + prefix, _name); +@@ -947,6 +960,7 @@ dev_t __sysfs_devname_to_devno(const char *prefix, const char *name, const char + } + done: + free(_name); ++ free(_parent); + return dev; + } + +diff --git a/libblkid/src/blkidP.h b/libblkid/src/blkidP.h +index 802a1b3..fe3736f 100644 +--- a/libblkid/src/blkidP.h ++++ b/libblkid/src/blkidP.h +@@ -301,7 +301,7 @@ struct blkid_struct_cache + #define BLKID_PROBE_NONE 1 + + #define BLKID_ERR_IO 5 +-#define BLKID_ERR_PROC 9 ++#define BLKID_ERR_SYSFS 9 + #define BLKID_ERR_MEM 12 + #define BLKID_ERR_CACHE 14 + #define BLKID_ERR_DEV 19 +diff --git a/libblkid/src/devname.c b/libblkid/src/devname.c +index 8f2d89a..4b9df5a 100644 +--- a/libblkid/src/devname.c ++++ b/libblkid/src/devname.c +@@ -39,6 +39,7 @@ + #include "canonicalize.h" /* $(top_srcdir)/include */ + #include "pathnames.h" + #include "sysfs.h" ++#include "fileutils.h" + + /* + * Find a dev struct in the cache by device name, if available. +@@ -442,178 +443,146 @@ ubi_probe_all(blkid_cache cache, int only_if_new) + } + + /* +- * Read the device data for all available block devices in the system. ++ * This function uses /sys to read all block devices in way compatible with ++ * /proc/partitions (like the original libblkid implementation) + */ +-static int probe_all(blkid_cache cache, int only_if_new) ++static int ++sysfs_probe_all(blkid_cache cache, int only_if_new, int only_removable) + { +- FILE *proc; +- char line[1024]; +- char ptname0[128 + 1], ptname1[128 + 1], *ptname = NULL; +- char *ptnames[2]; +- dev_t devs[2] = { 0, 0 }; +- int iswhole[2] = { 0, 0 }; +- int ma, mi; +- unsigned long long sz; +- int lens[2] = { 0, 0 }; +- int which = 0, last = 0; +- struct list_head *p, *pnext; ++ DIR *sysfs; ++ struct dirent *dev; + +- ptnames[0] = ptname0; +- ptnames[1] = ptname1; ++ sysfs = opendir(_PATH_SYS_BLOCK); ++ if (!sysfs) ++ return -BLKID_ERR_SYSFS; + +- if (!cache) +- return -BLKID_ERR_PARAM; ++ /* scan /sys/block */ ++ while ((dev = xreaddir(sysfs))) { ++ DIR *dir = NULL; ++ dev_t devno; ++ size_t nparts = 0; ++ unsigned int maxparts = 0, removable = 0; ++ struct dirent *part; ++ struct path_cxt *pc = NULL; ++ uint64_t size = 0; + +- if (cache->bic_flags & BLKID_BIC_FL_PROBED && +- time(NULL) - cache->bic_time < BLKID_PROBE_INTERVAL) +- return 0; ++ DBG(DEVNAME, ul_debug("checking %s", dev->d_name)); + +- blkid_read_cache(cache); +- evms_probe_all(cache, only_if_new); +-#ifdef VG_DIR +- lvm_probe_all(cache, only_if_new); +-#endif +- ubi_probe_all(cache, only_if_new); ++ devno = sysfs_devname_to_devno(dev->d_name); ++ if (!devno) ++ goto next; ++ pc = ul_new_sysfs_path(devno, NULL, NULL); ++ if (!pc) ++ goto next; ++ ++ if (ul_path_read_u64(pc, &size, "size") != 0) ++ size = 0; ++ if (ul_path_read_u32(pc, &removable, "removable") != 0) ++ removable = 0; ++ ++ /* ingnore empty devices */ ++ if (!size) ++ goto next; ++ ++ /* accept removeable if only removable requested */ ++ if (only_removable) { ++ if (!removable) ++ goto next; ++ ++ /* emulate /proc/partitions ++ * -- ignore empty devices and non-partitionable removable devices */ ++ } else { ++ if (ul_path_read_u32(pc, &maxparts, "ext_range") != 0) ++ maxparts = 0; ++ if (!maxparts && removable) ++ goto next; ++ } + +- proc = fopen(PROC_PARTITIONS, "r" UL_CLOEXECSTR); +- if (!proc) +- return -BLKID_ERR_PROC; ++ DBG(DEVNAME, ul_debug("read device name %s", dev->d_name)); + +- while (fgets(line, sizeof(line), proc)) { +- last = which; +- which ^= 1; +- ptname = ptnames[which]; ++ dir = ul_path_opendir(pc, NULL); ++ if (!dir) ++ goto next; + +- if (sscanf(line, " %d %d %llu %128[^\n ]", +- &ma, &mi, &sz, ptname) != 4) +- continue; +- devs[which] = makedev(ma, mi); +- +- DBG(DEVNAME, ul_debug("read device name %s", ptname)); +- +- /* Skip whole disk devs unless they have no partitions. +- * If base name of device has changed, also +- * check previous dev to see if it didn't have a partn. +- * heuristic: partition name ends in a digit, & partition +- * names contain whole device name as substring. +- * +- * Skip extended partitions. +- * heuristic: size is 1 +- */ ++ /* read /sys/block// do get partitions */ ++ while ((part = xreaddir(dir))) { ++ dev_t partno; + +- lens[which] = strlen(ptname); +- iswhole[which] = sysfs_devno_is_wholedisk(devs[which]); ++ if (!sysfs_blkdev_is_partition_dirent(dir, part, dev->d_name)) ++ continue; + +- /* probably partition, so check */ +- if (!iswhole[which]) { +- DBG(DEVNAME, ul_debug(" Probe partition dev %s, devno 0x%04X", +- ptname, (unsigned int) devs[which])); ++ /* ignore extended partitions ++ * -- recount size to blocks like /proc/partitions */ ++ if (ul_path_readf_u64(pc, &size, "%s/size", part->d_name) == 0 ++ && (size >> 1) == 1) ++ continue; ++ partno = __sysfs_devname_to_devno(NULL, part->d_name, dev->d_name); ++ if (!partno) ++ continue; + +- if (sz > 1) +- probe_one(cache, ptname, devs[which], 0, +- only_if_new, 0); +- lens[which] = 0; /* mark as checked */ ++ DBG(DEVNAME, ul_debug(" Probe partition dev %s, devno 0x%04X", ++ part->d_name, (unsigned int) partno)); ++ nparts++; ++ probe_one(cache, part->d_name, partno, 0, only_if_new, 0); + } + +- /* +- * If last was a whole disk and we just found a partition +- * on it, remove the whole-disk dev from the cache if +- * it exists. +- */ +- if (lens[last] && iswhole[last] +- && !strncmp(ptnames[last], ptname, lens[last])) { ++ if (!nparts) { ++ /* add non-partitioned whole disk to cache */ ++ DBG(DEVNAME, ul_debug(" Probe whole dev %s, devno 0x%04X", ++ dev->d_name, (unsigned int) devno)); ++ probe_one(cache, dev->d_name, devno, 0, only_if_new, 0); ++ } else { ++ /* remove partitioned whole-disk from cache */ ++ struct list_head *p, *pnext; + + list_for_each_safe(p, pnext, &cache->bic_devs) { +- blkid_dev tmp; +- +- /* find blkid dev for the whole-disk devno */ +- tmp = list_entry(p, struct blkid_struct_dev, +- bid_devs); +- if (tmp->bid_devno == devs[last]) { +- DBG(DEVNAME, ul_debug(" freeing %s", +- tmp->bid_name)); ++ blkid_dev tmp = list_entry(p, struct blkid_struct_dev, ++ bid_devs); ++ if (tmp->bid_devno == devno) { ++ DBG(DEVNAME, ul_debug(" freeing %s", tmp->bid_name)); + blkid_free_dev(tmp); + cache->bic_flags |= BLKID_BIC_FL_CHANGED; + break; + } + } +- lens[last] = 0; /* mark as checked */ +- } +- /* +- * If last was not checked because it looked like a whole-disk +- * dev, and the device's base name has changed, +- * check last as well. +- */ +- if (lens[last] && strncmp(ptnames[last], ptname, lens[last]) != 0) { +- DBG(DEVNAME, ul_debug(" Probe whole dev %s, devno 0x%04X", +- ptnames[last], (unsigned int) devs[last])); +- probe_one(cache, ptnames[last], devs[last], 0, +- only_if_new, 0); +- +- lens[last] = 0; /* mark as checked */ + } ++ next: ++ if (dir) ++ closedir(dir); ++ if (pc) ++ ul_unref_path(pc); + } + +- /* Handle the last device if it wasn't partitioned */ +- if (lens[which]) { +- DBG(DEVNAME, ul_debug(" Probe whole dev %s, devno 0x%04X", +- ptname, (unsigned int) devs[which])); +- probe_one(cache, ptname, devs[which], 0, only_if_new, 0); +- } +- +- fclose(proc); +- blkid_flush_cache(cache); ++ closedir(sysfs); + return 0; + } + +-/* Don't use it by default -- it's pretty slow (because cdroms, floppy, ...) ++/* ++ * Read the device data for all available block devices in the system. + */ +-static int probe_all_removable(blkid_cache cache) ++static int probe_all(blkid_cache cache, int only_if_new) + { +- struct path_cxt *pc; +- DIR *dir; +- struct dirent *d; +- + if (!cache) + return -BLKID_ERR_PARAM; + +- dir = opendir(_PATH_SYS_BLOCK); +- if (!dir) +- return -BLKID_ERR_PROC; +- +- pc = ul_new_path(NULL); ++ if (cache->bic_flags & BLKID_BIC_FL_PROBED && ++ time(NULL) - cache->bic_time < BLKID_PROBE_INTERVAL) ++ return 0; + +- while((d = readdir(dir))) { +- int removable = 0; +- dev_t devno; ++ blkid_read_cache(cache); + +-#ifdef _DIRENT_HAVE_D_TYPE +- if (d->d_type != DT_UNKNOWN && d->d_type != DT_LNK) +- continue; ++ evms_probe_all(cache, only_if_new); ++#ifdef VG_DIR ++ lvm_probe_all(cache, only_if_new); + #endif +- if (d->d_name[0] == '.' && +- ((d->d_name[1] == 0) || +- ((d->d_name[1] == '.') && (d->d_name[2] == 0)))) +- continue; +- +- devno = sysfs_devname_to_devno(d->d_name); +- if (!devno) +- continue; +- +- if (sysfs_blkdev_init_path(pc, devno, NULL) == 0 +- && ul_path_read_s32(pc, &removable, "removable") != 0) +- removable = 0; ++ ubi_probe_all(cache, only_if_new); + +- if (removable) +- probe_one(cache, d->d_name, devno, 0, 0, 1); +- } ++ sysfs_probe_all(cache, only_if_new, 0); + +- ul_unref_path(pc); +- closedir(dir); ++ blkid_flush_cache(cache); + return 0; + } + +- + /** + * blkid_probe_all: + * @cache: cache handler +@@ -677,7 +646,7 @@ int blkid_probe_all_removable(blkid_cache cache) + int ret; + + DBG(PROBE, ul_debug("Begin blkid_probe_all_removable()")); +- ret = probe_all_removable(cache); ++ ret = sysfs_probe_all(cache, 0, 1); + DBG(PROBE, ul_debug("End blkid_probe_all_removable() [rc=%d]", ret)); + return ret; + } +-- +1.8.3.1 + diff --git a/util-linux.spec b/util-linux.spec index 965736477196d2453763e6ca38d94ba1637b2dcd..eb3b760bba77c6df46c422cb6f24c2613d528cb2 100644 --- a/util-linux.spec +++ b/util-linux.spec @@ -3,7 +3,7 @@ Name: util-linux Version: 2.36.1 -Release: 2 +Release: 3 Summary: A random collection of Linux utilities License: GPLv2 and GPLv2+ and LGPLv2+ and BSD with advertising and Public Domain URL: https://git.kernel.org/pub/scm/utils/util-linux/util-linux.git @@ -39,6 +39,8 @@ Patch0: 2.36-login-lastlog-create.patch Patch1: Do-not-excute-Utmp-testcases.patch Patch2: backport-libfdisk-make-fdisk_partname-more-robust.patch Patch3: backport-libmount-fix-tab-parser-for-badly-terminated-lines.patch +Patch4: backport-libblkid-improve-debug-for-proc-partitions.patch +Patch5: backport-libblkid-use-sys-to-read-all-block-devices.patch Patch9000: Add-check-to-resolve-uname26-version-test-failed.patch @@ -388,6 +390,12 @@ fi %{_mandir}/man8/{swapoff.8*,swapon.8*,switch_root.8*,umount.8*,wdctl.8.gz,wipefs.8*,zramctl.8*} %changelog +* Thu Mar 18 2021 wangchen - 2.36.1-3 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:use /sys to read all block devices + * Mon Mar 1 2021 yangzhuangzhuang - 2.36.1-2 - Type:bugfix - ID:NA