diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-03-01 18:55:04 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-03-01 18:55:04 -0500 |
commit | 25c4e6c3f0c14d1575aa488ff4ca47e045ae51a0 (patch) | |
tree | 4ecf60124fd87fbd655393a081beecaf88746eea /fs/f2fs/segment.c | |
parent | 6053dc981449718d90a429933e99b441e1adaea6 (diff) | |
parent | 900f736251c81886f3064c9d489c85eddee921b7 (diff) |
Merge tag 'for-f2fs-4.11' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs
Pull f2fs updates from Jaegeuk Kim:
"This round introduces several interesting features such as on-disk NAT
bitmaps, IO alignment, and a discard thread. And it includes a couple
of major bug fixes as below.
Enhancements:
- introduce on-disk bitmaps to avoid scanning NAT blocks when getting
free nids
- support IO alignment to prepare open-channel SSD integration in
future
- introduce a discard thread to avoid long latency during checkpoint
and fstrim
- use SSR for warm node and enable inline_xattr by default
- introduce in-memory bitmaps to check FS consistency for debugging
- improve write_begin by avoiding needless read IO
Bug fixes:
- fix broken zone_reset behavior for SMR drive
- fix wrong victim selection policy during GC
- fix missing behavior when preparing discard commands
- fix bugs in atomic write support and fiemap
- workaround to handle multiple f2fs_add_link calls having same name
... and it includes a bunch of clean-up patches as well"
* tag 'for-f2fs-4.11' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (97 commits)
f2fs: avoid to flush nat journal entries
f2fs: avoid to issue redundant discard commands
f2fs: fix a plint compile warning
f2fs: add f2fs_drop_inode tracepoint
f2fs: Fix zoned block device support
f2fs: remove redundant set_page_dirty()
f2fs: fix to enlarge size of write_io_dummy mempool
f2fs: fix memory leak of write_io_dummy mempool during umount
f2fs: fix to update F2FS_{CP_}WB_DATA count correctly
f2fs: use MAX_FREE_NIDS for the free nids target
f2fs: introduce free nid bitmap
f2fs: new helper cur_cp_crc() getting crc in f2fs_checkpoint
f2fs: update the comment of default nr_pages to skipping
f2fs: drop the duplicate pval in f2fs_getxattr
f2fs: Don't update the xattr data that same as the exist
f2fs: kill __is_extent_same
f2fs: avoid bggc->fggc when enough free segments are avaliable after cp
f2fs: select target segment with closer temperature in SSR mode
f2fs: show simple call stack in fault injection message
f2fs: no need lock_op in f2fs_write_inline_data
...
Diffstat (limited to 'fs/f2fs/segment.c')
-rw-r--r-- | fs/f2fs/segment.c | 501 |
1 files changed, 364 insertions, 137 deletions
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 0d8802453758..4bd7a8b19332 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #define __reverse_ffz(x) __reverse_ffs(~(x)) | 26 | #define __reverse_ffz(x) __reverse_ffs(~(x)) |
27 | 27 | ||
28 | static struct kmem_cache *discard_entry_slab; | 28 | static struct kmem_cache *discard_entry_slab; |
29 | static struct kmem_cache *bio_entry_slab; | 29 | static struct kmem_cache *discard_cmd_slab; |
30 | static struct kmem_cache *sit_entry_set_slab; | 30 | static struct kmem_cache *sit_entry_set_slab; |
31 | static struct kmem_cache *inmem_entry_slab; | 31 | static struct kmem_cache *inmem_entry_slab; |
32 | 32 | ||
@@ -242,11 +242,12 @@ void drop_inmem_pages(struct inode *inode) | |||
242 | { | 242 | { |
243 | struct f2fs_inode_info *fi = F2FS_I(inode); | 243 | struct f2fs_inode_info *fi = F2FS_I(inode); |
244 | 244 | ||
245 | clear_inode_flag(inode, FI_ATOMIC_FILE); | ||
246 | |||
247 | mutex_lock(&fi->inmem_lock); | 245 | mutex_lock(&fi->inmem_lock); |
248 | __revoke_inmem_pages(inode, &fi->inmem_pages, true, false); | 246 | __revoke_inmem_pages(inode, &fi->inmem_pages, true, false); |
249 | mutex_unlock(&fi->inmem_lock); | 247 | mutex_unlock(&fi->inmem_lock); |
248 | |||
249 | clear_inode_flag(inode, FI_ATOMIC_FILE); | ||
250 | stat_dec_atomic_write(inode); | ||
250 | } | 251 | } |
251 | 252 | ||
252 | static int __commit_inmem_pages(struct inode *inode, | 253 | static int __commit_inmem_pages(struct inode *inode, |
@@ -262,7 +263,7 @@ static int __commit_inmem_pages(struct inode *inode, | |||
262 | .op_flags = REQ_SYNC | REQ_PRIO, | 263 | .op_flags = REQ_SYNC | REQ_PRIO, |
263 | .encrypted_page = NULL, | 264 | .encrypted_page = NULL, |
264 | }; | 265 | }; |
265 | bool submit_bio = false; | 266 | pgoff_t last_idx = ULONG_MAX; |
266 | int err = 0; | 267 | int err = 0; |
267 | 268 | ||
268 | list_for_each_entry_safe(cur, tmp, &fi->inmem_pages, list) { | 269 | list_for_each_entry_safe(cur, tmp, &fi->inmem_pages, list) { |
@@ -288,15 +289,15 @@ static int __commit_inmem_pages(struct inode *inode, | |||
288 | 289 | ||
289 | /* record old blkaddr for revoking */ | 290 | /* record old blkaddr for revoking */ |
290 | cur->old_addr = fio.old_blkaddr; | 291 | cur->old_addr = fio.old_blkaddr; |
291 | 292 | last_idx = page->index; | |
292 | submit_bio = true; | ||
293 | } | 293 | } |
294 | unlock_page(page); | 294 | unlock_page(page); |
295 | list_move_tail(&cur->list, revoke_list); | 295 | list_move_tail(&cur->list, revoke_list); |
296 | } | 296 | } |
297 | 297 | ||
298 | if (submit_bio) | 298 | if (last_idx != ULONG_MAX) |
299 | f2fs_submit_merged_bio_cond(sbi, inode, NULL, 0, DATA, WRITE); | 299 | f2fs_submit_merged_bio_cond(sbi, inode, 0, last_idx, |
300 | DATA, WRITE); | ||
300 | 301 | ||
301 | if (!err) | 302 | if (!err) |
302 | __revoke_inmem_pages(inode, revoke_list, false, false); | 303 | __revoke_inmem_pages(inode, revoke_list, false, false); |
@@ -315,6 +316,8 @@ int commit_inmem_pages(struct inode *inode) | |||
315 | f2fs_balance_fs(sbi, true); | 316 | f2fs_balance_fs(sbi, true); |
316 | f2fs_lock_op(sbi); | 317 | f2fs_lock_op(sbi); |
317 | 318 | ||
319 | set_inode_flag(inode, FI_ATOMIC_COMMIT); | ||
320 | |||
318 | mutex_lock(&fi->inmem_lock); | 321 | mutex_lock(&fi->inmem_lock); |
319 | err = __commit_inmem_pages(inode, &revoke_list); | 322 | err = __commit_inmem_pages(inode, &revoke_list); |
320 | if (err) { | 323 | if (err) { |
@@ -336,6 +339,8 @@ int commit_inmem_pages(struct inode *inode) | |||
336 | } | 339 | } |
337 | mutex_unlock(&fi->inmem_lock); | 340 | mutex_unlock(&fi->inmem_lock); |
338 | 341 | ||
342 | clear_inode_flag(inode, FI_ATOMIC_COMMIT); | ||
343 | |||
339 | f2fs_unlock_op(sbi); | 344 | f2fs_unlock_op(sbi); |
340 | return err; | 345 | return err; |
341 | } | 346 | } |
@@ -347,8 +352,10 @@ int commit_inmem_pages(struct inode *inode) | |||
347 | void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need) | 352 | void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need) |
348 | { | 353 | { |
349 | #ifdef CONFIG_F2FS_FAULT_INJECTION | 354 | #ifdef CONFIG_F2FS_FAULT_INJECTION |
350 | if (time_to_inject(sbi, FAULT_CHECKPOINT)) | 355 | if (time_to_inject(sbi, FAULT_CHECKPOINT)) { |
356 | f2fs_show_injection_info(FAULT_CHECKPOINT); | ||
351 | f2fs_stop_checkpoint(sbi, false); | 357 | f2fs_stop_checkpoint(sbi, false); |
358 | } | ||
352 | #endif | 359 | #endif |
353 | 360 | ||
354 | if (!need) | 361 | if (!need) |
@@ -381,7 +388,7 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi) | |||
381 | if (!available_free_memory(sbi, FREE_NIDS)) | 388 | if (!available_free_memory(sbi, FREE_NIDS)) |
382 | try_to_free_nids(sbi, MAX_FREE_NIDS); | 389 | try_to_free_nids(sbi, MAX_FREE_NIDS); |
383 | else | 390 | else |
384 | build_free_nids(sbi, false); | 391 | build_free_nids(sbi, false, false); |
385 | 392 | ||
386 | if (!is_idle(sbi)) | 393 | if (!is_idle(sbi)) |
387 | return; | 394 | return; |
@@ -423,6 +430,9 @@ static int submit_flush_wait(struct f2fs_sb_info *sbi) | |||
423 | 430 | ||
424 | if (sbi->s_ndevs && !ret) { | 431 | if (sbi->s_ndevs && !ret) { |
425 | for (i = 1; i < sbi->s_ndevs; i++) { | 432 | for (i = 1; i < sbi->s_ndevs; i++) { |
433 | trace_f2fs_issue_flush(FDEV(i).bdev, | ||
434 | test_opt(sbi, NOBARRIER), | ||
435 | test_opt(sbi, FLUSH_MERGE)); | ||
426 | ret = __submit_flush_wait(FDEV(i).bdev); | 436 | ret = __submit_flush_wait(FDEV(i).bdev); |
427 | if (ret) | 437 | if (ret) |
428 | break; | 438 | break; |
@@ -434,7 +444,7 @@ static int submit_flush_wait(struct f2fs_sb_info *sbi) | |||
434 | static int issue_flush_thread(void *data) | 444 | static int issue_flush_thread(void *data) |
435 | { | 445 | { |
436 | struct f2fs_sb_info *sbi = data; | 446 | struct f2fs_sb_info *sbi = data; |
437 | struct flush_cmd_control *fcc = SM_I(sbi)->cmd_control_info; | 447 | struct flush_cmd_control *fcc = SM_I(sbi)->fcc_info; |
438 | wait_queue_head_t *q = &fcc->flush_wait_queue; | 448 | wait_queue_head_t *q = &fcc->flush_wait_queue; |
439 | repeat: | 449 | repeat: |
440 | if (kthread_should_stop()) | 450 | if (kthread_should_stop()) |
@@ -463,16 +473,16 @@ repeat: | |||
463 | 473 | ||
464 | int f2fs_issue_flush(struct f2fs_sb_info *sbi) | 474 | int f2fs_issue_flush(struct f2fs_sb_info *sbi) |
465 | { | 475 | { |
466 | struct flush_cmd_control *fcc = SM_I(sbi)->cmd_control_info; | 476 | struct flush_cmd_control *fcc = SM_I(sbi)->fcc_info; |
467 | struct flush_cmd cmd; | 477 | struct flush_cmd cmd; |
468 | 478 | ||
469 | trace_f2fs_issue_flush(sbi->sb, test_opt(sbi, NOBARRIER), | ||
470 | test_opt(sbi, FLUSH_MERGE)); | ||
471 | |||
472 | if (test_opt(sbi, NOBARRIER)) | 479 | if (test_opt(sbi, NOBARRIER)) |
473 | return 0; | 480 | return 0; |
474 | 481 | ||
475 | if (!test_opt(sbi, FLUSH_MERGE) || !atomic_read(&fcc->submit_flush)) { | 482 | if (!test_opt(sbi, FLUSH_MERGE)) |
483 | return submit_flush_wait(sbi); | ||
484 | |||
485 | if (!atomic_read(&fcc->submit_flush)) { | ||
476 | int ret; | 486 | int ret; |
477 | 487 | ||
478 | atomic_inc(&fcc->submit_flush); | 488 | atomic_inc(&fcc->submit_flush); |
@@ -506,8 +516,8 @@ int create_flush_cmd_control(struct f2fs_sb_info *sbi) | |||
506 | struct flush_cmd_control *fcc; | 516 | struct flush_cmd_control *fcc; |
507 | int err = 0; | 517 | int err = 0; |
508 | 518 | ||
509 | if (SM_I(sbi)->cmd_control_info) { | 519 | if (SM_I(sbi)->fcc_info) { |
510 | fcc = SM_I(sbi)->cmd_control_info; | 520 | fcc = SM_I(sbi)->fcc_info; |
511 | goto init_thread; | 521 | goto init_thread; |
512 | } | 522 | } |
513 | 523 | ||
@@ -517,14 +527,14 @@ int create_flush_cmd_control(struct f2fs_sb_info *sbi) | |||
517 | atomic_set(&fcc->submit_flush, 0); | 527 | atomic_set(&fcc->submit_flush, 0); |
518 | init_waitqueue_head(&fcc->flush_wait_queue); | 528 | init_waitqueue_head(&fcc->flush_wait_queue); |
519 | init_llist_head(&fcc->issue_list); | 529 | init_llist_head(&fcc->issue_list); |
520 | SM_I(sbi)->cmd_control_info = fcc; | 530 | SM_I(sbi)->fcc_info = fcc; |
521 | init_thread: | 531 | init_thread: |
522 | fcc->f2fs_issue_flush = kthread_run(issue_flush_thread, sbi, | 532 | fcc->f2fs_issue_flush = kthread_run(issue_flush_thread, sbi, |
523 | "f2fs_flush-%u:%u", MAJOR(dev), MINOR(dev)); | 533 | "f2fs_flush-%u:%u", MAJOR(dev), MINOR(dev)); |
524 | if (IS_ERR(fcc->f2fs_issue_flush)) { | 534 | if (IS_ERR(fcc->f2fs_issue_flush)) { |
525 | err = PTR_ERR(fcc->f2fs_issue_flush); | 535 | err = PTR_ERR(fcc->f2fs_issue_flush); |
526 | kfree(fcc); | 536 | kfree(fcc); |
527 | SM_I(sbi)->cmd_control_info = NULL; | 537 | SM_I(sbi)->fcc_info = NULL; |
528 | return err; | 538 | return err; |
529 | } | 539 | } |
530 | 540 | ||
@@ -533,7 +543,7 @@ init_thread: | |||
533 | 543 | ||
534 | void destroy_flush_cmd_control(struct f2fs_sb_info *sbi, bool free) | 544 | void destroy_flush_cmd_control(struct f2fs_sb_info *sbi, bool free) |
535 | { | 545 | { |
536 | struct flush_cmd_control *fcc = SM_I(sbi)->cmd_control_info; | 546 | struct flush_cmd_control *fcc = SM_I(sbi)->fcc_info; |
537 | 547 | ||
538 | if (fcc && fcc->f2fs_issue_flush) { | 548 | if (fcc && fcc->f2fs_issue_flush) { |
539 | struct task_struct *flush_thread = fcc->f2fs_issue_flush; | 549 | struct task_struct *flush_thread = fcc->f2fs_issue_flush; |
@@ -543,7 +553,7 @@ void destroy_flush_cmd_control(struct f2fs_sb_info *sbi, bool free) | |||
543 | } | 553 | } |
544 | if (free) { | 554 | if (free) { |
545 | kfree(fcc); | 555 | kfree(fcc); |
546 | SM_I(sbi)->cmd_control_info = NULL; | 556 | SM_I(sbi)->fcc_info = NULL; |
547 | } | 557 | } |
548 | } | 558 | } |
549 | 559 | ||
@@ -623,60 +633,144 @@ static void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno) | |||
623 | mutex_unlock(&dirty_i->seglist_lock); | 633 | mutex_unlock(&dirty_i->seglist_lock); |
624 | } | 634 | } |
625 | 635 | ||
626 | static struct bio_entry *__add_bio_entry(struct f2fs_sb_info *sbi, | 636 | static void __add_discard_cmd(struct f2fs_sb_info *sbi, |
627 | struct bio *bio) | 637 | struct bio *bio, block_t lstart, block_t len) |
628 | { | 638 | { |
629 | struct list_head *wait_list = &(SM_I(sbi)->wait_list); | 639 | struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; |
630 | struct bio_entry *be = f2fs_kmem_cache_alloc(bio_entry_slab, GFP_NOFS); | 640 | struct list_head *cmd_list = &(dcc->discard_cmd_list); |
641 | struct discard_cmd *dc; | ||
631 | 642 | ||
632 | INIT_LIST_HEAD(&be->list); | 643 | dc = f2fs_kmem_cache_alloc(discard_cmd_slab, GFP_NOFS); |
633 | be->bio = bio; | 644 | INIT_LIST_HEAD(&dc->list); |
634 | init_completion(&be->event); | 645 | dc->bio = bio; |
635 | list_add_tail(&be->list, wait_list); | 646 | bio->bi_private = dc; |
647 | dc->lstart = lstart; | ||
648 | dc->len = len; | ||
649 | dc->state = D_PREP; | ||
650 | init_completion(&dc->wait); | ||
636 | 651 | ||
637 | return be; | 652 | mutex_lock(&dcc->cmd_lock); |
653 | list_add_tail(&dc->list, cmd_list); | ||
654 | mutex_unlock(&dcc->cmd_lock); | ||
638 | } | 655 | } |
639 | 656 | ||
640 | void f2fs_wait_all_discard_bio(struct f2fs_sb_info *sbi) | 657 | static void __remove_discard_cmd(struct f2fs_sb_info *sbi, struct discard_cmd *dc) |
641 | { | 658 | { |
642 | struct list_head *wait_list = &(SM_I(sbi)->wait_list); | 659 | int err = dc->bio->bi_error; |
643 | struct bio_entry *be, *tmp; | ||
644 | 660 | ||
645 | list_for_each_entry_safe(be, tmp, wait_list, list) { | 661 | if (dc->state == D_DONE) |
646 | struct bio *bio = be->bio; | 662 | atomic_dec(&(SM_I(sbi)->dcc_info->submit_discard)); |
647 | int err; | ||
648 | 663 | ||
649 | wait_for_completion_io(&be->event); | 664 | if (err == -EOPNOTSUPP) |
650 | err = be->error; | 665 | err = 0; |
651 | if (err == -EOPNOTSUPP) | ||
652 | err = 0; | ||
653 | 666 | ||
654 | if (err) | 667 | if (err) |
655 | f2fs_msg(sbi->sb, KERN_INFO, | 668 | f2fs_msg(sbi->sb, KERN_INFO, |
656 | "Issue discard failed, ret: %d", err); | 669 | "Issue discard failed, ret: %d", err); |
670 | bio_put(dc->bio); | ||
671 | list_del(&dc->list); | ||
672 | kmem_cache_free(discard_cmd_slab, dc); | ||
673 | } | ||
674 | |||
675 | /* This should be covered by global mutex, &sit_i->sentry_lock */ | ||
676 | void f2fs_wait_discard_bio(struct f2fs_sb_info *sbi, block_t blkaddr) | ||
677 | { | ||
678 | struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; | ||
679 | struct list_head *wait_list = &(dcc->discard_cmd_list); | ||
680 | struct discard_cmd *dc, *tmp; | ||
681 | struct blk_plug plug; | ||
682 | |||
683 | mutex_lock(&dcc->cmd_lock); | ||
657 | 684 | ||
658 | bio_put(bio); | 685 | blk_start_plug(&plug); |
659 | list_del(&be->list); | 686 | |
660 | kmem_cache_free(bio_entry_slab, be); | 687 | list_for_each_entry_safe(dc, tmp, wait_list, list) { |
688 | |||
689 | if (blkaddr == NULL_ADDR) { | ||
690 | if (dc->state == D_PREP) { | ||
691 | dc->state = D_SUBMIT; | ||
692 | submit_bio(dc->bio); | ||
693 | atomic_inc(&dcc->submit_discard); | ||
694 | } | ||
695 | continue; | ||
696 | } | ||
697 | |||
698 | if (dc->lstart <= blkaddr && blkaddr < dc->lstart + dc->len) { | ||
699 | if (dc->state == D_SUBMIT) | ||
700 | wait_for_completion_io(&dc->wait); | ||
701 | else | ||
702 | __remove_discard_cmd(sbi, dc); | ||
703 | } | ||
704 | } | ||
705 | blk_finish_plug(&plug); | ||
706 | |||
707 | /* this comes from f2fs_put_super */ | ||
708 | if (blkaddr == NULL_ADDR) { | ||
709 | list_for_each_entry_safe(dc, tmp, wait_list, list) { | ||
710 | wait_for_completion_io(&dc->wait); | ||
711 | __remove_discard_cmd(sbi, dc); | ||
712 | } | ||
661 | } | 713 | } |
714 | mutex_unlock(&dcc->cmd_lock); | ||
715 | } | ||
716 | |||
717 | static void f2fs_submit_discard_endio(struct bio *bio) | ||
718 | { | ||
719 | struct discard_cmd *dc = (struct discard_cmd *)bio->bi_private; | ||
720 | |||
721 | complete(&dc->wait); | ||
722 | dc->state = D_DONE; | ||
662 | } | 723 | } |
663 | 724 | ||
664 | static void f2fs_submit_bio_wait_endio(struct bio *bio) | 725 | static int issue_discard_thread(void *data) |
665 | { | 726 | { |
666 | struct bio_entry *be = (struct bio_entry *)bio->bi_private; | 727 | struct f2fs_sb_info *sbi = data; |
728 | struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; | ||
729 | wait_queue_head_t *q = &dcc->discard_wait_queue; | ||
730 | struct list_head *cmd_list = &dcc->discard_cmd_list; | ||
731 | struct discard_cmd *dc, *tmp; | ||
732 | struct blk_plug plug; | ||
733 | int iter = 0; | ||
734 | repeat: | ||
735 | if (kthread_should_stop()) | ||
736 | return 0; | ||
737 | |||
738 | blk_start_plug(&plug); | ||
739 | |||
740 | mutex_lock(&dcc->cmd_lock); | ||
741 | list_for_each_entry_safe(dc, tmp, cmd_list, list) { | ||
742 | if (dc->state == D_PREP) { | ||
743 | dc->state = D_SUBMIT; | ||
744 | submit_bio(dc->bio); | ||
745 | atomic_inc(&dcc->submit_discard); | ||
746 | if (iter++ > DISCARD_ISSUE_RATE) | ||
747 | break; | ||
748 | } else if (dc->state == D_DONE) { | ||
749 | __remove_discard_cmd(sbi, dc); | ||
750 | } | ||
751 | } | ||
752 | mutex_unlock(&dcc->cmd_lock); | ||
753 | |||
754 | blk_finish_plug(&plug); | ||
755 | |||
756 | iter = 0; | ||
757 | congestion_wait(BLK_RW_SYNC, HZ/50); | ||
667 | 758 | ||
668 | be->error = bio->bi_error; | 759 | wait_event_interruptible(*q, |
669 | complete(&be->event); | 760 | kthread_should_stop() || !list_empty(&dcc->discard_cmd_list)); |
761 | goto repeat; | ||
670 | } | 762 | } |
671 | 763 | ||
764 | |||
672 | /* this function is copied from blkdev_issue_discard from block/blk-lib.c */ | 765 | /* this function is copied from blkdev_issue_discard from block/blk-lib.c */ |
673 | static int __f2fs_issue_discard_async(struct f2fs_sb_info *sbi, | 766 | static int __f2fs_issue_discard_async(struct f2fs_sb_info *sbi, |
674 | struct block_device *bdev, block_t blkstart, block_t blklen) | 767 | struct block_device *bdev, block_t blkstart, block_t blklen) |
675 | { | 768 | { |
676 | struct bio *bio = NULL; | 769 | struct bio *bio = NULL; |
770 | block_t lblkstart = blkstart; | ||
677 | int err; | 771 | int err; |
678 | 772 | ||
679 | trace_f2fs_issue_discard(sbi->sb, blkstart, blklen); | 773 | trace_f2fs_issue_discard(bdev, blkstart, blklen); |
680 | 774 | ||
681 | if (sbi->s_ndevs) { | 775 | if (sbi->s_ndevs) { |
682 | int devi = f2fs_target_device_index(sbi, blkstart); | 776 | int devi = f2fs_target_device_index(sbi, blkstart); |
@@ -688,14 +782,12 @@ static int __f2fs_issue_discard_async(struct f2fs_sb_info *sbi, | |||
688 | SECTOR_FROM_BLOCK(blklen), | 782 | SECTOR_FROM_BLOCK(blklen), |
689 | GFP_NOFS, 0, &bio); | 783 | GFP_NOFS, 0, &bio); |
690 | if (!err && bio) { | 784 | if (!err && bio) { |
691 | struct bio_entry *be = __add_bio_entry(sbi, bio); | 785 | bio->bi_end_io = f2fs_submit_discard_endio; |
692 | |||
693 | bio->bi_private = be; | ||
694 | bio->bi_end_io = f2fs_submit_bio_wait_endio; | ||
695 | bio->bi_opf |= REQ_SYNC; | 786 | bio->bi_opf |= REQ_SYNC; |
696 | submit_bio(bio); | ||
697 | } | ||
698 | 787 | ||
788 | __add_discard_cmd(sbi, bio, lblkstart, blklen); | ||
789 | wake_up(&SM_I(sbi)->dcc_info->discard_wait_queue); | ||
790 | } | ||
699 | return err; | 791 | return err; |
700 | } | 792 | } |
701 | 793 | ||
@@ -703,24 +795,13 @@ static int __f2fs_issue_discard_async(struct f2fs_sb_info *sbi, | |||
703 | static int __f2fs_issue_discard_zone(struct f2fs_sb_info *sbi, | 795 | static int __f2fs_issue_discard_zone(struct f2fs_sb_info *sbi, |
704 | struct block_device *bdev, block_t blkstart, block_t blklen) | 796 | struct block_device *bdev, block_t blkstart, block_t blklen) |
705 | { | 797 | { |
706 | sector_t nr_sects = SECTOR_FROM_BLOCK(blklen); | 798 | sector_t sector, nr_sects; |
707 | sector_t sector; | ||
708 | int devi = 0; | 799 | int devi = 0; |
709 | 800 | ||
710 | if (sbi->s_ndevs) { | 801 | if (sbi->s_ndevs) { |
711 | devi = f2fs_target_device_index(sbi, blkstart); | 802 | devi = f2fs_target_device_index(sbi, blkstart); |
712 | blkstart -= FDEV(devi).start_blk; | 803 | blkstart -= FDEV(devi).start_blk; |
713 | } | 804 | } |
714 | sector = SECTOR_FROM_BLOCK(blkstart); | ||
715 | |||
716 | if (sector & (bdev_zone_sectors(bdev) - 1) || | ||
717 | nr_sects != bdev_zone_sectors(bdev)) { | ||
718 | f2fs_msg(sbi->sb, KERN_INFO, | ||
719 | "(%d) %s: Unaligned discard attempted (block %x + %x)", | ||
720 | devi, sbi->s_ndevs ? FDEV(devi).path: "", | ||
721 | blkstart, blklen); | ||
722 | return -EIO; | ||
723 | } | ||
724 | 805 | ||
725 | /* | 806 | /* |
726 | * We need to know the type of the zone: for conventional zones, | 807 | * We need to know the type of the zone: for conventional zones, |
@@ -735,7 +816,18 @@ static int __f2fs_issue_discard_zone(struct f2fs_sb_info *sbi, | |||
735 | return __f2fs_issue_discard_async(sbi, bdev, blkstart, blklen); | 816 | return __f2fs_issue_discard_async(sbi, bdev, blkstart, blklen); |
736 | case BLK_ZONE_TYPE_SEQWRITE_REQ: | 817 | case BLK_ZONE_TYPE_SEQWRITE_REQ: |
737 | case BLK_ZONE_TYPE_SEQWRITE_PREF: | 818 | case BLK_ZONE_TYPE_SEQWRITE_PREF: |
738 | trace_f2fs_issue_reset_zone(sbi->sb, blkstart); | 819 | sector = SECTOR_FROM_BLOCK(blkstart); |
820 | nr_sects = SECTOR_FROM_BLOCK(blklen); | ||
821 | |||
822 | if (sector & (bdev_zone_sectors(bdev) - 1) || | ||
823 | nr_sects != bdev_zone_sectors(bdev)) { | ||
824 | f2fs_msg(sbi->sb, KERN_INFO, | ||
825 | "(%d) %s: Unaligned discard attempted (block %x + %x)", | ||
826 | devi, sbi->s_ndevs ? FDEV(devi).path: "", | ||
827 | blkstart, blklen); | ||
828 | return -EIO; | ||
829 | } | ||
830 | trace_f2fs_issue_reset_zone(bdev, blkstart); | ||
739 | return blkdev_reset_zones(bdev, sector, | 831 | return blkdev_reset_zones(bdev, sector, |
740 | nr_sects, GFP_NOFS); | 832 | nr_sects, GFP_NOFS); |
741 | default: | 833 | default: |
@@ -800,13 +892,14 @@ static void __add_discard_entry(struct f2fs_sb_info *sbi, | |||
800 | struct cp_control *cpc, struct seg_entry *se, | 892 | struct cp_control *cpc, struct seg_entry *se, |
801 | unsigned int start, unsigned int end) | 893 | unsigned int start, unsigned int end) |
802 | { | 894 | { |
803 | struct list_head *head = &SM_I(sbi)->discard_list; | 895 | struct list_head *head = &SM_I(sbi)->dcc_info->discard_entry_list; |
804 | struct discard_entry *new, *last; | 896 | struct discard_entry *new, *last; |
805 | 897 | ||
806 | if (!list_empty(head)) { | 898 | if (!list_empty(head)) { |
807 | last = list_last_entry(head, struct discard_entry, list); | 899 | last = list_last_entry(head, struct discard_entry, list); |
808 | if (START_BLOCK(sbi, cpc->trim_start) + start == | 900 | if (START_BLOCK(sbi, cpc->trim_start) + start == |
809 | last->blkaddr + last->len) { | 901 | last->blkaddr + last->len && |
902 | last->len < MAX_DISCARD_BLOCKS(sbi)) { | ||
810 | last->len += end - start; | 903 | last->len += end - start; |
811 | goto done; | 904 | goto done; |
812 | } | 905 | } |
@@ -818,10 +911,11 @@ static void __add_discard_entry(struct f2fs_sb_info *sbi, | |||
818 | new->len = end - start; | 911 | new->len = end - start; |
819 | list_add_tail(&new->list, head); | 912 | list_add_tail(&new->list, head); |
820 | done: | 913 | done: |
821 | SM_I(sbi)->nr_discards += end - start; | 914 | SM_I(sbi)->dcc_info->nr_discards += end - start; |
822 | } | 915 | } |
823 | 916 | ||
824 | static void add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc) | 917 | static bool add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc, |
918 | bool check_only) | ||
825 | { | 919 | { |
826 | int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long); | 920 | int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long); |
827 | int max_blocks = sbi->blocks_per_seg; | 921 | int max_blocks = sbi->blocks_per_seg; |
@@ -835,12 +929,13 @@ static void add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
835 | int i; | 929 | int i; |
836 | 930 | ||
837 | if (se->valid_blocks == max_blocks || !f2fs_discard_en(sbi)) | 931 | if (se->valid_blocks == max_blocks || !f2fs_discard_en(sbi)) |
838 | return; | 932 | return false; |
839 | 933 | ||
840 | if (!force) { | 934 | if (!force) { |
841 | if (!test_opt(sbi, DISCARD) || !se->valid_blocks || | 935 | if (!test_opt(sbi, DISCARD) || !se->valid_blocks || |
842 | SM_I(sbi)->nr_discards >= SM_I(sbi)->max_discards) | 936 | SM_I(sbi)->dcc_info->nr_discards >= |
843 | return; | 937 | SM_I(sbi)->dcc_info->max_discards) |
938 | return false; | ||
844 | } | 939 | } |
845 | 940 | ||
846 | /* SIT_VBLOCK_MAP_SIZE should be multiple of sizeof(unsigned long) */ | 941 | /* SIT_VBLOCK_MAP_SIZE should be multiple of sizeof(unsigned long) */ |
@@ -848,7 +943,8 @@ static void add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
848 | dmap[i] = force ? ~ckpt_map[i] & ~discard_map[i] : | 943 | dmap[i] = force ? ~ckpt_map[i] & ~discard_map[i] : |
849 | (cur_map[i] ^ ckpt_map[i]) & ckpt_map[i]; | 944 | (cur_map[i] ^ ckpt_map[i]) & ckpt_map[i]; |
850 | 945 | ||
851 | while (force || SM_I(sbi)->nr_discards <= SM_I(sbi)->max_discards) { | 946 | while (force || SM_I(sbi)->dcc_info->nr_discards <= |
947 | SM_I(sbi)->dcc_info->max_discards) { | ||
852 | start = __find_rev_next_bit(dmap, max_blocks, end + 1); | 948 | start = __find_rev_next_bit(dmap, max_blocks, end + 1); |
853 | if (start >= max_blocks) | 949 | if (start >= max_blocks) |
854 | break; | 950 | break; |
@@ -858,13 +954,17 @@ static void add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
858 | && (end - start) < cpc->trim_minlen) | 954 | && (end - start) < cpc->trim_minlen) |
859 | continue; | 955 | continue; |
860 | 956 | ||
957 | if (check_only) | ||
958 | return true; | ||
959 | |||
861 | __add_discard_entry(sbi, cpc, se, start, end); | 960 | __add_discard_entry(sbi, cpc, se, start, end); |
862 | } | 961 | } |
962 | return false; | ||
863 | } | 963 | } |
864 | 964 | ||
865 | void release_discard_addrs(struct f2fs_sb_info *sbi) | 965 | void release_discard_addrs(struct f2fs_sb_info *sbi) |
866 | { | 966 | { |
867 | struct list_head *head = &(SM_I(sbi)->discard_list); | 967 | struct list_head *head = &(SM_I(sbi)->dcc_info->discard_entry_list); |
868 | struct discard_entry *entry, *this; | 968 | struct discard_entry *entry, *this; |
869 | 969 | ||
870 | /* drop caches */ | 970 | /* drop caches */ |
@@ -890,17 +990,14 @@ static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi) | |||
890 | 990 | ||
891 | void clear_prefree_segments(struct f2fs_sb_info *sbi, struct cp_control *cpc) | 991 | void clear_prefree_segments(struct f2fs_sb_info *sbi, struct cp_control *cpc) |
892 | { | 992 | { |
893 | struct list_head *head = &(SM_I(sbi)->discard_list); | 993 | struct list_head *head = &(SM_I(sbi)->dcc_info->discard_entry_list); |
894 | struct discard_entry *entry, *this; | 994 | struct discard_entry *entry, *this; |
895 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | 995 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); |
896 | struct blk_plug plug; | ||
897 | unsigned long *prefree_map = dirty_i->dirty_segmap[PRE]; | 996 | unsigned long *prefree_map = dirty_i->dirty_segmap[PRE]; |
898 | unsigned int start = 0, end = -1; | 997 | unsigned int start = 0, end = -1; |
899 | unsigned int secno, start_segno; | 998 | unsigned int secno, start_segno; |
900 | bool force = (cpc->reason == CP_DISCARD); | 999 | bool force = (cpc->reason == CP_DISCARD); |
901 | 1000 | ||
902 | blk_start_plug(&plug); | ||
903 | |||
904 | mutex_lock(&dirty_i->seglist_lock); | 1001 | mutex_lock(&dirty_i->seglist_lock); |
905 | 1002 | ||
906 | while (1) { | 1003 | while (1) { |
@@ -916,9 +1013,13 @@ void clear_prefree_segments(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
916 | 1013 | ||
917 | dirty_i->nr_dirty[PRE] -= end - start; | 1014 | dirty_i->nr_dirty[PRE] -= end - start; |
918 | 1015 | ||
919 | if (force || !test_opt(sbi, DISCARD)) | 1016 | if (!test_opt(sbi, DISCARD)) |
920 | continue; | 1017 | continue; |
921 | 1018 | ||
1019 | if (force && start >= cpc->trim_start && | ||
1020 | (end - 1) <= cpc->trim_end) | ||
1021 | continue; | ||
1022 | |||
922 | if (!test_opt(sbi, LFS) || sbi->segs_per_sec == 1) { | 1023 | if (!test_opt(sbi, LFS) || sbi->segs_per_sec == 1) { |
923 | f2fs_issue_discard(sbi, START_BLOCK(sbi, start), | 1024 | f2fs_issue_discard(sbi, START_BLOCK(sbi, start), |
924 | (end - start) << sbi->log_blocks_per_seg); | 1025 | (end - start) << sbi->log_blocks_per_seg); |
@@ -935,6 +1036,8 @@ next: | |||
935 | start = start_segno + sbi->segs_per_sec; | 1036 | start = start_segno + sbi->segs_per_sec; |
936 | if (start < end) | 1037 | if (start < end) |
937 | goto next; | 1038 | goto next; |
1039 | else | ||
1040 | end = start - 1; | ||
938 | } | 1041 | } |
939 | mutex_unlock(&dirty_i->seglist_lock); | 1042 | mutex_unlock(&dirty_i->seglist_lock); |
940 | 1043 | ||
@@ -946,11 +1049,62 @@ next: | |||
946 | cpc->trimmed += entry->len; | 1049 | cpc->trimmed += entry->len; |
947 | skip: | 1050 | skip: |
948 | list_del(&entry->list); | 1051 | list_del(&entry->list); |
949 | SM_I(sbi)->nr_discards -= entry->len; | 1052 | SM_I(sbi)->dcc_info->nr_discards -= entry->len; |
950 | kmem_cache_free(discard_entry_slab, entry); | 1053 | kmem_cache_free(discard_entry_slab, entry); |
951 | } | 1054 | } |
1055 | } | ||
952 | 1056 | ||
953 | blk_finish_plug(&plug); | 1057 | static int create_discard_cmd_control(struct f2fs_sb_info *sbi) |
1058 | { | ||
1059 | dev_t dev = sbi->sb->s_bdev->bd_dev; | ||
1060 | struct discard_cmd_control *dcc; | ||
1061 | int err = 0; | ||
1062 | |||
1063 | if (SM_I(sbi)->dcc_info) { | ||
1064 | dcc = SM_I(sbi)->dcc_info; | ||
1065 | goto init_thread; | ||
1066 | } | ||
1067 | |||
1068 | dcc = kzalloc(sizeof(struct discard_cmd_control), GFP_KERNEL); | ||
1069 | if (!dcc) | ||
1070 | return -ENOMEM; | ||
1071 | |||
1072 | INIT_LIST_HEAD(&dcc->discard_entry_list); | ||
1073 | INIT_LIST_HEAD(&dcc->discard_cmd_list); | ||
1074 | mutex_init(&dcc->cmd_lock); | ||
1075 | atomic_set(&dcc->submit_discard, 0); | ||
1076 | dcc->nr_discards = 0; | ||
1077 | dcc->max_discards = 0; | ||
1078 | |||
1079 | init_waitqueue_head(&dcc->discard_wait_queue); | ||
1080 | SM_I(sbi)->dcc_info = dcc; | ||
1081 | init_thread: | ||
1082 | dcc->f2fs_issue_discard = kthread_run(issue_discard_thread, sbi, | ||
1083 | "f2fs_discard-%u:%u", MAJOR(dev), MINOR(dev)); | ||
1084 | if (IS_ERR(dcc->f2fs_issue_discard)) { | ||
1085 | err = PTR_ERR(dcc->f2fs_issue_discard); | ||
1086 | kfree(dcc); | ||
1087 | SM_I(sbi)->dcc_info = NULL; | ||
1088 | return err; | ||
1089 | } | ||
1090 | |||
1091 | return err; | ||
1092 | } | ||
1093 | |||
1094 | static void destroy_discard_cmd_control(struct f2fs_sb_info *sbi, bool free) | ||
1095 | { | ||
1096 | struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; | ||
1097 | |||
1098 | if (dcc && dcc->f2fs_issue_discard) { | ||
1099 | struct task_struct *discard_thread = dcc->f2fs_issue_discard; | ||
1100 | |||
1101 | dcc->f2fs_issue_discard = NULL; | ||
1102 | kthread_stop(discard_thread); | ||
1103 | } | ||
1104 | if (free) { | ||
1105 | kfree(dcc); | ||
1106 | SM_I(sbi)->dcc_info = NULL; | ||
1107 | } | ||
954 | } | 1108 | } |
955 | 1109 | ||
956 | static bool __mark_sit_entry_dirty(struct f2fs_sb_info *sbi, unsigned int segno) | 1110 | static bool __mark_sit_entry_dirty(struct f2fs_sb_info *sbi, unsigned int segno) |
@@ -995,14 +1149,32 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del) | |||
995 | 1149 | ||
996 | /* Update valid block bitmap */ | 1150 | /* Update valid block bitmap */ |
997 | if (del > 0) { | 1151 | if (del > 0) { |
998 | if (f2fs_test_and_set_bit(offset, se->cur_valid_map)) | 1152 | if (f2fs_test_and_set_bit(offset, se->cur_valid_map)) { |
1153 | #ifdef CONFIG_F2FS_CHECK_FS | ||
1154 | if (f2fs_test_and_set_bit(offset, | ||
1155 | se->cur_valid_map_mir)) | ||
1156 | f2fs_bug_on(sbi, 1); | ||
1157 | else | ||
1158 | WARN_ON(1); | ||
1159 | #else | ||
999 | f2fs_bug_on(sbi, 1); | 1160 | f2fs_bug_on(sbi, 1); |
1161 | #endif | ||
1162 | } | ||
1000 | if (f2fs_discard_en(sbi) && | 1163 | if (f2fs_discard_en(sbi) && |
1001 | !f2fs_test_and_set_bit(offset, se->discard_map)) | 1164 | !f2fs_test_and_set_bit(offset, se->discard_map)) |
1002 | sbi->discard_blks--; | 1165 | sbi->discard_blks--; |
1003 | } else { | 1166 | } else { |
1004 | if (!f2fs_test_and_clear_bit(offset, se->cur_valid_map)) | 1167 | if (!f2fs_test_and_clear_bit(offset, se->cur_valid_map)) { |
1168 | #ifdef CONFIG_F2FS_CHECK_FS | ||
1169 | if (!f2fs_test_and_clear_bit(offset, | ||
1170 | se->cur_valid_map_mir)) | ||
1171 | f2fs_bug_on(sbi, 1); | ||
1172 | else | ||
1173 | WARN_ON(1); | ||
1174 | #else | ||
1005 | f2fs_bug_on(sbi, 1); | 1175 | f2fs_bug_on(sbi, 1); |
1176 | #endif | ||
1177 | } | ||
1006 | if (f2fs_discard_en(sbi) && | 1178 | if (f2fs_discard_en(sbi) && |
1007 | f2fs_test_and_clear_bit(offset, se->discard_map)) | 1179 | f2fs_test_and_clear_bit(offset, se->discard_map)) |
1008 | sbi->discard_blks++; | 1180 | sbi->discard_blks++; |
@@ -1167,17 +1339,6 @@ static void write_current_sum_page(struct f2fs_sb_info *sbi, | |||
1167 | f2fs_put_page(page, 1); | 1339 | f2fs_put_page(page, 1); |
1168 | } | 1340 | } |
1169 | 1341 | ||
1170 | static int is_next_segment_free(struct f2fs_sb_info *sbi, int type) | ||
1171 | { | ||
1172 | struct curseg_info *curseg = CURSEG_I(sbi, type); | ||
1173 | unsigned int segno = curseg->segno + 1; | ||
1174 | struct free_segmap_info *free_i = FREE_I(sbi); | ||
1175 | |||
1176 | if (segno < MAIN_SEGS(sbi) && segno % sbi->segs_per_sec) | ||
1177 | return !test_bit(segno, free_i->free_segmap); | ||
1178 | return 0; | ||
1179 | } | ||
1180 | |||
1181 | /* | 1342 | /* |
1182 | * Find a new segment from the free segments bitmap to right order | 1343 | * Find a new segment from the free segments bitmap to right order |
1183 | * This function should be returned with success, otherwise BUG | 1344 | * This function should be returned with success, otherwise BUG |
@@ -1382,16 +1543,39 @@ static int get_ssr_segment(struct f2fs_sb_info *sbi, int type) | |||
1382 | { | 1543 | { |
1383 | struct curseg_info *curseg = CURSEG_I(sbi, type); | 1544 | struct curseg_info *curseg = CURSEG_I(sbi, type); |
1384 | const struct victim_selection *v_ops = DIRTY_I(sbi)->v_ops; | 1545 | const struct victim_selection *v_ops = DIRTY_I(sbi)->v_ops; |
1546 | int i, cnt; | ||
1547 | bool reversed = false; | ||
1548 | |||
1549 | /* need_SSR() already forces to do this */ | ||
1550 | if (v_ops->get_victim(sbi, &(curseg)->next_segno, BG_GC, type, SSR)) | ||
1551 | return 1; | ||
1385 | 1552 | ||
1386 | if (IS_NODESEG(type) || !has_not_enough_free_secs(sbi, 0, 0)) | 1553 | /* For node segments, let's do SSR more intensively */ |
1387 | return v_ops->get_victim(sbi, | 1554 | if (IS_NODESEG(type)) { |
1388 | &(curseg)->next_segno, BG_GC, type, SSR); | 1555 | if (type >= CURSEG_WARM_NODE) { |
1556 | reversed = true; | ||
1557 | i = CURSEG_COLD_NODE; | ||
1558 | } else { | ||
1559 | i = CURSEG_HOT_NODE; | ||
1560 | } | ||
1561 | cnt = NR_CURSEG_NODE_TYPE; | ||
1562 | } else { | ||
1563 | if (type >= CURSEG_WARM_DATA) { | ||
1564 | reversed = true; | ||
1565 | i = CURSEG_COLD_DATA; | ||
1566 | } else { | ||
1567 | i = CURSEG_HOT_DATA; | ||
1568 | } | ||
1569 | cnt = NR_CURSEG_DATA_TYPE; | ||
1570 | } | ||
1389 | 1571 | ||
1390 | /* For data segments, let's do SSR more intensively */ | 1572 | for (; cnt-- > 0; reversed ? i-- : i++) { |
1391 | for (; type >= CURSEG_HOT_DATA; type--) | 1573 | if (i == type) |
1574 | continue; | ||
1392 | if (v_ops->get_victim(sbi, &(curseg)->next_segno, | 1575 | if (v_ops->get_victim(sbi, &(curseg)->next_segno, |
1393 | BG_GC, type, SSR)) | 1576 | BG_GC, i, SSR)) |
1394 | return 1; | 1577 | return 1; |
1578 | } | ||
1395 | return 0; | 1579 | return 0; |
1396 | } | 1580 | } |
1397 | 1581 | ||
@@ -1402,20 +1586,17 @@ static int get_ssr_segment(struct f2fs_sb_info *sbi, int type) | |||
1402 | static void allocate_segment_by_default(struct f2fs_sb_info *sbi, | 1586 | static void allocate_segment_by_default(struct f2fs_sb_info *sbi, |
1403 | int type, bool force) | 1587 | int type, bool force) |
1404 | { | 1588 | { |
1405 | struct curseg_info *curseg = CURSEG_I(sbi, type); | ||
1406 | |||
1407 | if (force) | 1589 | if (force) |
1408 | new_curseg(sbi, type, true); | 1590 | new_curseg(sbi, type, true); |
1409 | else if (type == CURSEG_WARM_NODE) | 1591 | else if (!is_set_ckpt_flags(sbi, CP_CRC_RECOVERY_FLAG) && |
1410 | new_curseg(sbi, type, false); | 1592 | type == CURSEG_WARM_NODE) |
1411 | else if (curseg->alloc_type == LFS && is_next_segment_free(sbi, type)) | ||
1412 | new_curseg(sbi, type, false); | 1593 | new_curseg(sbi, type, false); |
1413 | else if (need_SSR(sbi) && get_ssr_segment(sbi, type)) | 1594 | else if (need_SSR(sbi) && get_ssr_segment(sbi, type)) |
1414 | change_curseg(sbi, type, true); | 1595 | change_curseg(sbi, type, true); |
1415 | else | 1596 | else |
1416 | new_curseg(sbi, type, false); | 1597 | new_curseg(sbi, type, false); |
1417 | 1598 | ||
1418 | stat_inc_seg_type(sbi, curseg); | 1599 | stat_inc_seg_type(sbi, CURSEG_I(sbi, type)); |
1419 | } | 1600 | } |
1420 | 1601 | ||
1421 | void allocate_new_segments(struct f2fs_sb_info *sbi) | 1602 | void allocate_new_segments(struct f2fs_sb_info *sbi) |
@@ -1424,9 +1605,6 @@ void allocate_new_segments(struct f2fs_sb_info *sbi) | |||
1424 | unsigned int old_segno; | 1605 | unsigned int old_segno; |
1425 | int i; | 1606 | int i; |
1426 | 1607 | ||
1427 | if (test_opt(sbi, LFS)) | ||
1428 | return; | ||
1429 | |||
1430 | for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { | 1608 | for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { |
1431 | curseg = CURSEG_I(sbi, i); | 1609 | curseg = CURSEG_I(sbi, i); |
1432 | old_segno = curseg->segno; | 1610 | old_segno = curseg->segno; |
@@ -1439,6 +1617,24 @@ static const struct segment_allocation default_salloc_ops = { | |||
1439 | .allocate_segment = allocate_segment_by_default, | 1617 | .allocate_segment = allocate_segment_by_default, |
1440 | }; | 1618 | }; |
1441 | 1619 | ||
1620 | bool exist_trim_candidates(struct f2fs_sb_info *sbi, struct cp_control *cpc) | ||
1621 | { | ||
1622 | __u64 trim_start = cpc->trim_start; | ||
1623 | bool has_candidate = false; | ||
1624 | |||
1625 | mutex_lock(&SIT_I(sbi)->sentry_lock); | ||
1626 | for (; cpc->trim_start <= cpc->trim_end; cpc->trim_start++) { | ||
1627 | if (add_discard_addrs(sbi, cpc, true)) { | ||
1628 | has_candidate = true; | ||
1629 | break; | ||
1630 | } | ||
1631 | } | ||
1632 | mutex_unlock(&SIT_I(sbi)->sentry_lock); | ||
1633 | |||
1634 | cpc->trim_start = trim_start; | ||
1635 | return has_candidate; | ||
1636 | } | ||
1637 | |||
1442 | int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range) | 1638 | int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range) |
1443 | { | 1639 | { |
1444 | __u64 start = F2FS_BYTES_TO_BLK(range->start); | 1640 | __u64 start = F2FS_BYTES_TO_BLK(range->start); |
@@ -1573,6 +1769,8 @@ void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, | |||
1573 | 1769 | ||
1574 | *new_blkaddr = NEXT_FREE_BLKADDR(sbi, curseg); | 1770 | *new_blkaddr = NEXT_FREE_BLKADDR(sbi, curseg); |
1575 | 1771 | ||
1772 | f2fs_wait_discard_bio(sbi, *new_blkaddr); | ||
1773 | |||
1576 | /* | 1774 | /* |
1577 | * __add_sum_entry should be resided under the curseg_mutex | 1775 | * __add_sum_entry should be resided under the curseg_mutex |
1578 | * because, this function updates a summary entry in the | 1776 | * because, this function updates a summary entry in the |
@@ -1584,14 +1782,15 @@ void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, | |||
1584 | 1782 | ||
1585 | stat_inc_block_count(sbi, curseg); | 1783 | stat_inc_block_count(sbi, curseg); |
1586 | 1784 | ||
1587 | if (!__has_curseg_space(sbi, type)) | ||
1588 | sit_i->s_ops->allocate_segment(sbi, type, false); | ||
1589 | /* | 1785 | /* |
1590 | * SIT information should be updated before segment allocation, | 1786 | * SIT information should be updated before segment allocation, |
1591 | * since SSR needs latest valid block information. | 1787 | * since SSR needs latest valid block information. |
1592 | */ | 1788 | */ |
1593 | refresh_sit_entry(sbi, old_blkaddr, *new_blkaddr); | 1789 | refresh_sit_entry(sbi, old_blkaddr, *new_blkaddr); |
1594 | 1790 | ||
1791 | if (!__has_curseg_space(sbi, type)) | ||
1792 | sit_i->s_ops->allocate_segment(sbi, type, false); | ||
1793 | |||
1595 | mutex_unlock(&sit_i->sentry_lock); | 1794 | mutex_unlock(&sit_i->sentry_lock); |
1596 | 1795 | ||
1597 | if (page && IS_NODESEG(type)) | 1796 | if (page && IS_NODESEG(type)) |
@@ -1603,15 +1802,20 @@ void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, | |||
1603 | static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio) | 1802 | static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio) |
1604 | { | 1803 | { |
1605 | int type = __get_segment_type(fio->page, fio->type); | 1804 | int type = __get_segment_type(fio->page, fio->type); |
1805 | int err; | ||
1606 | 1806 | ||
1607 | if (fio->type == NODE || fio->type == DATA) | 1807 | if (fio->type == NODE || fio->type == DATA) |
1608 | mutex_lock(&fio->sbi->wio_mutex[fio->type]); | 1808 | mutex_lock(&fio->sbi->wio_mutex[fio->type]); |
1609 | 1809 | reallocate: | |
1610 | allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr, | 1810 | allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr, |
1611 | &fio->new_blkaddr, sum, type); | 1811 | &fio->new_blkaddr, sum, type); |
1612 | 1812 | ||
1613 | /* writeout dirty page into bdev */ | 1813 | /* writeout dirty page into bdev */ |
1614 | f2fs_submit_page_mbio(fio); | 1814 | err = f2fs_submit_page_mbio(fio); |
1815 | if (err == -EAGAIN) { | ||
1816 | fio->old_blkaddr = fio->new_blkaddr; | ||
1817 | goto reallocate; | ||
1818 | } | ||
1615 | 1819 | ||
1616 | if (fio->type == NODE || fio->type == DATA) | 1820 | if (fio->type == NODE || fio->type == DATA) |
1617 | mutex_unlock(&fio->sbi->wio_mutex[fio->type]); | 1821 | mutex_unlock(&fio->sbi->wio_mutex[fio->type]); |
@@ -1753,7 +1957,8 @@ void f2fs_wait_on_page_writeback(struct page *page, | |||
1753 | if (PageWriteback(page)) { | 1957 | if (PageWriteback(page)) { |
1754 | struct f2fs_sb_info *sbi = F2FS_P_SB(page); | 1958 | struct f2fs_sb_info *sbi = F2FS_P_SB(page); |
1755 | 1959 | ||
1756 | f2fs_submit_merged_bio_cond(sbi, NULL, page, 0, type, WRITE); | 1960 | f2fs_submit_merged_bio_cond(sbi, page->mapping->host, |
1961 | 0, page->index, type, WRITE); | ||
1757 | if (ordered) | 1962 | if (ordered) |
1758 | wait_on_page_writeback(page); | 1963 | wait_on_page_writeback(page); |
1759 | else | 1964 | else |
@@ -2228,7 +2433,7 @@ void flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
2228 | /* add discard candidates */ | 2433 | /* add discard candidates */ |
2229 | if (cpc->reason != CP_DISCARD) { | 2434 | if (cpc->reason != CP_DISCARD) { |
2230 | cpc->trim_start = segno; | 2435 | cpc->trim_start = segno; |
2231 | add_discard_addrs(sbi, cpc); | 2436 | add_discard_addrs(sbi, cpc, false); |
2232 | } | 2437 | } |
2233 | 2438 | ||
2234 | if (to_journal) { | 2439 | if (to_journal) { |
@@ -2263,8 +2468,12 @@ void flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
2263 | f2fs_bug_on(sbi, sit_i->dirty_sentries); | 2468 | f2fs_bug_on(sbi, sit_i->dirty_sentries); |
2264 | out: | 2469 | out: |
2265 | if (cpc->reason == CP_DISCARD) { | 2470 | if (cpc->reason == CP_DISCARD) { |
2471 | __u64 trim_start = cpc->trim_start; | ||
2472 | |||
2266 | for (; cpc->trim_start <= cpc->trim_end; cpc->trim_start++) | 2473 | for (; cpc->trim_start <= cpc->trim_end; cpc->trim_start++) |
2267 | add_discard_addrs(sbi, cpc); | 2474 | add_discard_addrs(sbi, cpc, false); |
2475 | |||
2476 | cpc->trim_start = trim_start; | ||
2268 | } | 2477 | } |
2269 | mutex_unlock(&sit_i->sentry_lock); | 2478 | mutex_unlock(&sit_i->sentry_lock); |
2270 | 2479 | ||
@@ -2276,7 +2485,7 @@ static int build_sit_info(struct f2fs_sb_info *sbi) | |||
2276 | struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); | 2485 | struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); |
2277 | struct sit_info *sit_i; | 2486 | struct sit_info *sit_i; |
2278 | unsigned int sit_segs, start; | 2487 | unsigned int sit_segs, start; |
2279 | char *src_bitmap, *dst_bitmap; | 2488 | char *src_bitmap; |
2280 | unsigned int bitmap_size; | 2489 | unsigned int bitmap_size; |
2281 | 2490 | ||
2282 | /* allocate memory for SIT information */ | 2491 | /* allocate memory for SIT information */ |
@@ -2305,6 +2514,13 @@ static int build_sit_info(struct f2fs_sb_info *sbi) | |||
2305 | !sit_i->sentries[start].ckpt_valid_map) | 2514 | !sit_i->sentries[start].ckpt_valid_map) |
2306 | return -ENOMEM; | 2515 | return -ENOMEM; |
2307 | 2516 | ||
2517 | #ifdef CONFIG_F2FS_CHECK_FS | ||
2518 | sit_i->sentries[start].cur_valid_map_mir | ||
2519 | = kzalloc(SIT_VBLOCK_MAP_SIZE, GFP_KERNEL); | ||
2520 | if (!sit_i->sentries[start].cur_valid_map_mir) | ||
2521 | return -ENOMEM; | ||
2522 | #endif | ||
2523 | |||
2308 | if (f2fs_discard_en(sbi)) { | 2524 | if (f2fs_discard_en(sbi)) { |
2309 | sit_i->sentries[start].discard_map | 2525 | sit_i->sentries[start].discard_map |
2310 | = kzalloc(SIT_VBLOCK_MAP_SIZE, GFP_KERNEL); | 2526 | = kzalloc(SIT_VBLOCK_MAP_SIZE, GFP_KERNEL); |
@@ -2331,17 +2547,22 @@ static int build_sit_info(struct f2fs_sb_info *sbi) | |||
2331 | bitmap_size = __bitmap_size(sbi, SIT_BITMAP); | 2547 | bitmap_size = __bitmap_size(sbi, SIT_BITMAP); |
2332 | src_bitmap = __bitmap_ptr(sbi, SIT_BITMAP); | 2548 | src_bitmap = __bitmap_ptr(sbi, SIT_BITMAP); |
2333 | 2549 | ||
2334 | dst_bitmap = kmemdup(src_bitmap, bitmap_size, GFP_KERNEL); | 2550 | sit_i->sit_bitmap = kmemdup(src_bitmap, bitmap_size, GFP_KERNEL); |
2335 | if (!dst_bitmap) | 2551 | if (!sit_i->sit_bitmap) |
2336 | return -ENOMEM; | 2552 | return -ENOMEM; |
2337 | 2553 | ||
2554 | #ifdef CONFIG_F2FS_CHECK_FS | ||
2555 | sit_i->sit_bitmap_mir = kmemdup(src_bitmap, bitmap_size, GFP_KERNEL); | ||
2556 | if (!sit_i->sit_bitmap_mir) | ||
2557 | return -ENOMEM; | ||
2558 | #endif | ||
2559 | |||
2338 | /* init SIT information */ | 2560 | /* init SIT information */ |
2339 | sit_i->s_ops = &default_salloc_ops; | 2561 | sit_i->s_ops = &default_salloc_ops; |
2340 | 2562 | ||
2341 | sit_i->sit_base_addr = le32_to_cpu(raw_super->sit_blkaddr); | 2563 | sit_i->sit_base_addr = le32_to_cpu(raw_super->sit_blkaddr); |
2342 | sit_i->sit_blocks = sit_segs << sbi->log_blocks_per_seg; | 2564 | sit_i->sit_blocks = sit_segs << sbi->log_blocks_per_seg; |
2343 | sit_i->written_valid_blocks = 0; | 2565 | sit_i->written_valid_blocks = 0; |
2344 | sit_i->sit_bitmap = dst_bitmap; | ||
2345 | sit_i->bitmap_size = bitmap_size; | 2566 | sit_i->bitmap_size = bitmap_size; |
2346 | sit_i->dirty_sentries = 0; | 2567 | sit_i->dirty_sentries = 0; |
2347 | sit_i->sents_per_block = SIT_ENTRY_PER_BLOCK; | 2568 | sit_i->sents_per_block = SIT_ENTRY_PER_BLOCK; |
@@ -2626,11 +2847,6 @@ int build_segment_manager(struct f2fs_sb_info *sbi) | |||
2626 | sm_info->min_ipu_util = DEF_MIN_IPU_UTIL; | 2847 | sm_info->min_ipu_util = DEF_MIN_IPU_UTIL; |
2627 | sm_info->min_fsync_blocks = DEF_MIN_FSYNC_BLOCKS; | 2848 | sm_info->min_fsync_blocks = DEF_MIN_FSYNC_BLOCKS; |
2628 | 2849 | ||
2629 | INIT_LIST_HEAD(&sm_info->discard_list); | ||
2630 | INIT_LIST_HEAD(&sm_info->wait_list); | ||
2631 | sm_info->nr_discards = 0; | ||
2632 | sm_info->max_discards = 0; | ||
2633 | |||
2634 | sm_info->trim_sections = DEF_BATCHED_TRIM_SECTIONS; | 2850 | sm_info->trim_sections = DEF_BATCHED_TRIM_SECTIONS; |
2635 | 2851 | ||
2636 | INIT_LIST_HEAD(&sm_info->sit_entry_set); | 2852 | INIT_LIST_HEAD(&sm_info->sit_entry_set); |
@@ -2641,6 +2857,10 @@ int build_segment_manager(struct f2fs_sb_info *sbi) | |||
2641 | return err; | 2857 | return err; |
2642 | } | 2858 | } |
2643 | 2859 | ||
2860 | err = create_discard_cmd_control(sbi); | ||
2861 | if (err) | ||
2862 | return err; | ||
2863 | |||
2644 | err = build_sit_info(sbi); | 2864 | err = build_sit_info(sbi); |
2645 | if (err) | 2865 | if (err) |
2646 | return err; | 2866 | return err; |
@@ -2734,6 +2954,9 @@ static void destroy_sit_info(struct f2fs_sb_info *sbi) | |||
2734 | if (sit_i->sentries) { | 2954 | if (sit_i->sentries) { |
2735 | for (start = 0; start < MAIN_SEGS(sbi); start++) { | 2955 | for (start = 0; start < MAIN_SEGS(sbi); start++) { |
2736 | kfree(sit_i->sentries[start].cur_valid_map); | 2956 | kfree(sit_i->sentries[start].cur_valid_map); |
2957 | #ifdef CONFIG_F2FS_CHECK_FS | ||
2958 | kfree(sit_i->sentries[start].cur_valid_map_mir); | ||
2959 | #endif | ||
2737 | kfree(sit_i->sentries[start].ckpt_valid_map); | 2960 | kfree(sit_i->sentries[start].ckpt_valid_map); |
2738 | kfree(sit_i->sentries[start].discard_map); | 2961 | kfree(sit_i->sentries[start].discard_map); |
2739 | } | 2962 | } |
@@ -2746,6 +2969,9 @@ static void destroy_sit_info(struct f2fs_sb_info *sbi) | |||
2746 | 2969 | ||
2747 | SM_I(sbi)->sit_info = NULL; | 2970 | SM_I(sbi)->sit_info = NULL; |
2748 | kfree(sit_i->sit_bitmap); | 2971 | kfree(sit_i->sit_bitmap); |
2972 | #ifdef CONFIG_F2FS_CHECK_FS | ||
2973 | kfree(sit_i->sit_bitmap_mir); | ||
2974 | #endif | ||
2749 | kfree(sit_i); | 2975 | kfree(sit_i); |
2750 | } | 2976 | } |
2751 | 2977 | ||
@@ -2756,6 +2982,7 @@ void destroy_segment_manager(struct f2fs_sb_info *sbi) | |||
2756 | if (!sm_info) | 2982 | if (!sm_info) |
2757 | return; | 2983 | return; |
2758 | destroy_flush_cmd_control(sbi, true); | 2984 | destroy_flush_cmd_control(sbi, true); |
2985 | destroy_discard_cmd_control(sbi, true); | ||
2759 | destroy_dirty_segmap(sbi); | 2986 | destroy_dirty_segmap(sbi); |
2760 | destroy_curseg(sbi); | 2987 | destroy_curseg(sbi); |
2761 | destroy_free_segmap(sbi); | 2988 | destroy_free_segmap(sbi); |
@@ -2771,15 +2998,15 @@ int __init create_segment_manager_caches(void) | |||
2771 | if (!discard_entry_slab) | 2998 | if (!discard_entry_slab) |
2772 | goto fail; | 2999 | goto fail; |
2773 | 3000 | ||
2774 | bio_entry_slab = f2fs_kmem_cache_create("bio_entry", | 3001 | discard_cmd_slab = f2fs_kmem_cache_create("discard_cmd", |
2775 | sizeof(struct bio_entry)); | 3002 | sizeof(struct discard_cmd)); |
2776 | if (!bio_entry_slab) | 3003 | if (!discard_cmd_slab) |
2777 | goto destroy_discard_entry; | 3004 | goto destroy_discard_entry; |
2778 | 3005 | ||
2779 | sit_entry_set_slab = f2fs_kmem_cache_create("sit_entry_set", | 3006 | sit_entry_set_slab = f2fs_kmem_cache_create("sit_entry_set", |
2780 | sizeof(struct sit_entry_set)); | 3007 | sizeof(struct sit_entry_set)); |
2781 | if (!sit_entry_set_slab) | 3008 | if (!sit_entry_set_slab) |
2782 | goto destroy_bio_entry; | 3009 | goto destroy_discard_cmd; |
2783 | 3010 | ||
2784 | inmem_entry_slab = f2fs_kmem_cache_create("inmem_page_entry", | 3011 | inmem_entry_slab = f2fs_kmem_cache_create("inmem_page_entry", |
2785 | sizeof(struct inmem_pages)); | 3012 | sizeof(struct inmem_pages)); |
@@ -2789,8 +3016,8 @@ int __init create_segment_manager_caches(void) | |||
2789 | 3016 | ||
2790 | destroy_sit_entry_set: | 3017 | destroy_sit_entry_set: |
2791 | kmem_cache_destroy(sit_entry_set_slab); | 3018 | kmem_cache_destroy(sit_entry_set_slab); |
2792 | destroy_bio_entry: | 3019 | destroy_discard_cmd: |
2793 | kmem_cache_destroy(bio_entry_slab); | 3020 | kmem_cache_destroy(discard_cmd_slab); |
2794 | destroy_discard_entry: | 3021 | destroy_discard_entry: |
2795 | kmem_cache_destroy(discard_entry_slab); | 3022 | kmem_cache_destroy(discard_entry_slab); |
2796 | fail: | 3023 | fail: |
@@ -2800,7 +3027,7 @@ fail: | |||
2800 | void destroy_segment_manager_caches(void) | 3027 | void destroy_segment_manager_caches(void) |
2801 | { | 3028 | { |
2802 | kmem_cache_destroy(sit_entry_set_slab); | 3029 | kmem_cache_destroy(sit_entry_set_slab); |
2803 | kmem_cache_destroy(bio_entry_slab); | 3030 | kmem_cache_destroy(discard_cmd_slab); |
2804 | kmem_cache_destroy(discard_entry_slab); | 3031 | kmem_cache_destroy(discard_entry_slab); |
2805 | kmem_cache_destroy(inmem_entry_slab); | 3032 | kmem_cache_destroy(inmem_entry_slab); |
2806 | } | 3033 | } |