6

I am trying to get some information (specifically block size) of block device in linux, in C++. Is it possible to get block size of a device without mounting it and possibly without looking into dynamic files (like the ones in /sys), but with a system call only.

I was trying with stat, but it returns data about /dev filesystem if I ask about /dev/sdb2.

If it's impossible with system call, where should i look in dynamic files (haven't been able to locate it either.)

3 Answers 3

9

You want to use ioctl, in particular BLKSSZGET.

Quoting linux/fs.h:

#define BLKSSZGET _IO(0x12,104)/* get block device sector size */ 

Untested example:

#include <sys/ioctl.h> #include <linux/fs.h> int fd = open("/dev/sda"); size_t blockSize; int rc = ioctl(fd, BLKSSZGET, &blockSize); 
Sign up to request clarification or add additional context in comments.

4 Comments

oh, may somebosy suggest, why am I getting a zero?
@shbk - is blockSize zero or rc? Both being zero would be suprising.
yeah,it was so. I should be more attentive. Thanks.
For the record: BLKSSZGET = logical block size, BLKBSZGET = physical block size, BLKGETSIZE64 = device size in bytes, BLKGETSIZE = device size/512. At least if the comments in fs.h and my experiments can be trusted.
1

There are multiple block sizes, there's the soft block size, the logical block size, and the physical block size. There's an ioctl (BLKSSZSET) to set the logical block size.

Demo sample (run as root):

#!/usr/bin/tcc -run #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> #include <linux/fs.h> int main() { int fd = open("/dev/sda", O_RDONLY); unsigned int soft_block_size = 0, logical_block_size = 0, physical_block_size = 0; int rcs = ioctl(fd, BLKBSZGET, &soft_block_size); int rcl = ioctl(fd, BLKSSZGET, &logical_block_size); int rcp = ioctl(fd, BLKPBSZGET, &physical_block_size); printf("Soft block size: %u\n", soft_block_size); printf("Logical block size: %u\n", logical_block_size); printf("Physical block size: %u\n", physical_block_size); } 

Error handling omitted for brevity.

On my system I get:

Soft block size: 4096 Logical block size: 512 Physical block size: 4096 

Comments

-1

I think the ioctl value should rather be unsigned long than size_t (the latest is more memory related), I would also initialize it to 0 (just in case BLKSSZGET returns unsigned int instead).

#include <sys/ioctl.h> #include <linux/fs.h> int fd = open("/dev/sda"); unsigned long blockSize = 0; int rc = ioctl(fd, BLKSSZGET, &blockSize); 

2 Comments

They're size_t's in fs.h, fwiw: #define BLKBSZGET _IOR(0x12,112,size_t) and #define BLKBSZSET _IOW(0x12,113,size_t).
They're unsigned int in kernel source though. Implementation calls put_uint which does put_user(val, (unsigned int __user *)arg).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.