diff options
Diffstat (limited to 'fs/read_write.c')
-rw-r--r-- | fs/read_write.c | 49 |
1 files changed, 41 insertions, 8 deletions
diff --git a/fs/read_write.c b/fs/read_write.c index 1f5088dec566..5bbf587f5bc1 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
@@ -1811,10 +1811,7 @@ static int generic_remap_check_len(struct inode *inode_in, | |||
1811 | return (remap_flags & REMAP_FILE_DEDUP) ? -EBADE : -EINVAL; | 1811 | return (remap_flags & REMAP_FILE_DEDUP) ? -EBADE : -EINVAL; |
1812 | } | 1812 | } |
1813 | 1813 | ||
1814 | /* | 1814 | /* Read a page's worth of file data into the page cache. */ |
1815 | * Read a page's worth of file data into the page cache. Return the page | ||
1816 | * locked. | ||
1817 | */ | ||
1818 | static struct page *vfs_dedupe_get_page(struct inode *inode, loff_t offset) | 1815 | static struct page *vfs_dedupe_get_page(struct inode *inode, loff_t offset) |
1819 | { | 1816 | { |
1820 | struct page *page; | 1817 | struct page *page; |
@@ -1826,11 +1823,33 @@ static struct page *vfs_dedupe_get_page(struct inode *inode, loff_t offset) | |||
1826 | put_page(page); | 1823 | put_page(page); |
1827 | return ERR_PTR(-EIO); | 1824 | return ERR_PTR(-EIO); |
1828 | } | 1825 | } |
1829 | lock_page(page); | ||
1830 | return page; | 1826 | return page; |
1831 | } | 1827 | } |
1832 | 1828 | ||
1833 | /* | 1829 | /* |
1830 | * Lock two pages, ensuring that we lock in offset order if the pages are from | ||
1831 | * the same file. | ||
1832 | */ | ||
1833 | static void vfs_lock_two_pages(struct page *page1, struct page *page2) | ||
1834 | { | ||
1835 | /* Always lock in order of increasing index. */ | ||
1836 | if (page1->index > page2->index) | ||
1837 | swap(page1, page2); | ||
1838 | |||
1839 | lock_page(page1); | ||
1840 | if (page1 != page2) | ||
1841 | lock_page(page2); | ||
1842 | } | ||
1843 | |||
1844 | /* Unlock two pages, being careful not to unlock the same page twice. */ | ||
1845 | static void vfs_unlock_two_pages(struct page *page1, struct page *page2) | ||
1846 | { | ||
1847 | unlock_page(page1); | ||
1848 | if (page1 != page2) | ||
1849 | unlock_page(page2); | ||
1850 | } | ||
1851 | |||
1852 | /* | ||
1834 | * Compare extents of two files to see if they are the same. | 1853 | * Compare extents of two files to see if they are the same. |
1835 | * Caller must have locked both inodes to prevent write races. | 1854 | * Caller must have locked both inodes to prevent write races. |
1836 | */ | 1855 | */ |
@@ -1867,10 +1886,24 @@ static int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff, | |||
1867 | dest_page = vfs_dedupe_get_page(dest, destoff); | 1886 | dest_page = vfs_dedupe_get_page(dest, destoff); |
1868 | if (IS_ERR(dest_page)) { | 1887 | if (IS_ERR(dest_page)) { |
1869 | error = PTR_ERR(dest_page); | 1888 | error = PTR_ERR(dest_page); |
1870 | unlock_page(src_page); | ||
1871 | put_page(src_page); | 1889 | put_page(src_page); |
1872 | goto out_error; | 1890 | goto out_error; |
1873 | } | 1891 | } |
1892 | |||
1893 | vfs_lock_two_pages(src_page, dest_page); | ||
1894 | |||
1895 | /* | ||
1896 | * Now that we've locked both pages, make sure they're still | ||
1897 | * mapped to the file data we're interested in. If not, | ||
1898 | * someone is invalidating pages on us and we lose. | ||
1899 | */ | ||
1900 | if (!PageUptodate(src_page) || !PageUptodate(dest_page) || | ||
1901 | src_page->mapping != src->i_mapping || | ||
1902 | dest_page->mapping != dest->i_mapping) { | ||
1903 | same = false; | ||
1904 | goto unlock; | ||
1905 | } | ||
1906 | |||
1874 | src_addr = kmap_atomic(src_page); | 1907 | src_addr = kmap_atomic(src_page); |
1875 | dest_addr = kmap_atomic(dest_page); | 1908 | dest_addr = kmap_atomic(dest_page); |
1876 | 1909 | ||
@@ -1882,8 +1915,8 @@ static int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff, | |||
1882 | 1915 | ||
1883 | kunmap_atomic(dest_addr); | 1916 | kunmap_atomic(dest_addr); |
1884 | kunmap_atomic(src_addr); | 1917 | kunmap_atomic(src_addr); |
1885 | unlock_page(dest_page); | 1918 | unlock: |
1886 | unlock_page(src_page); | 1919 | vfs_unlock_two_pages(src_page, dest_page); |
1887 | put_page(dest_page); | 1920 | put_page(dest_page); |
1888 | put_page(src_page); | 1921 | put_page(src_page); |
1889 | 1922 | ||