[f2fs-dev] [PATCH v5] f2fs: split discard command in prior to block layer

2018-08-06 Thread Chao Yu
From: Chao Yu 

Some devices has small max_{hw,}discard_sectors, so that in
__blkdev_issue_discard(), one big size discard bio can be split
into multiple small size discard bios, result in heavy load in IO
scheduler and device, which can hang other sync IO for long time.

Now, f2fs is trying to control discard commands more elaboratively,
in order to make less conflict in between discard IO and user IO
to enhance application's performance, so in this patch, we will
split discard bio in f2fs in prior to in block layer to reduce
issuing multiple discard bios in a short time.

Signed-off-by: Chao Yu 
---
v5:
- fix to add missing parenthese.
 fs/f2fs/f2fs.h|  23 +++
 fs/f2fs/segment.c | 148 +++---
 2 files changed, 127 insertions(+), 44 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index ca23fbc8da30..a83ea4416e03 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -178,7 +178,6 @@ enum {
 
 #define MAX_DISCARD_BLOCKS(sbi)BLKS_PER_SEC(sbi)
 #define DEF_MAX_DISCARD_REQUEST8   /* issue 8 discards per 
round */
-#define DEF_MAX_DISCARD_LEN512 /* Max. 2MB per discard */
 #define DEF_MIN_DISCARD_ISSUE_TIME 50  /* 50 ms, if exists */
 #define DEF_MID_DISCARD_ISSUE_TIME 500 /* 500 ms, if device busy */
 #define DEF_MAX_DISCARD_ISSUE_TIME 6   /* 60 s, if no candidates */
@@ -250,9 +249,10 @@ struct discard_entry {
(MAX_PLIST_NUM - 1) : (blk_num - 1))
 
 enum {
-   D_PREP,
-   D_SUBMIT,
-   D_DONE,
+   D_PREP, /* initial */
+   D_PARTIAL,  /* partially submitted */
+   D_SUBMIT,   /* all submitted */
+   D_DONE, /* finished */
 };
 
 struct discard_info {
@@ -277,7 +277,10 @@ struct discard_cmd {
struct block_device *bdev;  /* bdev */
unsigned short ref; /* reference count */
unsigned char state;/* state */
+   unsigned char issuing;  /* issuing discard */
int error;  /* bio error */
+   spinlock_t lock;/* for state/bio_ref updating */
+   unsigned short bio_ref; /* bio reference count */
 };
 
 enum {
@@ -710,22 +713,22 @@ static inline void set_extent_info(struct extent_info 
*ei, unsigned int fofs,
 }
 
 static inline bool __is_discard_mergeable(struct discard_info *back,
-   struct discard_info *front)
+   struct discard_info *front, unsigned int max_len)
 {
return (back->lstart + back->len == front->lstart) &&
-   (back->len + front->len < DEF_MAX_DISCARD_LEN);
+   (back->len + front->len <= max_len);
 }
 
 static inline bool __is_discard_back_mergeable(struct discard_info *cur,
-   struct discard_info *back)
+   struct discard_info *back, unsigned int max_len)
 {
-   return __is_discard_mergeable(back, cur);
+   return __is_discard_mergeable(back, cur, max_len);
 }
 
 static inline bool __is_discard_front_mergeable(struct discard_info *cur,
-   struct discard_info *front)
+   struct discard_info *front, unsigned int max_len)
 {
-   return __is_discard_mergeable(cur, front);
+   return __is_discard_mergeable(cur, front, max_len);
 }
 
 static inline bool __is_extent_mergeable(struct extent_info *back,
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 96f225b1596e..f93c37309bff 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -843,9 +843,12 @@ static struct discard_cmd *__create_discard_cmd(struct 
f2fs_sb_info *sbi,
dc->len = len;
dc->ref = 0;
dc->state = D_PREP;
+   dc->issuing = 0;
dc->error = 0;
init_completion(>wait);
list_add_tail(>list, pend_list);
+   spin_lock_init(>lock);
+   dc->bio_ref = 0;
atomic_inc(>discard_cmd_cnt);
dcc->undiscard_blks += len;
 
@@ -872,7 +875,7 @@ static void __detach_discard_cmd(struct discard_cmd_control 
*dcc,
struct discard_cmd *dc)
 {
if (dc->state == D_DONE)
-   atomic_dec(>issing_discard);
+   atomic_sub(dc->issuing, >issing_discard);
 
list_del(>list);
rb_erase(>rb_node, >root);
@@ -887,9 +890,17 @@ static void __remove_discard_cmd(struct f2fs_sb_info *sbi,
struct discard_cmd *dc)
 {
struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
+   unsigned long flags;
 
trace_f2fs_remove_discard(dc->bdev, dc->start, dc->len);
 
+   spin_lock_irqsave(>lock, flags);
+   if (dc->bio_ref) {
+   spin_unlock_irqrestore(>lock, flags);
+   return;
+   }
+   

[f2fs-dev] [PATCH] f2fs: support discard submission error injection

2018-08-06 Thread Chao Yu
This patch adds to support discard submission error injection for testing
error handling of __submit_discard_cmd().

Signed-off-by: Chao Yu 
---
 fs/f2fs/f2fs.h| 1 +
 fs/f2fs/segment.c | 8 
 fs/f2fs/super.c   | 1 +
 3 files changed, 10 insertions(+)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index ae9dfad58046..1e07fcd7f580 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -56,6 +56,7 @@ enum {
FAULT_TRUNCATE,
FAULT_IO,
FAULT_CHECKPOINT,
+   FAULT_DISCARD,
FAULT_MAX,
 };
 
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index ccad453bd2b7..db8a79ac5b3f 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -1045,10 +1045,18 @@ static void __submit_discard_cmd(struct f2fs_sb_info 
*sbi,
 
dc->len += len;
 
+#ifdef CONFIG_F2FS_FAULT_INJECTION
+   if (time_to_inject(sbi, FAULT_DISCARD)) {
+   f2fs_show_injection_info(FAULT_DISCARD);
+   err = -EIO;
+   goto submit;
+   }
+#endif
err = __blkdev_issue_discard(bdev,
SECTOR_FROM_BLOCK(start),
SECTOR_FROM_BLOCK(len),
GFP_NOFS, 0, );
+submit:
if (!err && bio) {
/*
 * should keep before submission to avoid D_DONE
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index ba2fd51580d2..254f74a6b481 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -55,6 +55,7 @@ char *f2fs_fault_name[FAULT_MAX] = {
[FAULT_TRUNCATE]= "truncate fail",
[FAULT_IO]  = "IO error",
[FAULT_CHECKPOINT]  = "checkpoint error",
+   [FAULT_DISCARD] = "discard error",
 };
 
 void f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned int rate)
-- 
2.18.0.rc1


--
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 v4] f2fs: split discard command in prior to block layer

2018-08-06 Thread Chao Yu
Some devices has small max_{hw,}discard_sectors, so that in
__blkdev_issue_discard(), one big size discard bio can be split
into multiple small size discard bios, result in heavy load in IO
scheduler and device, which can hang other sync IO for long time.

Now, f2fs is trying to control discard commands more elaboratively,
in order to make less conflict in between discard IO and user IO
to enhance application's performance, so in this patch, we will
split discard bio in f2fs in prior to in block layer to reduce
issuing multiple discard bios in a short time.

Signed-off-by: Chao Yu 
---
v4:
- add spin lock to update state and bio_ref atomically.
- add a new state D_PARTIAL to indicate partially submission.
- fix to update dcc->issing_discard correctly
- handle race case between __submit_discard_cmd/__remove_discard_cmd and
f2fs_submit_discard_endio
- fix to update dc->len correctly.
 fs/f2fs/f2fs.h|  23 +++
 fs/f2fs/segment.c | 148 +++---
 2 files changed, 127 insertions(+), 44 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index ca23fbc8da30..a83ea4416e03 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -178,7 +178,6 @@ enum {
 
 #define MAX_DISCARD_BLOCKS(sbi)BLKS_PER_SEC(sbi)
 #define DEF_MAX_DISCARD_REQUEST8   /* issue 8 discards per 
round */
-#define DEF_MAX_DISCARD_LEN512 /* Max. 2MB per discard */
 #define DEF_MIN_DISCARD_ISSUE_TIME 50  /* 50 ms, if exists */
 #define DEF_MID_DISCARD_ISSUE_TIME 500 /* 500 ms, if device busy */
 #define DEF_MAX_DISCARD_ISSUE_TIME 6   /* 60 s, if no candidates */
@@ -250,9 +249,10 @@ struct discard_entry {
(MAX_PLIST_NUM - 1) : (blk_num - 1))
 
 enum {
-   D_PREP,
-   D_SUBMIT,
-   D_DONE,
+   D_PREP, /* initial */
+   D_PARTIAL,  /* partially submitted */
+   D_SUBMIT,   /* all submitted */
+   D_DONE, /* finished */
 };
 
 struct discard_info {
@@ -277,7 +277,10 @@ struct discard_cmd {
struct block_device *bdev;  /* bdev */
unsigned short ref; /* reference count */
unsigned char state;/* state */
+   unsigned char issuing;  /* issuing discard */
int error;  /* bio error */
+   spinlock_t lock;/* for state/bio_ref updating */
+   unsigned short bio_ref; /* bio reference count */
 };
 
 enum {
@@ -710,22 +713,22 @@ static inline void set_extent_info(struct extent_info 
*ei, unsigned int fofs,
 }
 
 static inline bool __is_discard_mergeable(struct discard_info *back,
-   struct discard_info *front)
+   struct discard_info *front, unsigned int max_len)
 {
return (back->lstart + back->len == front->lstart) &&
-   (back->len + front->len < DEF_MAX_DISCARD_LEN);
+   (back->len + front->len <= max_len);
 }
 
 static inline bool __is_discard_back_mergeable(struct discard_info *cur,
-   struct discard_info *back)
+   struct discard_info *back, unsigned int max_len)
 {
-   return __is_discard_mergeable(back, cur);
+   return __is_discard_mergeable(back, cur, max_len);
 }
 
 static inline bool __is_discard_front_mergeable(struct discard_info *cur,
-   struct discard_info *front)
+   struct discard_info *front, unsigned int max_len)
 {
-   return __is_discard_mergeable(cur, front);
+   return __is_discard_mergeable(cur, front, max_len);
 }
 
 static inline bool __is_extent_mergeable(struct extent_info *back,
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 96f225b1596e..827cd3577756 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -843,9 +843,12 @@ static struct discard_cmd *__create_discard_cmd(struct 
f2fs_sb_info *sbi,
dc->len = len;
dc->ref = 0;
dc->state = D_PREP;
+   dc->issuing = 0;
dc->error = 0;
init_completion(>wait);
list_add_tail(>list, pend_list);
+   spin_lock_init(>lock);
+   dc->bio_ref = 0;
atomic_inc(>discard_cmd_cnt);
dcc->undiscard_blks += len;
 
@@ -872,7 +875,7 @@ static void __detach_discard_cmd(struct discard_cmd_control 
*dcc,
struct discard_cmd *dc)
 {
if (dc->state == D_DONE)
-   atomic_dec(>issing_discard);
+   atomic_sub(dc->issuing, >issing_discard);
 
list_del(>list);
rb_erase(>rb_node, >root);
@@ -887,9 +890,17 @@ static void __remove_discard_cmd(struct f2fs_sb_info *sbi,
struct discard_cmd *dc)
 {
struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
+   unsigned long 

Re: [f2fs-dev] [PATCH] fsck.f2fs: supply more check entries for checkpoint

2018-08-06 Thread Chao Yu
On 2018/8/3 12:09, Junling Zheng wrote:
> Supply some more check entries for checkpoint in sanity_check_ckpt()
> and validate_checkpoint() to sync them with kernel.
> 
> Signed-off-by: Junling Zheng 

Reviewed-by: Chao Yu 

Thanks,


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


Re: [f2fs-dev] [PATCH] f2fs: wake up gc thread immediately when gc_urgent is set

2018-08-06 Thread Chao Yu
On 2018/8/5 12:45, Sheng Yong wrote:
> Fixes: 5b0e95398e2b ("f2fs: introduce sbi->gc_mode to determine the policy")
> Signed-off-by: Sheng Yong 

Reviewed-by: Chao Yu 

Thanks,


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