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 <kzak@redhat.com>
This commit is contained in:
Karel Zak 2019-01-08 12:07:18 +01:00
parent 963413a1ad
commit 969e8cbeb1
2 changed files with 15 additions and 12 deletions

View File

@ -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 */
}
}

View File

@ -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