[f2fs-dev] [PATCH] f2fs: give message and set need_fsck given broken node id

2018-04-23 Thread Jaegeuk Kim
syzbot hit the following crash on upstream commit
83beed7b2b26f232d782127792dd0cd4362fdc41 (Fri Apr 20 17:56:32 2018 +)
Merge branch 'fixes' of 
git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal
syzbot dashboard link: 
https://syzkaller.appspot.com/bug?extid=d154ec99402c6f628887

C reproducer: https://syzkaller.appspot.com/x/repro.c?id=5414336294027264
syzkaller reproducer: 
https://syzkaller.appspot.com/x/repro.syz?id=5471683234234368
Raw console output: https://syzkaller.appspot.com/x/log.txt?id=5436660795834368
Kernel config: https://syzkaller.appspot.com/x/.config?id=1808800213120130118
compiler: gcc (GCC) 8.0.1 20180413 (experimental)

IMPORTANT: if you fix the bug, please add the following tag to the commit:
Reported-by: syzbot+d154ec99402c6f628...@syzkaller.appspotmail.com
It will help syzbot understand when the bug is fixed. See footer for details.
If you forward the report, please keep this part and the footer.

F2FS-fs (loop0): Magic Mismatch, valid(0xf2f52010) - read(0x0)
F2FS-fs (loop0): Can't find valid F2FS filesystem in 1th superblock
F2FS-fs (loop0): invalid crc value
[ cut here ]
kernel BUG at fs/f2fs/node.c:1185!
invalid opcode:  [#1] SMP KASAN
Dumping ftrace buffer:
   (ftrace buffer empty)
Modules linked in:
CPU: 1 PID: 4549 Comm: syzkaller704305 Not tainted 4.17.0-rc1+ #10
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 
01/01/2011
RIP: 0010:__get_node_page+0xb68/0x16e0 fs/f2fs/node.c:1185
RSP: 0018:8801d960e820 EFLAGS: 00010293
RAX: 8801d88205c0 RBX: 0003 RCX: 82f6cc06
RDX:  RSI: 82f6d5e8 RDI: 0004
RBP: 8801d960ec30 R08: 8801d88205c0 R09: ed003b5e46c2
R10: 0003 R11: 0003 R12: 8801a86e00c0
R13: 0001 R14: 8801a86e0530 R15: 8801d9745240
FS:  0072c880() GS:8801daf0() knlGS:
CS:  0010 DS:  ES:  CR0: 80050033
CR2: 7f3d403209b8 CR3: 0001d8f3f000 CR4: 001406e0
DR0:  DR1:  DR2: 
DR3:  DR6: fffe0ff0 DR7: 0400
Call Trace:
 get_node_page fs/f2fs/node.c:1237 [inline]
 truncate_xattr_node+0x152/0x2e0 fs/f2fs/node.c:1014
 remove_inode_page+0x200/0xaf0 fs/f2fs/node.c:1039
 f2fs_evict_inode+0xe86/0x1710 fs/f2fs/inode.c:547
 evict+0x4a6/0x960 fs/inode.c:557
 iput_final fs/inode.c:1519 [inline]
 iput+0x62d/0xa80 fs/inode.c:1545
 f2fs_fill_super+0x5f4e/0x7bf0 fs/f2fs/super.c:2849
 mount_bdev+0x30c/0x3e0 fs/super.c:1164
 f2fs_mount+0x34/0x40 fs/f2fs/super.c:3020
 mount_fs+0xae/0x328 fs/super.c:1267
 vfs_kern_mount.part.34+0xd4/0x4d0 fs/namespace.c:1037
 vfs_kern_mount fs/namespace.c:1027 [inline]
 do_new_mount fs/namespace.c:2518 [inline]
 do_mount+0x564/0x3070 fs/namespace.c:2848
 ksys_mount+0x12d/0x140 fs/namespace.c:3064
 __do_sys_mount fs/namespace.c:3078 [inline]
 __se_sys_mount fs/namespace.c:3075 [inline]
 __x64_sys_mount+0xbe/0x150 fs/namespace.c:3075
 do_syscall_64+0x1b1/0x800 arch/x86/entry/common.c:287
 entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x443dea
RSP: 002b:7ffcc7882368 EFLAGS: 0297 ORIG_RAX: 00a5
RAX: ffda RBX: 2c00 RCX: 00443dea
RDX: 2000 RSI: 2100 RDI: 7ffcc7882370
RBP: 0003 R08: 20016a00 R09: 000a
R10:  R11: 0297 R12: 0004
R13: 00402ce0 R14:  R15: 
RIP: __get_node_page+0xb68/0x16e0 fs/f2fs/node.c:1185 RSP: 8801d960e820
---[ end trace 4edbeb71f002bb76 ]---

Reported-by: syzbot+d154ec99402c6f628...@syzkaller.appspotmail.com
Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/f2fs.h  | 13 +
 fs/f2fs/inode.c |  6 +-
 fs/f2fs/node.c  | 23 +--
 3 files changed, 23 insertions(+), 19 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 8f3ad9662d13..d26aae5bf00d 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1583,18 +1583,6 @@ static inline bool __exist_node_summaries(struct 
f2fs_sb_info *sbi)
is_set_ckpt_flags(sbi, CP_FASTBOOT_FLAG));
 }
 
-/*
- * Check whether the given nid is within node id range.
- */
-static inline int check_nid_range(struct f2fs_sb_info *sbi, nid_t nid)
-{
-   if (unlikely(nid < F2FS_ROOT_INO(sbi)))
-   return -EINVAL;
-   if (unlikely(nid >= NM_I(sbi)->max_nid))
-   return -EINVAL;
-   return 0;
-}
-
 /*
  * Check whether the inode has blocks or not
  */
@@ -2768,6 +2756,7 @@ f2fs_hash_t f2fs_dentry_hash(const struct qstr *name_info,
 struct dnode_of_data;
 struct node_info;
 
+int check_nid_range(struct f2fs_sb_info *sbi, nid_t nid);
 bool available_free_memory(struct f2fs_sb_info *sbi, int type);
 int need_dentry_mark(struct f2fs_sb_info *sbi, nid_t nid);
 bool 

[f2fs-dev] [PATCH v2] f2fs: move mnt_want_write_file after range check

2018-04-23 Thread Yunlei He
This patch move mnt_want_write_file after range check,
it's needless to check arguments with it.

Signed-off-by: Yunlei He 
---
 fs/f2fs/file.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 16dad2b..25c5364 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -2061,15 +2061,15 @@ static int f2fs_ioc_gc_range(struct file *filp, 
unsigned long arg)
if (f2fs_readonly(sbi->sb))
return -EROFS;
 
+   end = range.start + range.len;
+   if (range.start < MAIN_BLKADDR(sbi) || end >= MAX_BLKADDR(sbi)) {
+   return -EINVAL;
+   }
+
ret = mnt_want_write_file(filp);
if (ret)
return ret;
 
-   end = range.start + range.len;
-   if (range.start < MAIN_BLKADDR(sbi) || end >= MAX_BLKADDR(sbi)) {
-   ret = -EINVAL;
-   goto out;
-   }
 do_more:
if (!range.sync) {
if (!mutex_trylock(>gc_mutex)) {
-- 
1.9.1


--
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH v2] f2fs: fix missing clear FI_NO_PREALLOC in some error case

2018-04-23 Thread Yunlei He
This patch fix missing clear FI_NO_PREALLOC in some error case

Signed-off-by: Yunlei He 
---
 fs/f2fs/file.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 16dad2b..2ce6c22 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -2923,6 +2923,8 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, 
struct iov_iter *from)
iov_iter_count(from)) ||
f2fs_has_inline_data(inode) ||
f2fs_force_buffered_io(inode, WRITE)) {
+   clear_inode_flag(inode,
+   FI_NO_PREALLOC);
inode_unlock(inode);
return -EAGAIN;
}
-- 
1.9.1


--
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH] f2fs: rename dio_rwsem to i_gc_rwsem

2018-04-23 Thread Chao Yu
RW semphore dio_rwsem in struct f2fs_inode_info is introduced to avoid
race between dio and data gc, but now, it is more wildly used to avoid
foreground operation vs data gc. So rename it to i_gc_rwsem to improve
its readability.

Signed-off-by: Chao Yu 
---
 fs/f2fs/data.c  |  6 +++---
 fs/f2fs/f2fs.h  |  2 +-
 fs/f2fs/file.c  | 28 ++--
 fs/f2fs/gc.c| 14 +++---
 fs/f2fs/super.c |  4 ++--
 5 files changed, 27 insertions(+), 27 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 5477fc09c3cd..f7365ce45450 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -2395,17 +2395,17 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, 
struct iov_iter *iter)
if (rw == WRITE && whint_mode == WHINT_MODE_OFF)
iocb->ki_hint = WRITE_LIFE_NOT_SET;
 
-   if (!down_read_trylock(_I(inode)->dio_rwsem[rw])) {
+   if (!down_read_trylock(_I(inode)->i_gc_rwsem[rw])) {
if (iocb->ki_flags & IOCB_NOWAIT) {
iocb->ki_hint = hint;
err = -EAGAIN;
goto out;
}
-   down_read(_I(inode)->dio_rwsem[rw]);
+   down_read(_I(inode)->i_gc_rwsem[rw]);
}
 
err = blockdev_direct_IO(iocb, inode, iter, get_data_block_dio);
-   up_read(_I(inode)->dio_rwsem[rw]);
+   up_read(_I(inode)->i_gc_rwsem[rw]);
 
if (rw == WRITE) {
if (whint_mode == WHINT_MODE_OFF)
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index c2b92cb377c6..96556ce7f754 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -653,7 +653,7 @@ struct f2fs_inode_info {
struct task_struct *inmem_task; /* store inmemory task */
struct mutex inmem_lock;/* lock for inmemory pages */
struct extent_tree *extent_tree;/* cached extent_tree entry */
-   struct rw_semaphore dio_rwsem[2];/* avoid racing between dio and gc */
+   struct rw_semaphore i_gc_rwsem[2];/* avoid racing between foreground op 
and gc */
struct rw_semaphore i_mmap_sem;
struct rw_semaphore i_xattr_sem; /* avoid racing between reading and 
changing EAs */
 
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 0cfa65c21d3f..e88d94846d50 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -1191,7 +1191,7 @@ static int f2fs_collapse_range(struct inode *inode, 
loff_t offset, loff_t len)
pg_end = (offset + len) >> PAGE_SHIFT;
 
/* avoid gc operation during block exchange */
-   down_write(_I(inode)->dio_rwsem[WRITE]);
+   down_write(_I(inode)->i_gc_rwsem[WRITE]);
 
down_write(_I(inode)->i_mmap_sem);
/* write out all dirty pages from offset */
@@ -1217,7 +1217,7 @@ static int f2fs_collapse_range(struct inode *inode, 
loff_t offset, loff_t len)
f2fs_i_size_write(inode, new_size);
 out_unlock:
up_write(_I(inode)->i_mmap_sem);
-   up_write(_I(inode)->dio_rwsem[WRITE]);
+   up_write(_I(inode)->i_gc_rwsem[WRITE]);
return ret;
 }
 
@@ -1393,7 +1393,7 @@ static int f2fs_insert_range(struct inode *inode, loff_t 
offset, loff_t len)
f2fs_balance_fs(sbi, true);
 
/* avoid gc operation during block exchange */
-   down_write(_I(inode)->dio_rwsem[WRITE]);
+   down_write(_I(inode)->i_gc_rwsem[WRITE]);
 
down_write(_I(inode)->i_mmap_sem);
ret = truncate_blocks(inode, i_size_read(inode), true);
@@ -1434,7 +1434,7 @@ static int f2fs_insert_range(struct inode *inode, loff_t 
offset, loff_t len)
f2fs_i_size_write(inode, new_size);
 out:
up_write(_I(inode)->i_mmap_sem);
-   up_write(_I(inode)->dio_rwsem[WRITE]);
+   up_write(_I(inode)->i_gc_rwsem[WRITE]);
return ret;
 }
 
@@ -1681,7 +1681,7 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
 
inode_lock(inode);
 
-   down_write(_I(inode)->dio_rwsem[WRITE]);
+   down_write(_I(inode)->i_gc_rwsem[WRITE]);
 
if (f2fs_is_atomic_file(inode))
goto out;
@@ -1709,7 +1709,7 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
stat_inc_atomic_write(inode);
stat_update_max_atomic_write(inode);
 out:
-   up_write(_I(inode)->dio_rwsem[WRITE]);
+   up_write(_I(inode)->i_gc_rwsem[WRITE]);
inode_unlock(inode);
mnt_drop_write_file(filp);
return ret;
@@ -1729,7 +1729,7 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp)
 
inode_lock(inode);
 
-   down_write(_I(inode)->dio_rwsem[WRITE]);
+   down_write(_I(inode)->i_gc_rwsem[WRITE]);
 
if (f2fs_is_volatile_file(inode)) {
ret = -EINVAL;
@@ -1755,7 +1755,7 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp)
clear_inode_flag(inode, FI_ATOMIC_REVOKE_REQUEST);
ret = -EINVAL;
}
-   up_write(_I(inode)->dio_rwsem[WRITE]);
+   up_write(_I(inode)->i_gc_rwsem[WRITE]);

[f2fs-dev] [PATCH v2] f2fs: avoid stucking GC due to atomic write

2018-04-23 Thread Chao Yu
f2fs doesn't allow abuse on atomic write class interface, so except
limiting in-mem pages' total memory usage capacity, we need to limit
atomic-write usage as well when filesystem is seriously fragmented,
otherwise we may run into infinite loop during foreground GC because
target blocks in victim segment are belong to atomic opened file for
long time.

Now, we will detect failure due to atomic write in foreground GC, if
the count exceeds threshold, we will drop all atomic written data in
cache, by this, I expect it can keep our system running safely to
prevent Dos attack.

In addition, his patch adds to show GC skip information in debugfs,
now it just shows count of skipped caused by atomic write.

Signed-off-by: Chao Yu 
---
v2:
- add to show skip info in debugfs.
 fs/f2fs/debug.c   |  8 
 fs/f2fs/f2fs.h|  2 ++
 fs/f2fs/file.c|  5 +
 fs/f2fs/gc.c  | 29 +
 fs/f2fs/gc.h  |  3 +++
 fs/f2fs/segment.c |  1 +
 fs/f2fs/segment.h |  2 ++
 7 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
index 0fbd674c66fb..607b258a9b61 100644
--- a/fs/f2fs/debug.c
+++ b/fs/f2fs/debug.c
@@ -104,6 +104,10 @@ static void update_general_status(struct f2fs_sb_info *sbi)
si->avail_nids = NM_I(sbi)->available_nids;
si->alloc_nids = NM_I(sbi)->nid_cnt[PREALLOC_NID];
si->bg_gc = sbi->bg_gc;
+   si->skipped_atomic_files[BG_GC] =
+   sbi->gc_thread->skipped_atomic_files[BG_GC];
+   si->skipped_atomic_files[FG_GC] =
+   sbi->gc_thread->skipped_atomic_files[FG_GC];
si->util_free = (int)(free_user_blocks(sbi) >> sbi->log_blocks_per_seg)
* 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
/ 2;
@@ -341,6 +345,10 @@ static int stat_show(struct seq_file *s, void *v)
si->bg_data_blks);
seq_printf(s, "  - node blocks : %d (%d)\n", si->node_blks,
si->bg_node_blks);
+   seq_printf(s, "Skipped : atomic write %llu (%llu)\n",
+   si->skipped_atomic_files[BG_GC] +
+   si->skipped_atomic_files[FG_GC],
+   si->skipped_atomic_files[BG_GC]);
seq_puts(s, "\nExtent Cache:\n");
seq_printf(s, "  - Hit Count: L1-1:%llu L1-2:%llu L2:%llu\n",
si->hit_largest, si->hit_cached,
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 75d3b4875429..c2b92cb377c6 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -2254,6 +2254,7 @@ enum {
FI_EXTRA_ATTR,  /* indicate file has extra attribute */
FI_PROJ_INHERIT,/* indicate file inherits projectid */
FI_PIN_FILE,/* indicate file should not be gced */
+   FI_ATOMIC_REVOKE_REQUEST,/* indicate atomic committed data has been 
dropped */
 };
 
 static inline void __mark_inode_dirty_flag(struct inode *inode,
@@ -3010,6 +3011,7 @@ struct f2fs_stat_info {
int bg_node_segs, bg_data_segs;
int tot_blks, data_blks, node_blks;
int bg_data_blks, bg_node_blks;
+   unsigned long long skipped_atomic_files[2];
int curseg[NR_CURSEG_TYPE];
int cursec[NR_CURSEG_TYPE];
int curzone[NR_CURSEG_TYPE];
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index a352804af244..0cfa65c21d3f 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -1702,6 +1702,7 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
 skip_flush:
set_inode_flag(inode, FI_HOT_DATA);
set_inode_flag(inode, FI_ATOMIC_FILE);
+   clear_inode_flag(inode, FI_ATOMIC_REVOKE_REQUEST);
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
 
F2FS_I(inode)->inmem_task = current;
@@ -1750,6 +1751,10 @@ static int f2fs_ioc_commit_atomic_write(struct file 
*filp)
ret = f2fs_do_sync_file(filp, 0, LLONG_MAX, 1, false);
}
 err_out:
+   if (is_inode_flag_set(inode, FI_ATOMIC_REVOKE_REQUEST)) {
+   clear_inode_flag(inode, FI_ATOMIC_REVOKE_REQUEST);
+   ret = -EINVAL;
+   }
up_write(_I(inode)->dio_rwsem[WRITE]);
inode_unlock(inode);
mnt_drop_write_file(filp);
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 2febb84b2fd6..ec6cb7b417a1 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -135,6 +135,9 @@ int init_gc_context(struct f2fs_sb_info *sbi)
 
init_rwsem(_th->gc_rwsem);
 
+   gc_th->skipped_atomic_files[BG_GC] = 0;
+   gc_th->skipped_atomic_files[FG_GC] = 0;
+
sbi->gc_thread = gc_th;
 
return 0;
@@ -629,7 +632,7 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct 
f2fs_summary *sum,
  * This can be used to move blocks, aka LBAs, directly on disk.
  */
 static void move_data_block(struct inode *inode, block_t bidx,
-   unsigned int segno, int 

[f2fs-dev] [PATCH v2] f2fs: fix to avoid race during access gc_thread pointer

2018-04-23 Thread Chao Yu
Thread AThread BThread C
- f2fs_remount
 - stop_gc_thread
- f2fs_sbi_store
- issue_discard_thread
   sbi->gc_thread = NULL;
  sbi->gc_thread->gc_wake = 1
  access 
sbi->gc_thread->gc_urgent

Previously, we allocate memory for sbi->gc_thread based on background
gc thread mount option, the memory can be released if we turn off
that mount option, but still there are several places access gc_thread
pointer without considering race condition, result in NULL point
dereference.

In order to fix this issue, keep gc_thread structure valid in sbi all
the time instead of alloc/free it dynamically.

In addition, add a rw semaphore to exclude rw operation in fields of
gc_thread.

Signed-off-by: Chao Yu 
---
v2:
- add a rw semaphore to exclude rw operation suggested by Jaegeuk.
 fs/f2fs/debug.c   |  3 +--
 fs/f2fs/f2fs.h|  9 ++-
 fs/f2fs/gc.c  | 78 ---
 fs/f2fs/gc.h  |  1 +
 fs/f2fs/segment.c | 10 +--
 fs/f2fs/super.c   | 26 +--
 fs/f2fs/sysfs.c   | 26 ++-
 7 files changed, 107 insertions(+), 46 deletions(-)

diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
index a66107b5cfff..0fbd674c66fb 100644
--- a/fs/f2fs/debug.c
+++ b/fs/f2fs/debug.c
@@ -221,8 +221,7 @@ static void update_mem_info(struct f2fs_sb_info *sbi)
si->cache_mem = 0;
 
/* build gc */
-   if (sbi->gc_thread)
-   si->cache_mem += sizeof(struct f2fs_gc_kthread);
+   si->cache_mem += sizeof(struct f2fs_gc_kthread);
 
/* build merge flush thread */
if (SM_I(sbi)->fcc_info)
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 8f3ad9662d13..75d3b4875429 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1412,6 +1412,11 @@ static inline struct sit_info *SIT_I(struct f2fs_sb_info 
*sbi)
return (struct sit_info *)(SM_I(sbi)->sit_info);
 }
 
+static inline struct f2fs_gc_kthread *GC_I(struct f2fs_sb_info *sbi)
+{
+   return (struct f2fs_gc_kthread *)(sbi->gc_thread);
+}
+
 static inline struct free_segmap_info *FREE_I(struct f2fs_sb_info *sbi)
 {
return (struct free_segmap_info *)(SM_I(sbi)->free_info);
@@ -2954,8 +2959,10 @@ bool f2fs_overwrite_io(struct inode *inode, loff_t pos, 
size_t len);
 /*
  * gc.c
  */
+int init_gc_context(struct f2fs_sb_info *sbi);
+void destroy_gc_context(struct f2fs_sb_info * sbi);
 int start_gc_thread(struct f2fs_sb_info *sbi);
-void stop_gc_thread(struct f2fs_sb_info *sbi);
+bool stop_gc_thread(struct f2fs_sb_info *sbi);
 block_t start_bidx_of_node(unsigned int node_ofs, struct inode *inode);
 int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, bool background,
unsigned int segno);
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 70418b34c5f6..2febb84b2fd6 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -26,8 +26,8 @@
 static int gc_thread_func(void *data)
 {
struct f2fs_sb_info *sbi = data;
-   struct f2fs_gc_kthread *gc_th = sbi->gc_thread;
-   wait_queue_head_t *wq = >gc_thread->gc_wait_queue_head;
+   struct f2fs_gc_kthread *gc_th = GC_I(sbi);
+   wait_queue_head_t *wq = _th->gc_wait_queue_head;
unsigned int wait_ms;
 
wait_ms = gc_th->min_sleep_time;
@@ -114,17 +114,15 @@ static int gc_thread_func(void *data)
return 0;
 }
 
-int start_gc_thread(struct f2fs_sb_info *sbi)
+int init_gc_context(struct f2fs_sb_info *sbi)
 {
struct f2fs_gc_kthread *gc_th;
-   dev_t dev = sbi->sb->s_bdev->bd_dev;
-   int err = 0;
 
gc_th = f2fs_kmalloc(sbi, sizeof(struct f2fs_gc_kthread), GFP_KERNEL);
-   if (!gc_th) {
-   err = -ENOMEM;
-   goto out;
-   }
+   if (!gc_th)
+   return -ENOMEM;
+
+   gc_th->f2fs_gc_task = NULL;
 
gc_th->urgent_sleep_time = DEF_GC_THREAD_URGENT_SLEEP_TIME;
gc_th->min_sleep_time = DEF_GC_THREAD_MIN_SLEEP_TIME;
@@ -135,35 +133,59 @@ int start_gc_thread(struct f2fs_sb_info *sbi)
gc_th->gc_urgent = 0;
gc_th->gc_wake= 0;
 
+   init_rwsem(_th->gc_rwsem);
+
sbi->gc_thread = gc_th;
-   init_waitqueue_head(>gc_thread->gc_wait_queue_head);
-   sbi->gc_thread->f2fs_gc_task = kthread_run(gc_thread_func, sbi,
+
+   return 0;
+}
+
+void destroy_gc_context(struct f2fs_sb_info *sbi)
+{
+   kfree(GC_I(sbi));
+   sbi->gc_thread = NULL;
+}
+
+int start_gc_thread(struct f2fs_sb_info *sbi)
+{
+   struct f2fs_gc_kthread *gc_th = GC_I(sbi);
+   dev_t dev = sbi->sb->s_bdev->bd_dev;
+   int err = 0;
+
+   init_waitqueue_head(_th->gc_wait_queue_head);
+   gc_th->f2fs_gc_task = kthread_run(gc_thread_func, sbi,
"f2fs_gc-%u:%u", MAJOR(dev), MINOR(dev));
if (IS_ERR(gc_th->f2fs_gc_task)) {

[f2fs-dev] [PATCH] f2fs: fix features filename in sysfs documentation

2018-04-23 Thread Eric Biggers
From: Eric Biggers 

The file is called "features", not "feature".

Signed-off-by: Eric Biggers 
---
 Documentation/ABI/testing/sysfs-fs-f2fs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs 
b/Documentation/ABI/testing/sysfs-fs-f2fs
index 540553c933b6..50a34bacb1ab 100644
--- a/Documentation/ABI/testing/sysfs-fs-f2fs
+++ b/Documentation/ABI/testing/sysfs-fs-f2fs
@@ -140,7 +140,7 @@ Contact:"Shuoran Liu" 
 Description:
 Shows total written kbytes issued to disk.
 
-What:  /sys/fs/f2fs//feature
+What:  /sys/fs/f2fs//features
 Date:  July 2017
 Contact:   "Jaegeuk Kim" 
 Description:
-- 
2.17.0.484.g0c8726318c-goog


--
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH v2] f2fs: wait IO writeback in commit_inmem_pages()

2018-04-23 Thread Chao Yu
From: Chao Yu 

Thread AThread B
- f2fs_ioc_commit_atomic_write
 - commit_inmem_pages
  - f2fs_submit_merged_write_cond
  : write data
- write_checkpoint
 - do_checkpoint
 : commit all node within CP
 -> SPO
  - f2fs_do_sync_file
   - file_write_and_wait_range
   : wait data writeback

In above race condition, data/node can be flushed in reversed order when
coming a checkpoint before f2fs_do_sync_file, after SPOR, it results in
atomic written data being corrupted.

This patch adds filemap_fdatawait() in commit_inmem_pages() to keep data
and node of atomic file being flushed orderly.

Signed-off-by: Chao Yu 
---
v2:
- clean up codes suggested by Jaegeuk.
 fs/f2fs/file.c| 4 
 fs/f2fs/segment.c | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index bac059474342..0cfa65c21d3f 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -217,6 +217,9 @@ static int f2fs_do_sync_file(struct file *file, loff_t 
start, loff_t end,
 
trace_f2fs_sync_file_enter(inode);
 
+   if (atomic)
+   goto write_done;
+
/* if fdatasync is triggered, let's do in-place-update */
if (datasync || get_dirty_pages(inode) <= SM_I(sbi)->min_fsync_blocks)
set_inode_flag(inode, FI_NEED_IPU);
@@ -228,6 +231,7 @@ static int f2fs_do_sync_file(struct file *file, loff_t 
start, loff_t end,
return ret;
}
 
+write_done:
/* if the inode is dirty, let's recover all the time */
if (!f2fs_skip_inode_update(inode, datasync)) {
f2fs_write_inode(inode, NULL);
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 710d817c4350..31336fc54d8e 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -419,6 +419,8 @@ static int __commit_inmem_pages(struct inode *inode)
__revoke_inmem_pages(inode, >inmem_pages, true, false);
} else {
__revoke_inmem_pages(inode, _list, false, false);
+
+   err = filemap_fdatawait(inode->i_mapping);
}
 
return err;
-- 
2.16.2.17.g38e79b1fd


--
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


Re: [f2fs-dev] [PATCH 3/3] f2fs: wait IO writeback in commit_inmem_pages()

2018-04-23 Thread Jaegeuk Kim
On 04/23, Chao Yu wrote:
> Thread A  Thread B
> - f2fs_ioc_commit_atomic_write
>  - commit_inmem_pages
>   - f2fs_submit_merged_write_cond
>   : write data
>   - write_checkpoint
>- do_checkpoint
>: commit all node within CP
>-> SPO
>   - f2fs_do_sync_file
>- file_write_and_wait_range
>: wait data writeback
> 
> In above race condition, data/node can be flushed in reversed order when
> coming a checkpoint before f2fs_do_sync_file, after SPOR, it results in
> atomic written data being corrupted.
> 
> This patch adds filemap_fdatawait() in commit_inmem_pages() to keep data
> and node of atomic file being flushed orderly.
> 
> Signed-off-by: Chao Yu 
> ---
>  fs/f2fs/file.c| 21 -
>  fs/f2fs/segment.c |  2 ++
>  2 files changed, 14 insertions(+), 9 deletions(-)
> 
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 5d710f7f2684..4ea418cbd189 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -217,15 +217,18 @@ static int f2fs_do_sync_file(struct file *file, loff_t 
> start, loff_t end,
>  
>   trace_f2fs_sync_file_enter(inode);

if (atomic)
goto write_done;

>  
> - /* if fdatasync is triggered, let's do in-place-update */
> - if (datasync || get_dirty_pages(inode) <= SM_I(sbi)->min_fsync_blocks)
> - set_inode_flag(inode, FI_NEED_IPU);
> - ret = file_write_and_wait_range(file, start, end);
> - clear_inode_flag(inode, FI_NEED_IPU);
> -
> - if (ret) {
> - trace_f2fs_sync_file_exit(inode, cp_reason, datasync, ret);
> - return ret;
> + if (!atomic) {
> + /* if fdatasync is triggered, let's do in-place-update */
> + if (datasync || get_dirty_pages(inode) <=
> + SM_I(sbi)->min_fsync_blocks)
> + set_inode_flag(inode, FI_NEED_IPU);
> + ret = file_write_and_wait_range(file, start, end);
> + clear_inode_flag(inode, FI_NEED_IPU);
> +
> + if (ret) {
> + trace_f2fs_sync_file_exit(inode, cp_reason, datasync, 
> ret);
> + return ret;
> + }
>   }

write_done:

>  
>   /* if the inode is dirty, let's recover all the time */
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index dcb4fcb8b1b0..3b66c4aa04a6 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -420,6 +420,8 @@ static int __commit_inmem_pages(struct inode *inode)
>   __revoke_inmem_pages(inode, >inmem_pages, true, false);
>   } else {
>   __revoke_inmem_pages(inode, _list, false, false);
> +
> + err = filemap_fdatawait(inode->i_mapping);
>   }
>  
>   return err;
> -- 
> 2.15.0.55.gc2ece9dc4de6

--
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
___
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: sepearte hot/cold in free nid

2018-04-23 Thread Chao Yu
On 2018/4/23 22:49, Jaegeuk Kim wrote:
> On 04/20, Chao Yu wrote:
>> On 2018/4/20 12:04, Chao Yu wrote:
>>> On 2018/4/20 11:37, Jaegeuk Kim wrote:
 On 04/20, Chao Yu wrote:
> As most indirect node, dindirect node, and xattr node won't be updated
> after they are created, but inode node and other direct node will change
> more frequently, so store their nat entries mixedly in whole nat table
> will suffer:
> - fragment nat table soon due to different update rate
> - more nat block update due to fragmented nat table
>
> In order to solve above issue, we're trying to separate whole nat table to
> two part:
> a. Hot free nid area:
>  - range: [nid #0, nid #x)
>  - store node block address for
>* inode node
>* other direct node
> b. Cold free nid area:
>  - range: [nid #x, max nid)
>  - store node block address for
>* indirect node
>* dindirect node
>* xattr node
>
> Allocation strategy example:
>
> Free nid: '-'
> Used nid: '='
>
> 1. Initial status:
> Free Nids:
> |---|
>   ^   ^   ^   
> ^
> Alloc Range:  |---|   
> |---|
>   hot_start   hot_end 
> cold_start  cold_end
>
> 2. Free nids have ran out:
> Free Nids:
> |===-===|
>   ^   ^   ^   
> ^
> Alloc Range:  |===|   
> |===|
>   hot_start   hot_end 
> cold_start  cold_end
>
> 3. Expand hot/cold area range:
> Free Nids:
> |===-===|
>   ^   ^   ^   
> ^
> Alloc Range:  |===|   
> |===|
>   hot_start   hot_end cold_start  
> cold_end
>
> 4. Hot free nids have ran out:
> Free Nids:
> |===-===|
>   ^   ^   ^   
> ^
> Alloc Range:  |===|   
> |===|
>   hot_start   hot_end cold_start  
> cold_end
>
> 5. Expand hot area range, hot/cold area boundary has been fixed:
> Free Nids:
> |===-===|
>   ^   ^   
> ^
> Alloc Range:  
> |===|===|
>   hot_start   hot_end(cold_start) 
> cold_end
>
> Run xfstests with generic/*:
>
> before
> node_write:   169660
> cp_count: 60118
> node/cp   2.82
>
> after:
> node_write:   159145
> cp_count: 84501
> node/cp:  2.64

 Nice trial tho, I don't see much benefit on this huge patch. I guess we 
 may be
 able to find an efficient way to achieve this issue rather than changing 
 whole
 stable codes.
>>>
>>> IMO, based on this, later, we can add more allocation policy to manage free 
>>> nid
>>> resource to get more benefit.
>>>
>>> If you worry about code stability, we can queue this patch in dev-test 
>>> branch to
>>> test this longer time.
>>>

 How about getting a free nid in the list from head or tail separately?
>>>
>>> I don't think this can get benefit from long time used image, since nat 
>>> table
>>> will be fragmented anyway, then we won't know free nid in head or in tail 
>>> comes
>>> from hot nat block or cold nat block.
>>>
>>> Anyway, I will have a try.
>>
>> A quick test result with below patch:
>>
>> node_write:187837, cp_count:76431
> 
> Can we gather some real numbers from android workloads?

No problem. :)

Thanks,

> 
> Thanks,
> 
>>
>> >From 9f88ea8a36a74f1d3ed8df57ceffb1b8ae41a161 Mon Sep 17 00:00:00 2001
>> From: Chao Yu 
>> Date: Fri, 20 Apr 2018 16:18:26 +0800
>> Subject: [PATCH] f2fs: separate hot/cold free nid simply
>>
>> Signed-off-by: Chao Yu 
>> ---
>>  fs/f2fs/f2fs.h  |  2 +-
>>  fs/f2fs/namei.c |  2 +-
>>  fs/f2fs/node.c  | 14 +-
>>  fs/f2fs/xattr.c |  2 +-
>>  4 files changed, 12 

Re: [f2fs-dev] [PATCH] f2fs: sepearte hot/cold in free nid

2018-04-23 Thread Jaegeuk Kim
On 04/20, Chao Yu wrote:
> On 2018/4/20 12:04, Chao Yu wrote:
> > On 2018/4/20 11:37, Jaegeuk Kim wrote:
> >> On 04/20, Chao Yu wrote:
> >>> As most indirect node, dindirect node, and xattr node won't be updated
> >>> after they are created, but inode node and other direct node will change
> >>> more frequently, so store their nat entries mixedly in whole nat table
> >>> will suffer:
> >>> - fragment nat table soon due to different update rate
> >>> - more nat block update due to fragmented nat table
> >>>
> >>> In order to solve above issue, we're trying to separate whole nat table to
> >>> two part:
> >>> a. Hot free nid area:
> >>>  - range: [nid #0, nid #x)
> >>>  - store node block address for
> >>>* inode node
> >>>* other direct node
> >>> b. Cold free nid area:
> >>>  - range: [nid #x, max nid)
> >>>  - store node block address for
> >>>* indirect node
> >>>* dindirect node
> >>>* xattr node
> >>>
> >>> Allocation strategy example:
> >>>
> >>> Free nid: '-'
> >>> Used nid: '='
> >>>
> >>> 1. Initial status:
> >>> Free Nids:
> >>> |---|
> >>>   ^   ^   ^   
> >>> ^
> >>> Alloc Range:  |---|   
> >>> |---|
> >>>   hot_start   hot_end 
> >>> cold_start  cold_end
> >>>
> >>> 2. Free nids have ran out:
> >>> Free Nids:
> >>> |===-===|
> >>>   ^   ^   ^   
> >>> ^
> >>> Alloc Range:  |===|   
> >>> |===|
> >>>   hot_start   hot_end 
> >>> cold_start  cold_end
> >>>
> >>> 3. Expand hot/cold area range:
> >>> Free Nids:
> >>> |===-===|
> >>>   ^   ^   ^   
> >>> ^
> >>> Alloc Range:  |===|   
> >>> |===|
> >>>   hot_start   hot_end cold_start  
> >>> cold_end
> >>>
> >>> 4. Hot free nids have ran out:
> >>> Free Nids:
> >>> |===-===|
> >>>   ^   ^   ^   
> >>> ^
> >>> Alloc Range:  |===|   
> >>> |===|
> >>>   hot_start   hot_end cold_start  
> >>> cold_end
> >>>
> >>> 5. Expand hot area range, hot/cold area boundary has been fixed:
> >>> Free Nids:
> >>> |===-===|
> >>>   ^   ^   
> >>> ^
> >>> Alloc Range:  
> >>> |===|===|
> >>>   hot_start   hot_end(cold_start) 
> >>> cold_end
> >>>
> >>> Run xfstests with generic/*:
> >>>
> >>> before
> >>> node_write:   169660
> >>> cp_count: 60118
> >>> node/cp   2.82
> >>>
> >>> after:
> >>> node_write:   159145
> >>> cp_count: 84501
> >>> node/cp:  2.64
> >>
> >> Nice trial tho, I don't see much benefit on this huge patch. I guess we 
> >> may be
> >> able to find an efficient way to achieve this issue rather than changing 
> >> whole
> >> stable codes.
> > 
> > IMO, based on this, later, we can add more allocation policy to manage free 
> > nid
> > resource to get more benefit.
> > 
> > If you worry about code stability, we can queue this patch in dev-test 
> > branch to
> > test this longer time.
> > 
> >>
> >> How about getting a free nid in the list from head or tail separately?
> > 
> > I don't think this can get benefit from long time used image, since nat 
> > table
> > will be fragmented anyway, then we won't know free nid in head or in tail 
> > comes
> > from hot nat block or cold nat block.
> > 
> > Anyway, I will have a try.
> 
> A quick test result with below patch:
> 
> node_write:187837, cp_count:76431

Can we gather some real numbers from android workloads?

Thanks,

> 
> >From 9f88ea8a36a74f1d3ed8df57ceffb1b8ae41a161 Mon Sep 17 00:00:00 2001
> From: Chao Yu 
> Date: Fri, 20 Apr 2018 16:18:26 +0800
> Subject: [PATCH] f2fs: separate hot/cold free nid simply
> 
> Signed-off-by: Chao Yu 
> ---
>  fs/f2fs/f2fs.h  |  2 +-
>  fs/f2fs/namei.c |  2 +-
>  fs/f2fs/node.c  | 14 +-
>  fs/f2fs/xattr.c |  2 +-
>  4 files changed, 12 insertions(+), 8 deletions(-)
> 
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index 

Re: [f2fs-dev] [PATCH] f2fs: move mnt_want_write_file after range check

2018-04-23 Thread Chao Yu
On 2018/4/23 17:11, heyunlei wrote:
> 
> 
>> -Original Message-
>> From: heyunlei
>> Sent: Monday, April 23, 2018 10:37 AM
>> To: jaeg...@kernel.org; Yuchao (T); linux-f2fs-devel@lists.sourceforge.net
>> Cc: Wangbintian; heyunlei; Zhangdianfang (Euler)
>> Subject: [f2fs-dev][PATCH] f2fs: move mnt_want_write_file after range check
>>
>> This patch move mnt_want_write_file after range check,
>> it's needless to check arguments with it.
>>
>> Signed-off-by: Yunlei He 
>> ---
>> fs/f2fs/file.c | 13 -
>> 1 file changed, 8 insertions(+), 5 deletions(-)
>>
>> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
>> index 16dad2b..165a60f 100644
>> --- a/fs/f2fs/file.c
>> +++ b/fs/f2fs/file.c
>> @@ -2061,15 +2061,18 @@ static int f2fs_ioc_gc_range(struct file *filp, 
>> unsigned long arg)
>>  if (f2fs_readonly(sbi->sb))
>>  return -EROFS;
>>
>> +end = range.start + range.len;
>> +if (range.start < MAIN_BLKADDR(sbi) || end >= MAX_BLKADDR(sbi)) {
>> +f2fs_msg(sbi->sb, KERN_WARNING,
>> +"range should be located in (%u, %u]",
>> +MAIN_BLKADDR(sbi), MAX_BLKADDR(sbi));
>> +return -EINVAL;
>> +}
> 
> Okay, btw, should we combine f2fs_ioc_gc and f2fs_ioc_gc_range? 
> we can add a value in input arguments to indicate whether it's range gc or 
> not.

That's not a big problem since it's just cleanup, if you want to, please go
ahead. :)

Thanks,

> 
> Thanks. 
>> +
>>  ret = mnt_want_write_file(filp);
>>  if (ret)
>>  return ret;
>>
>> -end = range.start + range.len;
>> -if (range.start < MAIN_BLKADDR(sbi) || end >= MAX_BLKADDR(sbi)) {
>> -ret = -EINVAL;
>> -goto out;
>> -}
>> do_more:
>>  if (!range.sync) {
>>  if (!mutex_trylock(>gc_mutex)) {
>> --
>> 1.9.1
> 
> 
> .
> 


--
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
___
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: move mnt_want_write_file after range check

2018-04-23 Thread heyunlei


>-Original Message-
>From: heyunlei
>Sent: Monday, April 23, 2018 10:37 AM
>To: jaeg...@kernel.org; Yuchao (T); linux-f2fs-devel@lists.sourceforge.net
>Cc: Wangbintian; heyunlei; Zhangdianfang (Euler)
>Subject: [f2fs-dev][PATCH] f2fs: move mnt_want_write_file after range check
>
>This patch move mnt_want_write_file after range check,
>it's needless to check arguments with it.
>
>Signed-off-by: Yunlei He 
>---
> fs/f2fs/file.c | 13 -
> 1 file changed, 8 insertions(+), 5 deletions(-)
>
>diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
>index 16dad2b..165a60f 100644
>--- a/fs/f2fs/file.c
>+++ b/fs/f2fs/file.c
>@@ -2061,15 +2061,18 @@ static int f2fs_ioc_gc_range(struct file *filp, 
>unsigned long arg)
>   if (f2fs_readonly(sbi->sb))
>   return -EROFS;
>
>+  end = range.start + range.len;
>+  if (range.start < MAIN_BLKADDR(sbi) || end >= MAX_BLKADDR(sbi)) {
>+  f2fs_msg(sbi->sb, KERN_WARNING,
>+  "range should be located in (%u, %u]",
>+  MAIN_BLKADDR(sbi), MAX_BLKADDR(sbi));
>+  return -EINVAL;
>+  }

Okay, btw, should we combine f2fs_ioc_gc and f2fs_ioc_gc_range? 
we can add a value in input arguments to indicate whether it's range gc or not.

Thanks. 
>+
>   ret = mnt_want_write_file(filp);
>   if (ret)
>   return ret;
>
>-  end = range.start + range.len;
>-  if (range.start < MAIN_BLKADDR(sbi) || end >= MAX_BLKADDR(sbi)) {
>-  ret = -EINVAL;
>-  goto out;
>-  }
> do_more:
>   if (!range.sync) {
>   if (!mutex_trylock(>gc_mutex)) {
>--
>1.9.1


--
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
___
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 missing clear FI_NO_PREALLOC in some error case

2018-04-23 Thread Chao Yu
On 2018/4/23 11:36, Yunlei He wrote:
> This patch clean f2fs_file_write_iter to avoid missing clear
> FI_NO_PREALLOC in some error case.
> 
> Signed-off-by: Yunlei He 
> ---
>  fs/f2fs/file.c | 35 ---
>  1 file changed, 16 insertions(+), 19 deletions(-)
> 
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 16dad2b..c7dff0b 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -2894,12 +2894,13 @@ static ssize_t f2fs_file_write_iter(struct kiocb 
> *iocb, struct iov_iter *from)
>  {
>   struct file *file = iocb->ki_filp;
>   struct inode *inode = file_inode(file);
> + int o_direct = iocb->ki_flags & IOCB_DIRECT;
>   ssize_t ret;
>  
>   if (unlikely(f2fs_cp_error(F2FS_I_SB(inode
>   return -EIO;
>  
> - if ((iocb->ki_flags & IOCB_NOWAIT) && !(iocb->ki_flags & IOCB_DIRECT))
> + if ((iocb->ki_flags & IOCB_NOWAIT) && !o_direct)
>   return -EINVAL;
>  
>   if (!inode_trylock(inode)) {
> @@ -2910,44 +2911,40 @@ static ssize_t f2fs_file_write_iter(struct kiocb 
> *iocb, struct iov_iter *from)
>  
>   ret = generic_write_checks(iocb, from);
>   if (ret > 0) {
> - bool preallocated = false;
>   size_t target_size = 0;
> - int err;
>  
> - if (iov_iter_fault_in_readable(from, iov_iter_count(from)))
> - set_inode_flag(inode, FI_NO_PREALLOC);
> -
> - if ((iocb->ki_flags & IOCB_NOWAIT) &&
> - (iocb->ki_flags & IOCB_DIRECT)) {
> + if ((iocb->ki_flags & IOCB_NOWAIT) && o_direct) {
>   if (!f2fs_overwrite_io(inode, iocb->ki_pos,
>   iov_iter_count(from)) ||
>   f2fs_has_inline_data(inode) ||
>   f2fs_force_buffered_io(inode, WRITE)) {

Just add clear_inode_flag(inode, FI_NO_PREALLOC) here is OK?

Thanks,

> - inode_unlock(inode);
> - return -EAGAIN;
> + ret = -EAGAIN;
> + goto out;
>   }
>  
>   } else {
> - preallocated = true;
> + if (iov_iter_fault_in_readable(from, 
> iov_iter_count(from)))
> + set_inode_flag(inode, FI_NO_PREALLOC);
> +
>   target_size = iocb->ki_pos + iov_iter_count(from);
>  
> - err = f2fs_preallocate_blocks(iocb, from);
> - if (err) {
> - clear_inode_flag(inode, FI_NO_PREALLOC);
> - inode_unlock(inode);
> - return err;
> - }
> + ret = f2fs_preallocate_blocks(iocb, from);
> + if (ret)
> + goto out;
>   }
>   ret = __generic_file_write_iter(iocb, from);
> - clear_inode_flag(inode, FI_NO_PREALLOC);
>  
>   /* if we couldn't write data, we should deallocate blocks. */
> - if (preallocated && i_size_read(inode) < target_size)
> + if (!is_inode_flag_set(inode, FI_NO_PREALLOC) &&
> + i_size_read(inode) < target_size)
>   f2fs_truncate(inode);
>  
>   if (ret > 0)
>   f2fs_update_iostat(F2FS_I_SB(inode), APP_WRITE_IO, ret);
>   }
> +
> +out:
> + clear_inode_flag(inode, FI_NO_PREALLOC);
>   inode_unlock(inode);
>  
>   if (ret > 0)
> 


--
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
___
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: move mnt_want_write_file after range check

2018-04-23 Thread Chao Yu
On 2018/4/23 10:37, Yunlei He wrote:
> This patch move mnt_want_write_file after range check,
> it's needless to check arguments with it.
> 
> Signed-off-by: Yunlei He 
> ---
>  fs/f2fs/file.c | 13 -
>  1 file changed, 8 insertions(+), 5 deletions(-)
> 
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 16dad2b..165a60f 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -2061,15 +2061,18 @@ static int f2fs_ioc_gc_range(struct file *filp, 
> unsigned long arg)
>   if (f2fs_readonly(sbi->sb))
>   return -EROFS;
>  
> + end = range.start + range.len;
> + if (range.start < MAIN_BLKADDR(sbi) || end >= MAX_BLKADDR(sbi)) {
> + f2fs_msg(sbi->sb, KERN_WARNING,
> + "range should be located in (%u, %u]",
> + MAIN_BLKADDR(sbi), MAX_BLKADDR(sbi));

We don't need add kmsg in this condition as handling parameter check in most
other interfaces.

Thanks,

> + return -EINVAL;
> + }
> +
>   ret = mnt_want_write_file(filp);
>   if (ret)
>   return ret;
>  
> - end = range.start + range.len;
> - if (range.start < MAIN_BLKADDR(sbi) || end >= MAX_BLKADDR(sbi)) {
> - ret = -EINVAL;
> - goto out;
> - }
>  do_more:
>   if (!range.sync) {
>   if (!mutex_trylock(>gc_mutex)) {
> 


--
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
___
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: do not check F2FS_INLINE_DOTS in recover

2018-04-23 Thread Chao Yu
On 2018/4/23 10:29, Sheng Yong wrote:
> Only dir may have F2FS_INLINE_DOTS flag, so there is no need to check
> the flag in recover flow.
> 
> Signed-off-by: Sheng Yong 

Reviewed-by: Chao Yu 

Thanks,


--
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
___
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: remove duplicated dquot_initialize and fix error handling

2018-04-23 Thread Chao Yu
On 2018/4/21 14:12, Sheng Yong wrote:
> This patch removes duplicated dquot_initialize in recover_orphan_inode(),
> and fix the error handling if dquot_initialize fails.
> 
> Signed-off-by: Sheng Yong 

Reviewed-by: Chao Yu 

Thanks,


--
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
___
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: check cap_resource only for data blocks

2018-04-23 Thread Chao Yu
On 2018/4/21 14:53, Jaegeuk Kim wrote:
> This patch changes the rule to check cap_resource for data blocks, not inode
> or node blocks in order to avoid selinux denial.
> 
> Signed-off-by: Jaegeuk Kim 

Reviewed-by: Chao Yu 

Thanks,


--
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


Re: [f2fs-dev] [PATCH] Revert "f2fs: introduce f2fs_set_page_dirty_nobuffer"

2018-04-23 Thread Chao Yu
On 2018/4/21 12:08, Jaegeuk Kim wrote:
> This patch reverts copied f2fs_set_page_dirty_nobuffer to use generic function
> for stability.
> 
> This reverts commit fe76b796fc5194cc3d57265002e3a748566d073f.
> 
> Signed-off-by: Jaegeuk Kim 

Reviewed-by: Chao Yu 

Thanks,


--
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


Re: [f2fs-dev] [PATCH] fsck.f2fs: fix stack overflow when reading out nat block

2018-04-23 Thread Chao Yu
On 2018/4/21 10:15, Jaegeuk Kim wrote:
> The size of nat_block is less then 4KB, resulting in stack overflow by 
> dev_read.
> 
> Signed-off-by: Jaegeuk Kim 

Reviewed-by: Chao Yu 

Thanks,


--
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [RFC PATCH] f2fs-tools: introduce tune.f2fs

2018-04-23 Thread Junling Zheng
Introduce tune.f2fs tool to change the f2fs parameters.
Currently this tool only supports adding or removing encrypt
feature bit in superblock.

Signed-off-by: Junling Zheng 
---
 fsck/Makefile.am  |  3 ++-
 fsck/fsck.h   |  5 +
 fsck/main.c   | 60 ++
 fsck/tune.c   | 46 +
 include/f2fs_fs.h | 61 +++
 man/Makefile.am   |  2 +-
 man/tune.f2fs.8   | 50 +
 7 files changed, 207 insertions(+), 20 deletions(-)
 create mode 100644 fsck/tune.c
 create mode 100644 man/tune.f2fs.8

diff --git a/fsck/Makefile.am b/fsck/Makefile.am
index 1fc7310..3efacfd 100644
--- a/fsck/Makefile.am
+++ b/fsck/Makefile.am
@@ -5,7 +5,7 @@ AM_CFLAGS = -Wall
 sbin_PROGRAMS = fsck.f2fs
 noinst_HEADERS = common.h dict.h dqblk_v2.h f2fs.h fsck.h node.h quotaio.h 
quotaio_tree.h quotaio_v2.h xattr.h
 include_HEADERS = $(top_srcdir)/include/quota.h
-fsck_f2fs_SOURCES = main.c fsck.c dump.c mount.c defrag.c resize.c \
+fsck_f2fs_SOURCES = main.c fsck.c dump.c mount.c defrag.c resize.c tune.c \
node.c segment.c dir.c sload.c xattr.c \
dict.c mkquota.c quotaio.c quotaio_tree.c quotaio_v2.c
 fsck_f2fs_LDADD = ${libselinux_LIBS} ${libuuid_LIBS} 
$(top_builddir)/lib/libf2fs.la
@@ -15,3 +15,4 @@ install-data-hook:
ln -sf fsck.f2fs $(DESTDIR)/$(sbindir)/defrag.f2fs
ln -sf fsck.f2fs $(DESTDIR)/$(sbindir)/resize.f2fs
ln -sf fsck.f2fs $(DESTDIR)/$(sbindir)/sload.f2fs
+   ln -sf fsck.f2fs $(DESTDIR)/$(sbindir)/tune.f2fs
diff --git a/fsck/fsck.h b/fsck/fsck.h
index 3e13fc6..39d6ed4 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -180,6 +180,8 @@ extern void write_superblock(struct f2fs_super_block *);
 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);
 
+extern int validate_super_block(struct f2fs_sb_info *, int);
+extern void print_sb_state(struct f2fs_super_block *);
 extern void print_raw_sb_info(struct f2fs_super_block *);
 
 extern u32 get_free_segments(struct f2fs_sb_info *);
@@ -220,6 +222,9 @@ int f2fs_resize(struct f2fs_sb_info *);
 /* sload.c */
 int f2fs_sload(struct f2fs_sb_info *);
 
+/* tune.c */
+int f2fs_tune(struct f2fs_sb_info *);
+
 /* segment.c */
 void reserve_new_block(struct f2fs_sb_info *, block_t *,
struct f2fs_summary *, int);
diff --git a/fsck/main.c b/fsck/main.c
index c4dd8b1..b8e1aee 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -29,6 +29,7 @@ extern struct sparse_file *f2fs_sparse_file;
 #endif
 
 INIT_FEATURE_TABLE;
+INIT_TUNE_FEATURE_TABLE;
 
 static char *absolute_path(const char *file)
 {
@@ -123,6 +124,15 @@ void sload_usage()
exit(1);
 }
 
+void tune_usage()
+{
+   MSG(0, "\nUsage: tune.f2fs [options] device\n");
+   MSG(0, "[options]:\n");
+   MSG(0, "  -d debug level [default:0]\n");
+   MSG(0, "  -O [^]feature[,...]\n");
+   exit(1);
+}
+
 static int is_digits(char *optarg)
 {
unsigned int i;
@@ -145,6 +155,8 @@ static void error_out(char *prog)
resize_usage();
else if (!strcmp("sload.f2fs", prog))
sload_usage();
+   else if (!strcmp("tune.f2fs", prog))
+   tune_usage();
else
MSG(0, "\nWrong program.\n");
 }
@@ -528,6 +540,32 @@ void f2fs_parse_options(int argc, char *argv[])
if (err != NOERROR)
break;
}
+   } else if (!strcmp("tune.f2fs", prog)) {
+   const char *option_string = "d:O:";
+
+   c.func = TUNE;
+   while ((option = getopt(argc, argv, option_string)) != EOF) {
+   switch (option) {
+   case 'd':
+   if (!is_digits(optarg)) {
+   err = EWRONG_OPT;
+   break;
+   }
+   c.dbg_lv = atoi(optarg);
+   MSG(0, "Info: Debug level = %d\n",
+   c.dbg_lv);
+   break;
+   case 'O':
+   if (parse_feature(tune_feature_table, optarg))
+   tune_usage();
+   break;
+   default:
+   err = EUNKNOWN_OPT;
+   break;
+   }
+   if (err != NOERROR)
+   break;
+   }
}
 
add_default_options();
@@ -736,6 +774,13 @@ static int do_sload(struct f2fs_sb_info *sbi)
return f2fs_sload(sbi);
 }
 
+static 

[f2fs-dev] [PATCH] fsck.f2fs: fix to avoid accessing invalid memory address

2018-04-23 Thread Chao Yu
This patch adds to check return value of calloc in write_superblock().

Signed-off-by: Chao Yu 
---
 fsck/mount.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/fsck/mount.c b/fsck/mount.c
index 7e936dc056e5..badbe639742e 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -2155,6 +2155,7 @@ void write_superblock(struct f2fs_super_block *new_sb)
u_int8_t *buf;
 
buf = calloc(BLOCK_SZ, 1);
+   ASSERT(buf);
 
memcpy(buf + F2FS_SUPER_OFFSET, new_sb, sizeof(*new_sb));
for (index = 0; index < 2; index++) {
-- 
2.15.0.55.gc2ece9dc4de6


--
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel