Re: [f2fs-dev] [PATCH] generic: add a testcase to test uid/gid recovery

2018-09-28 Thread Chao Yu
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

2018-09-28 Thread Chao Yu
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.

2018-09-28 Thread bugzilla-daemon
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

2018-09-28 Thread Jaegeuk Kim
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

2018-09-28 Thread Jaegeuk Kim
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

2018-09-28 Thread Jaegeuk Kim
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

2018-09-28 Thread Jaegeuk Kim
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

2018-09-28 Thread Jaegeuk Kim
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

2018-09-28 Thread Eryu Guan
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

2018-09-28 Thread Junling Zheng
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

2018-09-28 Thread Junling Zheng
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

2018-09-28 Thread Eryu Guan
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

2018-09-28 Thread Junling Zheng
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

2018-09-28 Thread Junling Zheng
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

2018-09-28 Thread Junling Zheng
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

2018-09-28 Thread Chao Yu
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

2018-09-28 Thread Chao Yu
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