[3.8.y.z extended stable] Patch "ext4: fix premature freeing of partial clusters split across leaf blocks" has been added to staging queue

Kamal Mostafa kamal at canonical.com
Fri Apr 18 17:23:27 UTC 2014


On Thu, 2014-04-17 at 16:30 -0700, Kamal Mostafa wrote:
> This is a note to let you know that I have just added a patch titled
> 
>     ext4: fix premature freeing of partial clusters split across leaf blocks
> 
> to the linux-3.8.y-queue branch of the 3.8.y.z extended stable tree 

This patch won't cleanly apply to 3.8 without a prerequisite that has
now been dropped from the queue (ext4: make punch hole code path work
with bigalloc).

So this patch (ext4: fix premature freeing) will also be dropped from
the 3.8-stable queue, unless one of the ext4 folks would like to provide
a backport which applies to 3.8-stable's fs/ext4/extents.c[0], or advice
about what that "if partial_cluster" line should look like when all is
said and done.

Thanks,

 -Kamal

[0] http://kernel.ubuntu.com/git?p=ubuntu/linux.git;a=blob;f=fs/ext4/extents.c;h=8b5c2646786fbe10cb559d8636544350cad9274c;hb=refs/heads/linux-3.8.y-queue#l2614



> which can be found at:
> 
>  http://kernel.ubuntu.com/git?p=ubuntu/linux.git;a=shortlog;h=refs/heads/linux-3.8.y-queue
> 
> This patch is scheduled to be released in version 3.8.13.22.
> 
> If you, or anyone else, feels it should not be added to this tree, please 
> reply to this email.
> 
> For more information about the 3.8.y.z tree, see
> https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable
> 
> Thanks.
> -Kamal
> 
> ------
> 
> From bbc128e90ae5c1af34a25d40cdda91038fde3468 Mon Sep 17 00:00:00 2001
> From: Eric Whitney <enwlinux at gmail.com>
> Date: Tue, 1 Apr 2014 19:49:30 -0400
> Subject: 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 at gmail.com>
> Signed-off-by: "Theodore Ts'o" <tytso at mit.edu>
> Signed-off-by: Kamal Mostafa <kamal at canonical.com>
> ---
>  fs/ext4/extents.c | 11 ++++++++---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
> index 7b22105..37f6849 100644
> --- a/fs/ext4/extents.c
> +++ b/fs/ext4/extents.c
> @@ -2646,10 +2646,15 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
>  		err = ext4_ext_correct_indexes(handle, inode, path);
> 
>  	/*
> -	 * Free the partial cluster only if the current extent does not
> -	 * reference it. Otherwise we might free used cluster.
> +	 * If there's a partial cluster and at least one extent remains in
> +	 * the leaf, free the partial cluster if it isn't shared with the
> +	 * current extent.  If there's a partial cluster and no extents
> +	 * remain in the leaf, it can't be freed here.  It can only be
> +	 * freed when it's possible to determine if it's not shared with
> +	 * any other extent - when the next leaf is processed or when space
> +	 * removal is complete.
>  	 */
> -	if (*partial_cluster > 0 &&
> +	if (*partial_cluster > 0 && eh->eh_entries &&
>  	    (EXT4_B2C(sbi, ext4_ext_pblock(ex) + ex_ee_len - 1) !=
>  	     *partial_cluster)) {
>  		int flags = EXT4_FREE_BLOCKS_FORGET;
> --
> 1.9.1
> 






More information about the kernel-team mailing list