-
-
Notifications
You must be signed in to change notification settings - Fork 206
Replace fdisk -l with sysfs-based disk enumeration (2tb+ drive support) #2035
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -802,24 +802,77 @@ enable_usb_storage() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| device_has_partitions() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local DEVICE="$1" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # fdisk normally says "doesn't contain a valid partition table" for | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # devices that lack a partition table - except for FAT32. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # FAT32 devices have a volume boot record that looks enough like an MBR | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # to satisfy fdisk. In that case, fdisk prints a partition table header | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # but no partitions. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # This check covers that: [ $(fdisk -l "$b" | wc -l) -eq 5 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # In both cases the output is 5 lines: 3 about device info, 1 empty line | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # and the 5th will be the table header or the invalid message. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local DISK_DATA=$(fdisk -l "$DEVICE" 2>/dev/null) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if echo "$DISK_DATA" | grep -q "doesn't contain a valid partition table" || | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [ "$(echo "$DISK_DATA" | wc -l)" -eq 5 ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # No partition table | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Check if device has any partitions by checking sysfs | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # A device with partitions will have entries like /sys/block/sda/sda1, /sys/block/vda/vda1, etc | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local device_name=$(basename "$DEVICE") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ ! -e "/sys/block/$device_name" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Device doesn't exist | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # There is a partition table | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Count partitions - handle nvme partition naming (nvme0n1p1) and traditional (sda1, vda1, hda1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ -n "$(ls -1 /sys/block/$device_name/ 2>/dev/null | grep -E "^${device_name}(p)?[0-9]")" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # There is a partition table | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # No partition table | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # List all block devices using sysfs | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Outputs one device path per line (e.g., /dev/sda, /dev/vda, /dev/nvme0n1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| list_block_devices() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TRACE_FUNC | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for dev in /sys/block/sd* /sys/block/nvme* /sys/block/vd* /sys/block/hd*; do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ -e "$dev" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "/dev/$(basename "$dev")" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| done | sort | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Build displayable disk information using sysfs (vs current busybox's 2tb limit per https://bugs.busybox.net/show_bug.cgi?id=16276) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Output format: "Disk /dev/<name>: <GB> GB" per line | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| disk_info_sysfs() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TRACE_FUNC | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local disk_info="" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DEBUG "disk_info_sysfs: Starting disk enumeration" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for dev in /sys/block/sd* /sys/block/nvme* /sys/block/vd* /sys/block/hd*; do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ -e "$dev" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local devname=$(basename "$dev") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DEBUG "disk_info_sysfs: Found device $dev (devname=$devname)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local size_bytes=$(cat "$dev/size" 2>/dev/null) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DEBUG "disk_info_sysfs: /dev/${devname} reports size_bytes=$size_bytes sectors from $dev/size" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ -n "$size_bytes" ] && [ "$size_bytes" -gt 0 ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Determine sector size for this device from sysfs; prefer hw_sector_size | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local sector_size=512 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ -r "$dev/queue/hw_sector_size" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sector_size=$(cat "$dev/queue/hw_sector_size" 2>/dev/null || echo 512) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DEBUG "disk_info_sysfs: /dev/${devname} using hw_sector_size=$sector_size from $dev/queue/hw_sector_size" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| elif [ -r "$dev/queue/logical_block_size" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sector_size=$(cat "$dev/queue/logical_block_size" 2>/dev/null || echo 512) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DEBUG "disk_info_sysfs: /dev/${devname} using logical_block_size=$sector_size from $dev/queue/logical_block_size" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DEBUG "disk_info_sysfs: /dev/${devname} using default sector_size=$sector_size (no queue info available)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Convert from sectors * sector_size to bytes, then to decimal GB. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Explanation of the constants: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # - We divide by 1,000,000,000 (1000000000) to report decimal GB (10^9 bytes), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # which matches the historical output used elsewhere in Heads. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # - Shell arithmetic is integer-only, so to round to the nearest GB we add | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # half the divisor (500,000,000) before dividing. This implements | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # rounding instead of truncation. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # If you prefer binary GiB (1024^3), replace the divisor and half-divisor | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # with 1073741824 and 536870912 respectively, or use `awk`/`printf` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # for fractional output. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local size_gb=$(((size_bytes * sector_size + 500000000) / 1000000000)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| disk_info="${disk_info}Disk /dev/${devname}: ${size_gb} GB\n" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DEBUG "disk_info_sysfs: /dev/${devname} calculated as ${size_gb} GB (${size_bytes} sectors * ${sector_size} bytes/sector = $((size_bytes * sector_size)) bytes)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo -n "$disk_info" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| list_usb_storage() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -1278,12 +1331,19 @@ is_gpt_bios_grub() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| NUMBER="${BASH_REMATCH[1]}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Now we know the device and partition number, get the type. This is | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # specific to GPT disks, MBR disks are shown differently by fdisk. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TRACE "$PART_DEV is partition $NUMBER of $DEVICE" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ "$(fdisk -l "/dev/$DEVICE" 2>/dev/null | awk '$1 == '"$NUMBER"' {print $5}')" == grub ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Check partition type using sysfs if available, otherwise check for grub type | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # For GPT disks, check /sys/class/block/<dev>/<partition>/uevent for PARTTYPENAME | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local part_sys="/sys/class/block/$DEVICE/$(basename "$PART_DEV")" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ -e "$part_sys/uevent" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if grep -q "PARTTYPENAME=BIOS boot" "$part_sys/uevent"; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TRACE "$PART_DEV is a GPT BIOS grub partition" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Fallback: try to detect using other sysfs attributes if available | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # For MBR disks, we would need to check partition type differently | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1334
to
+1345
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Check partition type using sysfs if available, otherwise check for grub type | |
| # For GPT disks, check /sys/class/block/<dev>/<partition>/uevent for PARTTYPENAME | |
| local part_sys="/sys/class/block/$DEVICE/$(basename "$PART_DEV")" | |
| if [ -e "$part_sys/uevent" ]; then | |
| if grep -q "PARTTYPENAME=BIOS boot" "$part_sys/uevent"; then | |
| TRACE "$PART_DEV is a GPT BIOS grub partition" | |
| return 0 | |
| fi | |
| fi | |
| # Fallback: try to detect using other sysfs attributes if available | |
| # For MBR disks, we would need to check partition type differently | |
| # Check partition type using sysfs if available. | |
| # For GPT disks, check /sys/class/block/<dev>/<partition>/uevent for PARTTYPE | |
| # matching the BIOS boot GUID (21686148-6449-6E6F-744E-656564454649). Some | |
| # environments may also expose PARTTYPENAME=BIOS boot via udev. | |
| local part_sys="/sys/class/block/$DEVICE/$(basename "$PART_DEV")" | |
| if [ -e "$part_sys/uevent" ]; then | |
| # Legacy/udev-based check: human-readable type name | |
| if grep -q "PARTTYPENAME=BIOS boot" "$part_sys/uevent"; then | |
| TRACE "$PART_DEV is a GPT BIOS grub partition (PARTTYPENAME)" | |
| return 0 | |
| fi | |
| # Preferred check: kernel-exported type GUID | |
| if grep -qi "PARTTYPE=21686148-6449-6E6F-744E-656564454649" "$part_sys/uevent"; then | |
| TRACE "$PART_DEV is a GPT BIOS grub partition (PARTTYPE GUID)" | |
| return 0 | |
| fi | |
| fi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In disk_info_sysfs(), /sys/block//size is a count of 512-byte sectors (same units as blockdev --getsz), not “sectors of hw_sector_size”. Multiplying it by hw_sector_size/logical_block_size will over-report sizes (e.g., 4Kn devices) and can overflow sooner. Consider using bytes from blockdev --getsize64 "/dev/$devname" (still avoids busybox fdisk), or treat size as 512-byte sectors and multiply by 512 unconditionally.