0

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?

zomega
  • 972

3 Answers3

1

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.

Stephen Kitt
  • 434,908
  • I tried 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
1

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:

  1. open() the device and issue the BLKGETSIZE64 ioctl(). That's what blockdev --getsize64 path/to/block/device does.

  2. 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).

  3. 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
    
  4. 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
0

/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