Bug 1653413

Summary: blkid: add --no-part-details to not return metadata from empty partitions
Product: Red Hat Enterprise Linux 8 Reporter: Bryan Gurney <bgurney>
Component: util-linuxAssignee: Karel Zak <kzak>
Status: CLOSED CURRENTRELEASE QA Contact: Radka Brychtova <rskvaril>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 8.0CC: awalsh, rskvaril
Target Milestone: rcFlags: pm-rhel: mirror+
Target Release: 8.0   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: util-linux-2.32.1-7.el Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2019-06-14 01:23:18 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 1658224    

Description Bryan Gurney 2018-11-26 19:11:25 UTC
Description of problem:

If "blkid -p" is executed against a partition, it will always return "0", even if there is no metadata on the partition (e.g.: a completely zeroed partition):

# hexdump -C -n 1073741824 /dev/nvme0n1p1
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
40000000

# blkid -p /dev/nvme0n1p1; echo $?
/dev/nvme0n1p1: PART_ENTRY_SCHEME="dos" PART_ENTRY_UUID="f15ed7ad-01" PART_ENTRY_TYPE="0x83" PART_ENTRY_NUMBER="1" PART_ENTRY_OFFSET="2048" PART_ENTRY_SIZE="209713152" PART_ENTRY_DISK="259:0"
0

This is different behavior from a completely zeroed whole device, which returns "2" ("no tokens found, and no devices identified):

# blkid -p /dev/nvme0n1; echo $?
2

The reason why I found this is because VDO uses blkid to detect if there is any prior metadata (as part of resolving the issue in BZ 1620572).  However, now if the user attempts to create a VDO volume on a partition, it will always fail, since the "blkid -p" command doesn't return 2.  This can be worked around by running "vdo create" with the "--force" switch.


Version-Release number of selected component (if applicable):
util-linux-2.32.1-6.el8.x86_64


How reproducible:
100%


Actual results:
"blkid -p" returns a status of 0, and outputs a line starting with PART_ENTRY_SCHEME

Expected results:
"blkid -p" returns a status of 2.

Additional info:

This first appeared after testing with vdo-6.2.0.273-9.el8.x86_64

Comment 1 Karel Zak 2018-11-28 10:17:24 UTC
Well, "blkid -p" has been originally designed to be usable in udev rules. So, it returns also information from partition table for the partition rather than only information about the device content only.

The content on  the device is always addressed by PTTYPE= (there is a partition table) or TYPE= (there is FS/RAID/... superblock). All you need is to grep for PTTYPE and TYPE rather than depend on return code.

I don't think we can change the current behaviour, the only way I see is to add a new option --no-part-details to disable all PART_ENTRY_*.

Comment 2 Bryan Gurney 2018-11-28 14:24:29 UTC
I think that a "--no-part-details" option sounds good.  It would be even better if this option could be used against any device, even non-partitions, which would hopefully result in the same behavior as before.

"I don't know if this device is a partition, and if it is, I don't want any PART_ENTRY_* tokens to count against the return code.  Were there any detected superblocks?"

If I grep for " TYPE" (with the leading space), grep returns "1"

# blkid -p /dev/nvme0n1p1; echo $?; blkid -p /dev/nvme0n1p1 | grep \ TYPE; echo $?; blkid -v
/dev/nvme0n1p1: PART_ENTRY_SCHEME="gpt" PART_ENTRY_NAME="pri" PART_ENTRY_UUID="29e1dccf-89ad-41f5-af46-99aa533bec98" PART_ENTRY_TYPE="0fc63daf-8483-4772-8e79-3d69d8477de4" PART_ENTRY_NUMBER="1" PART_ENTRY_OFFSET="2048" PART_ENTRY_SIZE="209713152" PART_ENTRY_DISK="259:0"
0
1
blkid from util-linux 2.32.1  (libblkid 2.32.1, 16-Jul-2018)

However, I should note that this behavior appears to be a regression from util-linux-2.23 (in RHEL 7.6):

# blkid -p /dev/nvme0n1p1; echo $?; blkid -p /dev/nvme0n1p1 | grep \ TYPE; echo $?; blkid -v
2
1
blkid from util-linux 2.23.2  (libblkid 2.23.0, 25-Apr-2013)

Comment 3 Karel Zak 2018-11-29 12:03:51 UTC
(In reply to Bryan Gurney from comment #2)
> I think that a "--no-part-details" option sounds good.  It would be even
> better if this option could be used against any device, even non-partitions,
> which would hopefully result in the same behavior as before.

There is flag in libblkid to enable/disable details about partitions. Now we always set the flag  on -p. My idea is to use --no-part-details to disable the flag at all. So, it will disable PART_ENTRY_* in all cases and keep return code "2" if there is nothing on the device.

I guess it's what you need.

> "I don't know if this device is a partition, and if it is, I don't want any
> PART_ENTRY_* tokens to count against the return code.  Were there any
> detected superblocks?"
> 
> If I grep for " TYPE" (with the leading space), grep returns "1"
> 
> # blkid -p /dev/nvme0n1p1; echo $?; blkid -p /dev/nvme0n1p1 | grep \ TYPE;
> echo $?; blkid -v
> /dev/nvme0n1p1: PART_ENTRY_SCHEME="gpt" PART_ENTRY_NAME="pri"
> PART_ENTRY_UUID="29e1dccf-89ad-41f5-af46-99aa533bec98"
> PART_ENTRY_TYPE="0fc63daf-8483-4772-8e79-3d69d8477de4" PART_ENTRY_NUMBER="1"
> PART_ENTRY_OFFSET="2048" PART_ENTRY_SIZE="209713152" PART_ENTRY_DISK="259:0"
> 0
> 1
> blkid from util-linux 2.32.1  (libblkid 2.32.1, 16-Jul-2018)
> 
> However, I should note that this behavior appears to be a regression from
> util-linux-2.23 (in RHEL 7.6):
> 
> # blkid -p /dev/nvme0n1p1; echo $?; blkid -p /dev/nvme0n1p1 | grep \ TYPE;
> echo $?; blkid -v
> 2
> 1
> blkid from util-linux 2.23.2  (libblkid 2.23.0, 25-Apr-2013)

Well, this change is expected ;-) and has been introduced by upstream commit f8098e2b2c0a8a98ccb603f53dfba0cc05683a39 in v2.27, because stuff from partition table is important and should not be ignored (etc.). Note that we now allow to address devices (for example for) mount by PARTUUID=.

Anyway, I think it's already possible to use -p to check for empty device, all you need is to care about PTYPE= and TYPE= on 0 return code. This solution is robust and portable.

The another possibility is to use wipefs(8). wipefs(8) does not try to be smart (like blkid) and it really cares about on-device content only.

I'm going to add --no-part-details to the upstream.