Re: [f2fs-dev] [PATCH 1/5] f2fs: use bucket sort to avoid tree lookup and list sort when nat flushing

2017-06-09 Thread Hou Pengyang

On 2017/6/7 17:44, Chao Yu wrote:

On 2017/5/20 20:24, Hou Pengyang wrote:

during flush_nat_entries, we do:
1) gang_lookup a radix tree, find all the dirty nat_entry_set;
2) sort nat_entry_set by nat_entry_set->entry_cnt, in order to
 write to journal as much as possible to avoid unnessary IO.

This patch optimize the look_up & sort algorithm by introducing an array:

 f2fs_nm_info->dirty_set[NAT_ENTRY_PER_BLOCK+1];
 (struct list_head dirty_set[NAT_ENTRY_PER_BLOCK + 1])

dirty_set[1] links all nat_entry_set whose entry_cnt is 1
dirty_set[2] links all nat_entry_set whose entry_cnt is 2
..
dirty_set[N] links all nat_entry_set whose entry_cnt is N

as one NAT block has NAT_ENTRY_PER_BLOCK entries at MOST, so there should NOT
be one nat_entry_set whose entry_cnt is larger than NAT_ENTRY_PER_BLOCK.

So it is enough for f2fs_nm_info->dirty_set to link all nat_entry_sets in 
system.

Update:
 we update nat_entry_set in real-time, e.g originally 
nat_entry_set->entry_cnt is
1, and licked by dirty_set[1]; then call __set_nat_cache_dirty to increase 
nat_entry'sentry_cnt, we move this nat_entry_set ot dirty_set[2]'s tail, no 
need to compare.

Flush:
 when flush dirty nat_entry_set, we just flush nat_entry_set from
f2fs_nm_info->dirty_set[0] to f2fs_nm_info->dirty_set[NAT_ENTRY_PER_BLOCK], 
where
gang_lookup and sort can be avoid.

footprint of this algorithm:  sizeof(struct list_head)*NAT_ENTRY_PER_BLOCK
   = 8*455 = 3.6k bytes

Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
  fs/f2fs/f2fs.h |  2 ++
  fs/f2fs/node.c | 56 ++--
  2 files changed, 24 insertions(+), 34 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 093d68a..88a96bb 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -628,6 +628,8 @@ struct f2fs_nm_info {

/* for checkpoint */
char *nat_bitmap;   /* NAT bitmap pointer */
+   /* list dirty_set whose */
+   struct list_head dirty_set[NAT_ENTRY_PER_BLOCK + 1]; /* for */

unsigned int nat_bits_blocks;   /* # of nat bits blocks */
unsigned char *nat_bits;/* NAT bits blocks */
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index d22db8c..340c33d 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -174,13 +174,14 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info 
*nm_i,
list_move_tail(>list, >entry_list);
nm_i->dirty_nat_cnt++;
head->entry_cnt++;
+   list_move_tail(>set_list, &(nm_i->dirty_set[head->entry_cnt]));
set_nat_flag(ne, IS_DIRTY, true);
  }

  static void __clear_nat_cache_dirty(struct f2fs_nm_info *nm_i,
struct nat_entry_set *set, struct nat_entry *ne)
  {
-   list_move_tail(>list, _i->nat_entries);
+   list_move_tail(>list, _i->nat_entries); /* to be shrinked */
set_nat_flag(ne, IS_DIRTY, false);
set->entry_cnt--;
nm_i->dirty_nat_cnt--;
@@ -2340,24 +2341,6 @@ static void remove_nats_in_journal(struct f2fs_sb_info 
*sbi)
up_write(>journal_rwsem);
  }

-static void __adjust_nat_entry_set(struct nat_entry_set *nes,
-   struct list_head *head, int max)
-{
-   struct nat_entry_set *cur;
-
-   if (nes->entry_cnt >= max)
-   goto add_out;
-
-   list_for_each_entry(cur, head, set_list) {
-   if (cur->entry_cnt >= nes->entry_cnt) {
-   list_add(>set_list, cur->set_list.prev);
-   return;
-   }
-   }
-add_out:
-   list_add_tail(>set_list, head);
-}
-
  static void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid,
struct page *page)
  {
@@ -2460,9 +2443,11 @@ static void __flush_nat_entry_set(struct f2fs_sb_info 
*sbi,

/* Allow dirty nats by node block allocation in write_begin */
if (!set->entry_cnt) {
+   list_del(>set_list);
radix_tree_delete(_I(sbi)->nat_set_root, set->set);
kmem_cache_free(nat_entry_set_slab, set);
-   }
+   } else
+   f2fs_bug_on(sbi, 1);


Should remove this bug_on, because there will be new nat entries allocated
during flush nat entries since we allow buffered write during checkpoint.

Thanks,


hi, chao, I've got it. I will send a new version of this patch.
Thanks,



  }

  /*
@@ -2473,10 +2458,8 @@ void flush_nat_entries(struct f2fs_sb_info *sbi, struct 
cp_control *cpc)
struct f2fs_nm_info *nm_i = NM_I(sbi);
struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
struct f2fs_journal *journal = curseg->journal;
-   struct nat_entry_set *setvec[SETVEC_SIZE];
struct nat_entry_set *set, *tmp;
-   unsigned int found;
-   nid_t set_idx = 0;
+   int i;

Re: [f2fs-dev] [PATCH v2 0/5] f2fs: improve performance of NAT/SIT flushing during cp

2017-06-09 Thread Hou Pengyang

On 2017/5/24 12:14, Jaegeuk Kim wrote:

Hi Pengyang,

Could you please shed a light on some performance gains by this?


Hi, Jaegeuk,
Sorry for replying so late.

I've tested the duration of nat-radix-tree traveling and list-sort of
nat-entry, it is about *100us* averagely during fragmentation(arm64 mobile).

100us seems nobody for CP, but I still think it make senses for scenario
where massive dirty nat_entries exist in system(corner case, hard to 
produce).


Thanks,


Thanks,

On 05/20, Hou Pengyang wrote:

This patches are to designed to optimize NAT/SIT flushing procedure:

patch 1) -- patch 3):

during flush_nat_entries, we do:
1) gang_lookup a radix tree, find all the dirty nat_entry_set;
2) sort nat_entry_set by nat_entry_set->entry_cnt, in order to
 write to journal as much as possible to avoid unnessary IO.

This patch optimize the look_up & sort algorithm by introducing an array:

 f2fs_nm_info->dirty_set[NAT_ENTRY_PER_BLOCK+1];
 (struct list_head dirty_set[NAT_ENTRY_PER_BLOCK + 1])

dirty_set[1] links all nat_entry_set whose entry_cnt is 1
dirty_set[2] links all nat_entry_set whose entry_cnt is 2
..
dirty_set[N] links all nat_entry_set whose entry_cnt is N

as one NAT block has NAT_ENTRY_PER_BLOCK entries at MOST, so there should NOT
be one nat_entry_set whose entry_cnt is larger than NAT_ENTRY_PER_BLOCK.

So it is enough for f2fs_nm_info->dirty_set to link all nat_entry_sets in 
system.

Update:
 we update nat_entry_set in real-time, e.g originally 
nat_entry_set->entry_cnt is
1, and licked by dirty_set[1]; then call __set_nat_cache_dirty to increase 
nat_entry's
entry_cnt, we move this nat_entry_set ot dirty_set[2]'s tail, no need to 
compare.

Flush:
 when flush dirty nat_entry_set, we just flush nat_entry_set from
f2fs_nm_info->dirty_set[0] to f2fs_nm_info->dirty_set[NAT_ENTRY_PER_BLOCK], 
where
gang_lookup and sort can be avoid.

footprint of this algorithm:  sizeof(struct list_head)*NAT_ENTRY_PER_BLOCK
   = 8*455 = 3.6k bytes

Same for SIT.

In patch 5), we use array to manage sit_entry_sets instead of list, which
can avoid list travel, and there is no need to alloc/free lab memory.
It is low footrpint consuming.

Hou Pengyang (5):
   f2fs: use bucket sort to avoid tree lookup and list sort when nat flushing
   f2fs: reconstruct sit flushing code
   f2fs: use bucket sort to avoid list sort when flush sit entries
   f2fs: avoid unnecessary to_journal checking
   f2fs: use an array to record sit_entry_set info to make sort fast

  fs/f2fs/f2fs.h|   5 +-
  fs/f2fs/node.c|  79 ---
  fs/f2fs/segment.c | 227 ++
  fs/f2fs/segment.h |   2 +-
  4 files changed, 147 insertions(+), 166 deletions(-)

--
2.10.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


.





--
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 4/5] f2fs: avoid unnecessary to_journal checking

2017-05-20 Thread Hou Pengyang
There is no need to do __has_cursem_space checking everytime, this patch fixes 
it.

Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
 fs/f2fs/node.c | 27 ++-
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 340c33d..58b4f7a 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -2373,25 +2373,15 @@ static void __update_nat_bits(struct f2fs_sb_info *sbi, 
nid_t start_nid,
 }
 
 static void __flush_nat_entry_set(struct f2fs_sb_info *sbi,
-   struct nat_entry_set *set, struct cp_control *cpc)
+   struct nat_entry_set *set, struct cp_control *cpc, bool 
to_journal)
 {
struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
struct f2fs_journal *journal = curseg->journal;
nid_t start_nid = set->set * NAT_ENTRY_PER_BLOCK;
-   bool to_journal = true;
struct f2fs_nat_block *nat_blk;
struct nat_entry *ne, *cur;
struct page *page = NULL;
 
-   /*
-* there are two steps to flush nat entries:
-* #1, flush nat entries to journal in current hot data summary block.
-* #2, flush nat entries to nat page.
-*/
-   if (enabled_nat_bits(sbi, cpc) ||
-   !__has_cursum_space(journal, set->entry_cnt, NAT_JOURNAL))
-   to_journal = false;
-
if (to_journal) {
down_write(>journal_rwsem);
} else {
@@ -2459,6 +2449,7 @@ void flush_nat_entries(struct f2fs_sb_info *sbi, struct 
cp_control *cpc)
struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
struct f2fs_journal *journal = curseg->journal;
struct nat_entry_set *set, *tmp;
+   bool to_journal = true;
int i;
LIST_HEAD(sets);
 
@@ -2476,9 +2467,19 @@ void flush_nat_entries(struct f2fs_sb_info *sbi, struct 
cp_control *cpc)
!__has_cursum_space(journal, nm_i->dirty_nat_cnt, NAT_JOURNAL))
remove_nats_in_journal(sbi);
 
+   /*
+* there are two steps to flush nat entries:
+* #1, flush nat entries to journal in current hot data summary block.
+* #2, flush nat entries to nat page.
+*/
for (i = 0; i <= NAT_ENTRY_PER_BLOCK; i++) {
-   list_for_each_entry_safe(set, tmp, _i->dirty_set[i], 
set_list)
-   __flush_nat_entry_set(sbi, set, cpc);
+   list_for_each_entry_safe(set, tmp, _i->dirty_set[i], 
set_list) {
+   if (to_journal && (enabled_nat_bits(sbi, cpc) ||
+   !__has_cursum_space(journal, set->entry_cnt, 
NAT_JOURNAL)))
+   to_journal = false;
+
+   __flush_nat_entry_set(sbi, set, cpc, to_journal);
+   }
f2fs_bug_on(sbi, !list_empty(_i->dirty_set[i]));
}
 
-- 
2.10.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 5/5] f2fs: use an array to record sit_entry_set info to make sort fast

2017-05-20 Thread Hou Pengyang
Currently, we dynamicly alloc sit_entry_set from slab, and link all the 
sit_entry_set
by sit_entry_set->set_list.

It is inefficient, since in add_sit_entry, we may need to travel all the list 
to find
the target sit_entry_set.

This patch fixes this by introducing a static array:

f2fs_sm_info->sit_sets
(struct sit_entry_set *sit_sets)

when we can find the target sit_entry_set in O(1) time, and then to update the 
sit_entry_set
info.

What's more there is no need to alloc/free slab memory.

footprint:(64bit machine)

1T   :  sizeof(struct sit_entry_set) * 1T/(2M*55) = 0.87M
128G :  sizeof(struct sit_entry_set) * 128G/(2M*55) = 1.16k
64G  :  0.55k
32G  :  0.27k


Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
 fs/f2fs/f2fs.h|  2 +-
 fs/f2fs/segment.c | 75 +++
 fs/f2fs/segment.h |  1 -
 3 files changed, 26 insertions(+), 52 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 198da30..429d33b 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -732,7 +732,7 @@ struct f2fs_sm_info {
/* for batched trimming */
unsigned int trim_sections; /* # of sections to trim */
 
-   struct list_head sit_entry_set; /* sit entry set list */
+   struct sit_entry_set *sit_sets; /* # of dirty segment in this 
sit_entry_set */
struct list_head dirty_set[SIT_ENTRY_PER_BLOCK + 1];
 
unsigned int ipu_policy;/* in-place-update policy */
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index af470d3..04d6329 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -28,7 +28,6 @@
 
 static struct kmem_cache *discard_entry_slab;
 static struct kmem_cache *discard_cmd_slab;
-static struct kmem_cache *sit_entry_set_slab;
 static struct kmem_cache *inmem_entry_slab;
 
 static unsigned long __reverse_ulong(unsigned char *str)
@@ -2641,56 +2640,30 @@ static struct page *get_next_sit_page(struct 
f2fs_sb_info *sbi,
return dst_page;
 }
 
-static struct sit_entry_set *grab_sit_entry_set(void)
-{
-   struct sit_entry_set *ses =
-   f2fs_kmem_cache_alloc(sit_entry_set_slab, GFP_NOFS);
-
-   ses->entry_cnt = 0;
-   INIT_LIST_HEAD(>set_list);
-   INIT_LIST_HEAD(>cnt_list);
-   return ses;
-}
-
 static void release_sit_entry_set(struct sit_entry_set *ses)
 {
-   list_del(>set_list);
list_del(>cnt_list);
-   kmem_cache_free(sit_entry_set_slab, ses);
+   INIT_LIST_HEAD(>cnt_list);
 }
 
 static void add_sit_entry(struct f2fs_sb_info *sbi,
-   unsigned int segno, struct list_head 
*head)
+   unsigned int segno)
 {
-   struct sit_entry_set *ses;
struct f2fs_sm_info *sm_i = SM_I(sbi);
-   unsigned int start_segno = START_SEGNO(segno);
+   unsigned int set = SIT_BLOCK_OFFSET(segno);
+   struct sit_entry_set *ses= _i->sit_sets[set];
 
-   list_for_each_entry(ses, head, set_list) {
-   if (ses->start_segno == start_segno) {
-   ses->entry_cnt++;
-   list_move_tail(>cnt_list, 
_i->dirty_set[ses->entry_cnt]);
-   return;
-   }
-   }
-
-   ses = grab_sit_entry_set();
-
-   ses->start_segno = start_segno;
ses->entry_cnt++;
list_move_tail(>cnt_list, _i->dirty_set[ses->entry_cnt]);
-   list_add(>set_list, head);
 }
 
 static void add_sits_in_set(struct f2fs_sb_info *sbi)
 {
-   struct f2fs_sm_info *sm_info = SM_I(sbi);
-   struct list_head *set_list = _info->sit_entry_set;
unsigned long *bitmap = SIT_I(sbi)->dirty_sentries_bitmap;
unsigned int segno;
 
for_each_set_bit(segno, bitmap, MAIN_SEGS(sbi))
-   add_sit_entry(sbi, segno, set_list);
+   add_sit_entry(sbi, segno);
 }
 
 static void remove_sits_in_journal(struct f2fs_sb_info *sbi)
@@ -2708,7 +2681,7 @@ static void remove_sits_in_journal(struct f2fs_sb_info 
*sbi)
dirtied = __mark_sit_entry_dirty(sbi, segno);
 
if (!dirtied)
-   add_sit_entry(sbi, segno, _I(sbi)->sit_entry_set);
+   add_sit_entry(sbi, segno);
}
update_sits_in_cursum(journal, -i);
up_write(>journal_rwsem);
@@ -2788,7 +2761,6 @@ void flush_sit_entries(struct f2fs_sb_info *sbi, struct 
cp_control *cpc)
struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
struct f2fs_journal *journal = curseg->journal;
struct sit_entry_set *ses, *tmp;
-   struct list_head *head = _I(sbi)->sit_entry_set;
bool to_journal = true;
int i;
 
@@ -2826,7 +2798,6 @@ void flush_sit_entries(struct f2fs_sb_info *sbi, struct 
cp_control *cpc)
f2fs_bug_on(sbi, !list_empty(_i->dirty_set[i]));

[f2fs-dev] [PATCH 1/5] f2fs: use bucket sort to avoid tree lookup and list sort when nat flushing

2017-05-20 Thread Hou Pengyang
during flush_nat_entries, we do: 
1) gang_lookup a radix tree, find all the dirty nat_entry_set;
2) sort nat_entry_set by nat_entry_set->entry_cnt, in order to 
write to journal as much as possible to avoid unnessary IO. 

This patch optimize the look_up & sort algorithm by introducing an array:

f2fs_nm_info->dirty_set[NAT_ENTRY_PER_BLOCK+1];
(struct list_head dirty_set[NAT_ENTRY_PER_BLOCK + 1]) 

dirty_set[1] links all nat_entry_set whose entry_cnt is 1
dirty_set[2] links all nat_entry_set whose entry_cnt is 2
..
dirty_set[N] links all nat_entry_set whose entry_cnt is N

as one NAT block has NAT_ENTRY_PER_BLOCK entries at MOST, so there should NOT 
be one nat_entry_set whose entry_cnt is larger than NAT_ENTRY_PER_BLOCK.

So it is enough for f2fs_nm_info->dirty_set to link all nat_entry_sets in 
system.

Update:
we update nat_entry_set in real-time, e.g originally 
nat_entry_set->entry_cnt is
1, and licked by dirty_set[1]; then call __set_nat_cache_dirty to increase 
nat_entry'sentry_cnt, we move this nat_entry_set ot dirty_set[2]'s tail, no 
need to compare.

Flush:
when flush dirty nat_entry_set, we just flush nat_entry_set from
f2fs_nm_info->dirty_set[0] to f2fs_nm_info->dirty_set[NAT_ENTRY_PER_BLOCK], 
where
gang_lookup and sort can be avoid.

footprint of this algorithm:  sizeof(struct list_head)*NAT_ENTRY_PER_BLOCK
  = 8*455 = 3.6k bytes

Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
 fs/f2fs/f2fs.h |  2 ++
 fs/f2fs/node.c | 56 ++--
 2 files changed, 24 insertions(+), 34 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 093d68a..88a96bb 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -628,6 +628,8 @@ struct f2fs_nm_info {
 
/* for checkpoint */
char *nat_bitmap;   /* NAT bitmap pointer */
+   /* list dirty_set whose */
+   struct list_head dirty_set[NAT_ENTRY_PER_BLOCK + 1]; /* for */
 
unsigned int nat_bits_blocks;   /* # of nat bits blocks */
unsigned char *nat_bits;/* NAT bits blocks */
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index d22db8c..340c33d 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -174,13 +174,14 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info 
*nm_i,
list_move_tail(>list, >entry_list);
nm_i->dirty_nat_cnt++;
head->entry_cnt++;
+   list_move_tail(>set_list, &(nm_i->dirty_set[head->entry_cnt]));
set_nat_flag(ne, IS_DIRTY, true);
 }
 
 static void __clear_nat_cache_dirty(struct f2fs_nm_info *nm_i,
struct nat_entry_set *set, struct nat_entry *ne)
 {
-   list_move_tail(>list, _i->nat_entries);
+   list_move_tail(>list, _i->nat_entries); /* to be shrinked */
set_nat_flag(ne, IS_DIRTY, false);
set->entry_cnt--;
nm_i->dirty_nat_cnt--;
@@ -2340,24 +2341,6 @@ static void remove_nats_in_journal(struct f2fs_sb_info 
*sbi)
up_write(>journal_rwsem);
 }
 
-static void __adjust_nat_entry_set(struct nat_entry_set *nes,
-   struct list_head *head, int max)
-{
-   struct nat_entry_set *cur;
-
-   if (nes->entry_cnt >= max)
-   goto add_out;
-
-   list_for_each_entry(cur, head, set_list) {
-   if (cur->entry_cnt >= nes->entry_cnt) {
-   list_add(>set_list, cur->set_list.prev);
-   return;
-   }
-   }
-add_out:
-   list_add_tail(>set_list, head);
-}
-
 static void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid,
struct page *page)
 {
@@ -2460,9 +2443,11 @@ static void __flush_nat_entry_set(struct f2fs_sb_info 
*sbi,
 
/* Allow dirty nats by node block allocation in write_begin */
if (!set->entry_cnt) {
+   list_del(>set_list);
radix_tree_delete(_I(sbi)->nat_set_root, set->set);
kmem_cache_free(nat_entry_set_slab, set);
-   }
+   } else
+   f2fs_bug_on(sbi, 1);
 }
 
 /*
@@ -2473,10 +2458,8 @@ void flush_nat_entries(struct f2fs_sb_info *sbi, struct 
cp_control *cpc)
struct f2fs_nm_info *nm_i = NM_I(sbi);
struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
struct f2fs_journal *journal = curseg->journal;
-   struct nat_entry_set *setvec[SETVEC_SIZE];
struct nat_entry_set *set, *tmp;
-   unsigned int found;
-   nid_t set_idx = 0;
+   int i;
LIST_HEAD(sets);
 
if (!nm_i->dirty_nat_cnt)
@@ -2493,19 +2476,12 @@ void flush_nat_entries(struct f2fs_sb_info *sbi, struct 
cp_control *cpc)
!__has_cursum_space(journal, nm_i->dirty_nat_cnt, NAT_JOURNAL))
remove_nats_in_journal(sbi);
 
-   while ((found = __gang_look

[f2fs-dev] [PATCH 0/3] f2fs: imporve performance for IPU

2017-05-05 Thread Hou Pengyang
Currently, if we do get_node_of_data before f2fs_lock_op, there may be dead 
lock  
as follows, where process A would be in infinite loop, and B will NOT be awaked.

Process A(cp):Process B:
f2fs_lock_all(sbi)
get_dnode_of_data < lock dn.node_page
flush_nodes f2fs_lock_op

However, in do_write_data_page path, we had better do get_node_of_data first, 
since
we can check IPU in prior and do IPU without f2fs_lock_op. It make senses for 
our 
current FSYNC IPU to avoid being blocked by cp. 

What's more, in patch 3), we do IPU if sync io is blocked by cp.


Hou Pengyang (3):
  f2fs: do get_dnode_of_data before f2fs_lock_op
  f2fs: check IPU after reading dnode from disk
  f2fs: try IPU if sync io is blocked by cp

 fs/f2fs/data.c | 77 --
 fs/f2fs/f2fs.h |  6 +
 fs/f2fs/node.c |  1 +
 3 files changed, 71 insertions(+), 13 deletions(-)

-- 
2.10.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 1/3] f2fs: do get_dnode_of_data before f2fs_lock_op

2017-05-05 Thread Hou Pengyang
Currently, if we do get_node_of_data before f2fs_lock_op, there may be dead lock
as follows, where process A would be in infinite loop, and B will NOT be awaked.

Process A(cp):Process B:
f2fs_lock_all(sbi)
get_dnode_of_data < lock dn.node_page
flush_nodes f2fs_lock_op

However, in do_write_data_page path, we had better do get_node_of_data first, 
since
we can check IPU in prior and do IPU without f2fs_lock_op. It make senses for 
our 
current FSYNC IPU to avoid being blocked by cp. 

Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
 fs/f2fs/data.c | 38 +++---
 fs/f2fs/f2fs.h |  1 +
 fs/f2fs/node.c |  1 +
 3 files changed, 29 insertions(+), 11 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 1254986..075d159 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1373,20 +1373,37 @@ int do_write_data_page(struct f2fs_io_info *fio)
}
}
 
-   if (fio->need_lock)
-   f2fs_lock_op(fio->sbi);
-
err = get_dnode_of_data(, page->index, LOOKUP_NODE);
-   if (err)
-   goto out;
+   if (!err) {
+   fio->old_blkaddr  = dn.data_blkaddr;
+   /* This page is already truncated */
+   if (fio->old_blkaddr == NULL_ADDR) {
+   ClearPageUptodate(page);
+   goto out_writepage;
+   }
+   unlock_page(dn.node_page);
+   dn.node_page_locked = false;
+   } else
+   return err;
 
-   fio->old_blkaddr = dn.data_blkaddr;
+   if (fio->need_lock)
+   f2fs_lock_op(fio->sbi);
 
-   /* This page is already truncated */
-   if (fio->old_blkaddr == NULL_ADDR) {
-   ClearPageUptodate(page);
-   goto out_writepage;
+   if (!dn.node_page_locked) {
+   /*
+* It is safe to lock_page here, since we've hold
+* reference of this page, but there may be conflict
+* with trucate/fallocate(FL_ZERO_RANGE/PUNCH_HOLE)
+* so after lock_page, we check dn->old_addr if is
+* NULL_ADDR.
+*/
+   lock_page(dn.node_page);
+   fio->old_blkaddr = datablock_addr(dn.node_page, dn.ofs_in_node);
+   if (fio->old_blkaddr == NULL_ADDR) {
+   goto out_writepage;
+   }
}
+
 got_it:
err = encrypt_one_page(fio);
if (err)
@@ -1416,7 +1433,6 @@ int do_write_data_page(struct f2fs_io_info *fio)
set_inode_flag(inode, FI_FIRST_BLOCK_WRITTEN);
 out_writepage:
f2fs_put_dnode();
-out:
if (fio->need_lock)
f2fs_unlock_op(fio->sbi);
return err;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index baefe37..2d50d7b 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -651,6 +651,7 @@ struct dnode_of_data {
nid_t nid;  /* node id of the direct node block */
unsigned int ofs_in_node;   /* data offset in the node page */
bool inode_page_locked; /* inode page is locked or not */
+   bool node_page_locked;  /* dnode page is locked or not */
bool node_changed;  /* is node block changed */
char cur_level; /* level of hole node page */
char max_level; /* level of current page located */
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 98351a4..7cc6114 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -650,6 +650,7 @@ int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t 
index, int mode)
dn->ofs_in_node = offset[level];
dn->node_page = npage[level];
dn->data_blkaddr = datablock_addr(dn->node_page, dn->ofs_in_node);
+   dn->node_page_locked = true;
return 0;
 
 release_pages:
-- 
2.10.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 3/3] f2fs: try IPU if sync io is blocked by cp

2017-05-05 Thread Hou Pengyang
For sync io, if it is blocked by cp, we try to do IPU for this page.

Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
 fs/f2fs/data.c | 36 
 fs/f2fs/f2fs.h |  5 +
 2 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index e41f5ed..26362ae 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1329,9 +1329,9 @@ static int encrypt_one_page(struct f2fs_io_info *fio)
return PTR_ERR(fio->encrypted_page);
 }
 
-static inline bool need_inplace_update(struct f2fs_io_info *fio)
+static inline bool safe_for_ipu(struct f2fs_io_info *fio)
 {
-   struct inode *inode = fio->page->mapping->host;
+   struct inode *inode = fio->page->mapping->host;
 
if (S_ISDIR(inode->i_mode) || f2fs_is_atomic_file(inode))
return false;
@@ -1339,6 +1339,16 @@ static inline bool need_inplace_update(struct 
f2fs_io_info *fio)
return false;
if (IS_ATOMIC_WRITTEN_PAGE(fio->page))
return false;
+   return true;
+
+}
+
+static inline bool need_inplace_update(struct f2fs_io_info *fio)
+{
+   struct inode *inode = fio->page->mapping->host;
+
+   if (!safe_for_ipu(fio))
+   return false;
 
return need_inplace_update_policy(inode, fio);
 }
@@ -1352,6 +1362,13 @@ static inline bool valid_ipu_blkaddr(struct f2fs_io_info 
*fio)
return true;
 }
 
+static inline bool is_sync_io(struct f2fs_io_info *fio)
+{
+   if (fio && fio->op == REQ_OP_WRITE && fio->op_flags & REQ_SYNC)
+   return true;
+   return false;
+}
+
 int do_write_data_page(struct f2fs_io_info *fio)
 {
struct page *page = fio->page;
@@ -1393,8 +1410,19 @@ int do_write_data_page(struct f2fs_io_info *fio)
} else
return err;
 
-   if (fio->need_lock)
-   f2fs_lock_op(fio->sbi);
+   /*
+* After checking all the IPU senario, we try to lock_op
+* If lock_op fail, we do another IPU try for sync io.
+*/
+   if (fio->need_lock && !f2fs_try_lock_op(fio->sbi)) {
+   if (valid_ipu_blkaddr(fio) &&
+   is_sync_io(fio) && safe_for_ipu(fio)) {
+   fio->need_lock = false;
+   ipu_force = true;
+   } else {
+   f2fs_lock_op(fio->sbi);
+   }
+   }
 
if (!dn.node_page_locked) {
/*
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 2d50d7b..e820253 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1268,6 +1268,11 @@ static inline bool enabled_nat_bits(struct f2fs_sb_info 
*sbi,
return (cpc) ? (cpc->reason & CP_UMOUNT) && set : set;
 }
 
+static inline int f2fs_try_lock_op(struct f2fs_sb_info *sbi)
+{
+   return down_read_trylock(>cp_rwsem);
+}
+
 static inline void f2fs_lock_op(struct f2fs_sb_info *sbi)
 {
down_read(>cp_rwsem);
-- 
2.10.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 2/3] f2fs: check IPU after reading dnode from disk

2017-05-05 Thread Hou Pengyang
Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
 fs/f2fs/data.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 075d159..e41f5ed 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1381,6 +1381,13 @@ int do_write_data_page(struct f2fs_io_info *fio)
ClearPageUptodate(page);
goto out_writepage;
}
+
+   if (valid_ipu_blkaddr(fio) && need_inplace_update(fio)) {
+   ipu_force = true;
+   fio->need_lock = false;
+   goto got_it;
+   }
+   /* If NOT IPU, we should unlock node_page for cp */
unlock_page(dn.node_page);
dn.node_page_locked = false;
} else
-- 
2.10.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 3/4] f2fs: check IPU before cp to avoid IPU being blocked by cp

2017-04-25 Thread Hou Pengyang
IPU checking is under f2fs_lock_op, as a result, some IPU page(such as 
fsync/fdatasync IPU)
may be blocked by a long time cp.

This patch fix this by doing IPU checking before f2fs_lock_op, so fsync IPU 
could go along with cp.

Suggested-by: He Yunlei <heyun...@huawei.com>
Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
 fs/f2fs/data.c| 14 +++---
 fs/f2fs/gc.c  |  1 +
 fs/f2fs/segment.c |  1 +
 3 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 183a426..9bf9c7d 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1380,19 +1380,20 @@ int do_write_data_page(struct f2fs_io_info *fio)
 * it had better in-place writes for updated data.
 */
if (need_inplace_update(fio)) {
-   f2fs_bug_on(fio->sbi, !fio->cp_rwsem_locked);
-   f2fs_unlock_op(fio->sbi);
-   fio->cp_rwsem_locked = false;
-
+   f2fs_bug_on(fio->sbi, fio->cp_rwsem_locked);
err = rewrite_data_page(fio);
trace_f2fs_do_write_data_page(fio->page, IPU);
set_inode_flag(inode, FI_UPDATE_WRITE);
} else {
+   if (!fio->cp_rwsem_locked)
+   f2fs_lock_op(fio->sbi);
write_data_page(, fio);
trace_f2fs_do_write_data_page(page, OPU);
set_inode_flag(inode, FI_APPEND_WRITE);
if (page->index == 0)
set_inode_flag(inode, FI_FIRST_BLOCK_WRITTEN);
+   if (!fio->cp_rwsem_locked)
+   f2fs_unlock_op(fio->sbi);
}
 out_writepage:
f2fs_put_dnode();
@@ -1473,13 +1474,12 @@ static int __write_data_page(struct page *page, bool 
*submitted,
if (!err)
goto out;
}
-   f2fs_lock_op(sbi);
+
+   fio.cp_rwsem_locked = false;
if (err == -EAGAIN)
err = do_write_data_page();
if (F2FS_I(inode)->last_disk_size < psize)
F2FS_I(inode)->last_disk_size = psize;
-   if (fio.cp_rwsem_locked)
-   f2fs_unlock_op(sbi);
 done:
if (err && err != -ENOENT)
goto redirty_out;
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index e034857..b32cc30 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -715,6 +715,7 @@ static void move_data_page(struct inode *inode, block_t 
bidx, int gc_type,
.old_blkaddr = NULL_ADDR,
.page = page,
.encrypted_page = NULL,
+   .cp_rwsem_locked = true,
};
bool is_dirty = PageDirty(page);
int err;
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 9f86b98..463a77b 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -293,6 +293,7 @@ static int __commit_inmem_pages(struct inode *inode,
.op_flags = REQ_SYNC | REQ_PRIO,
.old_blkaddr = NULL_ADDR,
.encrypted_page = NULL,
+   .cp_rwsem_locked = true,
};
pgoff_t last_idx = ULONG_MAX;
int err = 0;
-- 
2.10.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 0/4] optimize f2fs IPU v3

2017-04-25 Thread Hou Pengyang
patch 1): Reconstruct code in do_write_data_page, code logic stays unchanged,
patch 2): f2fs: lookup extent cache first under IPU scenario
patch 3): Check IPU before cp to avoid IPU being blocked by cp
patch 3): Unlock dnode before IPU

Change log for v3: 
- check IPU without f2fs_lock_op, to avoid IPU(fsync/fdatasync IPU) being 
blocked by long time cp

Hou Pengyang (4):
  f2fs: reconstruct code to write a data page
  f2fs: lookup extent cache first under IPU scenario
  f2fs: check IPU before cp to avoid IPU being blocked by cp
  f2fs: unlock dnode before IPU

 fs/f2fs/data.c| 98 +++
 fs/f2fs/file.c|  2 +-
 fs/f2fs/gc.c  |  2 ++
 fs/f2fs/segment.c |  2 ++
 fs/f2fs/segment.h |  2 +-
 5 files changed, 69 insertions(+), 37 deletions(-)

-- 
2.10.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 1/4] f2fs: reconstruct code to write a data page

2017-04-25 Thread Hou Pengyang
This patch introduces encrypt_one_page which encrypts one data page before
submit_bio, and change the use of need_inplace_update.

Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
Signed-off-by: Chao Yu <yuch...@huawei.com>
Signed-off-by: Jaegeuk Kim <jaeg...@kernel.org>
---
 fs/f2fs/data.c| 77 +--
 fs/f2fs/file.c|  2 +-
 fs/f2fs/segment.h |  2 +-
 3 files changed, 49 insertions(+), 32 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index b8dcd1e..02400b0 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1302,6 +1302,45 @@ static int f2fs_read_data_pages(struct file *file,
return f2fs_mpage_readpages(mapping, pages, NULL, nr_pages);
 }
 
+static int encrypt_one_page(struct f2fs_io_info *fio)
+{
+   struct inode *inode = fio->page->mapping->host;
+   gfp_t gfp_flags = GFP_NOFS;
+
+   if (!f2fs_encrypted_inode(inode) || !S_ISREG(inode->i_mode))
+   return 0;
+
+   /* wait for GCed encrypted page writeback */
+   f2fs_wait_on_encrypted_page_writeback(fio->sbi, fio->old_blkaddr);
+
+retry_encrypt:
+   fio->encrypted_page = fscrypt_encrypt_page(inode, fio->page,
+   PAGE_SIZE, 0, fio->page->index, gfp_flags);
+   if (!IS_ERR(fio->encrypted_page))
+   return 0;
+
+   /* flush pending IOs and wait for a while in the ENOMEM case */
+   if (PTR_ERR(fio->encrypted_page) == -ENOMEM) {
+   f2fs_flush_merged_bios(fio->sbi);
+   congestion_wait(BLK_RW_ASYNC, HZ/50);
+   gfp_flags |= __GFP_NOFAIL;
+   goto retry_encrypt;
+   }
+   return PTR_ERR(fio->encrypted_page);
+}
+
+static inline bool need_inplace_update(struct f2fs_io_info *fio)
+{
+   if (fio->old_blkaddr == NEW_ADDR)
+   return false;
+   if (is_cold_data(fio->page))
+   return false;
+   if (IS_ATOMIC_WRITTEN_PAGE(fio->page))
+   return false;
+
+   return need_inplace_update_policy(fio->page->mapping->host, fio);
+}
+
 int do_write_data_page(struct f2fs_io_info *fio)
 {
struct page *page = fio->page;
@@ -1322,30 +1361,9 @@ int do_write_data_page(struct f2fs_io_info *fio)
goto out_writepage;
}
 
-   if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode)) {
-   gfp_t gfp_flags = GFP_NOFS;
-
-   /* wait for GCed encrypted page writeback */
-   f2fs_wait_on_encrypted_page_writeback(F2FS_I_SB(inode),
-   fio->old_blkaddr);
-retry_encrypt:
-   fio->encrypted_page = fscrypt_encrypt_page(inode, fio->page,
-   PAGE_SIZE, 0,
-   fio->page->index,
-   gfp_flags);
-   if (IS_ERR(fio->encrypted_page)) {
-   err = PTR_ERR(fio->encrypted_page);
-   if (err == -ENOMEM) {
-   /* flush pending ios and wait for a while */
-   f2fs_flush_merged_bios(F2FS_I_SB(inode));
-   congestion_wait(BLK_RW_ASYNC, HZ/50);
-   gfp_flags |= __GFP_NOFAIL;
-   err = 0;
-   goto retry_encrypt;
-   }
-   goto out_writepage;
-   }
-   }
+   err = encrypt_one_page(fio);
+   if (err)
+   goto out_writepage;
 
set_page_writeback(page);
 
@@ -1353,15 +1371,14 @@ int do_write_data_page(struct f2fs_io_info *fio)
 * If current allocation needs SSR,
 * it had better in-place writes for updated data.
 */
-   if (unlikely(fio->old_blkaddr != NEW_ADDR &&
-   !is_cold_data(page) &&
-   !IS_ATOMIC_WRITTEN_PAGE(page) &&
-   need_inplace_update(inode, fio))) {
-   f2fs_unlock_op(F2FS_I_SB(inode));
+   if (need_inplace_update(fio)) {
+   f2fs_bug_on(fio->sbi, !fio->cp_rwsem_locked);
+   f2fs_unlock_op(fio->sbi);
fio->cp_rwsem_locked = false;
+
err = rewrite_data_page(fio);
+   trace_f2fs_do_write_data_page(fio->page, IPU);
set_inode_flag(inode, FI_UPDATE_WRITE);
-   trace_f2fs_do_write_data_page(page, IPU);
} else {
write_data_page(, fio);
trace_f2fs_do_write_data_page(page, OPU);
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index e7a2b54..a0d9588 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -1898,7 +1898,7 @@ static int f2fs_defragment_range(struct 

[f2fs-dev] [PATCH 2/4] f2fs: lookup extent cache first under IPU scenario

2017-04-25 Thread Hou Pengyang
If a page is cold, NOT atomit written and need_ipu now, there is
a high probability that IPU should be adapted. For IPU, we try to
check extent tree to get the block index first, instead of reading
the dnode page, where may lead to an useless dnode IO, since no need to
update the dnode index for IPU.

Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
Signed-off-by: Chao Yu <yuch...@huawei.com>
---
 fs/f2fs/data.c| 11 ++-
 fs/f2fs/gc.c  |  1 +
 fs/f2fs/segment.c |  1 +
 3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 02400b0..183a426 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1346,21 +1346,29 @@ int do_write_data_page(struct f2fs_io_info *fio)
struct page *page = fio->page;
struct inode *inode = page->mapping->host;
struct dnode_of_data dn;
+   struct extent_info ei = {0,0,0};
int err = 0;
 
set_new_dnode(, inode, NULL, NULL, 0);
+   if (need_inplace_update(fio) &&
+   f2fs_lookup_extent_cache(inode, page->index, )) {
+   fio->old_blkaddr = ei.blk + page->index - ei.fofs;
+   if (fio->old_blkaddr != NULL_ADDR &&
+   fio->old_blkaddr != NEW_ADDR)
+   goto got_it;
+   }
err = get_dnode_of_data(, page->index, LOOKUP_NODE);
if (err)
return err;
 
fio->old_blkaddr = dn.data_blkaddr;
-
/* This page is already truncated */
if (fio->old_blkaddr == NULL_ADDR) {
ClearPageUptodate(page);
goto out_writepage;
}
 
+got_it:
err = encrypt_one_page(fio);
if (err)
goto out_writepage;
@@ -1408,6 +1416,7 @@ static int __write_data_page(struct page *page, bool 
*submitted,
.type = DATA,
.op = REQ_OP_WRITE,
.op_flags = wbc_to_write_flags(wbc),
+   .old_blkaddr = NULL_ADDR,
.page = page,
.encrypted_page = NULL,
.submitted = false,
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 499a43f..e034857 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -712,6 +712,7 @@ static void move_data_page(struct inode *inode, block_t 
bidx, int gc_type,
.type = DATA,
.op = REQ_OP_WRITE,
.op_flags = REQ_SYNC,
+   .old_blkaddr = NULL_ADDR,
.page = page,
.encrypted_page = NULL,
};
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 2a95535..9f86b98 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -291,6 +291,7 @@ static int __commit_inmem_pages(struct inode *inode,
.type = DATA,
.op = REQ_OP_WRITE,
.op_flags = REQ_SYNC | REQ_PRIO,
+   .old_blkaddr = NULL_ADDR,
.encrypted_page = NULL,
};
pgoff_t last_idx = ULONG_MAX;
-- 
2.10.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 4/4] f2fs: unlock dnode before IPU

2017-04-25 Thread Hou Pengyang
Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
 fs/f2fs/data.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 9bf9c7d..1d7157b 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1381,9 +1381,11 @@ int do_write_data_page(struct f2fs_io_info *fio)
 */
if (need_inplace_update(fio)) {
f2fs_bug_on(fio->sbi, fio->cp_rwsem_locked);
+   f2fs_put_dnode();
err = rewrite_data_page(fio);
trace_f2fs_do_write_data_page(fio->page, IPU);
set_inode_flag(inode, FI_UPDATE_WRITE);
+   return err;
} else {
if (!fio->cp_rwsem_locked)
f2fs_lock_op(fio->sbi);
-- 
2.10.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 2/3] f2fs: lookup extent cache first under IPU scenario

2017-04-22 Thread Hou Pengyang
Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
Signed-off-by: Chao Yu <yuch...@huawei.com>
---
 fs/f2fs/data.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 6b18750..1c99ae1 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1367,8 +1367,32 @@ int do_write_data_page(struct f2fs_io_info *fio)
struct page *page = fio->page;
struct inode *inode = page->mapping->host;
struct dnode_of_data dn;
+   struct extent_info ei = {0,0,0};
int err = 0;
 
+   /*
+* If a page is cold, NOT atomit written and need_ipu now, there is
+* a high probability that IPU should be adapted. For IPU, we try to
+* check extent tree to get the block index first, instead of reading
+* the dnode page, where may lead to an useless dnode IO, since no need 
to
+* update the dnode index for IPU.
+*/
+   if (unlikely(need_inplace_update_block(fio, page) &&
+   f2fs_lookup_extent_cache(inode, page->index, ))) {
+
+   fio->old_blkaddr = ei.blk + page->index - ei.fofs;
+
+   if (fio->old_blkaddr != NEW_ADDR &&
+   fio->old_blkaddr != NULL_ADDR) {
+   err = f2fs_encrypt_page(fio, page);
+   if (err)
+   return err;
+   set_page_writeback(page);
+   err = do_rewrite_data_page(fio, page);
+   return err;
+   }
+   }
+
set_new_dnode(, inode, NULL, NULL, 0);
err = get_dnode_of_data(, page->index, LOOKUP_NODE);
if (err)
-- 
2.10.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 1/3] f2fs: reconstruct code to write a data page

2017-04-22 Thread Hou Pengyang
This patch introduces two functions:

1) f2fs_encrypt_page -- encrypt data page before submit_bio
2) do_rewrite_data_page -- IPU rewrite

The two functions are extraced from do_write_data_page, logic in
do_write_data_page stays unchanged.

Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
Signed-off-by: Chao Yu <yuch...@huawei.com>
---
 fs/f2fs/data.c | 83 --
 1 file changed, 58 insertions(+), 25 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index b8dcd1e..6b18750 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1302,26 +1302,11 @@ static int f2fs_read_data_pages(struct file *file,
return f2fs_mpage_readpages(mapping, pages, NULL, nr_pages);
 }
 
-int do_write_data_page(struct f2fs_io_info *fio)
+static int f2fs_encrypt_page(struct f2fs_io_info *fio, struct page *page)
 {
-   struct page *page = fio->page;
struct inode *inode = page->mapping->host;
-   struct dnode_of_data dn;
int err = 0;
 
-   set_new_dnode(, inode, NULL, NULL, 0);
-   err = get_dnode_of_data(, page->index, LOOKUP_NODE);
-   if (err)
-   return err;
-
-   fio->old_blkaddr = dn.data_blkaddr;
-
-   /* This page is already truncated */
-   if (fio->old_blkaddr == NULL_ADDR) {
-   ClearPageUptodate(page);
-   goto out_writepage;
-   }
-
if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode)) {
gfp_t gfp_flags = GFP_NOFS;
 
@@ -1343,9 +1328,63 @@ int do_write_data_page(struct f2fs_io_info *fio)
err = 0;
goto retry_encrypt;
}
-   goto out_writepage;
+   return err;
}
}
+   return err;
+}
+
+static int do_rewrite_data_page(struct f2fs_io_info *fio, struct page *page)
+{
+   struct inode *inode = page->mapping->host;
+   int err;
+
+   f2fs_bug_on(F2FS_P_SB(page), !fio->cp_rwsem_locked);
+
+   f2fs_unlock_op(F2FS_I_SB(inode));
+   fio->cp_rwsem_locked = false;
+   err = rewrite_data_page(fio);
+   set_inode_flag(inode, FI_UPDATE_WRITE);
+   trace_f2fs_do_write_data_page(page, IPU);
+   return err;
+
+}
+
+static inline bool need_inplace_update_block(struct f2fs_io_info *fio, struct 
page *page)
+{
+   struct inode *inode = page->mapping->host;
+
+   if (!is_cold_data(page) &&
+   !IS_ATOMIC_WRITTEN_PAGE(page) &&
+   need_inplace_update(inode, fio))
+   return true;
+
+   return false;
+}
+
+int do_write_data_page(struct f2fs_io_info *fio)
+{
+   struct page *page = fio->page;
+   struct inode *inode = page->mapping->host;
+   struct dnode_of_data dn;
+   int err = 0;
+
+   set_new_dnode(, inode, NULL, NULL, 0);
+   err = get_dnode_of_data(, page->index, LOOKUP_NODE);
+   if (err)
+   return err;
+
+   fio->old_blkaddr = dn.data_blkaddr;
+
+   /* This page is already truncated */
+   if (fio->old_blkaddr == NULL_ADDR) {
+   ClearPageUptodate(page);
+   goto out_writepage;
+   }
+
+   err = f2fs_encrypt_page(fio, page);
+   if (err)
+   goto out_writepage;
 
set_page_writeback(page);
 
@@ -1354,14 +1393,8 @@ int do_write_data_page(struct f2fs_io_info *fio)
 * it had better in-place writes for updated data.
 */
if (unlikely(fio->old_blkaddr != NEW_ADDR &&
-   !is_cold_data(page) &&
-   !IS_ATOMIC_WRITTEN_PAGE(page) &&
-   need_inplace_update(inode, fio))) {
-   f2fs_unlock_op(F2FS_I_SB(inode));
-   fio->cp_rwsem_locked = false;
-   err = rewrite_data_page(fio);
-   set_inode_flag(inode, FI_UPDATE_WRITE);
-   trace_f2fs_do_write_data_page(page, IPU);
+   need_inplace_update_block(fio, page))) {
+   err = do_rewrite_data_page(fio, page);
} else {
write_data_page(, fio);
trace_f2fs_do_write_data_page(page, OPU);
-- 
2.10.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 0/3] optimize f2fs IPU v2

2017-04-22 Thread Hou Pengyang
For IPU, there is no need to read dnode, these three patches are to fix this
issue.

patch 1): Reconstruct code in do_write_data_page, code logic stays unchanged,
patch 2): Under high-probability IPU scenario, we check extent_tree first
patch 3): Unlock dnode before IPU

v1->v2:
1) fix 
if(f2fs_encrypt_page())
XXX
to 
err = f2fs_encrypt_page() 
if (err)
XXX

otherwise do_write_data_page would return a wrong return value.

2) extract need_in_place_block(fio, page) for IPU checking.

Hou Pengyang (3):
  f2fs: reconstruct code to write a data page
  f2fs: lookup extent cache first under IPU scenario
  f2fs: unlock dnode before IPU

 fs/f2fs/data.c | 109 -
 1 file changed, 84 insertions(+), 25 deletions(-)

-- 
2.10.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 3/3] f2fs: unlock dnode before IPU

2017-04-22 Thread Hou Pengyang
Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
 fs/f2fs/data.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 1c99ae1..a0df451 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1418,7 +1418,9 @@ int do_write_data_page(struct f2fs_io_info *fio)
 */
if (unlikely(fio->old_blkaddr != NEW_ADDR &&
need_inplace_update_block(fio, page))) {
+   f2fs_put_dnode();
err = do_rewrite_data_page(fio, page);
+   return err;
} else {
write_data_page(, fio);
trace_f2fs_do_write_data_page(page, OPU);
-- 
2.10.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: skip encrypted inode in ASYNC IPU policy

2017-04-21 Thread Hou Pengyang
Async request may be throttled in block layer, so page for async may keep 
WRITE_BACK
for a long time.

For encrytped inode, we need wait on page writeback no matter if the device 
supports
BDI_CAP_STABLE_WRITES. This may result in a higher waiting page writeback time 
for 
async encrypted inode page.

This patch skips IPU for encrypted inode's updating write.

Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
 fs/f2fs/segment.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index 4a85035..99e1e21 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -590,7 +590,8 @@ static inline bool need_inplace_update(struct inode *inode,
 */
if (policy & (0x1 << F2FS_IPU_ASYNC) &&
fio && fio->op == REQ_OP_WRITE &&
-   !(fio->op_flags & REQ_SYNC))
+   !(fio->op_flags & REQ_SYNC) &&
+   !f2fs_encrypted_inode(inode))
return true;
 
/* this is only set during fdatasync */
-- 
2.10.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 3/3] f2fs: unlock dnode before IPU

2017-04-21 Thread Hou Pengyang
Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
 fs/f2fs/data.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 3a660f7..fcd907c 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1409,7 +1409,9 @@ int do_write_data_page(struct f2fs_io_info *fio)
!is_cold_data(page) &&
!IS_ATOMIC_WRITTEN_PAGE(page) &&
need_inplace_update(inode, fio))) {
+   f2fs_put_dnode();
err = do_rewrite_data_page(fio, page);
+   return err;
} else {
write_data_page(, fio);
trace_f2fs_do_write_data_page(page, OPU);
-- 
2.10.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 1/3] f2fs: fix a memleak issue

2017-02-27 Thread Hou Pengyang
On 2017/2/27 21:52, Kinglong Mee wrote:
> On 2/27/2017 21:02, Hou Pengyang wrote:
>> [fix: ae75f0ca76 f2fs: introduce free nid bitmap]
>> Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
>> ---
>>   fs/f2fs/node.c | 5 -
>>   1 file changed, 4 insertions(+), 1 deletion(-)
>>
>> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
>> index 6d43095..353c01d 100644
>> --- a/fs/f2fs/node.c
>> +++ b/fs/f2fs/node.c
>> @@ -2650,8 +2650,11 @@ int init_free_nid_cache(struct f2fs_sb_info *sbi)
>>
>>  nm_i->nat_block_bitmap = f2fs_kvzalloc(nm_i->nat_blocks / 8,
>>  GFP_KERNEL);
>> -if (!nm_i->nat_block_bitmap)
>> +if (!nm_i->nat_block_bitmap) {
>> +kvfree(nm_i->free_nid_bitmap);
>>  return -ENOMEM;
>> +}
>> +
>>  return 0;
>>   }
>
> If building node manager fail, destroy_node_manager will be called,
> I think there isn't any memory leak exist, right?
>
>  err = build_node_manager(sbi);
>  if (err) {
>  f2fs_msg(sb, KERN_ERR,
>  "Failed to initialize F2FS node manager");
>  goto free_nm;
>  }
>
>
Yup, I missed it :)
Thank you,

> thanks,
> Kinglong Mee
>
>



--
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 3/3] f2fs: fix a plint compile warning

2017-02-27 Thread Hou Pengyang
fix such pclint warning:
...
Loss of precision (arg. no. 2) (unsigned long long to unsigned int))

Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
 fs/f2fs/gc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 023f043..418fd98 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -1009,6 +1009,6 @@ void build_gc_manager(struct f2fs_sb_info *sbi)
ovp_count = SM_I(sbi)->ovp_segments << sbi->log_blocks_per_seg;
blocks_per_sec = sbi->blocks_per_seg * sbi->segs_per_sec;
 
-   sbi->fggc_threshold = div_u64((main_count - ovp_count) * blocks_per_sec,
+   sbi->fggc_threshold = div64_u64((main_count - ovp_count) * 
blocks_per_sec,
(main_count - resv_count));
 }
-- 
2.10.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 2/3] f2fs: add f2fs_drop_inode tracepoint

2017-02-27 Thread Hou Pengyang
Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
 fs/f2fs/super.c | 7 +--
 include/trace/events/f2fs.h | 7 +++
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 751e106..746296e 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -624,6 +624,7 @@ static struct inode *f2fs_alloc_inode(struct super_block 
*sb)
 
 static int f2fs_drop_inode(struct inode *inode)
 {
+   int ret;
/*
 * This is to avoid a deadlock condition like below.
 * writeback_single_inode(inode)
@@ -656,10 +657,12 @@ static int f2fs_drop_inode(struct inode *inode)
spin_lock(>i_lock);
atomic_dec(>i_count);
}
+   trace_f2fs_drop_inode(inode, 0);
return 0;
}
-
-   return generic_drop_inode(inode);
+   ret = generic_drop_inode(inode);
+   trace_f2fs_drop_inode(inode, ret);
+   return ret;
 }
 
 int f2fs_inode_dirtied(struct inode *inode, bool sync)
diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h
index ff31ccf..c80fcad0 100644
--- a/include/trace/events/f2fs.h
+++ b/include/trace/events/f2fs.h
@@ -315,6 +315,13 @@ DEFINE_EVENT(f2fs__inode_exit, f2fs_unlink_exit,
TP_ARGS(inode, ret)
 );
 
+DEFINE_EVENT(f2fs__inode_exit, f2fs_drop_inode,
+
+   TP_PROTO(struct inode *inode, int ret),
+
+   TP_ARGS(inode, ret)
+);
+
 DEFINE_EVENT(f2fs__inode, f2fs_truncate,
 
TP_PROTO(struct inode *inode),
-- 
2.10.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 1/3] f2fs: fix a memleak issue

2017-02-27 Thread Hou Pengyang
[fix: ae75f0ca76 f2fs: introduce free nid bitmap]
Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
 fs/f2fs/node.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 6d43095..353c01d 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -2650,8 +2650,11 @@ int init_free_nid_cache(struct f2fs_sb_info *sbi)
 
nm_i->nat_block_bitmap = f2fs_kvzalloc(nm_i->nat_blocks / 8,
GFP_KERNEL);
-   if (!nm_i->nat_block_bitmap)
+   if (!nm_i->nat_block_bitmap) {
+   kvfree(nm_i->free_nid_bitmap);
return -ENOMEM;
+   }
+
return 0;
 }
 
-- 
2.10.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: avoid unnecessary fg_gc

2017-02-24 Thread Hou Pengyang
On 2017/2/25 10:07, Jaegeuk Kim wrote:
> On 02/25, Hou Pengyang wrote:
>> On 2017/2/24 18:28, Chao Yu wrote:
>>> On 2017/2/24 18:01, Hou Pengyang wrote:
>>>> Under scenerio with large number of dirty nodes, and these nodes are 
>>>> flushed
>>>> in SSR mode during cp. enough free segemts now, no need to do fggc.
>>>
>>> We'd better break out of GC flow once we encounter cp error, so additional
>>> condition judgment is not needed.
>>>
>>
>> In (ret || !has_not_enough_free_secs(sbi, sec_freed, 0)),
>> if cp return error(NOT zero), flow will goto stop directly without
>> has_not_enough_free_secs checking;
>> if cp return ok(zero), has_not_enough_free_secs would be checked.
>
> Well, I think it'd be fine to do one gc by a background thread.
>
Currently we decide whether convert a bggc to fggc by:

if (gc_type == BG_GC && has_not_enough_free_secs(sbi, sec_freed, 0)) { 

  gc_type = FG_GC;

So how about move up write_checkpoint before gc_type = FG_GC, like:

if (gc_type == BG_GC && has_not_enough_free_secs(sbi, sec_freed, 0)) {
  write_checkpoint;
 if still has_not_enough_free_secs:
       gc_type = FG_GC;
  else
   stay BG_GC;

Thanks,

> Thanks,
>
>>
>> Thanks,
>>
>>> Thanks,
>>>
>>>>
>>>> Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
>>>> ---
>>>>fs/f2fs/gc.c | 2 +-
>>>>1 file changed, 1 insertion(+), 1 deletion(-)
>>>>
>>>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
>>>> index 6c996e3..41bdfb7 100644
>>>> --- a/fs/f2fs/gc.c
>>>> +++ b/fs/f2fs/gc.c
>>>> @@ -959,7 +959,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, bool 
>>>> background)
>>>> * garbage collections.
>>>> */
>>>>ret = write_checkpoint(sbi, );
>>>> -  if (ret)
>>>> +  if (ret || !has_not_enough_free_secs(sbi, sec_freed, 0))
>>>>goto stop;
>>>>} else if (gc_type == BG_GC && !background) {
>>>>/* f2fs_balance_fs doesn't need to do BG_GC in critical 
>>>> path. */
>>>>
>>>
>>>
>>> .
>>>
>>
>
> .
>



--
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: avoid unnecessary fg_gc

2017-02-24 Thread Hou Pengyang
On 2017/2/24 18:28, Chao Yu wrote:
> On 2017/2/24 18:01, Hou Pengyang wrote:
>> Under scenerio with large number of dirty nodes, and these nodes are flushed
>> in SSR mode during cp. enough free segemts now, no need to do fggc.
>
> We'd better break out of GC flow once we encounter cp error, so additional
> condition judgment is not needed.
>

In (ret || !has_not_enough_free_secs(sbi, sec_freed, 0)),
if cp return error(NOT zero), flow will goto stop directly without 
has_not_enough_free_secs checking;
if cp return ok(zero), has_not_enough_free_secs would be checked.

Thanks,

> Thanks,
>
>>
>> Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
>> ---
>>   fs/f2fs/gc.c | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
>> index 6c996e3..41bdfb7 100644
>> --- a/fs/f2fs/gc.c
>> +++ b/fs/f2fs/gc.c
>> @@ -959,7 +959,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, bool 
>> background)
>>   * garbage collections.
>>   */
>>  ret = write_checkpoint(sbi, );
>> -if (ret)
>> +if (ret || !has_not_enough_free_secs(sbi, sec_freed, 0))
>>  goto stop;
>>  } else if (gc_type == BG_GC && !background) {
>>  /* f2fs_balance_fs doesn't need to do BG_GC in critical path. */
>>
>
>
> .
>



--
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: avoid unnecessary fg_gc

2017-02-24 Thread Hou Pengyang
Under scenerio with large number of dirty nodes, and these nodes are flushed
in SSR mode during cp. enough free segemts now, no need to do fggc.

Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
 fs/f2fs/gc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 6c996e3..41bdfb7 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -959,7 +959,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, bool 
background)
 * garbage collections.
 */
ret = write_checkpoint(sbi, );
-   if (ret)
+   if (ret || !has_not_enough_free_secs(sbi, sec_freed, 0))
goto stop;
} else if (gc_type == BG_GC && !background) {
/* f2fs_balance_fs doesn't need to do BG_GC in critical path. */
-- 
2.10.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 2/2] f2fs:use fggc_set_cold_data instead of set_cold_data in fggc

2017-02-23 Thread Hou Pengyang
On 2017/2/24 10:07, Chao Yu wrote:
> On 2017/2/23 10:04, Hou Pengyang wrote:
>> On 2017/2/23 8:39, Jaegeuk Kim wrote:
>>> Hi Pengyang,
Hi Chao,
>>>
>>> On 02/22, Hou Pengyang wrote:
>>>> When no dirty colde segment for fggc ssr, we do NOT set_cold_data.
>>>
>>> The get_ssr_segment() finds a victim segment across all the hot/warm/cold 
>>> data
>>> logs. When does this happen?
>>>
>> Oh, I miss the travel across hot/warm/cold, sorry.
>> how about the following filter in get_victim_segment, which can avoid
>> unnecessary afterwards bitmap scanning.
>>
>> Thanks,
>>
>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
>> index a0eed23..00791d2 100644
>> --- a/fs/f2fs/gc.c
>> +++ b/fs/f2fs/gc.c
>> @@ -290,9 +290,16 @@ static int get_victim_by_default(struct
>> f2fs_sb_info *sbi,
>>   unsigned int secno, last_victim;
>>   unsigned int last_segment = MAIN_SEGS(sbi);
>>   unsigned int nsearched = 0;
>> +   int nr_dirty;
>>
>>   mutex_lock(_i->seglist_lock);
>>
>> +   if (alloc_mode == SSR) {
>> +   nr_dirty = dirty_i->nr_dirty[type];
>> +   if (!nr_dirty)
>
> Needs to clean up.
>
> if (!dirty_i->nr_dirty[type])

As Jaegeuk explained, p.max_search has skipped no # of victims scenario

if (p.max_search == 0)
goto out;
Thanks,
>
> Reviewed-by: Chao Yu <yuch...@huawei.com>
>
> Thanks,
>
>> +   goto out;
>> +   }
>> +
>>   p.alloc_mode = alloc_mode;
>>   select_policy(sbi, gc_type, type, );
>>
>>
>>> Thanks,
>>>
>>>>
>>>> Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
>>>> ---
>>>>fs/f2fs/gc.c | 21 -
>>>>1 file changed, 20 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
>>>> index 4ee749f..a0eed23 100644
>>>> --- a/fs/f2fs/gc.c
>>>> +++ b/fs/f2fs/gc.c
>>>> @@ -666,6 +666,25 @@ static void move_encrypted_block(struct inode *inode, 
>>>> block_t bidx,
>>>>f2fs_put_page(page, 1);
>>>>}
>>>>
>>>> +/*
>>>> + * If NOT enough dirty cold data segments for fggc, fggc would consume
>>>> + * a valuable free segment, which would slow down the fggc procedure,
>>>> + * If there are NO COLD dirty segment, we do not set_cold_page.
>>>> + */
>>>> +static void fggc_set_cold_data(struct page *page)
>>>> +{
>>>> +  struct f2fs_sb_info *sbi = F2FS_P_SB(page);
>>>> +  struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
>>>> +  int nr_cold_dirties;
>>>> +
>>>> +  mutex_lock(_i->seglist_lock);
>>>> +  nr_cold_dirties = dirty_i->nr_dirty[DIRTY_COLD_DATA];
>>>> +  mutex_unlock(_i->seglist_lock);
>>>> +
>>>> +  if (nr_cold_dirties)
>>>> +  set_cold_data(page);
>>>> +
>>>> +}
>>>>static void move_data_page(struct inode *inode, block_t bidx, int 
>>>> gc_type,
>>>>unsigned int 
>>>> segno, int off)
>>>>{
>>>> @@ -706,7 +725,7 @@ static void move_data_page(struct inode *inode, 
>>>> block_t bidx, int gc_type,
>>>>remove_dirty_inode(inode);
>>>>}
>>>>
>>>> -  set_cold_data(page);
>>>> +  fggc_set_cold_data(page);
>>>>
>>>>err = do_write_data_page();
>>>>if (err == -ENOMEM && is_dirty) {
>>>> --
>>>> 2.10.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
>>>
>>> .
>>>
>>
>>
>>
>> .
>>
>
>
> .
>



--
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 2/3] f2fs: remove unsafe bitmap checking

2017-02-23 Thread Hou Pengyang
proc A:  proc B:
- writeback_sb_inodes
- __writeback_single_inode   
- do_writepages
- f2fs_write_node_pages   
- f2fs_balance_fs_bg - write_checkpoint
- build_free_nids- flush_nat_entries
- __build_free_nids  - __flush_nat_entry_set
- ra_meta_pages  - get_next_nat_page
- current_nat_addr   - set_to_next_nat
[do nat_bitmap checking] - f2fs_change_bit

For proc A, nat_bitmap and nat_bitmap_mir would be compared without lock_op and 
nm_i->nat_tree_lock, while proc B is changing nat_bitmap/nat_bitmap_ver in cp.

So it is normal for nat_bitmap/nat_bitmap diffrence under such scenario.

This patch fix this by removing the monitoring point.

[Fix: 599a09b f2fs: check in-memory nat version bitmap]
Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
 fs/f2fs/node.h | 6 --
 1 file changed, 6 deletions(-)

diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
index d3d2893..3fc9c4b 100644
--- a/fs/f2fs/node.h
+++ b/fs/f2fs/node.h
@@ -209,12 +209,6 @@ static inline pgoff_t current_nat_addr(struct f2fs_sb_info 
*sbi, nid_t start)
(seg_off << sbi->log_blocks_per_seg << 1) +
(block_off & (sbi->blocks_per_seg - 1)));
 
-#ifdef CONFIG_F2FS_CHECK_FS
-   if (f2fs_test_bit(block_off, nm_i->nat_bitmap) !=
-   f2fs_test_bit(block_off, nm_i->nat_bitmap_mir))
-   f2fs_bug_on(sbi, 1);
-#endif
-
if (f2fs_test_bit(block_off, nm_i->nat_bitmap))
block_addr += sbi->blocks_per_seg;
 
-- 
2.10.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 3/3] f2fs: skip dirty bitmap scanning when no dirty segments

2017-02-23 Thread Hou Pengyang
Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
 fs/f2fs/gc.c | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 6c996e3..eaf9e68 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -293,13 +293,22 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
unsigned int secno, last_victim;
unsigned int last_segment = MAIN_SEGS(sbi);
unsigned int nsearched = 0;
+   int nr_dirty;
 
mutex_lock(_i->seglist_lock);
 
p.alloc_mode = alloc_mode;
-   select_policy(sbi, gc_type, type, );
-
p.min_segno = NULL_SEGNO;
+
+   if (alloc_mode == SSR)
+   nr_dirty = dirty_i->nr_dirty[type];
+   else
+   nr_dirty = dirty_i->nr_dirty[DIRTY];
+
+   if (!nr_dirty)
+   goto out;
+
+   select_policy(sbi, gc_type, type, );
p.min_cost = get_max_cost(sbi, );
 
if (p.max_search == 0)
-- 
2.10.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 1/3] f2fs: init local extent_info to avoid stale stack info in tp

2017-02-23 Thread Hou Pengyang
To avoid such stale(fops, blk, len) info in f2fs_lookup_extent_tree_end tp

dio-23095 [005] ...1 17878.856859: f2fs_lookup_extent_tree_end: 
dev = (259,30), ino = 856, pgofs = 0, 
ext_info(fofs: 3441207040, blk: 4294967232, len: 
3481143808)

Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
 fs/f2fs/data.c | 8 
 fs/f2fs/file.c | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 5f3bc98..f72493d 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -511,7 +511,7 @@ int f2fs_reserve_block(struct dnode_of_data *dn, pgoff_t 
index)
 
 int f2fs_get_block(struct dnode_of_data *dn, pgoff_t index)
 {
-   struct extent_info ei;
+   struct extent_info ei  = {0,0,0};
struct inode *inode = dn->inode;
 
if (f2fs_lookup_extent_cache(inode, index, )) {
@@ -528,7 +528,7 @@ struct page *get_read_data_page(struct inode *inode, 
pgoff_t index,
struct address_space *mapping = inode->i_mapping;
struct dnode_of_data dn;
struct page *page;
-   struct extent_info ei;
+   struct extent_info ei = {0,0,0};
int err;
struct f2fs_io_info fio = {
.sbi = F2FS_I_SB(inode),
@@ -803,7 +803,7 @@ int f2fs_map_blocks(struct inode *inode, struct 
f2fs_map_blocks *map,
int err = 0, ofs = 1;
unsigned int ofs_in_node, last_ofs_in_node;
blkcnt_t prealloc;
-   struct extent_info ei;
+   struct extent_info ei = {0,0,0};
block_t blkaddr;
 
if (!maxblocks)
@@ -1667,7 +1667,7 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
struct dnode_of_data dn;
struct page *ipage;
bool locked = false;
-   struct extent_info ei;
+   struct extent_info ei = {0,0,0};
int err = 0;
 
/*
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 1201648..36c1565 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -1877,7 +1877,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi,
 {
struct inode *inode = file_inode(filp);
struct f2fs_map_blocks map = { .m_next_pgofs = NULL };
-   struct extent_info ei;
+   struct extent_info ei = {0,0,0};
pgoff_t pg_start, pg_end;
unsigned int blk_per_seg = sbi->blocks_per_seg;
unsigned int total = 0, sec_num;
-- 
2.10.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 2/2] f2fs:use fggc_set_cold_data instead of set_cold_data in fggc

2017-02-22 Thread Hou Pengyang
On 2017/2/23 8:39, Jaegeuk Kim wrote:
> Hi Pengyang,
>
> On 02/22, Hou Pengyang wrote:
>> When no dirty colde segment for fggc ssr, we do NOT set_cold_data.
>
> The get_ssr_segment() finds a victim segment across all the hot/warm/cold data
> logs. When does this happen?
>
Oh, I miss the travel across hot/warm/cold, sorry.
how about the following filter in get_victim_segment, which can avoid
unnecessary afterwards bitmap scanning.

Thanks,

diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index a0eed23..00791d2 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -290,9 +290,16 @@ static int get_victim_by_default(struct 
f2fs_sb_info *sbi,
 unsigned int secno, last_victim;
 unsigned int last_segment = MAIN_SEGS(sbi);
 unsigned int nsearched = 0;
+   int nr_dirty;

 mutex_lock(_i->seglist_lock);

+   if (alloc_mode == SSR) {
+   nr_dirty = dirty_i->nr_dirty[type];
+   if (!nr_dirty)
+   goto out;
+   }
+
 p.alloc_mode = alloc_mode;
 select_policy(sbi, gc_type, type, );


> Thanks,
>
>>
>> Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
>> ---
>>   fs/f2fs/gc.c | 21 -
>>   1 file changed, 20 insertions(+), 1 deletion(-)
>>
>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
>> index 4ee749f..a0eed23 100644
>> --- a/fs/f2fs/gc.c
>> +++ b/fs/f2fs/gc.c
>> @@ -666,6 +666,25 @@ static void move_encrypted_block(struct inode *inode, 
>> block_t bidx,
>>  f2fs_put_page(page, 1);
>>   }
>>
>> +/*
>> + * If NOT enough dirty cold data segments for fggc, fggc would consume
>> + * a valuable free segment, which would slow down the fggc procedure,
>> + * If there are NO COLD dirty segment, we do not set_cold_page.
>> + */
>> +static void fggc_set_cold_data(struct page *page)
>> +{
>> +struct f2fs_sb_info *sbi = F2FS_P_SB(page);
>> +struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
>> +int nr_cold_dirties;
>> +
>> +mutex_lock(_i->seglist_lock);
>> +nr_cold_dirties = dirty_i->nr_dirty[DIRTY_COLD_DATA];
>> +mutex_unlock(_i->seglist_lock);
>> +
>> +if (nr_cold_dirties)
>> +set_cold_data(page);
>> +
>> +}
>>   static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
>>  unsigned int segno, int 
>> off)
>>   {
>> @@ -706,7 +725,7 @@ static void move_data_page(struct inode *inode, block_t 
>> bidx, int gc_type,
>>  remove_dirty_inode(inode);
>>  }
>>
>> -set_cold_data(page);
>> +fggc_set_cold_data(page);
>>
>>  err = do_write_data_page();
>>  if (err == -ENOMEM && is_dirty) {
>> --
>> 2.10.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
>
> .
>



--
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 1/2] f2fs fg_gc: node segment is prior to data segment selected victim

2017-02-22 Thread Hou Pengyang
As data segment gc may lead dnode dirty, so the greedy cost for data segment 
should be
valid blocks * 2, that is data segment is prior to node segment.

Team:OTHERS
Feature or Bugfix:Bugfix
Binary Source:No

Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
 fs/f2fs/gc.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index e93aecb..4ee749f 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -242,6 +242,13 @@ static unsigned int get_cb_cost(struct f2fs_sb_info *sbi, 
unsigned int segno)
return UINT_MAX - ((100 * (100 - u) * age) / (100 + u));
 }
 
+static unsigned int get_greedy_cost(struct f2fs_sb_info *sbi, unsigned int 
segno)
+{
+   unsigned int valid_blocks = get_valid_blocks(sbi, segno, 
sbi->segs_per_sec);
+   return IS_DATASEG(get_seg_entry(sbi, segno)->type) ?
+   valid_blocks * 2 : valid_blocks;
+}
+
 static inline unsigned int get_gc_cost(struct f2fs_sb_info *sbi,
unsigned int segno, struct victim_sel_policy *p)
 {
@@ -250,7 +257,7 @@ static inline unsigned int get_gc_cost(struct f2fs_sb_info 
*sbi,
 
/* alloc_mode == LFS */
if (p->gc_mode == GC_GREEDY)
-   return get_valid_blocks(sbi, segno, sbi->segs_per_sec);
+   return get_greedy_cost(sbi, segno);
else
return get_cb_cost(sbi, segno);
 }
-- 
2.10.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 2/2] f2fs:use fggc_set_cold_data instead of set_cold_data in fggc

2017-02-22 Thread Hou Pengyang
When no dirty colde segment for fggc ssr, we do NOT set_cold_data.

Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
 fs/f2fs/gc.c | 21 -
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 4ee749f..a0eed23 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -666,6 +666,25 @@ static void move_encrypted_block(struct inode *inode, 
block_t bidx,
f2fs_put_page(page, 1);
 }
 
+/*
+ * If NOT enough dirty cold data segments for fggc, fggc would consume
+ * a valuable free segment, which would slow down the fggc procedure,
+ * If there are NO COLD dirty segment, we do not set_cold_page.
+ */
+static void fggc_set_cold_data(struct page *page)
+{
+   struct f2fs_sb_info *sbi = F2FS_P_SB(page);
+   struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+   int nr_cold_dirties;
+
+   mutex_lock(_i->seglist_lock);
+   nr_cold_dirties = dirty_i->nr_dirty[DIRTY_COLD_DATA];
+   mutex_unlock(_i->seglist_lock);
+
+   if (nr_cold_dirties)
+   set_cold_data(page);
+
+}
 static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
unsigned int segno, int 
off)
 {
@@ -706,7 +725,7 @@ static void move_data_page(struct inode *inode, block_t 
bidx, int gc_type,
remove_dirty_inode(inode);
}
 
-   set_cold_data(page);
+   fggc_set_cold_data(page);
 
err = do_write_data_page();
if (err == -ENOMEM && is_dirty) {
-- 
2.10.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] [RFC] add ovp valid_blocks check for bg gc victim to fg_gc

2017-02-16 Thread Hou Pengyang
On 2017/2/17 10:54, Jaegeuk Kim wrote:
> On 02/17, Hou Pengyang wrote:
>> On 2017/2/17 7:48, Jaegeuk Kim wrote:
>>> Hi Pengyang,
>>>
>>> Nice
>> Hi Jaegeuk,
>> catch!
>>>
>>> I think fggc_threshold needs to be revised, and we need to consider about
>>> general victim selection as well.
>>>
>>> Could you take a look at this?
>>>
>>>>  From 23b265f5ca6405032d092e240c94a827f743e42b Mon Sep 17 00:00:00 2001
>>> From: Hou Pengyang <houpengy...@huawei.com>
>>> Date: Thu, 16 Feb 2017 12:34:31 +
>>> Subject: [PATCH] f2fs: add ovp valid_blocks check for bg gc victim to fg_gc
>>>
>>> For foreground gc, greedy algorithm should be adapted, which makes
>>> this formula work well:
>>>
>>> (2 * (100 / config.overprovision + 1) + 6)
>>>
>>> But currently, we fg_gc have a prior to select bg_gc victim segments to gc 
>>> first,
>>> these victims are selected by cost-benefit algorithm, we can't guarantee 
>>> such segments
>>> have the small valid blocks, which may destroy the f2fs rule, on the 
>>> worstest case, would
>>> consume all the free segments.
>>>
>>> This patch fix this by add a filter in check_bg_victims, if segment's has # 
>>> of valid blocks
>>> over overprovision ratio, skip such segments.
>>>
>>> Cc: <sta...@vger.kernel.org>
>>> Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
>>> Signed-off-by: Jaegeuk Kim <jaeg...@kernel.org>
>>> ---
>>>fs/f2fs/f2fs.h|  3 +++
>>>fs/f2fs/gc.c  | 22 --
>>>fs/f2fs/segment.h |  9 +
>>>3 files changed, 32 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
>>> index cc22dc458896..1c9f0cc8f027 100644
>>> --- a/fs/f2fs/f2fs.h
>>> +++ b/fs/f2fs/f2fs.h
>>> @@ -888,6 +888,9 @@ struct f2fs_sb_info {
>>> struct f2fs_gc_kthread  *gc_thread; /* GC thread */
>>> unsigned int cur_victim_sec;/* current victim section num */
>>>
>>> +   /* threshold for converting bg victims for fg */
>>> +   u64 fggc_threshold;
>>> +
>>> /* maximum # of trials to find a victim segment for SSR and GC */
>>> unsigned int max_victim_search;
>>>
>>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
>>> index 88e5e7b10ab6..fd4e479820e6 100644
>>> --- a/fs/f2fs/gc.c
>>> +++ b/fs/f2fs/gc.c
>>> @@ -166,7 +166,8 @@ static void select_policy(struct f2fs_sb_info *sbi, int 
>>> gc_type,
>>> p->ofs_unit = sbi->segs_per_sec;
>>> }
>>>
>>> -   if (p->max_search > sbi->max_victim_search)
>>> +   /* we need to check every dirty segments in the FG_GC case */
>>> +   if (gc_type != FG_GC && p->max_search > sbi->max_victim_search)
>>> p->max_search = sbi->max_victim_search;
>>>
>>> p->offset = sbi->last_victim[p->gc_mode];
>>> @@ -199,6 +200,10 @@ static unsigned int check_bg_victims(struct 
>>> f2fs_sb_info *sbi)
>>> for_each_set_bit(secno, dirty_i->victim_secmap, MAIN_SECS(sbi)) {
>>> if (sec_usage_check(sbi, secno))
>>> continue;
>>> +
>>> +   if (no_fggc_candidate(sbi, secno))
>>> +   continue;
>>> +
>>> clear_bit(secno, dirty_i->victim_secmap);
>>> return secno * sbi->segs_per_sec;
>>> }
>>> @@ -322,13 +327,15 @@ static int get_victim_by_default(struct f2fs_sb_info 
>>> *sbi,
>>> nsearched++;
>>> }
>>>
>>> -
>>> secno = GET_SECNO(sbi, segno);
>>>
>>> if (sec_usage_check(sbi, secno))
>>> goto next;
>>> if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
>>> goto next;
>>> +   if (gc_type == FG_GC && p.alloc_mode == LFS &&
>>> +   no_fggc_candidate(sbi, secno))
>>> +   goto next;
>>>
>>> cost = get_gc_cost(sbi, segno, );
>>>
>>> @@ -989,5 +996,16 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, bool 
>>> background)
>>>
>>>void build_gc_manager(struct f2fs_s

Re: [f2fs-dev] [RFC] add ovp valid_blocks check for bg gc victim to fg_gc

2017-02-16 Thread Hou Pengyang
On 2017/2/17 7:48, Jaegeuk Kim wrote:
> Hi Pengyang,
>
> Nice
Hi Jaegeuk,
catch!
>
> I think fggc_threshold needs to be revised, and we need to consider about
> general victim selection as well.
>
> Could you take a look at this?
>
>>From 23b265f5ca6405032d092e240c94a827f743e42b Mon Sep 17 00:00:00 2001
> From: Hou Pengyang <houpengy...@huawei.com>
> Date: Thu, 16 Feb 2017 12:34:31 +
> Subject: [PATCH] f2fs: add ovp valid_blocks check for bg gc victim to fg_gc
>
> For foreground gc, greedy algorithm should be adapted, which makes
> this formula work well:
>
>   (2 * (100 / config.overprovision + 1) + 6)
>
> But currently, we fg_gc have a prior to select bg_gc victim segments to gc 
> first,
> these victims are selected by cost-benefit algorithm, we can't guarantee such 
> segments
> have the small valid blocks, which may destroy the f2fs rule, on the worstest 
> case, would
> consume all the free segments.
>
> This patch fix this by add a filter in check_bg_victims, if segment's has # 
> of valid blocks
> over overprovision ratio, skip such segments.
>
> Cc: <sta...@vger.kernel.org>
> Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
> Signed-off-by: Jaegeuk Kim <jaeg...@kernel.org>
> ---
>   fs/f2fs/f2fs.h|  3 +++
>   fs/f2fs/gc.c  | 22 --
>   fs/f2fs/segment.h |  9 +
>   3 files changed, 32 insertions(+), 2 deletions(-)
>
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index cc22dc458896..1c9f0cc8f027 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -888,6 +888,9 @@ struct f2fs_sb_info {
>   struct f2fs_gc_kthread  *gc_thread; /* GC thread */
>   unsigned int cur_victim_sec;/* current victim section num */
>
> + /* threshold for converting bg victims for fg */
> + u64 fggc_threshold;
> +
>   /* maximum # of trials to find a victim segment for SSR and GC */
>   unsigned int max_victim_search;
>
> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> index 88e5e7b10ab6..fd4e479820e6 100644
> --- a/fs/f2fs/gc.c
> +++ b/fs/f2fs/gc.c
> @@ -166,7 +166,8 @@ static void select_policy(struct f2fs_sb_info *sbi, int 
> gc_type,
>   p->ofs_unit = sbi->segs_per_sec;
>   }
>
> - if (p->max_search > sbi->max_victim_search)
> + /* we need to check every dirty segments in the FG_GC case */
> + if (gc_type != FG_GC && p->max_search > sbi->max_victim_search)
>   p->max_search = sbi->max_victim_search;
>
>   p->offset = sbi->last_victim[p->gc_mode];
> @@ -199,6 +200,10 @@ static unsigned int check_bg_victims(struct f2fs_sb_info 
> *sbi)
>   for_each_set_bit(secno, dirty_i->victim_secmap, MAIN_SECS(sbi)) {
>   if (sec_usage_check(sbi, secno))
>   continue;
> +
> + if (no_fggc_candidate(sbi, secno))
> + continue;
> +
>   clear_bit(secno, dirty_i->victim_secmap);
>   return secno * sbi->segs_per_sec;
>   }
> @@ -322,13 +327,15 @@ static int get_victim_by_default(struct f2fs_sb_info 
> *sbi,
>   nsearched++;
>   }
>
> -
>   secno = GET_SECNO(sbi, segno);
>
>   if (sec_usage_check(sbi, secno))
>   goto next;
>   if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
>   goto next;
> + if (gc_type == FG_GC && p.alloc_mode == LFS &&
> + no_fggc_candidate(sbi, secno))
> + goto next;
>
>   cost = get_gc_cost(sbi, segno, );
>
> @@ -989,5 +996,16 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, bool 
> background)
>
>   void build_gc_manager(struct f2fs_sb_info *sbi)
>   {
> + u64 user_block_count, ovp_count, blocks_per_sec, th;
> +
>   DIRTY_I(sbi)->v_ops = _v_ops;
> +
> + /* threshold of # of valid blocks in a section for victims of FG_GC */
> + user_block_count = sbi->user_block_count;
> + ovp_count = SM_I(sbi)->ovp_segments << sbi->log_blocks_per_seg;

About the ovp_count calculation,

in mkfs.f2fs, we get ovp_segment by

 set_cp(overprov_segment_count, (get_sb(segment_count_main) -
get_cp(rsvd_segment_count)) *
 config.overprovision / 100);

 set_cp(overprov_segment_count, get_cp(overprov_segment_count) +
 get_cp(rsvd_segment_count));

where the overprov calculation is based on the space excluding the
rsvd segment, and the final overprov_segment is sum of the REAL
overprov segments and the

[f2fs-dev] [RFC] add ovp valid_blocks check for bg gc victim to fg_gc

2017-02-16 Thread Hou Pengyang
For foreground gc, greedy algorithm should be adapted, which makes
this formula work well:

(2 * (100 / config.overprovision + 1) + 6)

But currently, we fg_gc have a prior to select bg_gc victim segments to gc 
first,
these victims are selected by cost-benefit algorithm, we can't guarantee such 
segments
have the small valid blocks, which may destroy the f2fs rule, on the worstest 
case, would 
consume all the free segments.

This patch fix this by add a filter in check_bg_victims, if segment's has # of 
valid blocks
over overprovision ratio, skip such segments.

Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
 fs/f2fs/f2fs.h|  1 +
 fs/f2fs/gc.c  |  4 
 fs/f2fs/segment.h | 12 
 fs/f2fs/super.c   | 10 ++
 4 files changed, 27 insertions(+)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index c9a97c3..0afe94f 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -881,6 +881,7 @@ struct f2fs_sb_info {
struct mutex gc_mutex;  /* mutex for GC */
struct f2fs_gc_kthread  *gc_thread; /* GC thread */
unsigned int cur_victim_sec;/* current victim section num */
+   unsigned int fggc_threshold;/* threshold for converting bg victims 
for fg */
 
/* maximum # of trials to find a victim segment for SSR and GC */
unsigned int max_victim_search;
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 88e5e7b..18f3efa 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -199,6 +199,10 @@ static unsigned int check_bg_victims(struct f2fs_sb_info 
*sbi)
for_each_set_bit(secno, dirty_i->victim_secmap, MAIN_SECS(sbi)) {
if (sec_usage_check(sbi, secno))
continue;
+
+   if (valid_blocks_ovp_check(sbi, secno))
+   continue;
+
clear_bit(secno, dirty_i->victim_secmap);
return secno * sbi->segs_per_sec;
}
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index 5cb5755..2a6a1a9 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -716,6 +716,18 @@ static inline block_t sum_blk_addr(struct f2fs_sb_info 
*sbi, int base, int type)
- (base + 1) + type;
 }
 
+static inline bool valid_blocks_ovp_check(struct f2fs_sb_info *sbi, unsigned 
int secno)
+{
+   struct sit_info *sit_i = SIT_I(sbi);
+   unsigned int valid_blocks;
+
+   valid_blocks = sit_i->sec_entries[secno].valid_blocks;
+   if (valid_blocks >= sbi->fggc_threshold)
+   return true;
+   return false;
+
+}
+
 static inline bool sec_usage_check(struct f2fs_sb_info *sbi, unsigned int 
secno)
 {
if (IS_CURSEC(sbi, secno) || (sbi->cur_victim_sec == secno))
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 68a555b..54c4dac 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -2090,6 +2090,16 @@ static int f2fs_fill_super(struct super_block *sb, void 
*data, int silent)
if (err)
goto free_kobj;
}
+
+   sbi->fggc_threshold = (le32_to_cpu(sbi->ckpt->overprov_segment_count) -
+   
le32_to_cpu(sbi->ckpt->rsvd_segment_count)) * 100 /
+   
(le32_to_cpu(sbi->raw_super->segment_count_main) -
+   
le32_to_cpu(sbi->ckpt->rsvd_segment_count)) *
+   sbi->blocks_per_seg * sbi->segs_per_sec 
/ 100;
+
+   sbi->fggc_threshold = sbi->blocks_per_seg * sbi->segs_per_sec -
+   sbi->fggc_threshold;
+
kfree(options);
 
/* recover broken superblock */
-- 
2.10.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 conflict between atomic_write and truncate

2016-12-12 Thread Hou Pengyang
On 2016/12/13 3:18, Jaegeuk Kim wrote:
> Hi Pengyang,
>
Hi, kim,
> On 12/12, Hou Pengyang wrote:
>> In fsync_node_pages path, after locking the last_page for setting dirty,
>> we should check if the page has been truncated. Or there may be a mem leak,
>> as this dirty last_page will NOT be found in next page-cache travese.
>>
>> This patch adds page->mapping checking, and will NOT rewrite the page if
>> it has been truncated.
>>
>> Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
>> ---
>>   fs/f2fs/node.c | 5 +
>>   1 file changed, 5 insertions(+)
>>
>> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
>> index c1bbfdc..78c5b50 100644
>> --- a/fs/f2fs/node.c
>> +++ b/fs/f2fs/node.c
>> @@ -1410,6 +1410,11 @@ int fsync_node_pages(struct f2fs_sb_info *sbi, struct 
>> inode *inode,
>>  "Retry to write fsync mark: ino=%u, idx=%lx",
>>  ino, last_page->index);
>>  lock_page(last_page);
>
> We grabbed a reference count for this last_page, and thus, it won't be 
> released.
> Something that I missed?
>
Some path (e.g. shrink) would NOT release the page if we've grabbed it,
But truncate operation will invalidate the page from page-cache
regardless of the page reference.

Patch: 0fac558b965 f2fs: make atomic/volatile operation exclusive
seems fix this issue by adding inode_lock(inode) to avoid conflict
between atomic/volatile and truncate operation.

But this patch makes codes more robust.

Thanks.

> Thanks,
>
>> +if (unlikely(last_page->mapping != NODE_MAPPING(sbi))) {
>> +unlock_page(last_page);
>> +f2fs_put_page(last_page, 0);
>> +goto out;
>> +}
>>  f2fs_wait_on_page_writeback(last_page, NODE, true);
>>  set_page_dirty(last_page);
>>  unlock_page(last_page);
>> --
>> 2.10.1
>>
>>
>> --
>> Developer Access Program for Intel Xeon Phi Processors
>> Access to Intel Xeon Phi processor-based developer platforms.
>> With one year of Intel Parallel Studio XE.
>> Training and support from Colfax.
>> Order your platform today.http://sdm.link/xeonphi
>> ___
>> Linux-f2fs-devel mailing list
>> Linux-f2fs-devel@lists.sourceforge.net
>> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
>
> .
>



--
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] [RFC] f2fs: fix a race condition between evict & gc

2016-05-18 Thread Hou Pengyang
On 2016/5/18 1:23, Jaegeuk Kim wrote:
> On Tue, May 17, 2016 at 11:00:53AM +0800, Hou Pengyang wrote:
>> On 2016/5/16 23:10, Chao Yu wrote:
>> Hi chao,
>>> Hi Pengyang,
>>>
>>> On 2016/5/16 18:40, Hou Pengyang wrote:
>>>> When collecting data segment(gc_data_segment), there is a race condition
>>>> between evict and phases of gc:
>>>> 0) ra_node_page(dnode)
>>>> 1) ra_node_page(inode)
>>>><--- evict the inode
>>>> 2) f2fs_iget get the inode and add it to gc_list
>>>> 3) move_data_page
>>>>
>>>> In step 2), f2fs_iget does NOT find the inode and allocs a new inode as 
>>>> result,
>>>
>>> If inode was unlinked and then be evicted, f2fs_iget should fail when 
>>> reading
>>> inode's page as blkaddr of this node is null.
>> agree, after do_read_inode fail, the newly created inode would be
>> freed as a bad inode and f2fs_iget fails. But this may lead to create
>> file fail:
>> gc:iget_locked
>>  < touch/mkdir(reuse the evicted ino)
>> gc:free the bad inode
>
> Seems there is no problem.
>
> After f2fs_evict_inode(ino),
>
> f2fs_iget(ino)
>   - iget_failed()  f2fs_create()
> - f2fs_new_inode()
> - ino = alloc_nid()
> - insert_inode_locked()
>  *** spin_lock(_hash_lock)
>  - spin_lock(>i_lock)
>  - __iget(old)
>- make_bad_inode()- spin_unlock(>i_lock)
> - remove_inode_hash()- spin_unlock(_hash_lock)
>  - spin_lock(_hash_lock)   - wait_on_inode(old)

oh.. wait_on_inode. OK, Kim, get it, thanks for your answer.

>  - spin_lock(>i_lock)
>  - list_del
>  - spin_unlock(>i_lock)
>  - spin_unlock(_hash_lock)
> - unlock_new_inode()
>  - wake_up_bit(>i_state, __I_NEW) --> wake up!
>  - iput(old) whish was unhashed.
>  - goto to ***
> - iput()
>
>> during the bad inode allocated and freed in gc, the inode is reserved
>> in the global inode_hash, while the ino is a free nid in free_nid tree.
>>
>> touch/mkdir may reuse the ino, during the touch/mkdir path, the global
>> inode_hash would be checked if the ino file exists. Under this
>> scenario, because of the gc bad inode in inode_hash, touch/mkdir would
>> fail.
>>
>> ilookup seems better, as no need to alloc and free a bad inode.
>>
>> if ilookup fails, that exactly means inode has been evicted and no need
>> to gc;
>
> No, we should do gc for data blocks owned by *evicted* inodes as well.
>
> Thanks,
>
>> if ilookup success, before phase 3, is_alive to deal with the ino reuse
>> scenario;
>>
>> Do I miss anything else?
>> thanks
>>> If inode still have non-zero nlink value and then be evicted, we should 
>>> allow gc
>>> thread to reference this inode for moving its data pages.
>>>
>>> Thanks,
>>>
>>>> which is not resonable.
>>>>
>>>> This patch changes f2fs_iget to ilookup. when no inode is found, no new 
>>>> inode is
>>>> created.
>>>>
>>>> Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
>>>> ---
>>>>fs/f2fs/gc.c | 4 ++--
>>>>1 file changed, 2 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
>>>> index 38d56f6..6e73193 100644
>>>> --- a/fs/f2fs/gc.c
>>>> +++ b/fs/f2fs/gc.c
>>>> @@ -717,8 +717,8 @@ next_step:
>>>>ofs_in_node = le16_to_cpu(entry->ofs_in_node);
>>>>
>>>>if (phase == 2) {
>>>> -  inode = f2fs_iget(sb, dni.ino);
>>>> -  if (IS_ERR(inode) || is_bad_inode(inode))
>>>> +  inode = ilookup(sb, dni.ino);
>>>> +  if (!inode || IS_ERR(inode) || is_bad_inode(inode))
>>>>continue;
>>>>
>>>>/* if encrypted inode, let's go phase 3 */
>>>>
>>>
>>> .
>>>
>>
>>
>>
>> ---

Re: [f2fs-dev] [RFC] f2fs: fix a race condition between evict & gc

2016-05-16 Thread Hou Pengyang
On 2016/5/16 23:10, Chao Yu wrote:
Hi chao,
> Hi Pengyang,
>
> On 2016/5/16 18:40, Hou Pengyang wrote:
>> When collecting data segment(gc_data_segment), there is a race condition
>> between evict and phases of gc:
>> 0) ra_node_page(dnode)
>> 1) ra_node_page(inode)
>>  <--- evict the inode
>> 2) f2fs_iget get the inode and add it to gc_list
>> 3) move_data_page
>>
>> In step 2), f2fs_iget does NOT find the inode and allocs a new inode as 
>> result,
>
> If inode was unlinked and then be evicted, f2fs_iget should fail when reading
> inode's page as blkaddr of this node is null.
agree, after do_read_inode fail, the newly created inode would be
freed as a bad inode and f2fs_iget fails. But this may lead to create
file fail:
gc:iget_locked
< touch/mkdir(reuse the evicted ino)
gc:free the bad inode

during the bad inode allocated and freed in gc, the inode is reserved
in the global inode_hash, while the ino is a free nid in free_nid tree.

touch/mkdir may reuse the ino, during the touch/mkdir path, the global
inode_hash would be checked if the ino file exists. Under this
scenario, because of the gc bad inode in inode_hash, touch/mkdir would
fail.

ilookup seems better, as no need to alloc and free a bad inode.

if ilookup fails, that exactly means inode has been evicted and no need
to gc;
if ilookup success, before phase 3, is_alive to deal with the ino reuse
scenario;

Do I miss anything else?
thanks
> If inode still have non-zero nlink value and then be evicted, we should allow 
> gc
> thread to reference this inode for moving its data pages.
>
> Thanks,
>
>> which is not resonable.
>>
>> This patch changes f2fs_iget to ilookup. when no inode is found, no new 
>> inode is
>> created.
>>
>> Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
>> ---
>>   fs/f2fs/gc.c | 4 ++--
>>   1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
>> index 38d56f6..6e73193 100644
>> --- a/fs/f2fs/gc.c
>> +++ b/fs/f2fs/gc.c
>> @@ -717,8 +717,8 @@ next_step:
>>  ofs_in_node = le16_to_cpu(entry->ofs_in_node);
>>
>>  if (phase == 2) {
>> -inode = f2fs_iget(sb, dni.ino);
>> -if (IS_ERR(inode) || is_bad_inode(inode))
>> +inode = ilookup(sb, dni.ino);
>> +if (!inode || IS_ERR(inode) || is_bad_inode(inode))
>>  continue;
>>
>>  /* if encrypted inode, let's go phase 3 */
>>
>
> .
>



--
Mobile security can be enabling, not merely restricting. Employees who
bring their own devices (BYOD) to work are irked by the imposition of MDM
restrictions. Mobile Device Manager Plus allows you to control only the
apps on BYO-devices by containerizing them, leaving personal data untouched!
https://ad.doubleclick.net/ddm/clk/304595813;131938128;j
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [RFC] f2fs: fix a race condition between evict & gc

2016-05-16 Thread Hou Pengyang
When collecting data segment(gc_data_segment), there is a race condition
between evict and phases of gc:
0) ra_node_page(dnode)
1) ra_node_page(inode)
<--- evict the inode
2) f2fs_iget get the inode and add it to gc_list 
3) move_data_page

In step 2), f2fs_iget does NOT find the inode and allocs a new inode as result,
which is not resonable.

This patch changes f2fs_iget to ilookup. when no inode is found, no new inode is
created.

Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
---
 fs/f2fs/gc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 38d56f6..6e73193 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -717,8 +717,8 @@ next_step:
ofs_in_node = le16_to_cpu(entry->ofs_in_node);
 
if (phase == 2) {
-   inode = f2fs_iget(sb, dni.ino);
-   if (IS_ERR(inode) || is_bad_inode(inode))
+   inode = ilookup(sb, dni.ino);
+   if (!inode || IS_ERR(inode) || is_bad_inode(inode))
continue;
 
/* if encrypted inode, let's go phase 3 */
-- 
1.9.1


--
Mobile security can be enabling, not merely restricting. Employees who
bring their own devices (BYOD) to work are irked by the imposition of MDM
restrictions. Mobile Device Manager Plus allows you to control only the
apps on BYO-devices by containerizing them, leaving personal data untouched!
https://ad.doubleclick.net/ddm/clk/304595813;131938128;j
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


Re: [f2fs-dev] [PATCH 11/11] f2fs: retry to truncate blocks in -ENOMEM case

2016-05-04 Thread Hou Pengyang
On 2016/5/4 2:21, Jaegeuk Kim wrote:
> This patch modifies to retry truncating node blocks in -ENOMEM case.
>
Hi, Kim. in this patch, I think there is NO chance to retry for -ENOMEM.

This is because if exist_written_data returns false, we can confirm that
this inode has been released from orphan radix-tree:
f2fs_evict_inode
  ---> remove_inode_page
 ---> truncate_node
 ---> remove_orphan_inode
On this condition, err is 0, So it won't enter:
if (err && err != -ENOENT)
{
 ...
}
sequentially, there is no chance to truncate node blocks again.
I miss something else?

How about this patch?

--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -345,6 +345,7 @@ void f2fs_evict_inode(struct inode *inode)
 set_inode_flag(fi, FI_NO_ALLOC);
 i_size_write(inode, 0);

+retry:
 if (F2FS_HAS_BLOCKS(inode))
 err = f2fs_truncate(inode, true);

@@ -354,6 +355,11 @@ void f2fs_evict_inode(struct inode *inode)
 f2fs_unlock_op(sbi);
 }

+   if (err == -ENOMEM) {
+   err = 0;
+   goto retry;
+   }
+
 sb_end_intwrite(inode->i_sb);
  no_delete:
 stat_dec_inline_xattr(inode);
> Signed-off-by: Jaegeuk Kim 
> ---
>   fs/f2fs/inode.c | 7 ++-
>   1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
> index f4ac851..5cccd7a 100644
> --- a/fs/f2fs/inode.c
> +++ b/fs/f2fs/inode.c
> @@ -344,7 +344,7 @@ void f2fs_evict_inode(struct inode *inode)
>   sb_start_intwrite(inode->i_sb);
>   set_inode_flag(fi, FI_NO_ALLOC);
>   i_size_write(inode, 0);
> -
> +retry:
>   if (F2FS_HAS_BLOCKS(inode))
>   err = f2fs_truncate(inode, true);
>
> @@ -374,6 +374,11 @@ no_delete:
>
>   if (err && err != -ENOENT) {
>   if (!exist_written_data(sbi, inode->i_ino, ORPHAN_INO)) {
> + /* give more chances, if ENOMEM case */
> + if (err == -ENOMEM) {
> + err = 0;
> + goto retry;
> + }
>   /*
>* get here because we failed to release resource
>* of inode previously, reminder our user to run fsck
>



--
Find and fix application performance issues faster with Applications Manager
Applications Manager provides deep performance insights into multiple tiers of
your business applications. It resolves application problems quickly and
reduces your MTTR. Get your free trial!
https://ad.doubleclick.net/ddm/clk/302982198;130105516;z
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel