Skip to content

Commit

Permalink
f2fs: don't hold cmd_lock during waiting discard command
Browse files Browse the repository at this point in the history
Previously, with protection of cmd_lock, we will wait for end io of
discard command which potentially may lead long latency, making worse
concurrency.

So, in this patch, we try to add reference into discard entry to prevent
the entry being released by other thread, then we can avoid holding
global cmd_lock during waiting discard to finish.

Signed-off-by: Chao Yu <[email protected]>
Signed-off-by: Jaegeuk Kim <[email protected]>
  • Loading branch information
chaseyu authored and Jaegeuk Kim committed May 3, 2017
1 parent 4d97807 commit ec9895a
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 5 deletions.
1 change: 1 addition & 0 deletions fs/f2fs/f2fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ struct discard_cmd {
struct list_head list; /* command list */
struct completion wait; /* compleation */
struct block_device *bdev; /* bdev */
unsigned short ref; /* reference count */
int state; /* state */
int error; /* bio error */
};
Expand Down
25 changes: 20 additions & 5 deletions fs/f2fs/segment.c
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,7 @@ static struct discard_cmd *__create_discard_cmd(struct f2fs_sb_info *sbi,
dc->lstart = lstart;
dc->start = start;
dc->len = len;
dc->ref = 0;
dc->state = D_PREP;
dc->error = 0;
init_completion(&dc->wait);
Expand Down Expand Up @@ -1007,6 +1008,8 @@ static void __wait_discard_cmd(struct f2fs_sb_info *sbi, bool wait_cond)
mutex_lock(&dcc->cmd_lock);
list_for_each_entry_safe(dc, tmp, wait_list, list) {
if (!wait_cond || dc->state == D_DONE) {
if (dc->ref)
continue;
wait_for_completion_io(&dc->wait);
__remove_discard_cmd(sbi, dc);
}
Expand All @@ -1019,17 +1022,29 @@ void f2fs_wait_discard_bio(struct f2fs_sb_info *sbi, block_t blkaddr)
{
struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
struct discard_cmd *dc;
bool need_wait = false;

mutex_lock(&dcc->cmd_lock);

dc = (struct discard_cmd *)__lookup_rb_tree(&dcc->root, NULL, blkaddr);
if (dc) {
if (dc->state != D_PREP)
wait_for_completion_io(&dc->wait);
__punch_discard_cmd(sbi, dc, blkaddr);
if (dc->state == D_PREP) {
__punch_discard_cmd(sbi, dc, blkaddr);
} else {
dc->ref++;
need_wait = true;
}
}

mutex_unlock(&dcc->cmd_lock);

if (need_wait) {
wait_for_completion_io(&dc->wait);
mutex_lock(&dcc->cmd_lock);
f2fs_bug_on(sbi, dc->state != D_DONE);
dc->ref--;
if (!dc->ref)
__remove_discard_cmd(sbi, dc);
mutex_unlock(&dcc->cmd_lock);
}
}

/* This comes from f2fs_put_super */
Expand Down

0 comments on commit ec9895a

Please sign in to comment.