diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-14 20:09:00 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-14 20:09:00 -0500 |
| commit | 80eabba70260dcb55b05098f6c1fecbe5c0e518b (patch) | |
| tree | c9f5d19803a3387d2b9d8a6998eb9c58bad2a15a | |
| parent | 852d21ae1fcdf0e4de6b5bfa730d29cb013c7ff3 (diff) | |
| parent | ce98321bf7d274a470642ef99e1d82512673ce7c (diff) | |
Merge branch 'for-4.10/fs-unmap' of git://git.kernel.dk/linux-block
Pull fs meta data unmap optimization from Jens Axboe:
"A series from Jan Kara, providing a more efficient way for unmapping
meta data from in the buffer cache than doing it block-by-block.
Provide a general helper that existing callers can use"
* 'for-4.10/fs-unmap' of git://git.kernel.dk/linux-block:
fs: Remove unmap_underlying_metadata
fs: Add helper to clean bdev aliases under a bh and use it
ext2: Use clean_bdev_aliases() instead of iteration
ext4: Use clean_bdev_aliases() instead of iteration
direct-io: Use clean_bdev_aliases() instead of handmade iteration
fs: Provide function to unmap metadata for a range of blocks
| -rw-r--r-- | fs/buffer.c | 104 | ||||
| -rw-r--r-- | fs/direct-io.c | 28 | ||||
| -rw-r--r-- | fs/ext2/inode.c | 9 | ||||
| -rw-r--r-- | fs/ext4/extents.c | 13 | ||||
| -rw-r--r-- | fs/ext4/inode.c | 18 | ||||
| -rw-r--r-- | fs/ext4/page-io.c | 2 | ||||
| -rw-r--r-- | fs/mpage.c | 3 | ||||
| -rw-r--r-- | fs/ntfs/aops.c | 2 | ||||
| -rw-r--r-- | fs/ntfs/file.c | 5 | ||||
| -rw-r--r-- | fs/ocfs2/aops.c | 2 | ||||
| -rw-r--r-- | fs/ufs/balloc.c | 3 | ||||
| -rw-r--r-- | fs/ufs/inode.c | 3 | ||||
| -rw-r--r-- | include/linux/buffer_head.h | 7 |
13 files changed, 104 insertions, 95 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index a3bfd57c2697..d21771fcf7d3 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
| @@ -43,6 +43,7 @@ | |||
| 43 | #include <linux/bitops.h> | 43 | #include <linux/bitops.h> |
| 44 | #include <linux/mpage.h> | 44 | #include <linux/mpage.h> |
| 45 | #include <linux/bit_spinlock.h> | 45 | #include <linux/bit_spinlock.h> |
| 46 | #include <linux/pagevec.h> | ||
| 46 | #include <trace/events/block.h> | 47 | #include <trace/events/block.h> |
| 47 | 48 | ||
| 48 | static int fsync_buffers_list(spinlock_t *lock, struct list_head *list); | 49 | static int fsync_buffers_list(spinlock_t *lock, struct list_head *list); |
| @@ -1604,37 +1605,80 @@ void create_empty_buffers(struct page *page, | |||
| 1604 | } | 1605 | } |
| 1605 | EXPORT_SYMBOL(create_empty_buffers); | 1606 | EXPORT_SYMBOL(create_empty_buffers); |
| 1606 | 1607 | ||
| 1607 | /* | 1608 | /** |
| 1608 | * We are taking a block for data and we don't want any output from any | 1609 | * clean_bdev_aliases: clean a range of buffers in block device |
| 1609 | * buffer-cache aliases starting from return from that function and | 1610 | * @bdev: Block device to clean buffers in |
| 1610 | * until the moment when something will explicitly mark the buffer | 1611 | * @block: Start of a range of blocks to clean |
| 1611 | * dirty (hopefully that will not happen until we will free that block ;-) | 1612 | * @len: Number of blocks to clean |
| 1612 | * We don't even need to mark it not-uptodate - nobody can expect | 1613 | * |
| 1613 | * anything from a newly allocated buffer anyway. We used to used | 1614 | * We are taking a range of blocks for data and we don't want writeback of any |
| 1614 | * unmap_buffer() for such invalidation, but that was wrong. We definitely | 1615 | * buffer-cache aliases starting from return from this function and until the |
| 1615 | * don't want to mark the alias unmapped, for example - it would confuse | 1616 | * moment when something will explicitly mark the buffer dirty (hopefully that |
| 1616 | * anyone who might pick it with bread() afterwards... | 1617 | * will not happen until we will free that block ;-) We don't even need to mark |
| 1617 | * | 1618 | * it not-uptodate - nobody can expect anything from a newly allocated buffer |
| 1618 | * Also.. Note that bforget() doesn't lock the buffer. So there can | 1619 | * anyway. We used to use unmap_buffer() for such invalidation, but that was |
| 1619 | * be writeout I/O going on against recently-freed buffers. We don't | 1620 | * wrong. We definitely don't want to mark the alias unmapped, for example - it |
| 1620 | * wait on that I/O in bforget() - it's more efficient to wait on the I/O | 1621 | * would confuse anyone who might pick it with bread() afterwards... |
| 1621 | * only if we really need to. That happens here. | 1622 | * |
| 1622 | */ | 1623 | * Also.. Note that bforget() doesn't lock the buffer. So there can be |
| 1623 | void unmap_underlying_metadata(struct block_device *bdev, sector_t block) | 1624 | * writeout I/O going on against recently-freed buffers. We don't wait on that |
| 1625 | * I/O in bforget() - it's more efficient to wait on the I/O only if we really | ||
| 1626 | * need to. That happens here. | ||
| 1627 | */ | ||
| 1628 | void clean_bdev_aliases(struct block_device *bdev, sector_t block, sector_t len) | ||
| 1624 | { | 1629 | { |
| 1625 | struct buffer_head *old_bh; | 1630 | struct inode *bd_inode = bdev->bd_inode; |
| 1631 | struct address_space *bd_mapping = bd_inode->i_mapping; | ||
| 1632 | struct pagevec pvec; | ||
| 1633 | pgoff_t index = block >> (PAGE_SHIFT - bd_inode->i_blkbits); | ||
| 1634 | pgoff_t end; | ||
| 1635 | int i; | ||
| 1636 | struct buffer_head *bh; | ||
| 1637 | struct buffer_head *head; | ||
| 1626 | 1638 | ||
| 1627 | might_sleep(); | 1639 | end = (block + len - 1) >> (PAGE_SHIFT - bd_inode->i_blkbits); |
| 1640 | pagevec_init(&pvec, 0); | ||
| 1641 | while (index <= end && pagevec_lookup(&pvec, bd_mapping, index, | ||
| 1642 | min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) { | ||
| 1643 | for (i = 0; i < pagevec_count(&pvec); i++) { | ||
| 1644 | struct page *page = pvec.pages[i]; | ||
| 1628 | 1645 | ||
| 1629 | old_bh = __find_get_block_slow(bdev, block); | 1646 | index = page->index; |
| 1630 | if (old_bh) { | 1647 | if (index > end) |
| 1631 | clear_buffer_dirty(old_bh); | 1648 | break; |
| 1632 | wait_on_buffer(old_bh); | 1649 | if (!page_has_buffers(page)) |
| 1633 | clear_buffer_req(old_bh); | 1650 | continue; |
| 1634 | __brelse(old_bh); | 1651 | /* |
| 1652 | * We use page lock instead of bd_mapping->private_lock | ||
| 1653 | * to pin buffers here since we can afford to sleep and | ||
| 1654 | * it scales better than a global spinlock lock. | ||
| 1655 | */ | ||
| 1656 | lock_page(page); | ||
| 1657 | /* Recheck when the page is locked which pins bhs */ | ||
| 1658 | if (!page_has_buffers(page)) | ||
| 1659 | goto unlock_page; | ||
| 1660 | head = page_buffers(page); | ||
| 1661 | bh = head; | ||
| 1662 | do { | ||
| 1663 | if (!buffer_mapped(bh)) | ||
| 1664 | goto next; | ||
| 1665 | if (bh->b_blocknr >= block + len) | ||
| 1666 | break; | ||
| 1667 | clear_buffer_dirty(bh); | ||
| 1668 | wait_on_buffer(bh); | ||
| 1669 | clear_buffer_req(bh); | ||
| 1670 | next: | ||
| 1671 | bh = bh->b_this_page; | ||
| 1672 | } while (bh != head); | ||
| 1673 | unlock_page: | ||
| 1674 | unlock_page(page); | ||
| 1675 | } | ||
| 1676 | pagevec_release(&pvec); | ||
| 1677 | cond_resched(); | ||
| 1678 | index++; | ||
| 1635 | } | 1679 | } |
| 1636 | } | 1680 | } |
| 1637 | EXPORT_SYMBOL(unmap_underlying_metadata); | 1681 | EXPORT_SYMBOL(clean_bdev_aliases); |
| 1638 | 1682 | ||
| 1639 | /* | 1683 | /* |
| 1640 | * Size is a power-of-two in the range 512..PAGE_SIZE, | 1684 | * Size is a power-of-two in the range 512..PAGE_SIZE, |
| @@ -1745,8 +1789,7 @@ int __block_write_full_page(struct inode *inode, struct page *page, | |||
| 1745 | if (buffer_new(bh)) { | 1789 | if (buffer_new(bh)) { |
| 1746 | /* blockdev mappings never come here */ | 1790 | /* blockdev mappings never come here */ |
| 1747 | clear_buffer_new(bh); | 1791 | clear_buffer_new(bh); |
| 1748 | unmap_underlying_metadata(bh->b_bdev, | 1792 | clean_bdev_bh_alias(bh); |
| 1749 | bh->b_blocknr); | ||
| 1750 | } | 1793 | } |
| 1751 | } | 1794 | } |
| 1752 | bh = bh->b_this_page; | 1795 | bh = bh->b_this_page; |
| @@ -1992,8 +2035,7 @@ int __block_write_begin_int(struct page *page, loff_t pos, unsigned len, | |||
| 1992 | } | 2035 | } |
| 1993 | 2036 | ||
| 1994 | if (buffer_new(bh)) { | 2037 | if (buffer_new(bh)) { |
| 1995 | unmap_underlying_metadata(bh->b_bdev, | 2038 | clean_bdev_bh_alias(bh); |
| 1996 | bh->b_blocknr); | ||
| 1997 | if (PageUptodate(page)) { | 2039 | if (PageUptodate(page)) { |
| 1998 | clear_buffer_new(bh); | 2040 | clear_buffer_new(bh); |
| 1999 | set_buffer_uptodate(bh); | 2041 | set_buffer_uptodate(bh); |
| @@ -2633,7 +2675,7 @@ int nobh_write_begin(struct address_space *mapping, | |||
| 2633 | if (!buffer_mapped(bh)) | 2675 | if (!buffer_mapped(bh)) |
| 2634 | is_mapped_to_disk = 0; | 2676 | is_mapped_to_disk = 0; |
| 2635 | if (buffer_new(bh)) | 2677 | if (buffer_new(bh)) |
| 2636 | unmap_underlying_metadata(bh->b_bdev, bh->b_blocknr); | 2678 | clean_bdev_bh_alias(bh); |
| 2637 | if (PageUptodate(page)) { | 2679 | if (PageUptodate(page)) { |
| 2638 | set_buffer_uptodate(bh); | 2680 | set_buffer_uptodate(bh); |
| 2639 | continue; | 2681 | continue; |
diff --git a/fs/direct-io.c b/fs/direct-io.c index 835e23a4ee4b..86aa79859d4d 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c | |||
| @@ -843,24 +843,6 @@ out: | |||
| 843 | } | 843 | } |
| 844 | 844 | ||
| 845 | /* | 845 | /* |
| 846 | * Clean any dirty buffers in the blockdev mapping which alias newly-created | ||
| 847 | * file blocks. Only called for S_ISREG files - blockdevs do not set | ||
| 848 | * buffer_new | ||
| 849 | */ | ||
| 850 | static void clean_blockdev_aliases(struct dio *dio, struct buffer_head *map_bh) | ||
| 851 | { | ||
| 852 | unsigned i; | ||
| 853 | unsigned nblocks; | ||
| 854 | |||
| 855 | nblocks = map_bh->b_size >> dio->inode->i_blkbits; | ||
| 856 | |||
| 857 | for (i = 0; i < nblocks; i++) { | ||
| 858 | unmap_underlying_metadata(map_bh->b_bdev, | ||
| 859 | map_bh->b_blocknr + i); | ||
| 860 | } | ||
| 861 | } | ||
| 862 | |||
| 863 | /* | ||
| 864 | * If we are not writing the entire block and get_block() allocated | 846 | * If we are not writing the entire block and get_block() allocated |
| 865 | * the block for us, we need to fill-in the unused portion of the | 847 | * the block for us, we need to fill-in the unused portion of the |
| 866 | * block with zeros. This happens only if user-buffer, fileoffset or | 848 | * block with zeros. This happens only if user-buffer, fileoffset or |
| @@ -960,11 +942,15 @@ static int do_direct_IO(struct dio *dio, struct dio_submit *sdio, | |||
| 960 | goto do_holes; | 942 | goto do_holes; |
| 961 | 943 | ||
| 962 | sdio->blocks_available = | 944 | sdio->blocks_available = |
| 963 | map_bh->b_size >> sdio->blkbits; | 945 | map_bh->b_size >> blkbits; |
| 964 | sdio->next_block_for_io = | 946 | sdio->next_block_for_io = |
| 965 | map_bh->b_blocknr << sdio->blkfactor; | 947 | map_bh->b_blocknr << sdio->blkfactor; |
| 966 | if (buffer_new(map_bh)) | 948 | if (buffer_new(map_bh)) { |
| 967 | clean_blockdev_aliases(dio, map_bh); | 949 | clean_bdev_aliases( |
| 950 | map_bh->b_bdev, | ||
| 951 | map_bh->b_blocknr, | ||
| 952 | map_bh->b_size >> blkbits); | ||
| 953 | } | ||
| 968 | 954 | ||
| 969 | if (!sdio->blkfactor) | 955 | if (!sdio->blkfactor) |
| 970 | goto do_holes; | 956 | goto do_holes; |
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 046b642f3585..e173afe92661 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c | |||
| @@ -732,16 +732,13 @@ static int ext2_get_blocks(struct inode *inode, | |||
| 732 | } | 732 | } |
| 733 | 733 | ||
| 734 | if (IS_DAX(inode)) { | 734 | if (IS_DAX(inode)) { |
| 735 | int i; | ||
| 736 | |||
| 737 | /* | 735 | /* |
| 738 | * We must unmap blocks before zeroing so that writeback cannot | 736 | * We must unmap blocks before zeroing so that writeback cannot |
| 739 | * overwrite zeros with stale data from block device page cache. | 737 | * overwrite zeros with stale data from block device page cache. |
| 740 | */ | 738 | */ |
| 741 | for (i = 0; i < count; i++) { | 739 | clean_bdev_aliases(inode->i_sb->s_bdev, |
| 742 | unmap_underlying_metadata(inode->i_sb->s_bdev, | 740 | le32_to_cpu(chain[depth-1].key), |
| 743 | le32_to_cpu(chain[depth-1].key) + i); | 741 | count); |
| 744 | } | ||
| 745 | /* | 742 | /* |
| 746 | * block must be initialised before we put it in the tree | 743 | * block must be initialised before we put it in the tree |
| 747 | * so that it's not found by another thread before it's | 744 | * so that it's not found by another thread before it's |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 3e1014fe835e..b1f8416923ab 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
| @@ -3777,14 +3777,6 @@ out: | |||
| 3777 | return err; | 3777 | return err; |
| 3778 | } | 3778 | } |
| 3779 | 3779 | ||
| 3780 | static void unmap_underlying_metadata_blocks(struct block_device *bdev, | ||
| 3781 | sector_t block, int count) | ||
| 3782 | { | ||
| 3783 | int i; | ||
| 3784 | for (i = 0; i < count; i++) | ||
| 3785 | unmap_underlying_metadata(bdev, block + i); | ||
| 3786 | } | ||
| 3787 | |||
| 3788 | /* | 3780 | /* |
| 3789 | * Handle EOFBLOCKS_FL flag, clearing it if necessary | 3781 | * Handle EOFBLOCKS_FL flag, clearing it if necessary |
| 3790 | */ | 3782 | */ |
| @@ -4121,9 +4113,8 @@ out: | |||
| 4121 | * new. | 4113 | * new. |
| 4122 | */ | 4114 | */ |
| 4123 | if (allocated > map->m_len) { | 4115 | if (allocated > map->m_len) { |
| 4124 | unmap_underlying_metadata_blocks(inode->i_sb->s_bdev, | 4116 | clean_bdev_aliases(inode->i_sb->s_bdev, newblock + map->m_len, |
| 4125 | newblock + map->m_len, | 4117 | allocated - map->m_len); |
| 4126 | allocated - map->m_len); | ||
| 4127 | allocated = map->m_len; | 4118 | allocated = map->m_len; |
| 4128 | } | 4119 | } |
| 4129 | map->m_len = allocated; | 4120 | map->m_len = allocated; |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 72d593fa690d..88d57af1b516 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
| @@ -661,12 +661,8 @@ found: | |||
| 661 | if (flags & EXT4_GET_BLOCKS_ZERO && | 661 | if (flags & EXT4_GET_BLOCKS_ZERO && |
| 662 | map->m_flags & EXT4_MAP_MAPPED && | 662 | map->m_flags & EXT4_MAP_MAPPED && |
| 663 | map->m_flags & EXT4_MAP_NEW) { | 663 | map->m_flags & EXT4_MAP_NEW) { |
| 664 | ext4_lblk_t i; | 664 | clean_bdev_aliases(inode->i_sb->s_bdev, map->m_pblk, |
| 665 | 665 | map->m_len); | |
| 666 | for (i = 0; i < map->m_len; i++) { | ||
| 667 | unmap_underlying_metadata(inode->i_sb->s_bdev, | ||
| 668 | map->m_pblk + i); | ||
| 669 | } | ||
| 670 | ret = ext4_issue_zeroout(inode, map->m_lblk, | 666 | ret = ext4_issue_zeroout(inode, map->m_lblk, |
| 671 | map->m_pblk, map->m_len); | 667 | map->m_pblk, map->m_len); |
| 672 | if (ret) { | 668 | if (ret) { |
| @@ -1137,8 +1133,7 @@ static int ext4_block_write_begin(struct page *page, loff_t pos, unsigned len, | |||
| 1137 | if (err) | 1133 | if (err) |
| 1138 | break; | 1134 | break; |
| 1139 | if (buffer_new(bh)) { | 1135 | if (buffer_new(bh)) { |
| 1140 | unmap_underlying_metadata(bh->b_bdev, | 1136 | clean_bdev_bh_alias(bh); |
| 1141 | bh->b_blocknr); | ||
| 1142 | if (PageUptodate(page)) { | 1137 | if (PageUptodate(page)) { |
| 1143 | clear_buffer_new(bh); | 1138 | clear_buffer_new(bh); |
| 1144 | set_buffer_uptodate(bh); | 1139 | set_buffer_uptodate(bh); |
| @@ -2371,11 +2366,8 @@ static int mpage_map_one_extent(handle_t *handle, struct mpage_da_data *mpd) | |||
| 2371 | 2366 | ||
| 2372 | BUG_ON(map->m_len == 0); | 2367 | BUG_ON(map->m_len == 0); |
| 2373 | if (map->m_flags & EXT4_MAP_NEW) { | 2368 | if (map->m_flags & EXT4_MAP_NEW) { |
| 2374 | struct block_device *bdev = inode->i_sb->s_bdev; | 2369 | clean_bdev_aliases(inode->i_sb->s_bdev, map->m_pblk, |
| 2375 | int i; | 2370 | map->m_len); |
| 2376 | |||
| 2377 | for (i = 0; i < map->m_len; i++) | ||
| 2378 | unmap_underlying_metadata(bdev, map->m_pblk + i); | ||
| 2379 | } | 2371 | } |
| 2380 | return 0; | 2372 | return 0; |
| 2381 | } | 2373 | } |
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index e2332a65e8fb..d83b0f3c5fe9 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c | |||
| @@ -457,7 +457,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io, | |||
| 457 | } | 457 | } |
| 458 | if (buffer_new(bh)) { | 458 | if (buffer_new(bh)) { |
| 459 | clear_buffer_new(bh); | 459 | clear_buffer_new(bh); |
| 460 | unmap_underlying_metadata(bh->b_bdev, bh->b_blocknr); | 460 | clean_bdev_bh_alias(bh); |
| 461 | } | 461 | } |
| 462 | set_buffer_async_write(bh); | 462 | set_buffer_async_write(bh); |
| 463 | nr_to_submit++; | 463 | nr_to_submit++; |
diff --git a/fs/mpage.c b/fs/mpage.c index 98fc11aa7e0b..28af984a3d96 100644 --- a/fs/mpage.c +++ b/fs/mpage.c | |||
| @@ -555,8 +555,7 @@ static int __mpage_writepage(struct page *page, struct writeback_control *wbc, | |||
| 555 | if (mpd->get_block(inode, block_in_file, &map_bh, 1)) | 555 | if (mpd->get_block(inode, block_in_file, &map_bh, 1)) |
| 556 | goto confused; | 556 | goto confused; |
| 557 | if (buffer_new(&map_bh)) | 557 | if (buffer_new(&map_bh)) |
| 558 | unmap_underlying_metadata(map_bh.b_bdev, | 558 | clean_bdev_bh_alias(&map_bh); |
| 559 | map_bh.b_blocknr); | ||
| 560 | if (buffer_boundary(&map_bh)) { | 559 | if (buffer_boundary(&map_bh)) { |
| 561 | boundary_block = map_bh.b_blocknr; | 560 | boundary_block = map_bh.b_blocknr; |
| 562 | boundary_bdev = map_bh.b_bdev; | 561 | boundary_bdev = map_bh.b_bdev; |
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c index d0cf6fee5c77..cc91856b5e2d 100644 --- a/fs/ntfs/aops.c +++ b/fs/ntfs/aops.c | |||
| @@ -765,7 +765,7 @@ lock_retry_remap: | |||
| 765 | } | 765 | } |
| 766 | // TODO: Instantiate the hole. | 766 | // TODO: Instantiate the hole. |
| 767 | // clear_buffer_new(bh); | 767 | // clear_buffer_new(bh); |
| 768 | // unmap_underlying_metadata(bh->b_bdev, bh->b_blocknr); | 768 | // clean_bdev_bh_alias(bh); |
| 769 | ntfs_error(vol->sb, "Writing into sparse regions is " | 769 | ntfs_error(vol->sb, "Writing into sparse regions is " |
| 770 | "not supported yet. Sorry."); | 770 | "not supported yet. Sorry."); |
| 771 | err = -EOPNOTSUPP; | 771 | err = -EOPNOTSUPP; |
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index bf72a2c58b75..99510d811a8c 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c | |||
| @@ -740,8 +740,7 @@ map_buffer_cached: | |||
| 740 | set_buffer_uptodate(bh); | 740 | set_buffer_uptodate(bh); |
| 741 | if (unlikely(was_hole)) { | 741 | if (unlikely(was_hole)) { |
| 742 | /* We allocated the buffer. */ | 742 | /* We allocated the buffer. */ |
| 743 | unmap_underlying_metadata(bh->b_bdev, | 743 | clean_bdev_bh_alias(bh); |
| 744 | bh->b_blocknr); | ||
| 745 | if (bh_end <= pos || bh_pos >= end) | 744 | if (bh_end <= pos || bh_pos >= end) |
| 746 | mark_buffer_dirty(bh); | 745 | mark_buffer_dirty(bh); |
| 747 | else | 746 | else |
| @@ -784,7 +783,7 @@ map_buffer_cached: | |||
| 784 | continue; | 783 | continue; |
| 785 | } | 784 | } |
| 786 | /* We allocated the buffer. */ | 785 | /* We allocated the buffer. */ |
| 787 | unmap_underlying_metadata(bh->b_bdev, bh->b_blocknr); | 786 | clean_bdev_bh_alias(bh); |
| 788 | /* | 787 | /* |
| 789 | * If the buffer is fully outside the write, zero it, | 788 | * If the buffer is fully outside the write, zero it, |
| 790 | * set it uptodate, and mark it dirty so it gets | 789 | * set it uptodate, and mark it dirty so it gets |
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 9a88984f9f6f..4d9c6f5ec28a 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
| @@ -630,7 +630,7 @@ int ocfs2_map_page_blocks(struct page *page, u64 *p_blkno, | |||
| 630 | 630 | ||
| 631 | if (!buffer_mapped(bh)) { | 631 | if (!buffer_mapped(bh)) { |
| 632 | map_bh(bh, inode->i_sb, *p_blkno); | 632 | map_bh(bh, inode->i_sb, *p_blkno); |
| 633 | unmap_underlying_metadata(bh->b_bdev, bh->b_blocknr); | 633 | clean_bdev_bh_alias(bh); |
| 634 | } | 634 | } |
| 635 | 635 | ||
| 636 | if (PageUptodate(page)) { | 636 | if (PageUptodate(page)) { |
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index b035af54f538..a0376a2c1c29 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c | |||
| @@ -307,8 +307,7 @@ static void ufs_change_blocknr(struct inode *inode, sector_t beg, | |||
| 307 | (unsigned long long)(pos + newb), pos); | 307 | (unsigned long long)(pos + newb), pos); |
| 308 | 308 | ||
| 309 | bh->b_blocknr = newb + pos; | 309 | bh->b_blocknr = newb + pos; |
| 310 | unmap_underlying_metadata(bh->b_bdev, | 310 | clean_bdev_bh_alias(bh); |
| 311 | bh->b_blocknr); | ||
| 312 | mark_buffer_dirty(bh); | 311 | mark_buffer_dirty(bh); |
| 313 | ++j; | 312 | ++j; |
| 314 | bh = bh->b_this_page; | 313 | bh = bh->b_this_page; |
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 190d64be22ed..45ceb94e89e4 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c | |||
| @@ -1070,8 +1070,7 @@ static int ufs_alloc_lastblock(struct inode *inode, loff_t size) | |||
| 1070 | 1070 | ||
| 1071 | if (buffer_new(bh)) { | 1071 | if (buffer_new(bh)) { |
| 1072 | clear_buffer_new(bh); | 1072 | clear_buffer_new(bh); |
| 1073 | unmap_underlying_metadata(bh->b_bdev, | 1073 | clean_bdev_bh_alias(bh); |
| 1074 | bh->b_blocknr); | ||
| 1075 | /* | 1074 | /* |
| 1076 | * we do not zeroize fragment, because of | 1075 | * we do not zeroize fragment, because of |
| 1077 | * if it maped to hole, it already contains zeroes | 1076 | * if it maped to hole, it already contains zeroes |
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index ebbacd14d450..d67ab83823ad 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h | |||
| @@ -168,7 +168,12 @@ int inode_has_buffers(struct inode *); | |||
| 168 | void invalidate_inode_buffers(struct inode *); | 168 | void invalidate_inode_buffers(struct inode *); |
| 169 | int remove_inode_buffers(struct inode *inode); | 169 | int remove_inode_buffers(struct inode *inode); |
| 170 | int sync_mapping_buffers(struct address_space *mapping); | 170 | int sync_mapping_buffers(struct address_space *mapping); |
| 171 | void unmap_underlying_metadata(struct block_device *bdev, sector_t block); | 171 | void clean_bdev_aliases(struct block_device *bdev, sector_t block, |
| 172 | sector_t len); | ||
| 173 | static inline void clean_bdev_bh_alias(struct buffer_head *bh) | ||
| 174 | { | ||
| 175 | clean_bdev_aliases(bh->b_bdev, bh->b_blocknr, 1); | ||
| 176 | } | ||
| 172 | 177 | ||
| 173 | void mark_buffer_async_write(struct buffer_head *bh); | 178 | void mark_buffer_async_write(struct buffer_head *bh); |
| 174 | void __wait_on_buffer(struct buffer_head *); | 179 | void __wait_on_buffer(struct buffer_head *); |
