Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ext4: fix xattr block allocation/release with bigalloc

Currently when new xattr block is created or released we we would call
dquot_free_block() or dquot_alloc_block() respectively, among the else
decrementing or incrementing the number of blocks assigned to the
inode by one block.

This however does not work for bigalloc file system because we always
allocate/free the whole cluster so we have to count with that in
dquot_free_block() and dquot_alloc_block() as well.

Use the clusters-to-blocks conversion EXT4_C2B() when passing number of
blocks to the dquot_alloc/free functions to fix the problem.

The problem has been revealed by xfstests #117 (and possibly others).

Signed-off-by: Lukas Czerner <lczerner@redhat.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Cc: stable@vger.kernel.org

authored by

Lukas Czerner and committed by
Theodore Ts'o
1231b3a1 74cd15cd

+4 -3
+4 -3
fs/ext4/xattr.c
··· 549 549 error = ext4_handle_dirty_xattr_block(handle, inode, bh); 550 550 if (IS_SYNC(inode)) 551 551 ext4_handle_sync(handle); 552 - dquot_free_block(inode, 1); 552 + dquot_free_block(inode, EXT4_C2B(EXT4_SB(inode->i_sb), 1)); 553 553 ea_bdebug(bh, "refcount now=%d; releasing", 554 554 le32_to_cpu(BHDR(bh)->h_refcount)); 555 555 } ··· 832 832 else { 833 833 /* The old block is released after updating 834 834 the inode. */ 835 - error = dquot_alloc_block(inode, 1); 835 + error = dquot_alloc_block(inode, 836 + EXT4_C2B(EXT4_SB(sb), 1)); 836 837 if (error) 837 838 goto cleanup; 838 839 error = ext4_journal_get_write_access(handle, ··· 930 929 return error; 931 930 932 931 cleanup_dquot: 933 - dquot_free_block(inode, 1); 932 + dquot_free_block(inode, EXT4_C2B(EXT4_SB(sb), 1)); 934 933 goto cleanup; 935 934 936 935 bad_block: