aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/extents.c
diff options
context:
space:
mode:
authorLukas Czerner <lczerner@redhat.com>2013-04-03 23:33:28 -0400
committerTheodore Ts'o <tytso@mit.edu>2013-04-03 23:33:28 -0400
commitbe8981be6b820b637c88978b2241738487a98ebf (patch)
tree642810f46ba5ce06e9d66d915fbf304556e251bc /fs/ext4/extents.c
parentbc2d9db48c95ec6c9c5ecc97ddc61343d751f219 (diff)
ext4: try to prepend extent to the existing one
Currently when inserting extent in ext4_ext_insert_extent() we would only try to to see if we can append new extent to the found extent. If we can not, then we proceed with adding new extent into the extent tree, but then possibly merging it back again. We can avoid this situation by trying to append and prepend new extent to the existing ones. However since the new extent can be on either sides of the existing extent, we have to pick the right extent to try to append/prepend to. This patch adds the conditions to pick the right extent to append/prepend to and adds the actual prepending condition as well. This will also eliminate the need to use "reserved" block for possibly growing extent tree. Signed-off-by: Lukas Czerner <lczerner@redhat.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/extents.c')
-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);