linux-ext4.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Eric Sandeen <sandeen@redhat.com>
To: Forrest Liu <forrestl@synology.com>
Cc: "Theodore Ts'o" <tytso@mit.edu>,
	Ashish Sangwan <ashishsangwan2@gmail.com>,
	ext4 development <linux-ext4@vger.kernel.org>
Subject: Re: [PATCH] ext4: fix extent tree corruption that incurred by hole punch [V2]
Date: Fri, 14 Dec 2012 11:18:29 -0600	[thread overview]
Message-ID: <50CB5F65.9050300@redhat.com> (raw)
In-Reply-To: <CAJSVwFMW-pG4ca+EnnqTP2wXn8_zi5C+CihgrS-pvbkn9gnjmQ@mail.gmail.com>

On 12/13/12 10:04 AM, Forrest Liu wrote:
> @Ashish
>    I have modified the patch with your suggestion, could you help to review.
> 
> @Ted
>    I wrote a script to verify this problem.
>    This script needs tst_extents and fallocate executables from e2fsprogs, and
> fallocate needs your patch with bug fix to do hole punch.

Just FWIW, upstream fallocate in util-linux can punch holes already.

Usage:
 fallocate [options] <filename>

Options:
 -n, --keep-size     don't modify the length of the file
 -p, --punch-hole    punch holes in the file
...

-Eric

>    Steps to run the script
> 1) assign variable blkdev to path of block device that filesystem mount on
> 2) cd to mount point
> 3) run script
> 
> Thanks,
> Forrest
> 
> # verify hole punch bug
> #
> blkdev=/dev/sda1
> file=punch_test
> cmdfile=cmds
> filesize=`expr 1024 \* 1024 \* 1024`
> blksize=`tst_extents -R "stats" $blkdev | grep "Block size" | cut -d
> ':'  -f 2 | tr -d ' '`
> maxlblks=`expr $filesize \/ $blksize`
> 
> rm $file
> touch $file
> fallocate -l $filesize $file
> sync
> 
> inode=`tst_extents -R "stat ${file}" $blkdev | grep Inode | cut -d ' ' -f 2`
> echo "Inode number: $inode"
> 
> # punch every even blocks
> echo "Punch out every even blocks"
> i=0
> while [ "${i}" -lt "${maxlblks}" ]
> do
> 	offset=`expr $i \* $blksize`
> 	fallocate -p -o $offset -l $blksize $file
> 	i=$(($i+2))
> done
> 
> # get lblk from root->ns->down
> echo "inode <$inode>" > cmds
> echo "root" >> cmds
> echo "ns" >> cmds
> 
> a=`tst_extents -f $cmdfile $blkdev`
> echo "down" >> cmds
> b=`tst_extents -f $cmdfile $blkdev`
> 
> # get output form command "down"
> c=${b:${#a}}
> echo "Out put from command \"down\""
> echo $c
> 
> a=`echo ${c#*lblk} | cut -d ',' -f 1`
> lblk_low=`echo $a | cut -d '-' -f 1`
> lblk_hi=`echo $a | cut -d '-' -f 3`
> 
> echo ""
> echo "Punch out blocks $lblk_hi, ..., $lblk_low"
> 
> i=$lblk_hi
> while [ $i -ge $lblk_low ]
> do
> 	offset=`expr $i \* $blksize`
> 	fallocate -p -o $offset -l $blksize $file
> 	i=$(($i-1))
> done
> 
> # verify logical start value is correct or not
> echo "inode <$inode>" > cmds
> echo "root" >> cmds
> a=`tst_extents -f $cmdfile $blkdev`
> echo "ns" >> cmds
> b=`tst_extents -f $cmdfile $blkdev`
> 
> c=${b:${#a}}
> c=`echo ${c#*lblk} | cut -d ',' -f 1`
> lblk_start0=`echo $c | cut -d '-' -f 1`
> 
> echo "down" >> cmds
> c=`tst_extents -f $cmdfile $blkdev`
> c=${c:${#b}}
> c=`echo ${c#*lblk} | cut -d ',' -f 1`
> lblk_start1=`echo $c | cut -d '-' -f 1`
> 
> if [ $lblk_start0 -eq $lblk_start1 ]
> then
> 	echo "logical start valie is consistency:$lblk_start0,$lblk_start1"
> else
> 	echo "logical start valie is not consistency:$lblk_start0,$lblk_start1"
> fi
> 
> 
> 
> diff --git a/contrib/fallocate.c b/contrib/fallocate.c
> index 0e8319f..c1c08e1 100644
> --- a/contrib/fallocate.c
> +++ b/contrib/fallocate.c
> @@ -35,10 +35,11 @@
> 
>  // #include <linux/falloc.h>
>  #define FALLOC_FL_KEEP_SIZE	0x01
> +#define FALLOC_FL_PUNCH_HOLE	0x02 /* de-allocates range */
> 
>  void usage(void)
>  {
> -	printf("Usage: fallocate [-nt] [-o offset] -l length filename\n");
> +	printf("Usage: fallocate [-npt] [-o offset] -l length filename\n");
>  	exit(EXIT_FAILURE);
>  }
> 
> @@ -56,6 +57,7 @@ cvtnum(char *s)
>  	char		*sp;
>  	int		c;
> 
> +
>  	i = strtoll(s, &sp, 0);
>  	if (i == 0 && sp == s)
>  		return -1LL;
> @@ -94,12 +96,18 @@ int main(int argc, char **argv)
>  	int	error;
>  	int	tflag = 0;
> 
> -	while ((opt = getopt(argc, argv, "nl:ot")) != -1) {
> +	while ((opt = getopt(argc, argv, "npl:o:t")) != -1) {
>  		switch(opt) {
>  		case 'n':
>  			/* do not change filesize */
>  			falloc_mode = FALLOC_FL_KEEP_SIZE;
>  			break;
> +		case 'p':
> +			/* punch mode */
> +			falloc_mode = (FALLOC_FL_PUNCH_HOLE |
> +				FALLOC_FL_KEEP_SIZE);
> +			break;
> +
>  		case 'l':
>  			length = cvtnum(optarg);
>  			break;
> 
> 2012/12/13 Forrest Liu <forrestl@synology.com>:
>> When depth of extent tree is greater than 1, logical start value
>> of interior node didn't updated correctly in ext4_ext_rm_idx.
>>
>> Signed-off-by: Forrest Liu <forrestl@synology.com>
>> ---
>>  fs/ext4/extents.c |   22 ++++++++++++++++++----
>>  1 file changed, 18 insertions(+), 4 deletions(-)
>>
>> diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
>> index d3dd618..496952e 100644
>> --- a/fs/ext4/extents.c
>> +++ b/fs/ext4/extents.c
>> @@ -2190,13 +2190,14 @@ errout:
>>   * removes index from the index block.
>>   */
>>  static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
>> -                       struct ext4_ext_path *path)
>> +                       struct ext4_ext_path *path, int depth)
>>  {
>>         int err;
>>         ext4_fsblk_t leaf;
>>
>>         /* free index block */
>> -       path--;
>> +       depth--;
>> +       path = path + depth;
>>         leaf = ext4_idx_pblock(path->p_idx);
>>         if (unlikely(path->p_hdr->eh_entries == 0)) {
>>                 EXT4_ERROR_INODE(inode, "path->p_hdr->eh_entries == 0");
>> @@ -2221,6 +2222,19 @@ static int ext4_ext_rm_idx(handle_t *handle,
>> struct inode *inode,
>>
>>         ext4_free_blocks(handle, inode, NULL, leaf, 1,
>>                          EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET);
>> +
>> +       while (--depth >= 0) {
>> +               if (path->p_idx != EXT_FIRST_INDEX(path->p_hdr))
>> +                       break;
>> +               path--;
>> +               err = ext4_ext_get_access(handle, inode, path);
>> +               if (err)
>> +                       break;
>> +               path->p_idx->ei_block = (path+1)->p_idx->ei_block;
>> +               err = ext4_ext_dirty(handle, inode, path);
>> +               if (err)
>> +                       break;
>> +       }
>>         return err;
>>  }
>>
>> @@ -2557,7 +2571,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
>>         /* if this leaf is free, then we should
>>          * remove it from index block above */
>>         if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL)
>> -               err = ext4_ext_rm_idx(handle, inode, path + depth);
>> +               err = ext4_ext_rm_idx(handle, inode, path, depth);
>>
>>  out:
>>         return err;
>> @@ -2760,7 +2774,7 @@ again:
>>                                 /* index is empty, remove it;
>>                                  * handle must be already prepared by the
>>                                  * truncatei_leaf() */
>> -                               err = ext4_ext_rm_idx(handle, inode, path + i);
>> +                               err = ext4_ext_rm_idx(handle, inode, path, i);
>>                         }
>>                         /* root level has p_bh == NULL, brelse() eats this */
>>                         brelse(path[i].p_bh);
>> --
>> 1.7.9.5
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


  parent reply	other threads:[~2012-12-14 17:18 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-12-13 15:32 [PATCH] ext4: fix extent tree corruption that incurred by hole punch [V2] Forrest Liu
2012-12-13 16:04 ` Forrest Liu
2012-12-13 16:17   ` Forrest Liu
2012-12-14 17:18   ` Eric Sandeen [this message]
2012-12-17  4:25 ` Ashish Sangwan
2012-12-20  5:39 ` Theodore Ts'o
2012-12-20 15:11   ` Forrest Liu
2012-12-20 23:42     ` Theodore Ts'o
2012-12-20 23:43       ` [PATCH 1/3] e2fsck: fix incorrect interior node logical start values Theodore Ts'o
2012-12-20 23:43         ` [PATCH 2/3] libext2fs: ext2fs_extents_fix_parents() should not modify the handle location Theodore Ts'o
2012-12-20 23:43         ` [PATCH 3/3] e2fsck: make sure the extent tree is consistent after bogus node in the tree Theodore Ts'o
2012-12-21  3:19           ` Theodore Ts'o
2012-12-21 11:02             ` Forrest Liu
2012-12-21 15:34           ` Eric Sandeen
2012-12-21 20:47         ` [PATCH 1/3] e2fsck: fix incorrect interior node logical start values Eric Sandeen
2012-12-24 14:57           ` Theodore Ts'o

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=50CB5F65.9050300@redhat.com \
    --to=sandeen@redhat.com \
    --cc=ashishsangwan2@gmail.com \
    --cc=forrestl@synology.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=tytso@mit.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).