aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/extents.c108
1 files changed, 85 insertions, 23 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 892662334be9..6c5a70a7b573 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -1813,39 +1813,101 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
1813 } 1813 }
1814 depth = ext_depth(inode); 1814 depth = ext_depth(inode);
1815 ex = path[depth].p_ext; 1815 ex = path[depth].p_ext;
1816 eh = path[depth].p_hdr;
1816 if (unlikely(path[depth].p_hdr == NULL)) { 1817 if (unlikely(path[depth].p_hdr == NULL)) {
1817 EXT4_ERROR_INODE(inode, "path[%d].p_hdr == NULL", depth); 1818 EXT4_ERROR_INODE(inode, "path[%d].p_hdr == NULL", depth);
1818 return -EIO; 1819 return -EIO;
1819 } 1820 }
1820 1821
1821 /* try to insert block into found extent and return */ 1822 /* try to insert block into found extent and return */
1822 if (ex && !(flag & EXT4_GET_BLOCKS_PRE_IO) 1823 if (ex && !(flag & EXT4_GET_BLOCKS_PRE_IO)) {
1823 && ext4_can_extents_be_merged(inode, ex, newext)) {
1824 ext_debug("append [%d]%d block to %u:[%d]%d (from %llu)\n",
1825 ext4_ext_is_uninitialized(newext),
1826 ext4_ext_get_actual_len(newext),
1827 le32_to_cpu(ex->ee_block),
1828 ext4_ext_is_uninitialized(ex),
1829 ext4_ext_get_actual_len(ex),
1830 ext4_ext_pblock(ex));
1831 err = ext4_ext_get_access(handle, inode, path + depth);
1832 if (err)
1833 return err;
1834 1824
1835 /* 1825 /*
1836 * ext4_can_extents_be_merged should have checked that either 1826 * Try to see whether we should rather test the extent on
1837 * both extents are uninitialized, or both aren't. Thus we 1827 * right from ex, or from the left of ex. This is because
1838 * need to check only one of them here. 1828 * ext4_ext_find_extent() can return either extent on the
1829 * left, or on the right from the searched position. This
1830 * will make merging more effective.
1839 */ 1831 */
1840 if (ext4_ext_is_uninitialized(ex)) 1832 if (ex < EXT_LAST_EXTENT(eh) &&
1841 uninitialized = 1; 1833 (le32_to_cpu(ex->ee_block) +
1842 ex->ee_len = cpu_to_le16(ext4_ext_get_actual_len(ex) 1834 ext4_ext_get_actual_len(ex) <
1835 le32_to_cpu(newext->ee_block))) {
1836 ex += 1;
1837 goto prepend;
1838 } else if ((ex > EXT_FIRST_EXTENT(eh)) &&
1839 (le32_to_cpu(newext->ee_block) +
1840 ext4_ext_get_actual_len(newext) <
1841 le32_to_cpu(ex->ee_block)))
1842 ex -= 1;
1843
1844 /* Try to append newex to the ex */
1845 if (ext4_can_extents_be_merged(inode, ex, newext)) {
1846 ext_debug("append [%d]%d block to %u:[%d]%d"
1847 "(from %llu)\n",
1848 ext4_ext_is_uninitialized(newext),
1849 ext4_ext_get_actual_len(newext),
1850 le32_to_cpu(ex->ee_block),
1851 ext4_ext_is_uninitialized(ex),
1852 ext4_ext_get_actual_len(ex),
1853 ext4_ext_pblock(ex));
1854 err = ext4_ext_get_access(handle, inode,
1855 path + depth);
1856 if (err)
1857 return err;
1858
1859 /*
1860 * ext4_can_extents_be_merged should have checked
1861 * that either both extents are uninitialized, or
1862 * both aren't. Thus we need to check only one of
1863 * them here.
1864 */
1865 if (ext4_ext_is_uninitialized(ex))
1866 uninitialized = 1;
1867 ex->ee_len = cpu_to_le16(ext4_ext_get_actual_len(ex)
1843 + ext4_ext_get_actual_len(newext)); 1868 + ext4_ext_get_actual_len(newext));
1844 if (uninitialized) 1869 if (uninitialized)
1845 ext4_ext_mark_uninitialized(ex); 1870 ext4_ext_mark_uninitialized(ex);
1846 eh = path[depth].p_hdr; 1871 eh = path[depth].p_hdr;
1847 nearex = ex; 1872 nearex = ex;
1848 goto merge; 1873 goto merge;
1874 }
1875
1876prepend:
1877 /* Try to prepend newex to the ex */
1878 if (ext4_can_extents_be_merged(inode, newext, ex)) {
1879 ext_debug("prepend %u[%d]%d block to %u:[%d]%d"
1880 "(from %llu)\n",
1881 le32_to_cpu(newext->ee_block),
1882 ext4_ext_is_uninitialized(newext),
1883 ext4_ext_get_actual_len(newext),
1884 le32_to_cpu(ex->ee_block),
1885 ext4_ext_is_uninitialized(ex),
1886 ext4_ext_get_actual_len(ex),
1887 ext4_ext_pblock(ex));
1888 err = ext4_ext_get_access(handle, inode,
1889 path + depth);
1890 if (err)
1891 return err;
1892
1893 /*
1894 * ext4_can_extents_be_merged should have checked
1895 * that either both extents are uninitialized, or
1896 * both aren't. Thus we need to check only one of
1897 * them here.
1898 */
1899 if (ext4_ext_is_uninitialized(ex))
1900 uninitialized = 1;
1901 ex->ee_block = newext->ee_block;
1902 ext4_ext_store_pblock(ex, ext4_ext_pblock(newext));
1903 ex->ee_len = cpu_to_le16(ext4_ext_get_actual_len(ex)
1904 + ext4_ext_get_actual_len(newext));
1905 if (uninitialized)
1906 ext4_ext_mark_uninitialized(ex);
1907 eh = path[depth].p_hdr;
1908 nearex = ex;
1909 goto merge;
1910 }
1849 } 1911 }
1850 1912
1851 depth = ext_depth(inode); 1913 depth = ext_depth(inode);