diff options
| -rw-r--r-- | fs/buffer.c | 13 | ||||
| -rw-r--r-- | fs/ext3/inode.c | 23 |
2 files changed, 30 insertions, 6 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index 6e35762b6169..13edf7ad3ff1 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
| @@ -1596,6 +1596,16 @@ EXPORT_SYMBOL(unmap_underlying_metadata); | |||
| 1596 | * locked buffer. This only can happen if someone has written the buffer | 1596 | * locked buffer. This only can happen if someone has written the buffer |
| 1597 | * directly, with submit_bh(). At the address_space level PageWriteback | 1597 | * directly, with submit_bh(). At the address_space level PageWriteback |
| 1598 | * prevents this contention from occurring. | 1598 | * prevents this contention from occurring. |
| 1599 | * | ||
| 1600 | * If block_write_full_page() is called with wbc->sync_mode == | ||
| 1601 | * WB_SYNC_ALL, the writes are posted using WRITE_SYNC_PLUG; this | ||
| 1602 | * causes the writes to be flagged as synchronous writes, but the | ||
| 1603 | * block device queue will NOT be unplugged, since usually many pages | ||
| 1604 | * will be pushed to the out before the higher-level caller actually | ||
| 1605 | * waits for the writes to be completed. The various wait functions, | ||
| 1606 | * such as wait_on_writeback_range() will ultimately call sync_page() | ||
| 1607 | * which will ultimately call blk_run_backing_dev(), which will end up | ||
| 1608 | * unplugging the device queue. | ||
| 1599 | */ | 1609 | */ |
| 1600 | static int __block_write_full_page(struct inode *inode, struct page *page, | 1610 | static int __block_write_full_page(struct inode *inode, struct page *page, |
| 1601 | get_block_t *get_block, struct writeback_control *wbc) | 1611 | get_block_t *get_block, struct writeback_control *wbc) |
| @@ -1606,7 +1616,8 @@ static int __block_write_full_page(struct inode *inode, struct page *page, | |||
| 1606 | struct buffer_head *bh, *head; | 1616 | struct buffer_head *bh, *head; |
| 1607 | const unsigned blocksize = 1 << inode->i_blkbits; | 1617 | const unsigned blocksize = 1 << inode->i_blkbits; |
| 1608 | int nr_underway = 0; | 1618 | int nr_underway = 0; |
| 1609 | int write_op = (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE); | 1619 | int write_op = (wbc->sync_mode == WB_SYNC_ALL ? |
| 1620 | WRITE_SYNC_PLUG : WRITE); | ||
| 1610 | 1621 | ||
| 1611 | BUG_ON(!PageLocked(page)); | 1622 | BUG_ON(!PageLocked(page)); |
| 1612 | 1623 | ||
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 466a332e0bd1..fcfa24361856 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
| @@ -1521,12 +1521,16 @@ static int ext3_ordered_writepage(struct page *page, | |||
| 1521 | if (!page_has_buffers(page)) { | 1521 | if (!page_has_buffers(page)) { |
| 1522 | create_empty_buffers(page, inode->i_sb->s_blocksize, | 1522 | create_empty_buffers(page, inode->i_sb->s_blocksize, |
| 1523 | (1 << BH_Dirty)|(1 << BH_Uptodate)); | 1523 | (1 << BH_Dirty)|(1 << BH_Uptodate)); |
| 1524 | } else if (!walk_page_buffers(NULL, page_buffers(page), 0, PAGE_CACHE_SIZE, NULL, buffer_unmapped)) { | 1524 | page_bufs = page_buffers(page); |
| 1525 | /* Provide NULL instead of get_block so that we catch bugs if buffers weren't really mapped */ | 1525 | } else { |
| 1526 | return block_write_full_page(page, NULL, wbc); | 1526 | page_bufs = page_buffers(page); |
| 1527 | if (!walk_page_buffers(NULL, page_bufs, 0, PAGE_CACHE_SIZE, | ||
| 1528 | NULL, buffer_unmapped)) { | ||
| 1529 | /* Provide NULL get_block() to catch bugs if buffers | ||
| 1530 | * weren't really mapped */ | ||
| 1531 | return block_write_full_page(page, NULL, wbc); | ||
| 1532 | } | ||
| 1527 | } | 1533 | } |
| 1528 | page_bufs = page_buffers(page); | ||
| 1529 | |||
| 1530 | handle = ext3_journal_start(inode, ext3_writepage_trans_blocks(inode)); | 1534 | handle = ext3_journal_start(inode, ext3_writepage_trans_blocks(inode)); |
| 1531 | 1535 | ||
| 1532 | if (IS_ERR(handle)) { | 1536 | if (IS_ERR(handle)) { |
| @@ -1581,6 +1585,15 @@ static int ext3_writeback_writepage(struct page *page, | |||
| 1581 | if (ext3_journal_current_handle()) | 1585 | if (ext3_journal_current_handle()) |
| 1582 | goto out_fail; | 1586 | goto out_fail; |
| 1583 | 1587 | ||
| 1588 | if (page_has_buffers(page)) { | ||
| 1589 | if (!walk_page_buffers(NULL, page_buffers(page), 0, | ||
| 1590 | PAGE_CACHE_SIZE, NULL, buffer_unmapped)) { | ||
| 1591 | /* Provide NULL get_block() to catch bugs if buffers | ||
| 1592 | * weren't really mapped */ | ||
| 1593 | return block_write_full_page(page, NULL, wbc); | ||
| 1594 | } | ||
| 1595 | } | ||
| 1596 | |||
| 1584 | handle = ext3_journal_start(inode, ext3_writepage_trans_blocks(inode)); | 1597 | handle = ext3_journal_start(inode, ext3_writepage_trans_blocks(inode)); |
| 1585 | if (IS_ERR(handle)) { | 1598 | if (IS_ERR(handle)) { |
| 1586 | ret = PTR_ERR(handle); | 1599 | ret = PTR_ERR(handle); |
