My disk is sda and I have these size files:
/sys/dev/block/8:0/size
/sys/class/block/sda/size
/sys/block/sda/size
Which one should I use? The first one is used by lsblk
. Are there any differences?
Check out
ls -l /sys/dev/block/8:0 /sys/class/block/sda /sys/block/sda
You’ll see that all three point to the same directory.
There’s no difference between the files, other than their path.
ls -l
on the size files because I expected that. But it didn't work. Have to use realpath
next time.
– zomega
Dec 21 '22 at 19:51
If you have a path to a block device file such as /dev/sda
, /dev/disk/by-id/whatever
, some/path/to/my/loop/device
, there are several options to get its size on Linux including:
open() the device and issue the BLKGETSIZE64
ioctl()
. That's what blockdev --getsize64 path/to/block/device
does.
open() the device and issue the BLKGETSIZE
ioctl()
like blockdev --getsz path/to/block/device
does, and multiply that by 512 (not what the BLKSSZGET
ioctl() (as blocksize --getss path/to/block/device
) returns).
open() the device, lseek() to the end which will return the current cursor position. For instance, in zsh
:
zmodload zsh/system
{ sysseek -w end 0 && print $(( systell(0) )); } < path/to/block/device
Assuming sysfs is mounted in /sys
, find the corresponding path to the device file in there, read the size
file in there and multiply by 512 (not the values in any of the queue/*size
files in there).
For 1 to 3 above, you need at least read or write permission to the block device.
For 4, since the name of the block device file could be anything, the reliable way to identify the /sys path, and what lsblk
does as you found out is to rely on the major and minor device numbers which you obtain by doing a stat()
call on the path to the block device (for which you only need search access to the parent directory) and then use /sys/dev/block/<major>:<minor>
which will be a symlink to the directory in the /sys/devices
tree for the block device with <major>
and <minor>
as major/minor number.
For instance, with zsh
:
zmodload zsh/stat
stat -sH s path/to/block/device &&
[[ $s[mode] = b* ]] &&
print $(( $(</sys/dev/block/$(( s[rdev] >> 8 )):$(( s[rdev] & 0xff ))/size) * 512 ))
Or you could just get lsblk
to do it for you:
lsblk -nbdo size path/to/block/device
/sys/dev/block/8:0
, /sys/class/block/sda
and /sys/block/sda
are all just symlinks pointing to the same location so it doesn't matter which you use.
$ realpath /sys/dev/block/8:0
/sys/devices/pci0000:00/0000:00:01.2/0000:02:00.1/ata4/host3/target3:0:0/3:0:0:0/block/sda
$ realpath /sys/class/block/sda
/sys/devices/pci0000:00/0000:00:01.2/0000:02:00.1/ata4/host3/target3:0:0/3:0:0:0/block/sda
$ realpath /sys/block/sda
/sys/devices/pci0000:00/0000:00:01.2/0000:02:00.1/ata4/host3/target3:0:0/3:0:0:0/block/sda
lsblk -nbdo size /dev/sda
then you don't need to worry about what path under /sys to use or what unit the value may be in. – Stéphane Chazelas Dec 21 '22 at 10:56