Re: [f2fs-dev] [PATCH] generic: add a testcase to test uid/gid recovery
On 2018/9/28 20:26, Eryu Guan wrote: > On Tue, Sep 25, 2018 at 04:45:58PM +0800, Chao Yu wrote: >> After fsync, filesystem should guarantee inode metadata including >> uid/gid being persisted, so even after sudden power-cut, durign >> mount, we should recover uid/gid fields correctly, in order to not >> loss those meta info. >> >> So adding this testcase to check whether generic filesystem can >> guarantee that. >> >> Signed-off-by: Chao Yu > > Looks good to me. Just two minor issues inline, and I'll just fix them > on commit. > >> --- >> tests/generic/505 | 95 +++ >> tests/generic/505.out | 2 + >> tests/generic/group | 1 + >> 3 files changed, 98 insertions(+) >> create mode 100755 tests/generic/505 >> create mode 100644 tests/generic/505.out >> >> diff --git a/tests/generic/505 b/tests/generic/505 >> new file mode 100755 >> index ..103a1e9bbe47 >> --- /dev/null >> +++ b/tests/generic/505 >> @@ -0,0 +1,95 @@ >> +#! /bin/bash >> +# SPDX-License-Identifier: GPL-2.0 >> +# Copyright (c) 2018 Huawei. All Rights Reserved. >> +# >> +# FS QA Test 505 >> +# >> +# This testcase is trying to test recovery flow of generic filesystem, w/ >> below >> +# steps, once uid or gid changes, after we fsync that file, we can expect >> that >> +# uid/gid can be recovered after sudden power-cuts. >> +# 1. touch testfile; >> +# 1.1 sync (optional) >> +# 2. chown 100 testfile; >> +# 3. chgrp 100 testfile; >> +# 4. xfs_io -f testfile -c "fsync"; >> +# 5. godown; >> +# 6. umount; >> +# 7. mount; >> +# 8. check uid/gid >> +# >> +seq=`basename $0` >> +seqres=$RESULT_DIR/$seq >> +echo "QA output created by $seq" >> + >> +here=`pwd` >> +tmp=/tmp/$$ >> +status=1# failure is the default! >> +trap "_cleanup; exit \$status" 0 1 2 3 15 >> + >> +_cleanup() >> +{ >> +cd / >> +rm -f $tmp.* >> +} >> + >> +# get standard environment, filters and checks >> +. ./common/rc >> +. ./common/filter >> + >> +# remove previous $seqres.full before test >> +rm -f $seqres.full >> + >> +# real QA test starts here >> +_supported_fs generic >> +_supported_os Linux >> + >> +_require_scratch >> +_require_scratch_shutdown >> + >> +_scratch_mkfs >/dev/null 2>&1 >> +_require_metadata_journaling $SCRATCH_DEV >> + >> +testfile=$SCRATCH_MNT/testfile >> +stat_opt='-c "uid: %u, gid: %g"' >> + >> +_do_check() > > Name local functions without the leading underscore, which usually > indicates it's a global helper function. Okay. > >> +{ >> +_scratch_mount >> + >> +touch $testfile >> + >> +if [ "$1" == "sync" ]; then >> +sync >> +fi >> + >> +chown 100 $testfile >> +chgrp 100 $testfile >> + >> +before=`stat "$stat_opt" $testfile` >> + >> +$XFS_IO_PROG -f $testfile -c "fsync" | _filter_xfs_io >> + >> +_scratch_shutdown | tee -a $seqres.full >> +_scratch_unmount >> +_scratch_mount > > _scratch_cycle_mount Yes, that's more clean, thanks. :) Thanks, > > Thanks, > Eryu > >> + >> +after=`stat "$stat_opt" $testfile` >> + >> +# check inode's uid/gid >> +if [ "$before" != "$after" ]; then >> +echo "Before: $before" >> +echo "After : $after" >> +fi >> +echo "Before: $before" >> $seqres.full >> +echo "After : $after" >> $seqres.full >> + >> +rm $testfile >> +_scratch_unmount >> +} >> + >> +_do_check >> +_do_check sync >> + >> +status=0 >> +echo "Silence is golden" >> +exit >> diff --git a/tests/generic/505.out b/tests/generic/505.out >> new file mode 100644 >> index ..80e3bd1d9abb >> --- /dev/null >> +++ b/tests/generic/505.out >> @@ -0,0 +1,2 @@ >> +QA output created by 505 >> +Silence is golden >> diff --git a/tests/generic/group b/tests/generic/group >> index 55155de8bc29..4da0e1888f57 100644 >> --- a/tests/generic/group >> +++ b/tests/generic/group >> @@ -507,3 +507,4 @@ >> 502 auto quick log >> 503 auto quick dax punch collapse zero >> 504 auto quick locks >> +505 shutdown auto quick metadata >> -- >> 2.18.0.rc1 >> > > . > ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH 1/2] f2fs: fix missing up_read
On 2018/9/29 1:48, Jaegeuk Kim wrote: > This patch fixes missing up_read call. I guess we need to add additional type of error injection to simulate on-disk blkaddr corruption, then we can cover all those error paths. > > Fixes: c9b60788fc76 ("f2fs: fix to do sanity check with block address in main > area") > Cc: # 4.19+ > Signed-off-by: Jaegeuk Kim Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [Bug 200871] F2FS experiences data loss (entry is completely lost) when an I/O failure occurs.
https://bugzilla.kernel.org/show_bug.cgi?id=200871 --- Comment #15 from Chao Yu (c...@kernel.org) --- diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 71f5953..1b5d391 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -114,6 +114,11 @@ static void f2fs_write_end_io(struct bio *bio) mapping_set_error(page->mapping, -EIO); if (type == F2FS_WB_CP_DATA) f2fs_stop_checkpoint(sbi, true); + printk("f2fs_write_end_io, ino:%lu, idx:%lu, eio:%d, type:%d\n", + page->mapping->host->i_ino, + page->index, + test_bit(AS_EIO, >mapping->flags), + type); } f2fs_bug_on(sbi, page->mapping == NODE_MAPPING(sbi) && diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 5907775..76ac293 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1912,6 +1912,8 @@ int f2fs_wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, } ret2 = filemap_check_errors(NODE_MAPPING(sbi)); + printk("f2fs_wait_on_node_pages_writeback, eio:%d\n", + test_bit(AS_EIO, _MAPPING(sbi)->flags)); if (!ret) ret = ret2; Could you help to add above code to reproduce this issue in your environment? -- You are receiving this mail because: You are watching the assignee of the bug. ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH] f2fs: fix quota info to adjust recovered data
Testing other fix. --- fs/f2fs/checkpoint.c | 7 +++ fs/f2fs/f2fs.h | 1 + fs/f2fs/gc.c | 10 +- fs/f2fs/super.c | 22 +- 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 524b87667cf4..3fde91f41a91 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -1494,6 +1494,7 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) { struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); unsigned long long ckpt_ver; + bool need_up = false; int err = 0; if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) { @@ -1506,6 +1507,10 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) f2fs_msg(sbi->sb, KERN_WARNING, "Start checkpoint disabled!"); } + if (!is_sbi_flag_set(sbi, SBI_QUOTA_INIT)) { + need_up = true; + down_read(>sb->s_umount); + } mutex_lock(>cp_mutex); if (!is_sbi_flag_set(sbi, SBI_IS_DIRTY) && @@ -1582,6 +1587,8 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "finish checkpoint"); out: mutex_unlock(>cp_mutex); + if (need_up) + up_read(>sb->s_umount); return err; } diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 57c829dd107e..30194f2f108e 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1096,6 +1096,7 @@ enum { SBI_IS_SHUTDOWN,/* shutdown by ioctl */ SBI_IS_RECOVERED, /* recovered orphan/data */ SBI_CP_DISABLED,/* CP was disabled last mount */ + SBI_QUOTA_INIT, /* avoid sb->s_umount lock */ SBI_QUOTA_NEED_FLUSH, /* need to flush quota info in CP */ SBI_QUOTA_SKIP_FLUSH, /* skip flushing quota in current CP */ SBI_QUOTA_NEED_REPAIR, /* quota file may be corrupted */ diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index adaf5a695b12..deece448cb3b 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -55,9 +55,14 @@ static int gc_thread_func(void *data) f2fs_stop_checkpoint(sbi, false); } - if (!sb_start_write_trylock(sbi->sb)) + if (!down_read_trylock(>sb->s_umount)) continue; + set_sbi_flag(sbi, SBI_QUOTA_INIT); + + if (!sb_start_write_trylock(sbi->sb)) + goto next_umount; + /* * [GC triggering condition] * 0. GC is not conducted currently. @@ -104,6 +109,9 @@ static int gc_thread_func(void *data) f2fs_balance_fs_bg(sbi); next: sb_end_write(sbi->sb); +next_umount: + clear_sbi_flag(sbi, SBI_QUOTA_INIT); + up_read(>sb->s_umount); } while (!kthread_should_stop()); return 0; diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index a28c245b1288..40a77a4eb465 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1029,6 +1029,8 @@ static void f2fs_put_super(struct super_block *sb) int i; bool dropped; + set_sbi_flag(sbi, SBI_QUOTA_INIT); + f2fs_quota_off_umount(sb); /* prevent remaining shrinker jobs */ @@ -1122,11 +1124,17 @@ int f2fs_sync_fs(struct super_block *sb, int sync) if (sync) { struct cp_control cpc; + bool keep = is_sbi_flag_set(sbi, SBI_QUOTA_INIT); cpc.reason = __get_cp_reason(sbi); mutex_lock(>gc_mutex); + if (sbi->sb->s_writers.frozen >= SB_FREEZE_WRITE) + set_sbi_flag(sbi, SBI_QUOTA_INIT); + err = f2fs_write_checkpoint(sbi, ); + if (!keep) + clear_sbi_flag(sbi, SBI_QUOTA_INIT); mutex_unlock(>gc_mutex); } f2fs_trace_ios(NULL, 1); @@ -1534,6 +1542,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) } } #endif + set_sbi_flag(sbi, SBI_QUOTA_INIT); /* recover superblocks we couldn't write due to previous RO mount */ if (!(*flags & SB_RDONLY) && is_sbi_flag_set(sbi, SBI_NEED_SB_WRITE)) { @@ -1653,6 +1662,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) (test_opt(sbi, POSIX_ACL) ? SB_POSIXACL : 0); limit_reserve_root(sbi); + clear_sbi_flag(sbi, SBI_QUOTA_INIT); *flags = (*flags & ~SB_LAZYTIME) | (sb->s_flags & SB_LAZYTIME); return 0; restore_gc: @@ -1673,6 +1683,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) #endif sbi->mount_opt = org_mount_opt; sb->s_flags =
[f2fs-dev] [PATCH 1/2] f2fs: fix missing up_read
This patch fixes missing up_read call. Fixes: c9b60788fc76 ("f2fs: fix to do sanity check with block address in main area") Cc: # 4.19+ Signed-off-by: Jaegeuk Kim --- fs/f2fs/node.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 3994b44541b4..acb819b8fc42 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1541,8 +1541,10 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, } if (__is_valid_data_blkaddr(ni.blk_addr) && - !f2fs_is_valid_blkaddr(sbi, ni.blk_addr, DATA_GENERIC)) + !f2fs_is_valid_blkaddr(sbi, ni.blk_addr, DATA_GENERIC)) { + up_read(>node_write); goto redirty_out; + } if (atomic && !test_opt(sbi, NOBARRIER)) fio.op_flags |= REQ_PREFLUSH | REQ_FUA; -- 2.19.0.605.g01d371f741-goog ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH 2/2] f2fs: keep lazytime on remount
This patch fixes losing lazytime when remounting f2fs. Signed-off-by: Jaegeuk Kim --- fs/f2fs/super.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 603386525336..74056fa064ff 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1655,6 +1655,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) limit_reserve_root(sbi); clear_sbi_flag(sbi, SBI_IS_MOUNT); + *flags = (*flags & ~SB_LAZYTIME) | (sb->s_flags & SB_LAZYTIME); return 0; restore_gc: if (need_restart_gc) { -- 2.19.0.605.g01d371f741-goog ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH] f2fs: fix quota info to adjust recovered data
On 09/27, Chao Yu wrote: > On 2018/9/26 10:09, Jaegeuk Kim wrote: > > Oh, yeah. :P > > I started to run all my tests with this. Let me see what will happen. > > Any updates of this test? Not a good result. I'm trying to fix some bug in your patch. Could you take a look at this? --- fs/f2fs/checkpoint.c | 8 fs/f2fs/f2fs.h | 1 + fs/f2fs/gc.c | 4 fs/f2fs/super.c | 12 +++- 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 524b87667cf4..b4b1586c683c 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -1494,6 +1494,7 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) { struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); unsigned long long ckpt_ver; + bool need_up = false; int err = 0; if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) { @@ -1506,6 +1507,11 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) f2fs_msg(sbi->sb, KERN_WARNING, "Start checkpoint disabled!"); } + if (!is_sbi_flag_set(sbi, SBI_IS_MOUNT) && + !is_sbi_flag_set(sbi, SBI_IS_CLOSE)) { + need_up = true; + down_read(>sb->s_umount); + } mutex_lock(>cp_mutex); if (!is_sbi_flag_set(sbi, SBI_IS_DIRTY) && @@ -1582,6 +1588,8 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "finish checkpoint"); out: mutex_unlock(>cp_mutex); + if (need_up) + up_read(>sb->s_umount); return err; } diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 57c829dd107e..461656aed78a 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1089,6 +1089,7 @@ struct inode_management { enum { SBI_IS_DIRTY, /* dirty flag for checkpoint */ SBI_IS_CLOSE, /* specify unmounting */ + SBI_IS_MOUNT, /* specify mounting */ SBI_NEED_FSCK, /* need fsck.f2fs to fix */ SBI_POR_DOING, /* recovery is doing or not */ SBI_NEED_SB_WRITE, /* need to recover superblock */ diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index adaf5a695b12..ee6dbd72ad8a 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -55,6 +55,9 @@ static int gc_thread_func(void *data) f2fs_stop_checkpoint(sbi, false); } + if (!down_read_trylock(>sb->s_umount)) + continue; + if (!sb_start_write_trylock(sbi->sb)) continue; @@ -104,6 +107,7 @@ static int gc_thread_func(void *data) f2fs_balance_fs_bg(sbi); next: sb_end_write(sbi->sb); + up_read(>sb->s_umount); } while (!kthread_should_stop()); return 0; diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 1d89d5e9e829..603386525336 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1534,6 +1534,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) } } #endif + set_sbi_flag(sbi, SBI_IS_MOUNT); /* recover superblocks we couldn't write due to previous RO mount */ if (!(*flags & SB_RDONLY) && is_sbi_flag_set(sbi, SBI_NEED_SB_WRITE)) { @@ -1653,6 +1654,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) (test_opt(sbi, POSIX_ACL) ? SB_POSIXACL : 0); limit_reserve_root(sbi); + clear_sbi_flag(sbi, SBI_IS_MOUNT); return 0; restore_gc: if (need_restart_gc) { @@ -1672,6 +1674,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) #endif sbi->mount_opt = org_mount_opt; sb->s_flags = old_sb_flags; + clear_sbi_flag(sbi, SBI_IS_MOUNT); return err; } @@ -1705,6 +1708,7 @@ static ssize_t f2fs_quota_read(struct super_block *sb, int type, char *data, congestion_wait(BLK_RW_ASYNC, HZ/50); goto repeat; } + set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); return PTR_ERR(page); } @@ -1716,6 +1720,7 @@ static ssize_t f2fs_quota_read(struct super_block *sb, int type, char *data, } if (unlikely(!PageUptodate(page))) { f2fs_put_page(page, 1); + set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); return -EIO; } @@ -1757,6 +1762,7 @@ static ssize_t f2fs_quota_write(struct super_block *sb, int type, congestion_wait(BLK_RW_ASYNC, HZ/50); goto
Re: [f2fs-dev] [PATCH v2] f2fs: checkpoint disabling
Note that, it requires "f2fs: return correct errno in f2fs_gc". This adds a lightweight non-persistent snapshotting scheme to f2fs. To use, mount with the option checkpoint=disable, and to return to normal operation, remount with checkpoint=enable. If the filesystem is shut down before remounting with checkpoint=enable, it will revert back to its apparent state when it was first mounted with checkpoint=disable. This is useful for situations where you wish to be able to roll back the state of the disk in case of some critical failure. Signed-off-by: Daniel Rosenberg Signed-off-by: Jaegeuk Kim --- Change log from v1: - fix fsync loop Documentation/filesystems/f2fs.txt | 5 ++ fs/f2fs/checkpoint.c | 16 fs/f2fs/data.c | 14 +++- fs/f2fs/debug.c| 3 +- fs/f2fs/f2fs.h | 15 +++- fs/f2fs/file.c | 12 ++- fs/f2fs/gc.c | 9 ++- fs/f2fs/inode.c| 6 +- fs/f2fs/namei.c| 19 + fs/f2fs/segment.c | 75 +- fs/f2fs/segment.h | 15 fs/f2fs/super.c| 118 - include/linux/f2fs_fs.h| 1 + 13 files changed, 294 insertions(+), 14 deletions(-) diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt index bde3e91e5372..e46c2147ddf8 100644 --- a/Documentation/filesystems/f2fs.txt +++ b/Documentation/filesystems/f2fs.txt @@ -212,6 +212,11 @@ fsync_mode=%s Control the policy of fsync. Currently supports "posix", non-atomic files likewise "nobarrier" mount option. test_dummy_encryption Enable dummy encryption, which provides a fake fscrypt context. The fake fscrypt context is used by xfstests. +checkpoint=%s Set to "disable" to turn off checkpointing. Set to "enable" + to reenable checkpointing. Is enabled by default. While + disabled, any unmounting or unexpected shutdowns will cause + the filesystem contents to appear as they did when the + filesystem was mounted with that option. DEBUGFS ENTRIES diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index d312d2829d5a..01e0d8f5bbbe 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -1214,6 +1214,11 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc) if (is_sbi_flag_set(sbi, SBI_NEED_FSCK)) __set_ckpt_flags(ckpt, CP_FSCK_FLAG); + if (is_sbi_flag_set(sbi, SBI_CP_DISABLED)) + __set_ckpt_flags(ckpt, CP_DISABLED_FLAG); + else + __clear_ckpt_flags(ckpt, CP_DISABLED_FLAG); + /* set this flag to activate crc|cp_ver for recovery */ __set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG); __clear_ckpt_flags(ckpt, CP_NOCRC_RECOVERY_FLAG); @@ -1421,6 +1426,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) clear_sbi_flag(sbi, SBI_IS_DIRTY); clear_sbi_flag(sbi, SBI_NEED_CP); + sbi->unusable_block_count = 0; __set_cp_next_pack(sbi); /* @@ -1445,6 +1451,16 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) unsigned long long ckpt_ver; int err = 0; + if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) { + if (cpc->reason != CP_PAUSE) { + if (cpc->reason != CP_UMOUNT) + f2fs_msg(sbi->sb, KERN_WARNING, + "Wrong disabled checkpoint!"); + return 0; + } + f2fs_msg(sbi->sb, KERN_WARNING, + "Start checkpoint disabled!"); + } mutex_lock(>cp_mutex); if (!is_sbi_flag_set(sbi, SBI_IS_DIRTY) && diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index cb3ebcae0398..dc66c1948d8c 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -537,7 +537,8 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio) if (fio->in_list) goto next; out: - if (is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN)) + if (is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN) || + f2fs_is_checkpoint_ready(sbi)) __submit_merged_bio(io); up_write(>io_rwsem); } @@ -1695,6 +1696,10 @@ static inline bool check_inplace_update_policy(struct inode *inode, is_inode_flag_set(inode, FI_NEED_IPU)) return true; + if (unlikely(fio && is_sbi_flag_set(sbi, SBI_CP_DISABLED) && + !f2fs_is_checkpointed_data(sbi, fio->old_blkaddr))) + return true; + return false; } @@ -1725,6 +1730,9 @@
Re: [f2fs-dev] [PATCH] generic: add a testcase to test uid/gid recovery
On Tue, Sep 25, 2018 at 05:16:31PM +0800, Chao Yu wrote: > Hi Eryu, > > There are several fields in inode rather than uid/gid didn't recover in > f2fs, I'm not sure we need to cover all of them with one generic testcase, > or with several testcases. Any suggestion? Sorry for the late response! Several targeted test cases would be fine. Thanks, Eryu ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH v2 3/5] fsck.f2fs: unify the updating of superblocks
Rename write_superblock() to update_superblock() and make it support updating specified one superblock or both two superblocks, then unify all places where sb needs to be updated. Signed-off-by: Junling Zheng --- Change log from v1: - Rename enum SB_ADDR members and define SB_MASK(i). fsck/fsck.h | 12 ++- fsck/mount.c | 94 +++ fsck/resize.c | 20 ++- 3 files changed, 47 insertions(+), 79 deletions(-) diff --git a/fsck/fsck.h b/fsck/fsck.h index 6042e68..bdd7f8d 100644 --- a/fsck/fsck.h +++ b/fsck/fsck.h @@ -32,6 +32,15 @@ enum { EUNKNOWN_ARG, }; +enum SB_ADDR { + SB0_ADDR = 0, + SB1_ADDR, + SB_MAX_ADDR, +}; + +#define SB_MASK(i) (1 << i) +#define SB_MASK_ALL(SB_MASK(SB0_ADDR) | SB_MASK(SB1_ADDR)) + /* fsck.c */ struct orphan_info { u32 nr_inodes; @@ -178,7 +188,7 @@ extern void move_curseg_info(struct f2fs_sb_info *, u64, int); extern void write_curseg_info(struct f2fs_sb_info *); extern int find_next_free_block(struct f2fs_sb_info *, u64 *, int, int); extern void write_checkpoint(struct f2fs_sb_info *); -extern void write_superblock(struct f2fs_super_block *); +extern void update_superblock(struct f2fs_super_block *, int); extern void update_data_blkaddr(struct f2fs_sb_info *, nid_t, u16, block_t); extern void update_nat_blkaddr(struct f2fs_sb_info *, nid_t, nid_t, block_t); diff --git a/fsck/mount.c b/fsck/mount.c index 1daef75..74ff7c6 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -475,8 +475,28 @@ void print_sb_state(struct f2fs_super_block *sb) MSG(0, "\n"); } +void update_superblock(struct f2fs_super_block *sb, int sb_mask) +{ + int addr, ret; + u_int8_t *buf; + + buf = calloc(BLOCK_SZ, 1); + ASSERT(buf); + + memcpy(buf + F2FS_SUPER_OFFSET, sb, sizeof(*sb)); + for (addr = SB0_ADDR; addr < SB_MAX_ADDR; addr++) { + if (SB_MASK(addr) & sb_mask) { + ret = dev_write_block(buf, addr); + ASSERT(ret >= 0); + } + } + + free(buf); + DBG(0, "Info: Done to update superblock\n"); +} + static inline int sanity_check_area_boundary(struct f2fs_super_block *sb, - u64 offset) + enum SB_ADDR sb_addr) { u32 segment0_blkaddr = get_sb(segment0_blkaddr); u32 cp_blkaddr = get_sb(cp_blkaddr); @@ -542,14 +562,11 @@ static inline int sanity_check_area_boundary(struct f2fs_super_block *sb, segment_count_main << log_blocks_per_seg); return -1; } else if (main_end_blkaddr < seg_end_blkaddr) { - int err; - set_sb(segment_count, (main_end_blkaddr - segment0_blkaddr) >> log_blocks_per_seg); - err = dev_write(sb, offset, sizeof(struct f2fs_super_block)); - MSG(0, "Info: Fix alignment: %s, start(%u) end(%u) block(%u)\n", - err ? "failed": "done", + update_superblock(sb, SB_MASK(sb_addr)); + MSG(0, "Info: Fix alignment: start(%u) end(%u) block(%u)\n", main_blkaddr, segment0_blkaddr + (segment_count << log_blocks_per_seg), @@ -558,7 +575,7 @@ static inline int sanity_check_area_boundary(struct f2fs_super_block *sb, return 0; } -int sanity_check_raw_super(struct f2fs_super_block *sb, u64 offset) +int sanity_check_raw_super(struct f2fs_super_block *sb, enum SB_ADDR sb_addr) { unsigned int blocksize; @@ -600,30 +617,24 @@ int sanity_check_raw_super(struct f2fs_super_block *sb, u64 offset) if (get_sb(segment_count) > F2FS_MAX_SEGMENT) return -1; - if (sanity_check_area_boundary(sb, offset)) + if (sanity_check_area_boundary(sb, sb_addr)) return -1; return 0; } -int validate_super_block(struct f2fs_sb_info *sbi, int block) +int validate_super_block(struct f2fs_sb_info *sbi, enum SB_ADDR sb_addr) { - u64 offset; char buf[F2FS_BLKSIZE]; sbi->raw_super = malloc(sizeof(struct f2fs_super_block)); - if (block == 0) - offset = F2FS_SUPER_OFFSET; - else - offset = F2FS_BLKSIZE + F2FS_SUPER_OFFSET; - - if (dev_read_block(buf, block)) + if (dev_read_block(buf, sb_addr)) return -1; memcpy(sbi->raw_super, buf + F2FS_SUPER_OFFSET, sizeof(struct f2fs_super_block)); - if (!sanity_check_raw_super(sbi->raw_super, offset)) { + if (!sanity_check_raw_super(sbi->raw_super, sb_addr)) { /* get kernel version */ if (c.kd >= 0) { dev_read_version(c.version, 0, VERSION_LEN); @@ -642,13 +653,9 @@ int
[f2fs-dev] [PATCH 2/5] f2fs-tools: rename CHECKSUM_OFFSET to CP_CHKSUM_OFFSET
This patch renamed CHECKSUM_OFFSET to CP_CHKSUM_OFFSET. Reviewed-by: Chao Yu Signed-off-by: Junling Zheng --- fsck/fsck.c| 4 ++-- fsck/mount.c | 4 ++-- fsck/resize.c | 8 include/f2fs_fs.h | 6 +++--- mkfs/f2fs_format.c | 14 +++--- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index d550403..f080d3c 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -2010,8 +2010,8 @@ static void fix_checkpoint(struct f2fs_sb_info *sbi) set_cp(valid_node_count, fsck->chk.valid_node_cnt); set_cp(valid_inode_count, fsck->chk.valid_inode_cnt); - crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, cp, CHECKSUM_OFFSET); - *((__le32 *)((unsigned char *)cp + CHECKSUM_OFFSET)) = cpu_to_le32(crc); + crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, cp, CP_CHKSUM_OFFSET); + *((__le32 *)((unsigned char *)cp + CP_CHKSUM_OFFSET)) = cpu_to_le32(crc); cp_blk_no = get_sb(cp_blkaddr); if (sbi->cur_cp == 2) diff --git a/fsck/mount.c b/fsck/mount.c index 2c2473d..1daef75 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -2252,8 +2252,8 @@ void write_checkpoint(struct f2fs_sb_info *sbi) flags = update_nat_bits_flags(sb, cp, flags); set_cp(ckpt_flags, flags); - crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, cp, CHECKSUM_OFFSET); - *((__le32 *)((unsigned char *)cp + CHECKSUM_OFFSET)) = cpu_to_le32(crc); + crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, cp, CP_CHKSUM_OFFSET); + *((__le32 *)((unsigned char *)cp + CP_CHKSUM_OFFSET)) = cpu_to_le32(crc); cp_blk_no = get_sb(cp_blkaddr); if (sbi->cur_cp == 2) diff --git a/fsck/resize.c b/fsck/resize.c index fe8a61a..e9612b3 100644 --- a/fsck/resize.c +++ b/fsck/resize.c @@ -90,10 +90,10 @@ static int get_new_sb(struct f2fs_super_block *sb) * It requires more pages for cp. */ if (max_sit_bitmap_size > MAX_SIT_BITMAP_SIZE_IN_CKPT) { - max_nat_bitmap_size = CHECKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1; + max_nat_bitmap_size = CP_CHKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1; set_sb(cp_payload, F2FS_BLK_ALIGN(max_sit_bitmap_size)); } else { - max_nat_bitmap_size = CHECKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1 + max_nat_bitmap_size = CP_CHKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1 - max_sit_bitmap_size; set_sb(cp_payload, 0); } @@ -520,8 +520,8 @@ static void rebuild_checkpoint(struct f2fs_sb_info *sbi, (unsigned char *)cp); new_cp->checkpoint_ver = cpu_to_le64(cp_ver + 1); - crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, new_cp, CHECKSUM_OFFSET); - *((__le32 *)((unsigned char *)new_cp + CHECKSUM_OFFSET)) = + crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, new_cp, CP_CHKSUM_OFFSET); + *((__le32 *)((unsigned char *)new_cp + CP_CHKSUM_OFFSET)) = cpu_to_le32(crc); /* Write a new checkpoint in the other set */ diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index 2c086a9..38a0da4 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -278,7 +278,7 @@ static inline uint64_t bswap_64(uint64_t val) #define PAGE_CACHE_SIZE4096 #define BITS_PER_BYTE 8 #define F2FS_SUPER_MAGIC 0xF2F52010 /* F2FS Magic Number */ -#define CHECKSUM_OFFSET4092 +#define CP_CHKSUM_OFFSET 4092 #define MAX_PATH_LEN 64 #define MAX_DEVICES8 @@ -682,9 +682,9 @@ struct f2fs_checkpoint { } __attribute__((packed)); #define MAX_SIT_BITMAP_SIZE_IN_CKPT\ - (CHECKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1 - 64) + (CP_CHKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1 - 64) #define MAX_BITMAP_SIZE_IN_CKPT\ - (CHECKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1) + (CP_CHKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1) /* * For orphan inode management diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c index 4b88d93..621126c 100644 --- a/mkfs/f2fs_format.c +++ b/mkfs/f2fs_format.c @@ -342,12 +342,12 @@ static int f2fs_prepare_super_block(void) * It requires more pages for cp. */ if (max_sit_bitmap_size > MAX_SIT_BITMAP_SIZE_IN_CKPT) { - max_nat_bitmap_size = CHECKSUM_OFFSET - + max_nat_bitmap_size = CP_CHKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1; set_sb(cp_payload, F2FS_BLK_ALIGN(max_sit_bitmap_size)); } else { max_nat_bitmap_size = - CHECKSUM_OFFSET - sizeof(struct f2fs_checkpoint) + 1 +
Re: [f2fs-dev] [PATCH] generic: add a testcase to test uid/gid recovery
On Tue, Sep 25, 2018 at 04:45:58PM +0800, Chao Yu wrote: > After fsync, filesystem should guarantee inode metadata including > uid/gid being persisted, so even after sudden power-cut, durign > mount, we should recover uid/gid fields correctly, in order to not > loss those meta info. > > So adding this testcase to check whether generic filesystem can > guarantee that. > > Signed-off-by: Chao Yu Looks good to me. Just two minor issues inline, and I'll just fix them on commit. > --- > tests/generic/505 | 95 +++ > tests/generic/505.out | 2 + > tests/generic/group | 1 + > 3 files changed, 98 insertions(+) > create mode 100755 tests/generic/505 > create mode 100644 tests/generic/505.out > > diff --git a/tests/generic/505 b/tests/generic/505 > new file mode 100755 > index ..103a1e9bbe47 > --- /dev/null > +++ b/tests/generic/505 > @@ -0,0 +1,95 @@ > +#! /bin/bash > +# SPDX-License-Identifier: GPL-2.0 > +# Copyright (c) 2018 Huawei. All Rights Reserved. > +# > +# FS QA Test 505 > +# > +# This testcase is trying to test recovery flow of generic filesystem, w/ > below > +# steps, once uid or gid changes, after we fsync that file, we can expect > that > +# uid/gid can be recovered after sudden power-cuts. > +# 1. touch testfile; > +# 1.1 sync (optional) > +# 2. chown 100 testfile; > +# 3. chgrp 100 testfile; > +# 4. xfs_io -f testfile -c "fsync"; > +# 5. godown; > +# 6. umount; > +# 7. mount; > +# 8. check uid/gid > +# > +seq=`basename $0` > +seqres=$RESULT_DIR/$seq > +echo "QA output created by $seq" > + > +here=`pwd` > +tmp=/tmp/$$ > +status=1 # failure is the default! > +trap "_cleanup; exit \$status" 0 1 2 3 15 > + > +_cleanup() > +{ > + cd / > + rm -f $tmp.* > +} > + > +# get standard environment, filters and checks > +. ./common/rc > +. ./common/filter > + > +# remove previous $seqres.full before test > +rm -f $seqres.full > + > +# real QA test starts here > +_supported_fs generic > +_supported_os Linux > + > +_require_scratch > +_require_scratch_shutdown > + > +_scratch_mkfs >/dev/null 2>&1 > +_require_metadata_journaling $SCRATCH_DEV > + > +testfile=$SCRATCH_MNT/testfile > +stat_opt='-c "uid: %u, gid: %g"' > + > +_do_check() Name local functions without the leading underscore, which usually indicates it's a global helper function. > +{ > + _scratch_mount > + > + touch $testfile > + > + if [ "$1" == "sync" ]; then > + sync > + fi > + > + chown 100 $testfile > + chgrp 100 $testfile > + > + before=`stat "$stat_opt" $testfile` > + > + $XFS_IO_PROG -f $testfile -c "fsync" | _filter_xfs_io > + > + _scratch_shutdown | tee -a $seqres.full > + _scratch_unmount > + _scratch_mount _scratch_cycle_mount Thanks, Eryu > + > + after=`stat "$stat_opt" $testfile` > + > + # check inode's uid/gid > + if [ "$before" != "$after" ]; then > + echo "Before: $before" > + echo "After : $after" > + fi > + echo "Before: $before" >> $seqres.full > + echo "After : $after" >> $seqres.full > + > + rm $testfile > + _scratch_unmount > +} > + > +_do_check > +_do_check sync > + > +status=0 > +echo "Silence is golden" > +exit > diff --git a/tests/generic/505.out b/tests/generic/505.out > new file mode 100644 > index ..80e3bd1d9abb > --- /dev/null > +++ b/tests/generic/505.out > @@ -0,0 +1,2 @@ > +QA output created by 505 > +Silence is golden > diff --git a/tests/generic/group b/tests/generic/group > index 55155de8bc29..4da0e1888f57 100644 > --- a/tests/generic/group > +++ b/tests/generic/group > @@ -507,3 +507,4 @@ > 502 auto quick log > 503 auto quick dax punch collapse zero > 504 auto quick locks > +505 shutdown auto quick metadata > -- > 2.18.0.rc1 > ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH 4/5] f2fs-tools: introduce sb checksum
This patch introduced crc for superblock. Signed-off-by: Junling Zheng --- fsck/mount.c | 33 + fsck/resize.c | 12 ++-- include/f2fs_fs.h | 6 +- mkfs/f2fs_format.c | 8 4 files changed, 52 insertions(+), 7 deletions(-) diff --git a/fsck/mount.c b/fsck/mount.c index 74ff7c6..9019921 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -340,6 +340,7 @@ void print_raw_sb_info(struct f2fs_super_block *sb) DISP_u32(sb, node_ino); DISP_u32(sb, meta_ino); DISP_u32(sb, cp_payload); + DISP_u32(sb, crc); DISP("%-.256s", sb, version); printf("\n"); } @@ -467,6 +468,9 @@ void print_sb_state(struct f2fs_super_block *sb) if (f & cpu_to_le32(F2FS_FEATURE_LOST_FOUND)) { MSG(0, "%s", " lost_found"); } + if (f & cpu_to_le32(F2FS_FEATURE_SB_CHKSUM)) { + MSG(0, "%s", " sb_checksum"); + } MSG(0, "\n"); MSG(0, "Info: superblock encrypt level = %d, salt = ", sb->encryption_level); @@ -479,10 +483,20 @@ void update_superblock(struct f2fs_super_block *sb, int sb_mask) { int addr, ret; u_int8_t *buf; + u32 old_crc, new_crc; buf = calloc(BLOCK_SZ, 1); ASSERT(buf); + if (get_sb(feature) & F2FS_FEATURE_SB_CHKSUM) { + old_crc = get_sb(crc); + new_crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, sb, + SB_CHKSUM_OFFSET); + set_sb(crc, new_crc); + MSG(1, "Info: SB CRC is updated (0x%x -> 0x%x)\n", + old_crc, new_crc); + } + memcpy(buf + F2FS_SUPER_OFFSET, sb, sizeof(*sb)); for (addr = SB0_ADDR; addr < SB_MAX_ADDR; addr++) { if (SB_MASK(addr) & sb_mask) { @@ -575,10 +589,29 @@ static inline int sanity_check_area_boundary(struct f2fs_super_block *sb, return 0; } +static int verify_sb_chksum(struct f2fs_super_block *sb) +{ + if (SB_CHKSUM_OFFSET != get_sb(checksum_offset)) { + MSG(0, "\tInvalid SB CRC offset: %u\n", + get_sb(checksum_offset)); + return -1; + } + if (f2fs_crc_valid(get_sb(crc), sb, + get_sb(checksum_offset))) { + MSG(0, "\tInvalid SB CRC: 0x%x\n", get_sb(crc)); + return -1; + } + return 0; +} + int sanity_check_raw_super(struct f2fs_super_block *sb, enum SB_ADDR sb_addr) { unsigned int blocksize; + if ((get_sb(feature) & F2FS_FEATURE_SB_CHKSUM) && + verify_sb_chksum(sb)) + return -1; + if (F2FS_SUPER_MAGIC != get_sb(magic)) return -1; diff --git a/fsck/resize.c b/fsck/resize.c index 5161a1f..3462165 100644 --- a/fsck/resize.c +++ b/fsck/resize.c @@ -603,9 +603,6 @@ static int f2fs_resize_grow(struct f2fs_sb_info *sbi) } } - print_raw_sb_info(sb); - print_raw_sb_info(new_sb); - old_main_blkaddr = get_sb(main_blkaddr); new_main_blkaddr = get_newsb(main_blkaddr); offset = new_main_blkaddr - old_main_blkaddr; @@ -629,6 +626,9 @@ static int f2fs_resize_grow(struct f2fs_sb_info *sbi) migrate_sit(sbi, new_sb, offset_seg); rebuild_checkpoint(sbi, new_sb, offset_seg); update_superblock(new_sb, SB_MASK_ALL); + print_raw_sb_info(sb); + print_raw_sb_info(new_sb); + return 0; } @@ -658,9 +658,6 @@ static int f2fs_resize_shrink(struct f2fs_sb_info *sbi) } } - print_raw_sb_info(sb); - print_raw_sb_info(new_sb); - old_main_blkaddr = get_sb(main_blkaddr); new_main_blkaddr = get_newsb(main_blkaddr); offset = old_main_blkaddr - new_main_blkaddr; @@ -690,6 +687,9 @@ static int f2fs_resize_shrink(struct f2fs_sb_info *sbi) /* move whole data region */ //if (err) // migrate_main(sbi, offset); + print_raw_sb_info(sb); + print_raw_sb_info(new_sb); + return 0; } diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index 38a0da4..f80632a 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -279,6 +279,7 @@ static inline uint64_t bswap_64(uint64_t val) #define BITS_PER_BYTE 8 #define F2FS_SUPER_MAGIC 0xF2F52010 /* F2FS Magic Number */ #define CP_CHKSUM_OFFSET 4092 +#define SB_CHKSUM_OFFSET 3068 #define MAX_PATH_LEN 64 #define MAX_DEVICES8 @@ -579,6 +580,7 @@ enum { #define F2FS_FEATURE_INODE_CRTIME 0x0100 #define F2FS_FEATURE_LOST_FOUND0x0200 #define F2FS_FEATURE_VERITY0x0400 /* reserved */ +#define F2FS_FEATURE_SB_CHKSUM 0x0800 #define MAX_VOLUME_NAME512 @@ -632,7 +634,8 @@ struct f2fs_super_block {
[f2fs-dev] [PATCH 1/5] f2fs: support superblock checksum
Now we support crc32 checksum for superblock. Reviewed-by: Chao Yu Signed-off-by: Junling Zheng --- fs/f2fs/f2fs.h | 2 ++ fs/f2fs/super.c | 29 + fs/f2fs/sysfs.c | 7 +++ include/linux/f2fs_fs.h | 3 ++- 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 4525f4f82af0..d50d6efda96b 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -147,6 +147,7 @@ struct f2fs_mount_info { #define F2FS_FEATURE_INODE_CRTIME 0x0100 #define F2FS_FEATURE_LOST_FOUND0x0200 #define F2FS_FEATURE_VERITY0x0400 /* reserved */ +#define F2FS_FEATURE_SB_CHKSUM 0x0800 #define F2FS_HAS_FEATURE(sb, mask) \ ((F2FS_SB(sb)->raw_super->feature & cpu_to_le32(mask)) != 0) @@ -3376,6 +3377,7 @@ F2FS_FEATURE_FUNCS(flexible_inline_xattr, FLEXIBLE_INLINE_XATTR); F2FS_FEATURE_FUNCS(quota_ino, QUOTA_INO); F2FS_FEATURE_FUNCS(inode_crtime, INODE_CRTIME); F2FS_FEATURE_FUNCS(lost_found, LOST_FOUND); +F2FS_FEATURE_FUNCS(sb_chksum, SB_CHKSUM); #ifdef CONFIG_BLK_DEV_ZONED static inline int get_blkz_type(struct f2fs_sb_info *sbi, diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index bd57be470e23..3ffc336caea8 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -2149,6 +2149,26 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, (bh->b_data + F2FS_SUPER_OFFSET); struct super_block *sb = sbi->sb; unsigned int blocksize; + size_t crc_offset = 0; + __u32 crc = 0; + + /* Check checksum_offset and crc in superblock */ + if (le32_to_cpu(raw_super->feature) & F2FS_FEATURE_SB_CHKSUM) { + crc_offset = le32_to_cpu(raw_super->checksum_offset); + if (crc_offset != + offsetof(struct f2fs_super_block, crc)) { + f2fs_msg(sb, KERN_INFO, + "Invalid SB checksum offset: %zu", + crc_offset); + return 1; + } + crc = le32_to_cpu(raw_super->crc); + if (!f2fs_crc_valid(sbi, crc, raw_super, crc_offset)) { + f2fs_msg(sb, KERN_INFO, + "Invalid SB checksum value: %u", crc); + return 1; + } + } if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic)) { f2fs_msg(sb, KERN_INFO, @@ -2568,6 +2588,7 @@ static int read_raw_super_block(struct f2fs_sb_info *sbi, int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover) { struct buffer_head *bh; + __u32 crc = 0; int err; if ((recover && f2fs_readonly(sbi->sb)) || @@ -2576,6 +2597,13 @@ int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover) return -EROFS; } + /* we should update superblock crc here */ + if (!recover && f2fs_sb_has_sb_chksum(sbi->sb)) { + crc = f2fs_crc32(sbi, F2FS_RAW_SUPER(sbi), + offsetof(struct f2fs_super_block, crc)); + F2FS_RAW_SUPER(sbi)->crc = cpu_to_le32(crc); + } + /* write back-up superblock first */ bh = sb_bread(sbi->sb, sbi->valid_super_block ? 0 : 1); if (!bh) diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c index cd2e030e47b8..c86d91be6c48 100644 --- a/fs/f2fs/sysfs.c +++ b/fs/f2fs/sysfs.c @@ -120,6 +120,9 @@ static ssize_t features_show(struct f2fs_attr *a, if (f2fs_sb_has_lost_found(sb)) len += snprintf(buf + len, PAGE_SIZE - len, "%s%s", len ? ", " : "", "lost_found"); + if (f2fs_sb_has_sb_chksum(sb)) + len += snprintf(buf + len, PAGE_SIZE - len, "%s%s", + len ? ", " : "", "sb_checksum"); len += snprintf(buf + len, PAGE_SIZE - len, "\n"); return len; } @@ -337,6 +340,7 @@ enum feat_id { FEAT_QUOTA_INO, FEAT_INODE_CRTIME, FEAT_LOST_FOUND, + FEAT_SB_CHECKSUM, }; static ssize_t f2fs_feature_show(struct f2fs_attr *a, @@ -353,6 +357,7 @@ static ssize_t f2fs_feature_show(struct f2fs_attr *a, case FEAT_QUOTA_INO: case FEAT_INODE_CRTIME: case FEAT_LOST_FOUND: + case FEAT_SB_CHECKSUM: return snprintf(buf, PAGE_SIZE, "supported\n"); } return 0; @@ -433,6 +438,7 @@ F2FS_FEATURE_RO_ATTR(flexible_inline_xattr, FEAT_FLEXIBLE_INLINE_XATTR); F2FS_FEATURE_RO_ATTR(quota_ino, FEAT_QUOTA_INO); F2FS_FEATURE_RO_ATTR(inode_crtime, FEAT_INODE_CRTIME); F2FS_FEATURE_RO_ATTR(lost_found, FEAT_LOST_FOUND); +F2FS_FEATURE_RO_ATTR(sb_checksum, FEAT_SB_CHECKSUM); #define ATTR_LIST(name) (_attr_##name.attr) static struct attribute *f2fs_attrs[] = { @@ -489,6 +495,7 @@ static struct attribute *f2fs_feat_attrs[] = { ATTR_LIST(quota_ino),
[f2fs-dev] [PATCH 5/5] fsck.f2fs: try to recover cp_payload from valid cp pack
From: Chao Yu If sb checksum is not enabled, and cp pack is valid due to no crc inconsistence, let's try to recover cp_payload based on cp_pack_start_sum in cp pack. Signed-off-by: Chao Yu --- fsck/f2fs.h | 5 + fsck/mount.c | 10 +++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/fsck/f2fs.h b/fsck/f2fs.h index d216444..0d0d5e2 100644 --- a/fsck/f2fs.h +++ b/fsck/f2fs.h @@ -259,6 +259,11 @@ static inline unsigned long __bitmap_size(struct f2fs_sb_info *sbi, int flag) return 0; } +static inline block_t __cp_payload(struct f2fs_sb_info *sbi) +{ + return le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload); +} + static inline void *__bitmap_ptr(struct f2fs_sb_info *sbi, int flag) { struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); diff --git a/fsck/mount.c b/fsck/mount.c index 9019921..0e8fa41 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -975,12 +975,16 @@ int sanity_check_ckpt(struct f2fs_sb_info *sbi) } cp_pack_start_sum = __start_sum_addr(sbi); - cp_payload = get_sb(cp_payload); + cp_payload = __cp_payload(sbi); if (cp_pack_start_sum < cp_payload + 1 || cp_pack_start_sum > blocks_per_seg - 1 - NR_CURSEG_TYPE) { - MSG(0, "\tWrong cp_pack_start_sum(%u)\n", cp_pack_start_sum); - return 1; + MSG(0, "\tWrong cp_pack_start_sum(%u) or cp_payload(%u)\n", + cp_pack_start_sum, cp_payload); + if ((get_sb(feature) & F2FS_FEATURE_SB_CHKSUM)) + return 1; + set_sb(cp_payload, cp_pack_start_sum - 1); + update_superblock(sb, SB_MASK_ALL); } return 0; -- 2.19.0 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH 1/2] f2fs: clear PageError on the read path
On 2018-9-26 9:46, Jaegeuk Kim wrote: > When running fault injection test, I hit somewhat wrong behavior in f2fs_gc -> > gc_data_segment(): > > 0. fault injection generated some PageError'ed pages > > 1. gc_data_segment > -> f2fs_get_read_data_page(REQ_RAHEAD) > > 2. move_data_page > -> f2fs_get_lock_data_page() > -> f2f_get_read_data_page() >-> f2fs_submit_page_read() > -> submit_bio(READ) > -> return EIO due to PageError > -> fail to move data > > Signed-off-by: Jaegeuk Kim > --- > fs/f2fs/data.c | 5 - > 1 file changed, 4 insertions(+), 1 deletion(-) > > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c > index 41102c227eee..cb3ebcae0398 100644 > --- a/fs/f2fs/data.c > +++ b/fs/f2fs/data.c > @@ -77,7 +77,8 @@ static void __read_end_io(struct bio *bio) > /* PG_error was set if any post_read step failed */ > if (bio->bi_status || PageError(page)) { > ClearPageUptodate(page); > - SetPageError(page); > + /* will re-read again later */ > + ClearPageError(page); > } else { > SetPageUptodate(page); How about: if (PaegeError(page)) ClearPageError(page); if (bio->bi_status) { ClearPageUptodate(page); SetPageError(page); } else { SetPageUptodate(page); ClearPageError(page); } So that below codes are not needed. Thanks, > } > @@ -591,6 +592,7 @@ static int f2fs_submit_page_read(struct inode *inode, > struct page *page, > bio_put(bio); > return -EFAULT; > } > + ClearPageError(page); > __submit_bio(F2FS_I_SB(inode), bio, DATA); > return 0; > } > @@ -1571,6 +1573,7 @@ static int f2fs_mpage_readpages(struct address_space > *mapping, > if (bio_add_page(bio, page, blocksize, 0) < blocksize) > goto submit_and_realloc; > > + ClearPageError(page); > last_block_in_bio = block_nr; > goto next_page; > set_error_page: > ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH 2/2] f2fs: return correct errno in f2fs_gc
On 2018/9/26 9:46, Jaegeuk Kim wrote: > This fixes overriding error number in f2fs_gc. > > Signed-off-by: Jaegeuk Kim Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel