Block device information without mounting in Linux
Asked Answered
W

3

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

Warty answered 7/12, 2011 at 13:41 Comment(0)
A
8

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);
Alyce answered 7/12, 2011 at 13:41 Comment(4)
oh, may somebosy suggest, why am I getting a zero?Gym
@shbk - is blockSize zero or rc? Both being zero would be suprising.Alyce
yeah,it was so. I should be more attentive. Thanks.Gym
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.Gabriel
D
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
Deflagrate answered 25/3 at 2:31 Comment(0)
I
-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);
Ignite answered 22/1, 2014 at 7:52 Comment(2)
They're size_t's in fs.h, fwiw: #define BLKBSZGET _IOR(0x12,112,size_t) and #define BLKBSZSET _IOW(0x12,113,size_t).Symphony
They're unsigned int in kernel source though. Implementation calls put_uint which does put_user(val, (unsigned int __user *)arg).Deflagrate

© 2022 - 2024 — McMap. All rights reserved.