All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <djwong@us.ibm.com>
To: Andreas Dilger <adilger.kernel@dilger.ca>
Cc: Theodore Tso <tytso@mit.edu>,
	Sunil Mushran <sunil.mushran@oracle.com>,
	Amir Goldstein <amir73il@gmail.com>,
	linux-kernel <linux-kernel@vger.kernel.org>,
	Andi Kleen <andi@firstfloor.org>, Mingming Cao <cmm@us.ibm.com>,
	Joel Becker <jlbec@evilplan.org>,
	linux-fsdevel <linux-fsdevel@vger.kernel.org>,
	linux-ext4@vger.kernel.org, Coly Li <colyli@gmail.com>
Subject: Re: [PATCH 09/16] ext4: Calculate and verify block bitmap checksum
Date: Fri, 2 Sep 2011 12:08:29 -0700	[thread overview]
Message-ID: <20110902190829.GJ12086@tux1.beaverton.ibm.com> (raw)
In-Reply-To: <2492E720-3316-4561-8C9C-BBC6E8670EAD@dilger.ca>

On Thu, Sep 01, 2011 at 12:08:44AM -0600, Andreas Dilger wrote:
> On 2011-08-31, at 6:31 PM, Darrick J. Wong wrote:
> > Compute and verify the checksum of the block bitmap; this checksum is stored in
> > the block group descriptor.
> > 
> > Signed-off-by: Darrick J. Wong <djwong@us.ibm.com>
> > ---
> > fs/ext4/balloc.c  |   43 ++++++++++++++++++++++++++++++++++---------
> > fs/ext4/ext4.h    |    7 ++++++-
> > fs/ext4/ialloc.c  |    5 +++++
> > fs/ext4/mballoc.c |   34 ++++++++++++++++++++++++++++++++++
> > 4 files changed, 79 insertions(+), 10 deletions(-)
> > 
> > 
> > diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
> > index f8224ad..36d3020 100644
> > --- a/fs/ext4/balloc.c
> > +++ b/fs/ext4/balloc.c
> > @@ -105,6 +105,10 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
> > 			ext4_free_inodes_set(sb, gdp, 0);
> > 			ext4_itable_unused_set(sb, gdp, 0);
> > 			memset(bh->b_data, 0xff, sb->s_blocksize);
> > +			ext4_bitmap_csum_set(sb, block_group,
> > +					     &gdp->bg_block_bitmap_csum, bh,
> > +					     (EXT4_BLOCKS_PER_GROUP(sb) + 7) /
> > +					     8);
> > 			return 0;
> > 		}
> > 		memset(bh->b_data, 0, sb->s_blocksize);
> > @@ -175,6 +179,11 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
> > 		 */
> > 		ext4_mark_bitmap_end(group_blocks, sb->s_blocksize * 8,
> > 				     bh->b_data);
> > +		ext4_bitmap_csum_set(sb, block_group,
> > +				     &gdp->bg_block_bitmap_csum, bh,
> > +				     (EXT4_BLOCKS_PER_GROUP(sb) + 7) / 8);
> > +		gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group,
> > +							gdp);
> > 	}
> > 	return free_blocks - ext4_group_used_meta_blocks(sb, block_group, gdp);
> > }
> > @@ -232,10 +241,10 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
> > 	return desc;
> > }
> > 
> > -static int ext4_valid_block_bitmap(struct super_block *sb,
> > -					struct ext4_group_desc *desc,
> > -					unsigned int block_group,
> > -					struct buffer_head *bh)
> > +int ext4_valid_block_bitmap(struct super_block *sb,
> > +			    struct ext4_group_desc *desc,
> > +			    unsigned int block_group,
> > +			    struct buffer_head *bh)
> > {
> > 	ext4_grpblk_t offset;
> > 	ext4_grpblk_t next_zero_bit;
> > @@ -312,12 +321,12 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
> > 	}
> > 
> > 	if (bitmap_uptodate(bh))
> > -		return bh;
> > +		goto verify;
> > 
> > 	lock_buffer(bh);
> > 	if (bitmap_uptodate(bh)) {
> > 		unlock_buffer(bh);
> > -		return bh;
> > +		goto verify;
> > 	}
> > 	ext4_lock_group(sb, block_group);
> > 	if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
> > @@ -336,7 +345,7 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
> > 		 */
> > 		set_bitmap_uptodate(bh);
> > 		unlock_buffer(bh);
> > -		return bh;
> > +		goto verify;
> > 	}
> > 	/*
> > 	 * submit the buffer_head for read. We can
> > @@ -353,11 +362,27 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
> > 			    block_group, bitmap_blk);
> > 		return NULL;
> > 	}
> > -	ext4_valid_block_bitmap(sb, desc, block_group, bh);
> > +
> > +verify:
> > +	if (buffer_verified(bh))
> > +		return bh;
> > 	/*
> > 	 * file system mounted not to panic on error,
> > -	 * continue with corrupt bitmap
> > +	 * -EIO with corrupt bitmap
> > 	 */
> > +	ext4_lock_group(sb, block_group);
> > +	if (!ext4_valid_block_bitmap(sb, desc, block_group, bh) ||
> > +	    !ext4_bitmap_csum_verify(sb, block_group,
> > +				     desc->bg_block_bitmap_csum, bh,
> > +				     (EXT4_BLOCKS_PER_GROUP(sb) + 7) / 8)) {
> > +		ext4_unlock_group(sb, block_group);
> > +		put_bh(bh);
> > +		ext4_error(sb, "Corrupt block bitmap - block_group = %u, "
> > +			   "block_bitmap = %llu", block_group, bitmap_blk);
> > +		return NULL;
> > +	}
> > +	ext4_unlock_group(sb, block_group);
> > +	set_buffer_verified(bh);
> > 	return bh;
> > }
> > 
> > diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
> > index 248cbd2..df149b3 100644
> > --- a/fs/ext4/ext4.h
> > +++ b/fs/ext4/ext4.h
> > @@ -269,7 +269,8 @@ struct ext4_group_desc
> > 	__le16	bg_free_inodes_count_lo;/* Free inodes count */
> > 	__le16	bg_used_dirs_count_lo;	/* Directories count */
> > 	__le16	bg_flags;		/* EXT4_BG_flags (INODE_UNINIT, etc) */
> > -	__u32	bg_reserved[2];		/* Likely block/inode bitmap checksum */
> > +	__u32	bg_reserved[1];		/* unclaimed */
> > +	__le32	bg_block_bitmap_csum;	/* crc32c(uuid+group+bbitmap) */
> 
> Same comment as for the inode bitmap checksum - it should be split into
> two __le16 fields, so that we get at least some coverage for the vast
> majority of existing filesystems.
> 
> > 	__le16  bg_itable_unused_lo;	/* Unused inodes count */
> > 	__le16  bg_checksum;		/* crc16(sb_uuid+group+desc) */
> > 	__le32	bg_block_bitmap_hi;	/* Blocks bitmap block MSB */
> > @@ -1731,6 +1732,10 @@ void ext4_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
> > 			  __le32 *csum, struct buffer_head *bh, int sz);
> > 
> > /* balloc.c */
> > +extern int ext4_valid_block_bitmap(struct super_block *sb,
> > +				   struct ext4_group_desc *desc,
> > +				   unsigned int block_group,
> > +				   struct buffer_head *bh);
> > extern unsigned int ext4_block_group(struct super_block *sb,
> > 			ext4_fsblk_t blocknr);
> > extern ext4_grpblk_t ext4_block_group_offset(struct super_block *sb,
> > diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
> > index 53faffc..a335d19 100644
> > --- a/fs/ext4/ialloc.c
> > +++ b/fs/ext4/ialloc.c
> > @@ -984,6 +984,11 @@ got:
> > 			free = ext4_free_blocks_after_init(sb, group, gdp);
> > 			gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
> > 			ext4_free_blks_set(sb, gdp, free);
> > +			ext4_bitmap_csum_set(sb, group,
> > +					     &gdp->bg_block_bitmap_csum,
> > +					     block_bitmap_bh,
> > +					     (EXT4_BLOCKS_PER_GROUP(sb) + 7) /
> > +					     8);
> > 			gdp->bg_checksum = ext4_group_desc_csum(sbi, group,
> > 								gdp);
> > 		}
> > diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
> > index 17a5a57..8dc3055 100644
> > --- a/fs/ext4/mballoc.c
> > +++ b/fs/ext4/mballoc.c
> > @@ -895,6 +895,33 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
> > 		if (bh[i] && !buffer_uptodate(bh[i]))
> > 			goto out;
> > 
> > +	for (i = 0; i < groups_per_page; i++) {
> > +		struct ext4_group_desc *desc;
> > +
> > +		if (!bh[i] || !bh[i]->b_end_io)
> > +			continue;
> 
> Please don't treat pointers as boolean values.  I'd prefer to see a
> proper comparison like "bh[i] == NULL" here.
> 
> Also, it isn't obvious why the check for b_end_io is needed here?

If b_end_io is set then the block is being read in and needs checking.
BH_Verified would work just as well here and be a little clearer.  I think I
had this patch written before I added the BH_Verified flag and forgot to update
this patch.  Oops. Good catch.

> > +		desc = ext4_get_group_desc(sb, first_group + i, NULL);
> > +		if (!desc)
> > +			goto out;
> > +
> > +		if (buffer_verified(bh[i]))
> > +			continue;
> > +		ext4_lock_group(sb, first_group + i);
> > +		if (!ext4_valid_block_bitmap(sb, desc, first_group + i,
> > +					     bh[i]) ||
> > +		    !ext4_bitmap_csum_verify(sb, first_group + i,
> > +					     desc->bg_block_bitmap_csum, bh[i],
> > +					     (EXT4_BLOCKS_PER_GROUP(sb) + 7) /
> > +					      8)) {
> > +			ext4_unlock_group(sb, first_group + i);
> > +			ext4_error(sb, "Corrupt block bitmap, group = %u",
> > +				   first_group + i);
> > +			goto out;
> > +		}
> > +		ext4_unlock_group(sb, first_group + i);
> > +		set_buffer_verified(bh[i]);
> > +	}
> 
> Since this is CPU intensive, it might make sense to start computing the
> block bitmap checksums as soon as the buffer is uptodate, instead of
> waiting for all of the buffers to be read and _then_ doing the checksums.
> 
> Even better might be to do move all of the above code to do the checksum
> to be in a new the b_end_io callback, so that it can start as soon as each
> buffer is read from disk, to maximize CPU and IO overlap, like:

Good suggestion.  I'll put it into the next rev.

--D

> struct ext4_csum_data {
>         struct superblock *cd_sb;
>         ext4_group_t       cd_group;
> };
> 
> static void ext4_end_buffered_read_sync_csum(struct buffer_head *bh,
>                                              int uptodate)
> {
>         struct superblock *sb = (struct ext4_csum_data *)(bh->b_private)->cd_sb;
> 	ext4_group_t group = (struct ext4_csum_data *)(bh->b_private)->cd_group;
> 
>         end_buffered_read_sync(bh, uptodate);
> 
>         if (uptodate) {
> 		struct ext4_group_desc *desc;
> 
> 
> 		desc = ext4_get_group_desc(sb, group, NULL);
> 		if (!desc)
> 			return;
> 
> 		ext4_lock_group(sb, group);
> 		if (ext4_valid_block_bitmap(sb, desc, group, bh) &&
> 		    ext4_bitmap_csum_verify(sb, group,
> 					    desc->bg_block_bitmap_csum, bh,
> 					    (EXT4_BLOCKS_PER_GROUP(sb) + 7) / 8))
> 			set_buffer_verified(bh);
> 
> 		ext4_unlock_group(rcd->rcd_sb, rcd->rcd_group);
> 	}
> }
> 
> Then later in the code can just check buffer_verified() in the caller:
> 
> ext4_read_block_bitmap()
> {
>         /* read all groups the page covers into the cache */
>         for (i = 0; i < groups_per_page; i++) {
> 		:
> 		:
>                 set_bitmap_uptodate(bh[i]);
>                 ecd[i].cd_sb = sb;
>                 ecd[i].cd_group = first_group + i;
>                 bh[i]->b_end_io = ext4_end_buffer_read_sync_csum;
>                 submit_bh(READ, bh[i]);
>                 mb_debug(1, "read bitmap for group %u\n", first_group + i);
> 	}
> 
> 	err = 0;
>         /* always wait for I/O completion before returning */
>         for (i = 0; i < groups_per_page; i++) {
>                 if (bh[i]) {
>                         wait_on_buffer(bh[i]);
> 			if (!buffer_uptodate(bh[i]) ||
> 			    !buffer_verified(bh[i]))
> 				err = -EIO;
> 		}
> 	}
> 
> 
> > 	err = 0;
> > 	first_block = page->index * blocks_per_page;
> > 	for (i = 0; i < blocks_per_page; i++) {
> > @@ -2829,6 +2856,9 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
> > 	}
> > 	len = ext4_free_blks_count(sb, gdp) - ac->ac_b_ex.fe_len;
> > 	ext4_free_blks_set(sb, gdp, len);
> > +	ext4_bitmap_csum_set(sb, ac->ac_b_ex.fe_group,
> > +			     &gdp->bg_block_bitmap_csum, bitmap_bh,
> > +			     (EXT4_BLOCKS_PER_GROUP(sb) + 7) / 8);
> > 	gdp->bg_checksum = ext4_group_desc_csum(sbi, ac->ac_b_ex.fe_group, gdp);
> > 
> > 	ext4_unlock_group(sb, ac->ac_b_ex.fe_group);
> > @@ -4638,6 +4668,8 @@ do_more:
> > 
> > 	ret = ext4_free_blks_count(sb, gdp) + count;
> > 	ext4_free_blks_set(sb, gdp, ret);
> > +	ext4_bitmap_csum_set(sb, block_group, &gdp->bg_block_bitmap_csum,
> > +			     bitmap_bh, (EXT4_BLOCKS_PER_GROUP(sb) + 7) / 8);
> > 	gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group, gdp);
> > 	ext4_unlock_group(sb, block_group);
> > 	percpu_counter_add(&sbi->s_freeblocks_counter, count);
> > @@ -4780,6 +4812,8 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
> > 	mb_free_blocks(NULL, &e4b, bit, count);
> > 	blk_free_count = blocks_freed + ext4_free_blks_count(sb, desc);
> > 	ext4_free_blks_set(sb, desc, blk_free_count);
> > +	ext4_bitmap_csum_set(sb, block_group, &desc->bg_block_bitmap_csum,
> > +			     bitmap_bh, (EXT4_BLOCKS_PER_GROUP(sb) + 7) / 8);
> > 	desc->bg_checksum = ext4_group_desc_csum(sbi, block_group, desc);
> > 	ext4_unlock_group(sb, block_group);
> > 	percpu_counter_add(&sbi->s_freeblocks_counter, blocks_freed);
> > 
> 

  parent reply	other threads:[~2011-09-02 19:08 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-09-01  0:30 [PATCH v1 00/16] ext4: Add metadata checksumming Darrick J. Wong
2011-09-01  0:30 ` [PATCH 01/16] ext4: ext4_dx_add_entry should dirty directory metadata with the directory inode Darrick J. Wong
2011-09-01  0:30 ` [PATCH 02/16] ext4: ext4_rename should dirty dir_bh with the correct directory Darrick J. Wong
2011-09-01  0:30 ` [PATCH 03/16] ext4: ext4_mkdir should dirty dir_block with the parent inode Darrick J. Wong
2011-09-01  0:30 ` [PATCH 04/16] ext4: Create a new BH_Verified flag to avoid unnecessary metadata validation Darrick J. Wong
2011-09-01  0:31 ` [PATCH 05/16] ext4: Create a rocompat flag for extended metadata checksumming Darrick J. Wong
2011-09-01  0:31 ` [PATCH 06/16] ext4: Calculate and verify inode checksums Darrick J. Wong
2011-09-01  2:30   ` Andreas Dilger
2011-09-02 19:32     ` Darrick J. Wong
2011-09-02 22:02       ` Andreas Dilger
2011-09-05 17:57         ` Darrick J. Wong
2011-09-01  0:31 ` [PATCH 07/16] ext4: Create bitmap checksum helper functions Darrick J. Wong
2011-09-01  0:31 ` [PATCH 08/16] ext4: Calculate and verify checksums for inode bitmaps Darrick J. Wong
2011-09-01  4:49   ` Andreas Dilger
2011-09-02 19:18     ` Darrick J. Wong
2011-09-02 21:27       ` Andreas Dilger
2011-09-05 18:22         ` Darrick J. Wong
2011-09-05 18:27           ` Andi Kleen
2011-09-05 19:45           ` James Bottomley
2011-09-05 22:12             ` Darrick J. Wong
2011-09-01  0:31 ` [PATCH 09/16] ext4: Calculate and verify block bitmap checksum Darrick J. Wong
     [not found]   ` <2492E720-3316-4561-8C9C-BBC6E8670EAD@dilger.ca>
2011-09-02 19:08     ` Darrick J. Wong [this message]
2011-09-02 21:06       ` Andreas Dilger
2011-09-01  0:31 ` [PATCH 10/16] ext4: Verify and calculate checksums for extent tree blocks Darrick J. Wong
     [not found]   ` <26584BE9-B716-40D5-B3B4-8C5912869648@dilger.ca>
2011-09-02 19:02     ` Darrick J. Wong
2011-09-01  0:31 ` [PATCH 11/16] ext4: Calculate and verify checksums for htree nodes Darrick J. Wong
2011-09-01  0:31 ` [PATCH 12/16] ext4: Calculate and verify checksums of directory leaf blocks Darrick J. Wong
     [not found]   ` <4D5D8FB2-0D8A-4D30-B6D8-51158395C1C9@dilger.ca>
2011-09-02 18:57     ` Darrick J. Wong
2011-09-02 20:52       ` Andreas Dilger
2011-09-05 18:30         ` Darrick J. Wong
2011-09-01  0:32 ` [PATCH 13/16] ext4: Calculate and verify checksums of extended attribute blocks Darrick J. Wong
     [not found]   ` <F4A42DCE-F91C-419B-9153-65A7EA91D241@dilger.ca>
2011-09-02 18:43     ` Darrick J. Wong
2011-09-01  0:32 ` [PATCH 14/16] ext4: Make inode checksum cover empty space Darrick J. Wong
     [not found]   ` <4540D5DB-53D9-4C33-BC6B-868870D42AF3@dilger.ca>
2011-09-02 18:42     ` Darrick J. Wong
2011-09-01  0:32 ` [PATCH 15/16] ext4: Calculate and verify superblock checksum Darrick J. Wong
     [not found]   ` <2882FBB2-797C-4D27-8569-B6826DD34F68@dilger.ca>
2011-09-02 18:40     ` Darrick J. Wong
2011-09-01  0:32 ` [PATCH 16/16] jbd2: Support CRC32C transaction checksums Darrick J. Wong
     [not found]   ` <99019900-30B1-450A-9620-E94371A30CC6@dilger.ca>
2011-09-02 18:31     ` Darrick J. Wong
2011-09-02 14:15 ` [PATCH v1 00/16] ext4: Add metadata checksumming Greg Freemyer
2011-09-02 14:15   ` Greg Freemyer
2011-09-02 18:22   ` Darrick J. Wong
2011-09-02 18:22     ` Darrick J. Wong
2011-09-04 11:41     ` Martin K. Petersen
2011-09-04 16:54       ` Andi Kleen
2011-09-04 17:17         ` Martin K. Petersen
2011-09-04 17:44           ` Andi Kleen
2011-09-04 22:19             ` Martin K. Petersen
2011-09-05 18:55               ` Darrick J. Wong
2011-09-05 18:45       ` Darrick J. Wong
2011-09-06 12:59         ` Martin K. Petersen

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=20110902190829.GJ12086@tux1.beaverton.ibm.com \
    --to=djwong@us.ibm.com \
    --cc=adilger.kernel@dilger.ca \
    --cc=amir73il@gmail.com \
    --cc=andi@firstfloor.org \
    --cc=cmm@us.ibm.com \
    --cc=colyli@gmail.com \
    --cc=jlbec@evilplan.org \
    --cc=linux-ext4@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=sunil.mushran@oracle.com \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.