Patch "f2fs: cover large section in sanity check of super" has been added to the 4.5-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
f2fs: cover large section in sanity check of super
to the 4.5-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
f2fs-cover-large-section-in-sanity-check-of-super.patch
and it can be found in the queue-4.5 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
fd694733d523df1e0a583cf5c4c08e41d7bf9fa3Mon Sep 17 00:00:00 2001
From: Jaegeuk Kim <[email protected]>
Date: Sun, 20 Mar 2016 15:33:20 -0700
Subject: f2fs: cover large section in sanity check of super
From: Jaegeuk Kim <[email protected]>
commit fd694733d523df1e0a583cf5c4c08e41d7bf9fa3 upstream.
This patch fixes the bug which does not cover a large section case when checking the sanity of superblock.
If f2fs detects misalignment, it will fix the superblock during the mount time, so it doesn't need to trigger fsck.f2fs further.
--- fs/f2fs/super.c | 102 +++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 37 deletions(-)
fs/f2fs/super.c +65 -37
@@ -926,9 +926,25 @@ static loff_t max_file_blocks(void)return result; } +static int __f2fs_commit_super (struct buffer_head *bh, +struct f2fs_super_block *super) +{ +lock_buffer (bh); +if (super) +memcpy (bh->b_data +F2FS_SUPER_OFFSET , super,sizeof (*super)); +set_buffer_uptodate (bh); +set_buffer_dirty (bh); +unlock_buffer (bh); + +/* it's rare case, we can do fua all the time */ +return __sync_dirty_buffer (bh,WRITE_FLUSH_FUA ); +} +static inline bool sanity_check_area_boundary (struct super_block *sb, -struct f2fs_super_block *raw_super) +struct buffer_head *bh) { +struct f2fs_super_block *raw_super = (struct f2fs_super_block *) + (bh->b_data +F2FS_SUPER_OFFSET );u32 segment0_blkaddr =le32_to_cpu (raw_super->segment0_blkaddr);u32 cp_blkaddr =le32_to_cpu (raw_super->cp_blkaddr);u32 sit_blkaddr =le32_to_cpu (raw_super->sit_blkaddr);
@@ -942,6 +958,10 @@ static inline bool sanity_check_area_bouu32 segment_count_main =le32_to_cpu (raw_super->segment_count_main);u32 segment_count =le32_to_cpu (raw_super->segment_count);u32 log_blocks_per_seg =le32_to_cpu (raw_super->log_blocks_per_seg); +u64 main_end_blkaddr = main_blkaddr + + (segment_count_main << log_blocks_per_seg); +u64 seg_end_blkaddr = segment0_blkaddr + + (segment_count << log_blocks_per_seg);if (segment0_blkaddr != cp_blkaddr) { f2fs_msg(sb, KERN_INFO,
@@ -986,22 +1006,45 @@ static inline bool sanity_check_area_boureturn true; } -if (main_blkaddr + (segment_count_main << log_blocks_per_seg) != - segment0_blkaddr + (segment_count << log_blocks_per_seg)) { +if (main_end_blkaddr > seg_end_blkaddr) {f2fs_msg (sb,KERN_INFO , -"Wrong MAIN_AREA boundary, start(%u) end(%u) blocks(%u)" , +"Wrong MAIN_AREA boundary, start(%u) end(%u) block(%u)" , main_blkaddr, - segment0_blkaddr + (segment_count << log_blocks_per_seg), + segment0_blkaddr + + (segment_count << log_blocks_per_seg), segment_count_main << log_blocks_per_seg);return true; + }else if (main_end_blkaddr < seg_end_blkaddr) { +int err =0 ; +char *res; + +/* fix in-memory information all the time */ + raw_super->segment_count =cpu_to_le32 ((main_end_blkaddr - + segment0_blkaddr) >> log_blocks_per_seg); + +if (f2fs_readonly (sb) ||bdev_read_only (sb->s_bdev)) { + res ="internally" ; + }else { + err =__f2fs_commit_super (bh,NULL ); + res = err ?"failed" :"done" ; + } +f2fs_msg (sb,KERN_INFO , +"Fix alignment : %s, start(%u) end(%u) block(%u)" , + res, main_blkaddr, + segment0_blkaddr + + (segment_count << log_blocks_per_seg), + segment_count_main << log_blocks_per_seg); +if (err) +return true; } -return false; }static int sanity_check_raw_super (struct super_block *sb, -struct f2fs_super_block *raw_super) +struct buffer_head *bh) { +struct f2fs_super_block *raw_super = (struct f2fs_super_block *) + (bh->b_data +F2FS_SUPER_OFFSET );unsigned int blocksize;if (F2FS_SUPER_MAGIC !=le32_to_cpu (raw_super->magic)) {
@@ -1068,7 +1111,7 @@ static int sanity_check_raw_super(struct }/* check CP/SIT/NAT/SSA/MAIN_AREA area boundary */ -if (sanity_check_area_boundary (sb, raw_super)) +if (sanity_check_area_boundary (sb, bh))return 1 ;return 0 ;
@@ -1144,7 +1187,7 @@ static int read_raw_super_block(struct s {int block;struct buffer_head *bh; -struct f2fs_super_block *super, *buf; +struct f2fs_super_block *super;int err =0 ; super =kzalloc (sizeof (struct f2fs_super_block ),GFP_KERNEL );
@@ -1160,11 +1203,8 @@ static int read_raw_super_block(struct scontinue ; } - buf = (struct f2fs_super_block *) - (bh->b_data +F2FS_SUPER_OFFSET ); -/* sanity checking of raw super */ -if (sanity_check_raw_super (sb, buf)) { +if (sanity_check_raw_super (sb, bh)) {f2fs_msg (sb,KERN_ERR ,"Can't find valid F2FS filesystem in %dth superblock" , block +1 );
@@ -1174,7 +1214,8 @@ static int read_raw_super_block(struct s }if (!*raw_super) { -memcpy (super, buf,sizeof (*super)); +memcpy (super, bh->b_data +F2FS_SUPER_OFFSET , +sizeof (*super)); *valid_super_block = block; *raw_super = super; }
@@ -1194,42 +1235,29 @@ static int read_raw_super_block(struct sreturn err; } -static int __f2fs_commit_super (struct f2fs_sb_info *sbi,int block) +int f2fs_commit_super (struct f2fs_sb_info *sbi,bool recover) { -struct f2fs_super_block *super =F2FS_RAW_SUPER (sbi);struct buffer_head *bh;int err; - bh =sb_getblk (sbi->sb, block); +/* write back-up superblock first */ + bh =sb_getblk (sbi->sb, sbi->valid_super_block ?0 :1 );if (!bh)return -EIO ; - -lock_buffer (bh); -memcpy (bh->b_data +F2FS_SUPER_OFFSET , super,sizeof (*super)); -set_buffer_uptodate (bh); -set_buffer_dirty (bh); -unlock_buffer (bh); - -/* it's rare case, we can do fua all the time */ - err =__sync_dirty_buffer (bh,WRITE_FLUSH_FUA ); + err =__f2fs_commit_super (bh,F2FS_RAW_SUPER (sbi));brelse (bh); -return err; -} - -int f2fs_commit_super (struct f2fs_sb_info *sbi,bool recover) -{ -int err; - -/* write back-up superblock first */ - err =__f2fs_commit_super (sbi, sbi->valid_super_block ?0 :1 ); -/* if we are in recovery path, skip writing valid superblock */ if (recover || err)return err;/* write current valid superblock */ -return __f2fs_commit_super (sbi, sbi->valid_super_block); + bh =sb_getblk (sbi->sb, sbi->valid_super_block); +if (!bh) +return -EIO ; + err =__f2fs_commit_super (bh,F2FS_RAW_SUPER (sbi)); +brelse (bh); +return err; }static int f2fs_fill_super (struct super_block *sb,void *data,int silent)
Patches currently in stable-queue which might be from [email protected] are
queue-4.5/f2fs-cover-large-section-in-sanity-check-of-super.patch queue-4.5/f2fs-slightly-reorganize-read_raw_super_block.patch queue-4.5/f2fs-do-f2fs_balance_fs-when-block-is-allocated.patch queue-4.5/f2fs-don-t-need-to-call-set_page_dirty-for-io-error.patch queue-4.5/f2fs-crypto-handle-unexpected-lack-of-encryption-keys.patch queue-4.5/f2fs-crypto-fix-corrupted-symlink-in-encrypted-case.patch queue-4.5/f2fs-crypto-make-sure-the-encryption-info-is-initialized-on-opendir-2.patch queue-4.5/ext4-fscrypto-avoid-rcu-lookup-in-d_revalidate.patch