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
_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel