From 969e8cbeb124581b376bc5534c716d1b18144190 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 8 Jan 2019 12:07:18 +0100 Subject: libblkid: improve whole-disk detection when read /proc/partitions blkid(8) in high-level mode checks partitions and unpartitioned whole-disk devices from the file /proc/partitions. The current heuristic assumes that partition name ends with a digit. Unfortunately, this is not correct -- for example md0 or nvme0n1 are whole-disk devices. This commit uses sysfs_devno_is_wholedisk() to make sure the device is a partition (according to kernel or DM). It's probably more expensive, because this way requires more syscalls (to read stuff from /sys etc.). The patch also adds more information to the blkid(8) man page. Addresses: https://github.com/karelzak/util-linux/issues/728 Signed-off-by: Karel Zak --- libblkid/src/devname.c | 25 ++++++++++++++----------- misc-utils/blkid.8 | 2 +- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/libblkid/src/devname.c b/libblkid/src/devname.c index 986bcf241..129a349ac 100644 --- a/libblkid/src/devname.c +++ b/libblkid/src/devname.c @@ -452,6 +452,7 @@ static int probe_all(blkid_cache cache, int only_if_new) char ptname0[128 + 1], ptname1[128 + 1], *ptname = NULL; char *ptnames[2]; dev_t devs[2]; + int iswhole[2] = { 0, 0 }; int ma, mi; unsigned long long sz; int lens[2] = { 0, 0 }; @@ -489,7 +490,7 @@ static int probe_all(blkid_cache cache, int only_if_new) continue; devs[which] = makedev(ma, mi); - DBG(DEVNAME, ul_debug("read partition name %s", ptname)); + 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 @@ -499,15 +500,14 @@ static int probe_all(blkid_cache cache, int only_if_new) * * Skip extended partitions. * heuristic: size is 1 - * - * FIXME: skip /dev/{ida,cciss,rd} whole-disk devs */ lens[which] = strlen(ptname); + iswhole[which] = sysfs_devno_is_wholedisk(devs[which]); - /* ends in a digit, clearly a partition, so check */ - if (isdigit(ptname[lens[which] - 1])) { - DBG(DEVNAME, ul_debug("partition dev %s, devno 0x%04X", + /* probably partition, so check */ + if (!iswhole[which]) { + DBG(DEVNAME, ul_debug(" partition dev %s, devno 0x%04X", ptname, (unsigned int) devs[which])); if (sz > 1) @@ -521,7 +521,9 @@ static int probe_all(blkid_cache cache, int only_if_new) * on it, remove the whole-disk dev from the cache if * it exists. */ - if (lens[last] && !strncmp(ptnames[last], ptname, lens[last])) { + if (lens[last] && iswhole[last] + && !strncmp(ptnames[last], ptname, lens[last])) { + list_for_each_safe(p, pnext, &cache->bic_devs) { blkid_dev tmp; @@ -529,14 +531,14 @@ static int probe_all(blkid_cache cache, int only_if_new) tmp = list_entry(p, struct blkid_struct_dev, bid_devs); if (tmp->bid_devno == devs[last]) { - DBG(DEVNAME, ul_debug("freeing %s", + DBG(DEVNAME, ul_debug(" freeing %s", tmp->bid_name)); blkid_free_dev(tmp); cache->bic_flags |= BLKID_BIC_FL_CHANGED; break; } } - lens[last] = 0; + lens[last] = 0; /* mark as checked */ } /* * If last was not checked because it looked like a whole-disk @@ -544,11 +546,12 @@ static int probe_all(blkid_cache cache, int only_if_new) * check last as well. */ if (lens[last] && strncmp(ptnames[last], ptname, lens[last])) { - DBG(DEVNAME, ul_debug("whole dev %s, devno 0x%04X", + DBG(DEVNAME, ul_debug(" 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; + + lens[last] = 0; /* mark as checked */ } } diff --git a/misc-utils/blkid.8 b/misc-utils/blkid.8 index d1cec1dea..ac36bee48 100644 --- a/misc-utils/blkid.8 +++ b/misc-utils/blkid.8 @@ -78,7 +78,7 @@ is specified, tokens from only this device are displayed. It is possible to specify multiple .I device arguments on the command line. -If none is given, all devices which appear in +If none is given, all partitions or unpartitioned devices which appear in .I /proc/partitions are shown, if they are recognized. .PP -- cgit v1.2.3-55-g7522