clinuxioctl

get physical block size of a device


In the below code I'm trying to get the physical block size of a device via file/directory path residing in the file system mount point of that device. I am supposed to get the same info as the command sudo blockdev --getpbsz /dev/sdc, but the ioctl call is getting failed with error message Inappropriate ioctl for device.

#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fs.h>
#include <sys/ioctl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

int main() {
    const int fd = open("/tmp", O_DIRECTORY | O_RDONLY);
    if (fd == -1) {
        printf("error %s\n", strerror(errno));
        return EXIT_FAILURE;
    }

    unsigned long num_blocks = 0;
    if (ioctl(fd, BLKPBSZGET, &num_blocks) == -1) {
        printf("error %s\n", strerror(errno));
        return EXIT_FAILURE;
    }
    printf("physical block size: %lu", num_blocks);

    close(fd);

    return EXIT_SUCCESS;
}

Output

error Inappropriate ioctl for device 

Solution

  • The ioctl call BLKPBSZGET is meant to be used on block device files for exemple on /dev/sdc, not on a file or directory residing in a filesystem /tmp/

    Determine the block device associated with the filesystem where your target directory resides with df and get the filesystem

    $ df /tmp/
    Filesystem      1K-blocks     Used Available Use% Mounted on
    /dev/sdc       1055762868 26105084 975954312   3% /
    

    So your code should be like that:

    #include <stdlib.h>
    #include <stdio.h>
    #include <fcntl.h>
    #include <linux/fs.h>
    #include <sys/ioctl.h>
    #include <string.h>
    #include <errno.h>
    #include <unistd.h>
    
    int main() {
        const int fd = open("/dev/sdc", O_RDONLY);
        if (fd == -1) {
            printf("Error: %s\n", strerror(errno));
            return EXIT_FAILURE;
        }
    
        unsigned int block_size = 0;
        if (ioctl(fd, BLKPBSZGET, &block_size) == -1) {
            printf("ioctl error: %s\n", strerror(errno));
            close(fd);
            return EXIT_FAILURE;
        }
    
        printf("Physical block size: %u bytes\n", block_size);
    
        close(fd);
        return EXIT_SUCCESS;
    }
    

    And give me the write output:

    $ gcc main.c
    $ ./a.out
    Error: Permission denied
    $ sudo !!
    sudo ./a.out
    Physical block size: 4096 bytes
    

    Oups, I missed to give you my sources (https://forums.raspberrypi.com/viewtopic.php?t=263949)