Commit f69475dd authored by Jaegeuk Kim's avatar Jaegeuk Kim

f2fs: factor out discard_cmd usage from general rb_tree use

This is a second part to remove the mixed use of rb_tree in discard_cmd from
extent_cache.

This should also fix arm32 memory alignment issue caused by shared rb_entry.

[struct discard_cmd]               [struct rb_entry]
[0] struct rb_node rb_node;        [0] struct rb_node rb_node;
  union {                              union {
    struct {                             struct {
[16]  block_t lstart;              [12]    unsigned int ofs;
      block_t len;                         unsigned int len;
                                         };
                                         unsigned long long key;
                                       } __packed;

Cc: <stable@vger.kernel.org>
Fixes: 004b6862 ("f2fs: use rb-tree to track pending discard commands")
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 043d2d00
...@@ -192,7 +192,7 @@ static struct rb_entry *__lookup_rb_tree_slow(struct rb_root_cached *root, ...@@ -192,7 +192,7 @@ static struct rb_entry *__lookup_rb_tree_slow(struct rb_root_cached *root,
return NULL; return NULL;
} }
struct rb_entry *f2fs_lookup_rb_tree(struct rb_root_cached *root, static struct rb_entry *f2fs_lookup_rb_tree(struct rb_root_cached *root,
struct rb_entry *cached_re, unsigned int ofs) struct rb_entry *cached_re, unsigned int ofs)
{ {
struct rb_entry *re; struct rb_entry *re;
...@@ -204,7 +204,7 @@ struct rb_entry *f2fs_lookup_rb_tree(struct rb_root_cached *root, ...@@ -204,7 +204,7 @@ struct rb_entry *f2fs_lookup_rb_tree(struct rb_root_cached *root,
return re; return re;
} }
struct rb_node **f2fs_lookup_rb_tree_for_insert(struct f2fs_sb_info *sbi, static struct rb_node **f2fs_lookup_rb_tree_for_insert(struct f2fs_sb_info *sbi,
struct rb_root_cached *root, struct rb_root_cached *root,
struct rb_node **parent, struct rb_node **parent,
unsigned int ofs, bool *leftmost) unsigned int ofs, bool *leftmost)
...@@ -238,7 +238,7 @@ struct rb_node **f2fs_lookup_rb_tree_for_insert(struct f2fs_sb_info *sbi, ...@@ -238,7 +238,7 @@ struct rb_node **f2fs_lookup_rb_tree_for_insert(struct f2fs_sb_info *sbi,
* in order to simplify the insertion after. * in order to simplify the insertion after.
* tree must stay unchanged between lookup and insertion. * tree must stay unchanged between lookup and insertion.
*/ */
struct rb_entry *f2fs_lookup_rb_tree_ret(struct rb_root_cached *root, static struct rb_entry *f2fs_lookup_rb_tree_ret(struct rb_root_cached *root,
struct rb_entry *cached_re, struct rb_entry *cached_re,
unsigned int ofs, unsigned int ofs,
struct rb_entry **prev_entry, struct rb_entry **prev_entry,
...@@ -311,36 +311,6 @@ struct rb_entry *f2fs_lookup_rb_tree_ret(struct rb_root_cached *root, ...@@ -311,36 +311,6 @@ struct rb_entry *f2fs_lookup_rb_tree_ret(struct rb_root_cached *root,
return re; return re;
} }
bool f2fs_check_rb_tree_consistence(struct f2fs_sb_info *sbi,
struct rb_root_cached *root)
{
#ifdef CONFIG_F2FS_CHECK_FS
struct rb_node *cur = rb_first_cached(root), *next;
struct rb_entry *cur_re, *next_re;
if (!cur)
return true;
while (cur) {
next = rb_next(cur);
if (!next)
return true;
cur_re = rb_entry(cur, struct rb_entry, rb_node);
next_re = rb_entry(next, struct rb_entry, rb_node);
if (cur_re->ofs + cur_re->len > next_re->ofs) {
f2fs_info(sbi, "inconsistent rbtree, cur(%u, %u) next(%u, %u)",
cur_re->ofs, cur_re->len,
next_re->ofs, next_re->len);
return false;
}
cur = next;
}
#endif
return true;
}
static struct kmem_cache *extent_tree_slab; static struct kmem_cache *extent_tree_slab;
static struct kmem_cache *extent_node_slab; static struct kmem_cache *extent_node_slab;
......
...@@ -353,15 +353,7 @@ struct discard_info { ...@@ -353,15 +353,7 @@ struct discard_info {
struct discard_cmd { struct discard_cmd {
struct rb_node rb_node; /* rb node located in rb-tree */ struct rb_node rb_node; /* rb node located in rb-tree */
union { struct discard_info di; /* discard info */
struct {
block_t lstart; /* logical start address */
block_t len; /* length */
block_t start; /* actual start address in dev */
};
struct discard_info di; /* discard info */
};
struct list_head list; /* command list */ struct list_head list; /* command list */
struct completion wait; /* compleation */ struct completion wait; /* compleation */
struct block_device *bdev; /* bdev */ struct block_device *bdev; /* bdev */
...@@ -4132,19 +4124,6 @@ void f2fs_leave_shrinker(struct f2fs_sb_info *sbi); ...@@ -4132,19 +4124,6 @@ void f2fs_leave_shrinker(struct f2fs_sb_info *sbi);
* extent_cache.c * extent_cache.c
*/ */
bool sanity_check_extent_cache(struct inode *inode); bool sanity_check_extent_cache(struct inode *inode);
struct rb_entry *f2fs_lookup_rb_tree(struct rb_root_cached *root,
struct rb_entry *cached_re, unsigned int ofs);
struct rb_node **f2fs_lookup_rb_tree_for_insert(struct f2fs_sb_info *sbi,
struct rb_root_cached *root,
struct rb_node **parent,
unsigned int ofs, bool *leftmost);
struct rb_entry *f2fs_lookup_rb_tree_ret(struct rb_root_cached *root,
struct rb_entry *cached_re, unsigned int ofs,
struct rb_entry **prev_entry, struct rb_entry **next_entry,
struct rb_node ***insert_p, struct rb_node **insert_parent,
bool force, bool *leftmost);
bool f2fs_check_rb_tree_consistence(struct f2fs_sb_info *sbi,
struct rb_root_cached *root);
void f2fs_init_extent_tree(struct inode *inode); void f2fs_init_extent_tree(struct inode *inode);
void f2fs_drop_extent_tree(struct inode *inode); void f2fs_drop_extent_tree(struct inode *inode);
void f2fs_destroy_extent_node(struct inode *inode); void f2fs_destroy_extent_node(struct inode *inode);
......
...@@ -933,9 +933,9 @@ static struct discard_cmd *__create_discard_cmd(struct f2fs_sb_info *sbi, ...@@ -933,9 +933,9 @@ static struct discard_cmd *__create_discard_cmd(struct f2fs_sb_info *sbi,
dc = f2fs_kmem_cache_alloc(discard_cmd_slab, GFP_NOFS, true, NULL); dc = f2fs_kmem_cache_alloc(discard_cmd_slab, GFP_NOFS, true, NULL);
INIT_LIST_HEAD(&dc->list); INIT_LIST_HEAD(&dc->list);
dc->bdev = bdev; dc->bdev = bdev;
dc->lstart = lstart; dc->di.lstart = lstart;
dc->start = start; dc->di.start = start;
dc->len = len; dc->di.len = len;
dc->ref = 0; dc->ref = 0;
dc->state = D_PREP; dc->state = D_PREP;
dc->queued = 0; dc->queued = 0;
...@@ -950,20 +950,108 @@ static struct discard_cmd *__create_discard_cmd(struct f2fs_sb_info *sbi, ...@@ -950,20 +950,108 @@ static struct discard_cmd *__create_discard_cmd(struct f2fs_sb_info *sbi,
return dc; return dc;
} }
static struct discard_cmd *__attach_discard_cmd(struct f2fs_sb_info *sbi, static bool f2fs_check_discard_tree(struct f2fs_sb_info *sbi)
struct block_device *bdev, block_t lstart, {
block_t start, block_t len, #ifdef CONFIG_F2FS_CHECK_FS
struct rb_node *parent, struct rb_node **p, struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
bool leftmost) struct rb_node *cur = rb_first_cached(&dcc->root), *next;
struct discard_cmd *cur_dc, *next_dc;
while (cur) {
next = rb_next(cur);
if (!next)
return true;
cur_dc = rb_entry(cur, struct discard_cmd, rb_node);
next_dc = rb_entry(next, struct discard_cmd, rb_node);
if (cur_dc->di.lstart + cur_dc->di.len > next_dc->di.lstart) {
f2fs_info(sbi, "broken discard_rbtree, "
"cur(%u, %u) next(%u, %u)",
cur_dc->di.lstart, cur_dc->di.len,
next_dc->di.lstart, next_dc->di.len);
return false;
}
cur = next;
}
#endif
return true;
}
static struct discard_cmd *__lookup_discard_cmd(struct f2fs_sb_info *sbi,
block_t blkaddr)
{ {
struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
struct rb_node *node = dcc->root.rb_root.rb_node;
struct discard_cmd *dc; struct discard_cmd *dc;
dc = __create_discard_cmd(sbi, bdev, lstart, start, len); while (node) {
dc = rb_entry(node, struct discard_cmd, rb_node);
rb_link_node(&dc->rb_node, parent, p); if (blkaddr < dc->di.lstart)
rb_insert_color_cached(&dc->rb_node, &dcc->root, leftmost); node = node->rb_left;
else if (blkaddr >= dc->di.lstart + dc->di.len)
node = node->rb_right;
else
return dc;
}
return NULL;
}
static struct discard_cmd *__lookup_discard_cmd_ret(struct rb_root_cached *root,
block_t blkaddr,
struct discard_cmd **prev_entry,
struct discard_cmd **next_entry,
struct rb_node ***insert_p,
struct rb_node **insert_parent)
{
struct rb_node **pnode = &root->rb_root.rb_node;
struct rb_node *parent = NULL, *tmp_node;
struct discard_cmd *dc;
*insert_p = NULL;
*insert_parent = NULL;
*prev_entry = NULL;
*next_entry = NULL;
if (RB_EMPTY_ROOT(&root->rb_root))
return NULL;
while (*pnode) {
parent = *pnode;
dc = rb_entry(*pnode, struct discard_cmd, rb_node);
if (blkaddr < dc->di.lstart)
pnode = &(*pnode)->rb_left;
else if (blkaddr >= dc->di.lstart + dc->di.len)
pnode = &(*pnode)->rb_right;
else
goto lookup_neighbors;
}
*insert_p = pnode;
*insert_parent = parent;
dc = rb_entry(parent, struct discard_cmd, rb_node);
tmp_node = parent;
if (parent && blkaddr > dc->di.lstart)
tmp_node = rb_next(parent);
*next_entry = rb_entry_safe(tmp_node, struct discard_cmd, rb_node);
tmp_node = parent;
if (parent && blkaddr < dc->di.lstart)
tmp_node = rb_prev(parent);
*prev_entry = rb_entry_safe(tmp_node, struct discard_cmd, rb_node);
return NULL;
lookup_neighbors:
/* lookup prev node for merging backward later */
tmp_node = rb_prev(&dc->rb_node);
*prev_entry = rb_entry_safe(tmp_node, struct discard_cmd, rb_node);
/* lookup next node for merging frontward later */
tmp_node = rb_next(&dc->rb_node);
*next_entry = rb_entry_safe(tmp_node, struct discard_cmd, rb_node);
return dc; return dc;
} }
...@@ -975,7 +1063,7 @@ static void __detach_discard_cmd(struct discard_cmd_control *dcc, ...@@ -975,7 +1063,7 @@ static void __detach_discard_cmd(struct discard_cmd_control *dcc,
list_del(&dc->list); list_del(&dc->list);
rb_erase_cached(&dc->rb_node, &dcc->root); rb_erase_cached(&dc->rb_node, &dcc->root);
dcc->undiscard_blks -= dc->len; dcc->undiscard_blks -= dc->di.len;
kmem_cache_free(discard_cmd_slab, dc); kmem_cache_free(discard_cmd_slab, dc);
...@@ -988,7 +1076,7 @@ static void __remove_discard_cmd(struct f2fs_sb_info *sbi, ...@@ -988,7 +1076,7 @@ static void __remove_discard_cmd(struct f2fs_sb_info *sbi,
struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
unsigned long flags; unsigned long flags;
trace_f2fs_remove_discard(dc->bdev, dc->start, dc->len); trace_f2fs_remove_discard(dc->bdev, dc->di.start, dc->di.len);
spin_lock_irqsave(&dc->lock, flags); spin_lock_irqsave(&dc->lock, flags);
if (dc->bio_ref) { if (dc->bio_ref) {
...@@ -1006,7 +1094,7 @@ static void __remove_discard_cmd(struct f2fs_sb_info *sbi, ...@@ -1006,7 +1094,7 @@ static void __remove_discard_cmd(struct f2fs_sb_info *sbi,
printk_ratelimited( printk_ratelimited(
"%sF2FS-fs (%s): Issue discard(%u, %u, %u) failed, ret: %d", "%sF2FS-fs (%s): Issue discard(%u, %u, %u) failed, ret: %d",
KERN_INFO, sbi->sb->s_id, KERN_INFO, sbi->sb->s_id,
dc->lstart, dc->start, dc->len, dc->error); dc->di.lstart, dc->di.start, dc->di.len, dc->error);
__detach_discard_cmd(dcc, dc); __detach_discard_cmd(dcc, dc);
} }
...@@ -1122,14 +1210,14 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi, ...@@ -1122,14 +1210,14 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi,
if (is_sbi_flag_set(sbi, SBI_NEED_FSCK)) if (is_sbi_flag_set(sbi, SBI_NEED_FSCK))
return 0; return 0;
trace_f2fs_issue_discard(bdev, dc->start, dc->len); trace_f2fs_issue_discard(bdev, dc->di.start, dc->di.len);
lstart = dc->lstart; lstart = dc->di.lstart;
start = dc->start; start = dc->di.start;
len = dc->len; len = dc->di.len;
total_len = len; total_len = len;
dc->len = 0; dc->di.len = 0;
while (total_len && *issued < dpolicy->max_requests && !err) { while (total_len && *issued < dpolicy->max_requests && !err) {
struct bio *bio = NULL; struct bio *bio = NULL;
...@@ -1145,7 +1233,7 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi, ...@@ -1145,7 +1233,7 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi,
if (*issued == dpolicy->max_requests) if (*issued == dpolicy->max_requests)
last = true; last = true;
dc->len += len; dc->di.len += len;
if (time_to_inject(sbi, FAULT_DISCARD)) { if (time_to_inject(sbi, FAULT_DISCARD)) {
err = -EIO; err = -EIO;
...@@ -1207,34 +1295,41 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi, ...@@ -1207,34 +1295,41 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi,
return err; return err;
} }
static void __insert_discard_tree(struct f2fs_sb_info *sbi, static void __insert_discard_cmd(struct f2fs_sb_info *sbi,
struct block_device *bdev, block_t lstart, struct block_device *bdev, block_t lstart,
block_t start, block_t len, block_t start, block_t len)
struct rb_node **insert_p,
struct rb_node *insert_parent)
{ {
struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
struct rb_node **p; struct rb_node **p = &dcc->root.rb_root.rb_node;
struct rb_node *parent = NULL; struct rb_node *parent = NULL;
struct discard_cmd *dc;
bool leftmost = true; bool leftmost = true;
if (insert_p && insert_parent) { /* look up rb tree to find parent node */
parent = insert_parent; while (*p) {
p = insert_p; parent = *p;
goto do_insert; dc = rb_entry(parent, struct discard_cmd, rb_node);
if (lstart < dc->di.lstart) {
p = &(*p)->rb_left;
} else if (lstart >= dc->di.lstart + dc->di.len) {
p = &(*p)->rb_right;
leftmost = false;
} else {
f2fs_bug_on(sbi, 1);
}
} }
p = f2fs_lookup_rb_tree_for_insert(sbi, &dcc->root, &parent, dc = __create_discard_cmd(sbi, bdev, lstart, start, len);
lstart, &leftmost);
do_insert: rb_link_node(&dc->rb_node, parent, p);
__attach_discard_cmd(sbi, bdev, lstart, start, len, parent, rb_insert_color_cached(&dc->rb_node, &dcc->root, leftmost);
p, leftmost);
} }
static void __relocate_discard_cmd(struct discard_cmd_control *dcc, static void __relocate_discard_cmd(struct discard_cmd_control *dcc,
struct discard_cmd *dc) struct discard_cmd *dc)
{ {
list_move_tail(&dc->list, &dcc->pend_list[plist_idx(dc->len)]); list_move_tail(&dc->list, &dcc->pend_list[plist_idx(dc->di.len)]);
} }
static void __punch_discard_cmd(struct f2fs_sb_info *sbi, static void __punch_discard_cmd(struct f2fs_sb_info *sbi,
...@@ -1244,7 +1339,7 @@ static void __punch_discard_cmd(struct f2fs_sb_info *sbi, ...@@ -1244,7 +1339,7 @@ static void __punch_discard_cmd(struct f2fs_sb_info *sbi,
struct discard_info di = dc->di; struct discard_info di = dc->di;
bool modified = false; bool modified = false;
if (dc->state == D_DONE || dc->len == 1) { if (dc->state == D_DONE || dc->di.len == 1) {
__remove_discard_cmd(sbi, dc); __remove_discard_cmd(sbi, dc);
return; return;
} }
...@@ -1252,23 +1347,22 @@ static void __punch_discard_cmd(struct f2fs_sb_info *sbi, ...@@ -1252,23 +1347,22 @@ static void __punch_discard_cmd(struct f2fs_sb_info *sbi,
dcc->undiscard_blks -= di.len; dcc->undiscard_blks -= di.len;
if (blkaddr > di.lstart) { if (blkaddr > di.lstart) {
dc->len = blkaddr - dc->lstart; dc->di.len = blkaddr - dc->di.lstart;
dcc->undiscard_blks += dc->len; dcc->undiscard_blks += dc->di.len;
__relocate_discard_cmd(dcc, dc); __relocate_discard_cmd(dcc, dc);
modified = true; modified = true;
} }
if (blkaddr < di.lstart + di.len - 1) { if (blkaddr < di.lstart + di.len - 1) {
if (modified) { if (modified) {
__insert_discard_tree(sbi, dc->bdev, blkaddr + 1, __insert_discard_cmd(sbi, dc->bdev, blkaddr + 1,
di.start + blkaddr + 1 - di.lstart, di.start + blkaddr + 1 - di.lstart,
di.lstart + di.len - 1 - blkaddr, di.lstart + di.len - 1 - blkaddr);
NULL, NULL);
} else { } else {
dc->lstart++; dc->di.lstart++;
dc->len--; dc->di.len--;
dc->start++; dc->di.start++;
dcc->undiscard_blks += dc->len; dcc->undiscard_blks += dc->di.len;
__relocate_discard_cmd(dcc, dc); __relocate_discard_cmd(dcc, dc);
} }
} }
...@@ -1287,17 +1381,14 @@ static void __update_discard_tree_range(struct f2fs_sb_info *sbi, ...@@ -1287,17 +1381,14 @@ static void __update_discard_tree_range(struct f2fs_sb_info *sbi,
SECTOR_TO_BLOCK(bdev_max_discard_sectors(bdev)); SECTOR_TO_BLOCK(bdev_max_discard_sectors(bdev));
block_t end = lstart + len; block_t end = lstart + len;
dc = (struct discard_cmd *)f2fs_lookup_rb_tree_ret(&dcc->root, dc = __lookup_discard_cmd_ret(&dcc->root, lstart,
NULL, lstart, &prev_dc, &next_dc, &insert_p, &insert_parent);
(struct rb_entry **)&prev_dc,
(struct rb_entry **)&next_dc,
&insert_p, &insert_parent, true, NULL);
if (dc) if (dc)
prev_dc = dc; prev_dc = dc;
if (!prev_dc) { if (!prev_dc) {
di.lstart = lstart; di.lstart = lstart;
di.len = next_dc ? next_dc->lstart - lstart : len; di.len = next_dc ? next_dc->di.lstart - lstart : len;
di.len = min(di.len, len); di.len = min(di.len, len);
di.start = start; di.start = start;
} }
...@@ -1308,16 +1399,16 @@ static void __update_discard_tree_range(struct f2fs_sb_info *sbi, ...@@ -1308,16 +1399,16 @@ static void __update_discard_tree_range(struct f2fs_sb_info *sbi,
struct discard_cmd *tdc = NULL; struct discard_cmd *tdc = NULL;
if (prev_dc) { if (prev_dc) {
di.lstart = prev_dc->lstart + prev_dc->len; di.lstart = prev_dc->di.lstart + prev_dc->di.len;
if (di.lstart < lstart) if (di.lstart < lstart)
di.lstart = lstart; di.lstart = lstart;
if (di.lstart >= end) if (di.lstart >= end)
break; break;
if (!next_dc || next_dc->lstart > end) if (!next_dc || next_dc->di.lstart > end)
di.len = end - di.lstart; di.len = end - di.lstart;
else else
di.len = next_dc->lstart - di.lstart; di.len = next_dc->di.lstart - di.lstart;
di.start = start + di.lstart - lstart; di.start = start + di.lstart - lstart;
} }
...@@ -1350,10 +1441,9 @@ static void __update_discard_tree_range(struct f2fs_sb_info *sbi, ...@@ -1350,10 +1441,9 @@ static void __update_discard_tree_range(struct f2fs_sb_info *sbi,
merged = true; merged = true;
} }
if (!merged) { if (!merged)
__insert_discard_tree(sbi, bdev, di.lstart, di.start, __insert_discard_cmd(sbi, bdev,
di.len, NULL, NULL); di.lstart, di.start, di.len);
}
next: next:
prev_dc = next_dc; prev_dc = next_dc;
if (!prev_dc) if (!prev_dc)
...@@ -1392,15 +1482,11 @@ static void __issue_discard_cmd_orderly(struct f2fs_sb_info *sbi, ...@@ -1392,15 +1482,11 @@ static void __issue_discard_cmd_orderly(struct f2fs_sb_info *sbi,
struct rb_node **insert_p = NULL, *insert_parent = NULL; struct rb_node **insert_p = NULL, *insert_parent = NULL;
struct discard_cmd *dc; struct discard_cmd *dc;
struct blk_plug plug; struct blk_plug plug;
unsigned int pos = dcc->next_pos;
bool io_interrupted = false; bool io_interrupted = false;
mutex_lock(&dcc->cmd_lock); mutex_lock(&dcc->cmd_lock);
dc = (struct discard_cmd *)f2fs_lookup_rb_tree_ret(&dcc->root, dc = __lookup_discard_cmd_ret(&dcc->root, dcc->next_pos,
NULL, pos, &prev_dc, &next_dc, &insert_p, &insert_parent);
(struct rb_entry **)&prev_dc,
(struct rb_entry **)&next_dc,
&insert_p, &insert_parent, true, NULL);
if (!dc) if (!dc)
dc = next_dc; dc = next_dc;
...@@ -1418,7 +1504,7 @@ static void __issue_discard_cmd_orderly(struct f2fs_sb_info *sbi, ...@@ -1418,7 +1504,7 @@ static void __issue_discard_cmd_orderly(struct f2fs_sb_info *sbi,
break; break;
} }
dcc->next_pos = dc->lstart + dc->len; dcc->next_pos = dc->di.lstart + dc->di.len;
err = __submit_discard_cmd(sbi, dpolicy, dc, issued); err = __submit_discard_cmd(sbi, dpolicy, dc, issued);
if (*issued >= dpolicy->max_requests) if (*issued >= dpolicy->max_requests)
...@@ -1477,8 +1563,7 @@ static int __issue_discard_cmd(struct f2fs_sb_info *sbi, ...@@ -1477,8 +1563,7 @@ static int __issue_discard_cmd(struct f2fs_sb_info *sbi,
if (list_empty(pend_list)) if (list_empty(pend_list))
goto next; goto next;
if (unlikely(dcc->rbtree_check)) if (unlikely(dcc->rbtree_check))
f2fs_bug_on(sbi, !f2fs_check_rb_tree_consistence(sbi, f2fs_bug_on(sbi, !f2fs_check_discard_tree(sbi));
&dcc->root));
blk_start_plug(&plug); blk_start_plug(&plug);
list_for_each_entry_safe(dc, tmp, pend_list, list) { list_for_each_entry_safe(dc, tmp, pend_list, list) {
f2fs_bug_on(sbi, dc->state != D_PREP); f2fs_bug_on(sbi, dc->state != D_PREP);
...@@ -1556,7 +1641,7 @@ static unsigned int __wait_one_discard_bio(struct f2fs_sb_info *sbi, ...@@ -1556,7 +1641,7 @@ static unsigned int __wait_one_discard_bio(struct f2fs_sb_info *sbi,
dc->ref--; dc->ref--;
if (!dc->ref) { if (!dc->ref) {
if (!dc->error) if (!dc->error)
len = dc->len; len = dc->di.len;
__remove_discard_cmd(sbi, dc); __remove_discard_cmd(sbi, dc);
} }
mutex_unlock(&dcc->cmd_lock); mutex_unlock(&dcc->cmd_lock);
...@@ -1579,14 +1664,15 @@ static unsigned int __wait_discard_cmd_range(struct f2fs_sb_info *sbi, ...@@ -1579,14 +1664,15 @@ static unsigned int __wait_discard_cmd_range(struct f2fs_sb_info *sbi,
mutex_lock(&dcc->cmd_lock); mutex_lock(&dcc->cmd_lock);
list_for_each_entry_safe(iter, tmp, wait_list, list) { list_for_each_entry_safe(iter, tmp, wait_list, list) {
if (iter->lstart + iter->len <= start || end <= iter->lstart) if (iter->di.lstart + iter->di.len <= start ||
end <= iter->di.lstart)
continue; continue;
if (iter->len < dpolicy->granularity) if (iter->di.len < dpolicy->granularity)
continue; continue;
if (iter->state == D_DONE && !iter->ref) { if (iter->state == D_DONE && !iter->ref) {
wait_for_completion_io(&iter->wait); wait_for_completion_io(&iter->wait);
if (!iter->error) if (!iter->error)
trimmed += iter->len; trimmed += iter->di.len;
__remove_discard_cmd(sbi, iter); __remove_discard_cmd(sbi, iter);
} else { } else {
iter->ref++; iter->ref++;
...@@ -1630,8 +1716,7 @@ static void f2fs_wait_discard_bio(struct f2fs_sb_info *sbi, block_t blkaddr) ...@@ -1630,8 +1716,7 @@ static void f2fs_wait_discard_bio(struct f2fs_sb_info *sbi, block_t blkaddr)
bool need_wait = false; bool need_wait = false;
mutex_lock(&dcc->cmd_lock); mutex_lock(&dcc->cmd_lock);
dc = (struct discard_cmd *)f2fs_lookup_rb_tree(&dcc->root, dc = __lookup_discard_cmd(sbi, blkaddr);
NULL, blkaddr);
if (dc) { if (dc) {
if (dc->state == D_PREP) { if (dc->state == D_PREP) {
__punch_discard_cmd(sbi, dc, blkaddr); __punch_discard_cmd(sbi, dc, blkaddr);
...@@ -2964,24 +3049,20 @@ static unsigned int __issue_discard_cmd_range(struct f2fs_sb_info *sbi, ...@@ -2964,24 +3049,20 @@ static unsigned int __issue_discard_cmd_range(struct f2fs_sb_info *sbi,
mutex_lock(&dcc->cmd_lock); mutex_lock(&dcc->cmd_lock);
if (unlikely(dcc->rbtree_check)) if (unlikely(dcc->rbtree_check))
f2fs_bug_on(sbi, !f2fs_check_rb_tree_consistence(sbi, f2fs_bug_on(sbi, !f2fs_check_discard_tree(sbi));
&dcc->root));
dc = __lookup_discard_cmd_ret(&dcc->root, start,
dc = (struct discard_cmd *)f2fs_lookup_rb_tree_ret(&dcc->root, &prev_dc, &next_dc, &insert_p, &insert_parent);
NULL, start,
(struct rb_entry **)&prev_dc,
(struct rb_entry **)&next_dc,
&insert_p, &insert_parent, true, NULL);
if (!dc) if (!dc)
dc = next_dc; dc = next_dc;
blk_start_plug(&plug); blk_start_plug(&plug);
while (dc && dc->lstart <= end) { while (dc && dc->di.lstart <= end) {
struct rb_node *node; struct rb_node *node;
int err = 0; int err = 0;
if (dc->len < dpolicy->granularity) if (dc->di.len < dpolicy->granularity)
goto skip; goto skip;
if (dc->state != D_PREP) { if (dc->state != D_PREP) {
...@@ -2992,7 +3073,7 @@ static unsigned int __issue_discard_cmd_range(struct f2fs_sb_info *sbi, ...@@ -2992,7 +3073,7 @@ static unsigned int __issue_discard_cmd_range(struct f2fs_sb_info *sbi,
err = __submit_discard_cmd(sbi, dpolicy, dc, &issued); err = __submit_discard_cmd(sbi, dpolicy, dc, &issued);
if (issued >= dpolicy->max_requests) { if (issued >= dpolicy->max_requests) {
start = dc->lstart + dc->len; start = dc->di.lstart + dc->di.len;
if (err) if (err)
__remove_discard_cmd(sbi, dc); __remove_discard_cmd(sbi, dc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment