ext4: fix premature freeing of partial clusters split across leaf blocks
authorEric Whitney <enwlinux@gmail.com>
Tue, 1 Apr 2014 23:49:30 +0000 (19:49 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 22 Apr 2014 23:49:21 +0000 (16:49 -0700)
commita5f4e47fdf6b7629bae8282080f3a48ad0180eae
tree539e29c5f319ae37914730e6af122076a3d7783f
parent09f052fac4546b1d1c4623a912d60b3a1a40cab5
ext4: fix premature freeing of partial clusters split across leaf blocks

commit ad6599ab3ac98a4474544086e048ce86ec15a4d1 upstream.

Xfstests generic/311 and shared/298 fail when run on a bigalloc file
system.  Kernel error messages produced during the tests report that
blocks to be freed are already on the to-be-freed list.  When e2fsck
is run at the end of the tests, it typically reports bad i_blocks and
bad free blocks counts.

The bug that causes these failures is located in ext4_ext_rm_leaf().
Code at the end of the function frees a partial cluster if it's not
shared with an extent remaining in the leaf.  However, if all the
extents in the leaf have been removed, the code dereferences an
invalid extent pointer (off the front of the leaf) when the check for
sharing is made.  This generally has the effect of unconditionally
freeing the partial cluster, which leads to the observed failures
when the partial cluster is shared with the last extent in the next
leaf.

Fix this by attempting to free the cluster only if extents remain in
the leaf.  Any remaining partial cluster will be freed if possible
when the next leaf is processed or when leaf removal is complete.

Signed-off-by: Eric Whitney <enwlinux@gmail.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/ext4/extents.c