Search code examples
linuxscriptingquotadisk-access

Detect block size for quota in Linux


The limit placed on disk quota in Linux is counted in blocks. However, I found no reliable way to determine the block size. Tutorials I found refer to block size as 512 bytes, and sometimes as 1024 bytes.

I got confused reading a post on LinuxForum.org for what a block size really means. So I tried to find that meaning in the context of quota.

I found a "Determine the block size on hard disk filesystem for disk quota" tip on NixCraft, that suggested the command:

dumpe2fs /dev/sdXN | grep -i 'Block size'

or

blockdev --getbsz /dev/sdXN

But on my system those commands returned 4096, and when I checked the real quota block size on the same system, I got a block size of 1024 bytes.

Is there a scriptable way to determine the quota block size on a device, short of creating a known sized file, and checking it's quota usage?


Solution

  • The filesystem blocksize and the quota blocksize are potentially different. The quota blocksize is given by the BLOCK_SIZE macro defined in <sys/mount.h> (/usr/include/sys/mount.h):

    #ifndef _SYS_MOUNT_H
    #define _SYS_MOUNT_H    1
    
    #include <features.h>
    #include <sys/ioctl.h>
    
    #define BLOCK_SIZE      1024
    #define BLOCK_SIZE_BITS 10
    ...
    

    The filesystem blocksize for a given filesystem is returned by the statvfs call:

    #include <stdio.h>
    #include <sys/statvfs.h>
    
    int main(int argc, char *argv[])
    {
        char *fn;
        struct statvfs vfs;
    
        if (argc > 1)
            fn = argv[1];
        else
            fn = argv[0];
    
        if (statvfs(fn, &vfs))
        {
            perror("statvfs");
            return 1;
        }
    
        printf("(%s) bsize: %lu\n", fn, vfs.f_bsize);
    
        return 0;
    }
    

    The <sys/quota.h> header includes a convenience macro to convert filesystem blocks to disk quota blocks:

    /*
     * Convert count of filesystem blocks to diskquota blocks, meant
     * for filesystems where i_blksize != BLOCK_SIZE
     */
    #define fs_to_dq_blocks(num, blksize) (((num) * (blksize)) / BLOCK_SIZE)