diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/fs-writeback.c | 60 |
1 files changed, 53 insertions, 7 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index d99601af9e4..a9ee474f969 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
| @@ -440,6 +440,7 @@ void generic_sync_sb_inodes(struct super_block *sb, | |||
| 440 | struct writeback_control *wbc) | 440 | struct writeback_control *wbc) |
| 441 | { | 441 | { |
| 442 | const unsigned long start = jiffies; /* livelock avoidance */ | 442 | const unsigned long start = jiffies; /* livelock avoidance */ |
| 443 | int sync = wbc->sync_mode == WB_SYNC_ALL; | ||
| 443 | 444 | ||
| 444 | spin_lock(&inode_lock); | 445 | spin_lock(&inode_lock); |
| 445 | if (!wbc->for_kupdate || list_empty(&sb->s_io)) | 446 | if (!wbc->for_kupdate || list_empty(&sb->s_io)) |
| @@ -516,7 +517,49 @@ void generic_sync_sb_inodes(struct super_block *sb, | |||
| 516 | if (!list_empty(&sb->s_more_io)) | 517 | if (!list_empty(&sb->s_more_io)) |
| 517 | wbc->more_io = 1; | 518 | wbc->more_io = 1; |
| 518 | } | 519 | } |
| 519 | spin_unlock(&inode_lock); | 520 | |
| 521 | if (sync) { | ||
| 522 | struct inode *inode, *old_inode = NULL; | ||
| 523 | |||
| 524 | /* | ||
| 525 | * Data integrity sync. Must wait for all pages under writeback, | ||
| 526 | * because there may have been pages dirtied before our sync | ||
| 527 | * call, but which had writeout started before we write it out. | ||
| 528 | * In which case, the inode may not be on the dirty list, but | ||
| 529 | * we still have to wait for that writeout. | ||
| 530 | */ | ||
| 531 | list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { | ||
| 532 | struct address_space *mapping; | ||
| 533 | |||
| 534 | if (inode->i_state & (I_FREEING|I_WILL_FREE)) | ||
| 535 | continue; | ||
| 536 | mapping = inode->i_mapping; | ||
| 537 | if (mapping->nrpages == 0) | ||
| 538 | continue; | ||
| 539 | __iget(inode); | ||
| 540 | spin_unlock(&inode_lock); | ||
| 541 | /* | ||
| 542 | * We hold a reference to 'inode' so it couldn't have | ||
| 543 | * been removed from s_inodes list while we dropped the | ||
| 544 | * inode_lock. We cannot iput the inode now as we can | ||
| 545 | * be holding the last reference and we cannot iput it | ||
| 546 | * under inode_lock. So we keep the reference and iput | ||
| 547 | * it later. | ||
| 548 | */ | ||
| 549 | iput(old_inode); | ||
| 550 | old_inode = inode; | ||
| 551 | |||
| 552 | filemap_fdatawait(mapping); | ||
| 553 | |||
| 554 | cond_resched(); | ||
| 555 | |||
| 556 | spin_lock(&inode_lock); | ||
| 557 | } | ||
| 558 | spin_unlock(&inode_lock); | ||
| 559 | iput(old_inode); | ||
| 560 | } else | ||
| 561 | spin_unlock(&inode_lock); | ||
| 562 | |||
| 520 | return; /* Leave any unwritten inodes on s_io */ | 563 | return; /* Leave any unwritten inodes on s_io */ |
| 521 | } | 564 | } |
| 522 | EXPORT_SYMBOL_GPL(generic_sync_sb_inodes); | 565 | EXPORT_SYMBOL_GPL(generic_sync_sb_inodes); |
| @@ -596,13 +639,16 @@ void sync_inodes_sb(struct super_block *sb, int wait) | |||
| 596 | .range_start = 0, | 639 | .range_start = 0, |
| 597 | .range_end = LLONG_MAX, | 640 | .range_end = LLONG_MAX, |
| 598 | }; | 641 | }; |
| 599 | unsigned long nr_dirty = global_page_state(NR_FILE_DIRTY); | ||
| 600 | unsigned long nr_unstable = global_page_state(NR_UNSTABLE_NFS); | ||
| 601 | 642 | ||
| 602 | wbc.nr_to_write = nr_dirty + nr_unstable + | 643 | if (!wait) { |
| 603 | (inodes_stat.nr_inodes - inodes_stat.nr_unused) + | 644 | unsigned long nr_dirty = global_page_state(NR_FILE_DIRTY); |
| 604 | nr_dirty + nr_unstable; | 645 | unsigned long nr_unstable = global_page_state(NR_UNSTABLE_NFS); |
| 605 | wbc.nr_to_write += wbc.nr_to_write / 2; /* Bit more for luck */ | 646 | |
| 647 | wbc.nr_to_write = nr_dirty + nr_unstable + | ||
| 648 | (inodes_stat.nr_inodes - inodes_stat.nr_unused); | ||
| 649 | } else | ||
| 650 | wbc.nr_to_write = LONG_MAX; /* doesn't actually matter */ | ||
| 651 | |||
| 606 | sync_sb_inodes(sb, &wbc); | 652 | sync_sb_inodes(sb, &wbc); |
| 607 | } | 653 | } |
| 608 | 654 | ||
