From mboxrd@z Thu Jan 1 00:00:00 1970 From: hujianyang Subject: [PATCH RFC] f2fs: recovering broken superblock during mount Date: Wed, 20 May 2015 15:01:04 +0800 Message-ID: <555C3130.9010205@huawei.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: Received: from sog-mx-3.v43.ch3.sourceforge.com ([172.29.43.193] helo=mx.sourceforge.net) by sfs-ml-2.v29.ch3.sourceforge.com with esmtp (Exim 4.76) (envelope-from ) id 1Yuy0R-0000vx-PM for linux-f2fs-devel@lists.sourceforge.net; Wed, 20 May 2015 07:01:31 +0000 Received: from szxga01-in.huawei.com ([58.251.152.64]) by sog-mx-3.v43.ch3.sourceforge.com with esmtps (TLSv1:RC4-SHA:128) (Exim 4.76) id 1Yuy0O-0003fS-PI for linux-f2fs-devel@lists.sourceforge.net; Wed, 20 May 2015 07:01:31 +0000 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linux-f2fs-devel-bounces@lists.sourceforge.net To: Jaegeuk Kim Cc: linux-f2fs-devel@lists.sourceforge.net Hi Jaegeuk, There are two superblocks in f2fs. I wrapped one of them by 'dd' in a reliability test. After this, the polluted f2fs partition can be mounted with an error message: F2FS-fs (sdd3): Magic Mismatch, valid(0xf2f52010) - read(0x0) F2FS-fs (sdd3): Can't find valid F2FS filesystem in 1th superblock Seems the broken superblock can't be recovered by f2fs driver or fsck.f2fs. Tell me how to recover if I was wrong.:) So I'd like to provide a patch to recover broken f2fs superblock during mount. But I'm not pleased with my patch. I wish you and others could give me some suggestions. Do you think it's necessary to recover the superblock? and can we change 'f2fs_commit_super' a little to reuse this function during superblock recovery? Thanks, Hu diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index ae14fc4..126f8fa 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -965,6 +965,33 @@ static void init_sb_info(struct f2fs_sb_info *sbi) clear_sbi_flag(sbi, SBI_NEED_FSCK); } +static int get_valid_super_block(struct super_block *sb, + struct buffer_head **buffer, int block) +{ + struct f2fs_super_block *super; + + *buffer = sb_bread(sb, block); + if (!*buffer) { + f2fs_msg(sb, KERN_ERR, "Unable to read %dth superblock", + block + 1); + return -EIO; + } + + super = (struct f2fs_super_block *) + ((char *)(*buffer)->b_data + F2FS_SUPER_OFFSET); + + /* sanity checking of raw super */ + if (sanity_check_raw_super(sb, super)) { + brelse(*buffer); + f2fs_msg(sb, KERN_ERR, + "Can't find valid F2FS filesystem in %dth superblock", + block + 1); + return -EINVAL; + } + + return 0; +} + /* * Read f2fs raw super block. * Because we have two copies of super block, so read the first one at first, @@ -975,37 +1002,41 @@ static int read_raw_super_block(struct super_block *sb, struct buffer_head **raw_super_buf) { int block = 0; - -retry: - *raw_super_buf = sb_bread(sb, block); - if (!*raw_super_buf) { - f2fs_msg(sb, KERN_ERR, "Unable to read %dth superblock", - block + 1); - if (block == 0) { - block++; - goto retry; - } else { - return -EIO; - } + struct buffer_head *buffer0 = NULL, *buffer1 = NULL; + bool readonly = f2fs_readonly(sb) || bdev_read_only(sb->s_bdev); + int err0, err1; + + err0 = get_valid_super_block(sb, &buffer0, 0); + if (!err0 && readonly) + goto set_raw_super; + + err1 = get_valid_super_block(sb, &buffer1, 1); + if (err0 && err1) + return err1; + + if (err0 && !err1) { + buffer0 = buffer1; + if (readonly) + goto set_raw_super; + } else if (!err0 && !err1) { + brelse(buffer1); + goto set_raw_super; } + f2fs_msg(sb, KERN_INFO, "Recover superblock"); + block = buffer0->b_blocknr; + buffer0->b_blocknr = block ? 0 : 1; + mark_buffer_dirty(buffer0); + sync_dirty_buffer(buffer0); + buffer0->b_blocknr = block; + clear_buffer_write_io_error(buffer0); + set_buffer_uptodate(buffer0); + +set_raw_super: + *raw_super_buf = buffer0; *raw_super = (struct f2fs_super_block *) ((char *)(*raw_super_buf)->b_data + F2FS_SUPER_OFFSET); - /* sanity checking of raw super */ - if (sanity_check_raw_super(sb, *raw_super)) { - brelse(*raw_super_buf); - f2fs_msg(sb, KERN_ERR, - "Can't find valid F2FS filesystem in %dth superblock", - block + 1); - if (block == 0) { - block++; - goto retry; - } else { - return -EINVAL; - } - } - return 0; } ------------------------------------------------------------------------------ One dashboard for servers and applications across Physical-Virtual-Cloud Widest out-of-the-box monitoring support with 50+ applications Performance metrics, stats and reports that give you Actionable Insights Deep dive visibility with transaction tracing using APM Insight. http://ad.doubleclick.net/ddm/clk/290420510;117567292;y