aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChao Yu <yuchao0@huawei.com>2018-09-27 11:41:16 -0400
committerJaegeuk Kim <jaegeuk@kernel.org>2018-09-30 21:39:54 -0400
commitbab475c5414e8d1fa182fd17ae966864e9c85741 (patch)
treede02f7fdd1e1afed101d5740e433e85e8efcc94c
parentd440c52d3151a28358f4c2d52d8583a0aa54ab83 (diff)
Revert: "f2fs: check last page index in cached bio to decide submission"
There is one case that we can leave bio in f2fs, result in hanging page writeback waiter. Thread A Thread B - f2fs_write_cache_pages - f2fs_submit_page_write page #0 cached in bio #0 of cold log - f2fs_submit_page_write page #1 cached in bio #1 of warm log - f2fs_write_cache_pages - f2fs_submit_page_write bio is full, submit bio #1 contain page #1 - f2fs_submit_merged_write_cond(, page #1) fail to submit bio #0 due to page #1 is not in any cached bios. Signed-off-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r--fs/f2fs/checkpoint.c3
-rw-r--r--fs/f2fs/data.c38
-rw-r--r--fs/f2fs/f2fs.h4
-rw-r--r--fs/f2fs/node.c11
-rw-r--r--fs/f2fs/segment.c11
5 files changed, 32 insertions, 35 deletions
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index f4b9b81e3ed6..97b429ba2911 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -276,8 +276,7 @@ static int __f2fs_write_meta_page(struct page *page,
276 dec_page_count(sbi, F2FS_DIRTY_META); 276 dec_page_count(sbi, F2FS_DIRTY_META);
277 277
278 if (wbc->for_reclaim) 278 if (wbc->for_reclaim)
279 f2fs_submit_merged_write_cond(sbi, page->mapping->host, 279 f2fs_submit_merged_write_cond(sbi, NULL, page, 0, META);
280 0, page->index, META);
281 280
282 unlock_page(page); 281 unlock_page(page);
283 282
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 41102c227eee..ea16cadd416e 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -322,8 +322,8 @@ static void __submit_merged_bio(struct f2fs_bio_info *io)
322 io->bio = NULL; 322 io->bio = NULL;
323} 323}
324 324
325static bool __has_merged_page(struct f2fs_bio_info *io, 325static bool __has_merged_page(struct f2fs_bio_info *io, struct inode *inode,
326 struct inode *inode, nid_t ino, pgoff_t idx) 326 struct page *page, nid_t ino)
327{ 327{
328 struct bio_vec *bvec; 328 struct bio_vec *bvec;
329 struct page *target; 329 struct page *target;
@@ -332,7 +332,7 @@ static bool __has_merged_page(struct f2fs_bio_info *io,
332 if (!io->bio) 332 if (!io->bio)
333 return false; 333 return false;
334 334
335 if (!inode && !ino) 335 if (!inode && !page && !ino)
336 return true; 336 return true;
337 337
338 bio_for_each_segment_all(bvec, io->bio, i) { 338 bio_for_each_segment_all(bvec, io->bio, i) {
@@ -342,11 +342,10 @@ static bool __has_merged_page(struct f2fs_bio_info *io,
342 else 342 else
343 target = fscrypt_control_page(bvec->bv_page); 343 target = fscrypt_control_page(bvec->bv_page);
344 344
345 if (idx != target->index)
346 continue;
347
348 if (inode && inode == target->mapping->host) 345 if (inode && inode == target->mapping->host)
349 return true; 346 return true;
347 if (page && page == target)
348 return true;
350 if (ino && ino == ino_of_node(target)) 349 if (ino && ino == ino_of_node(target))
351 return true; 350 return true;
352 } 351 }
@@ -355,7 +354,8 @@ static bool __has_merged_page(struct f2fs_bio_info *io,
355} 354}
356 355
357static bool has_merged_page(struct f2fs_sb_info *sbi, struct inode *inode, 356static bool has_merged_page(struct f2fs_sb_info *sbi, struct inode *inode,
358 nid_t ino, pgoff_t idx, enum page_type type) 357 struct page *page, nid_t ino,
358 enum page_type type)
359{ 359{
360 enum page_type btype = PAGE_TYPE_OF_BIO(type); 360 enum page_type btype = PAGE_TYPE_OF_BIO(type);
361 enum temp_type temp; 361 enum temp_type temp;
@@ -366,7 +366,7 @@ static bool has_merged_page(struct f2fs_sb_info *sbi, struct inode *inode,
366 io = sbi->write_io[btype] + temp; 366 io = sbi->write_io[btype] + temp;
367 367
368 down_read(&io->io_rwsem); 368 down_read(&io->io_rwsem);
369 ret = __has_merged_page(io, inode, ino, idx); 369 ret = __has_merged_page(io, inode, page, ino);
370 up_read(&io->io_rwsem); 370 up_read(&io->io_rwsem);
371 371
372 /* TODO: use HOT temp only for meta pages now. */ 372 /* TODO: use HOT temp only for meta pages now. */
@@ -397,12 +397,12 @@ static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi,
397} 397}
398 398
399static void __submit_merged_write_cond(struct f2fs_sb_info *sbi, 399static void __submit_merged_write_cond(struct f2fs_sb_info *sbi,
400 struct inode *inode, nid_t ino, pgoff_t idx, 400 struct inode *inode, struct page *page,
401 enum page_type type, bool force) 401 nid_t ino, enum page_type type, bool force)
402{ 402{
403 enum temp_type temp; 403 enum temp_type temp;
404 404
405 if (!force && !has_merged_page(sbi, inode, ino, idx, type)) 405 if (!force && !has_merged_page(sbi, inode, page, ino, type))
406 return; 406 return;
407 407
408 for (temp = HOT; temp < NR_TEMP_TYPE; temp++) { 408 for (temp = HOT; temp < NR_TEMP_TYPE; temp++) {
@@ -421,10 +421,10 @@ void f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type)
421} 421}
422 422
423void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi, 423void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi,
424 struct inode *inode, nid_t ino, pgoff_t idx, 424 struct inode *inode, struct page *page,
425 enum page_type type) 425 nid_t ino, enum page_type type)
426{ 426{
427 __submit_merged_write_cond(sbi, inode, ino, idx, type, false); 427 __submit_merged_write_cond(sbi, inode, page, ino, type, false);
428} 428}
429 429
430void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi) 430void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi)
@@ -1952,7 +1952,7 @@ out:
1952 ClearPageUptodate(page); 1952 ClearPageUptodate(page);
1953 1953
1954 if (wbc->for_reclaim) { 1954 if (wbc->for_reclaim) {
1955 f2fs_submit_merged_write_cond(sbi, inode, 0, page->index, DATA); 1955 f2fs_submit_merged_write_cond(sbi, NULL, page, 0, DATA);
1956 clear_inode_flag(inode, FI_HOT_DATA); 1956 clear_inode_flag(inode, FI_HOT_DATA);
1957 f2fs_remove_dirty_inode(inode); 1957 f2fs_remove_dirty_inode(inode);
1958 submitted = NULL; 1958 submitted = NULL;
@@ -2010,10 +2010,10 @@ static int f2fs_write_cache_pages(struct address_space *mapping,
2010 pgoff_t index; 2010 pgoff_t index;
2011 pgoff_t end; /* Inclusive */ 2011 pgoff_t end; /* Inclusive */
2012 pgoff_t done_index; 2012 pgoff_t done_index;
2013 pgoff_t last_idx = ULONG_MAX;
2014 int cycled; 2013 int cycled;
2015 int range_whole = 0; 2014 int range_whole = 0;
2016 int tag; 2015 int tag;
2016 int nwritten = 0;
2017 2017
2018 pagevec_init(&pvec); 2018 pagevec_init(&pvec);
2019 2019
@@ -2116,7 +2116,7 @@ continue_unlock:
2116 done = 1; 2116 done = 1;
2117 break; 2117 break;
2118 } else if (submitted) { 2118 } else if (submitted) {
2119 last_idx = page->index; 2119 nwritten++;
2120 } 2120 }
2121 2121
2122 if (--wbc->nr_to_write <= 0 && 2122 if (--wbc->nr_to_write <= 0 &&
@@ -2138,9 +2138,9 @@ continue_unlock:
2138 if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) 2138 if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
2139 mapping->writeback_index = done_index; 2139 mapping->writeback_index = done_index;
2140 2140
2141 if (last_idx != ULONG_MAX) 2141 if (nwritten)
2142 f2fs_submit_merged_write_cond(F2FS_M_SB(mapping), mapping->host, 2142 f2fs_submit_merged_write_cond(F2FS_M_SB(mapping), mapping->host,
2143 0, last_idx, DATA); 2143 NULL, 0, DATA);
2144 2144
2145 return ret; 2145 return ret;
2146} 2146}
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 668836c2d678..f633662bf645 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -3032,8 +3032,8 @@ int f2fs_init_post_read_processing(void);
3032void f2fs_destroy_post_read_processing(void); 3032void f2fs_destroy_post_read_processing(void);
3033void f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type); 3033void f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type);
3034void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi, 3034void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi,
3035 struct inode *inode, nid_t ino, pgoff_t idx, 3035 struct inode *inode, struct page *page,
3036 enum page_type type); 3036 nid_t ino, enum page_type type);
3037void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi); 3037void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi);
3038int f2fs_submit_page_bio(struct f2fs_io_info *fio); 3038int f2fs_submit_page_bio(struct f2fs_io_info *fio);
3039void f2fs_submit_page_write(struct f2fs_io_info *fio); 3039void f2fs_submit_page_write(struct f2fs_io_info *fio);
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index acb819b8fc42..b1e3ff8147f6 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -1565,8 +1565,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,
1565 up_read(&sbi->node_write); 1565 up_read(&sbi->node_write);
1566 1566
1567 if (wbc->for_reclaim) { 1567 if (wbc->for_reclaim) {
1568 f2fs_submit_merged_write_cond(sbi, page->mapping->host, 0, 1568 f2fs_submit_merged_write_cond(sbi, NULL, page, 0, NODE);
1569 page->index, NODE);
1570 submitted = NULL; 1569 submitted = NULL;
1571 } 1570 }
1572 1571
@@ -1631,13 +1630,13 @@ int f2fs_fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode,
1631 unsigned int *seq_id) 1630 unsigned int *seq_id)
1632{ 1631{
1633 pgoff_t index; 1632 pgoff_t index;
1634 pgoff_t last_idx = ULONG_MAX;
1635 struct pagevec pvec; 1633 struct pagevec pvec;
1636 int ret = 0; 1634 int ret = 0;
1637 struct page *last_page = NULL; 1635 struct page *last_page = NULL;
1638 bool marked = false; 1636 bool marked = false;
1639 nid_t ino = inode->i_ino; 1637 nid_t ino = inode->i_ino;
1640 int nr_pages; 1638 int nr_pages;
1639 int nwritten = 0;
1641 1640
1642 if (atomic) { 1641 if (atomic) {
1643 last_page = last_fsync_dnode(sbi, ino); 1642 last_page = last_fsync_dnode(sbi, ino);
@@ -1715,7 +1714,7 @@ continue_unlock:
1715 f2fs_put_page(last_page, 0); 1714 f2fs_put_page(last_page, 0);
1716 break; 1715 break;
1717 } else if (submitted) { 1716 } else if (submitted) {
1718 last_idx = page->index; 1717 nwritten++;
1719 } 1718 }
1720 1719
1721 if (page == last_page) { 1720 if (page == last_page) {
@@ -1741,8 +1740,8 @@ continue_unlock:
1741 goto retry; 1740 goto retry;
1742 } 1741 }
1743out: 1742out:
1744 if (last_idx != ULONG_MAX) 1743 if (nwritten)
1745 f2fs_submit_merged_write_cond(sbi, NULL, ino, last_idx, NODE); 1744 f2fs_submit_merged_write_cond(sbi, NULL, NULL, ino, NODE);
1746 return ret ? -EIO: 0; 1745 return ret ? -EIO: 0;
1747} 1746}
1748 1747
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 3fa8870569cc..e16dae0f0a5b 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -371,7 +371,7 @@ static int __f2fs_commit_inmem_pages(struct inode *inode)
371 .io_type = FS_DATA_IO, 371 .io_type = FS_DATA_IO,
372 }; 372 };
373 struct list_head revoke_list; 373 struct list_head revoke_list;
374 pgoff_t last_idx = ULONG_MAX; 374 bool submit_bio = false;
375 int err = 0; 375 int err = 0;
376 376
377 INIT_LIST_HEAD(&revoke_list); 377 INIT_LIST_HEAD(&revoke_list);
@@ -406,14 +406,14 @@ retry:
406 } 406 }
407 /* record old blkaddr for revoking */ 407 /* record old blkaddr for revoking */
408 cur->old_addr = fio.old_blkaddr; 408 cur->old_addr = fio.old_blkaddr;
409 last_idx = page->index; 409 submit_bio = true;
410 } 410 }
411 unlock_page(page); 411 unlock_page(page);
412 list_move_tail(&cur->list, &revoke_list); 412 list_move_tail(&cur->list, &revoke_list);
413 } 413 }
414 414
415 if (last_idx != ULONG_MAX) 415 if (submit_bio)
416 f2fs_submit_merged_write_cond(sbi, inode, 0, last_idx, DATA); 416 f2fs_submit_merged_write_cond(sbi, inode, NULL, 0, DATA);
417 417
418 if (err) { 418 if (err) {
419 /* 419 /*
@@ -3181,8 +3181,7 @@ void f2fs_wait_on_page_writeback(struct page *page,
3181 if (PageWriteback(page)) { 3181 if (PageWriteback(page)) {
3182 struct f2fs_sb_info *sbi = F2FS_P_SB(page); 3182 struct f2fs_sb_info *sbi = F2FS_P_SB(page);
3183 3183
3184 f2fs_submit_merged_write_cond(sbi, page->mapping->host, 3184 f2fs_submit_merged_write_cond(sbi, NULL, page, 0, type);
3185 0, page->index, type);
3186 if (ordered) 3185 if (ordered)
3187 wait_on_page_writeback(page); 3186 wait_on_page_writeback(page);
3188 else 3187 else