vesontio vesontio - 1 year ago 87
Linux Question

Portable way to determine sector size in Linux

I want to write a small program in C which can determine the sector size of a hard disk. I wanted to read the file located in

, and it worked in CentOS 6/7.

However when I tested in CentOS 5.11, the file
is missing, and I have only found

Thus, I'd like to know how can I determine (APIs) the sector size in CentOS 5, or is there an other better way to do so. Thanks.

Answer Source

The fdisk utility displays this information (and runs successfully on kernels older even than than the 2.6.x vintage on CentOS 5), so that seems a likely place to look for an answer. Fortunately, we're living in the wonderful world of open source, so all it requires is a little investigation.

The fdisk program is provided by the util-linux package, so we need that first.

The sector size is displayed in the output of fdisk like this:

Disk /dev/sda: 477 GiB, 512110190592 bytes, 1000215216 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes

If we look for Sector size in the util-linux code, we find it in disk-utils/fdisk-list.c:

fdisk_info(cxt, _("Sector size (logical/physical): %lu bytes / %lu bytes"),

So, it looks like we need to find fdisk_get_sector_size, which is defined in libfdisk/src/context.c:

unsigned long fdisk_get_sector_size(struct fdisk_context *cxt)
    return cxt->sector_size;

Well, that wasn't super helpful. We need to find out where cxt->sector_size is set:

$ grep -lri 'cxt->sector_size.*=' | grep -v tests

I'm going to start with alignment.c, since that filename sounds promising. Looking through that file for the same regex I used to list the files, we find this:

cxt->sector_size = get_sector_size(cxt->dev_fd);

Which leads me to:

static unsigned long get_sector_size(int fd)
    int sect_sz;

    if (!blkdev_get_sector_size(fd, &sect_sz))
        return (unsigned long) sect_sz;

Which in turn leads me to the definition of blkdev_get_sector_size in lib/blkdev.c:

int blkdev_get_sector_size(int fd, int *sector_size)
    if (ioctl(fd, BLKSSZGET, sector_size) >= 0)
        return 0;
    return -1;
int blkdev_get_sector_size(int fd __attribute__((__unused__)), int *sector_size)
    *sector_size = DEFAULT_SECTOR_SIZE;
    return 0;

And there we go. There is a BLKSSZGET ioctl that seems useful. A search for BLKSSZGET leads us to this stackoverflow question, which includes the following information in a comment:

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. – Edward Falk Jul 10 '12 at 19:33

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download