• Kazuya Mio's avatar
    ext4: ensure f_bfree returned by ext4_statfs() is non-negative · d02a9391
    Kazuya Mio authored
    I found the issue that the number of free blocks went negative.
    # stat -f /mnt/mp1/
      File: "/mnt/mp1/"
        ID: e175ccb83a872efe Namelen: 255     Type: ext2/ext3
    Block size: 4096       Fundamental block size: 4096
    Blocks: Total: 258022     Free: -15        Available: -13122
    Inodes: Total: 65536      Free: 63029
    
    f_bfree in struct statfs will go negative when the filesystem has
    few free blocks. Because the number of dirty blocks is bigger than
    the number of free blocks in the following two cases.
    
    CASE 1:
    ext4_da_writepages
      mpage_da_map_and_submit
        ext4_map_blocks
          ext4_ext_map_blocks
            ext4_mb_new_blocks
              ext4_mb_diskspace_used
                percpu_counter_sub(&sbi->s_freeblocks_counter, ac->ac_b_ex.fe_len);
            <--- interrupt statfs systemcall --->
            ext4_da_update_reserve_space
                percpu_counter_sub(&sbi->s_dirtyblocks_counter,
                                used + ei->i_allocated_meta_blocks);
    
    CASE 2:
    ext4_write_begin
      __block_write_begin
        ext4_map_blocks
          ext4_ext_map_blocks
            ext4_mb_new_blocks
              ext4_mb_diskspace_used
                percpu_counter_sub(&sbi->s_freeblocks_counter, ac->ac_b_ex.fe_len);
                <--- interrupt statfs systemcall --->
                percpu_counter_sub(&sbi->s_dirtyblocks_counter, reserv_blks);
    
    To avoid the issue, this patch ensures that f_bfree is non-negative.
    Signed-off-by: default avatarKazuya Mio <k-mio@sx.jp.nec.com>
    d02a9391
super.c 137 KB