aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_btree.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2008-10-30 01:56:53 -0400
committerLachlan McIlroy <lachlan@sgi.com>2008-10-30 01:56:53 -0400
commit687b890a184fef263ebb773926e1f4aa69240d01 (patch)
treeb8f80c134ff994927225367d148ee63f4d76506b /fs/xfs/xfs_btree.c
parent9eaead51bed957af0070a277d945744a76df0c8b (diff)
[XFS] implement generic xfs_btree_lshift
Make the btree left shift code generic. Based on a patch from David Chinner with lots of changes to follow the original btree implementations more closely. While this loses some of the generic helper routines for inserting/moving/removing records it also solves some of the one off bugs in the original code and makes it easier to verify. SGI-PV: 985583 SGI-Modid: xfs-linux-melb:xfs-kern:32197a Signed-off-by: Christoph Hellwig <hch@infradead.org> Signed-off-by: Lachlan McIlroy <lachlan@sgi.com> Signed-off-by: Bill O'Donnell <billodo@sgi.com> Signed-off-by: David Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs/xfs_btree.c')
-rw-r--r--fs/xfs/xfs_btree.c185
1 files changed, 185 insertions, 0 deletions
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c
index e1a213781849..2b0d1422c4c6 100644
--- a/fs/xfs/xfs_btree.c
+++ b/fs/xfs/xfs_btree.c
@@ -1841,6 +1841,191 @@ error0:
1841} 1841}
1842 1842
1843/* 1843/*
1844 * Move 1 record left from cur/level if possible.
1845 * Update cur to reflect the new path.
1846 */
1847int /* error */
1848xfs_btree_lshift(
1849 struct xfs_btree_cur *cur,
1850 int level,
1851 int *stat) /* success/failure */
1852{
1853 union xfs_btree_key key; /* btree key */
1854 struct xfs_buf *lbp; /* left buffer pointer */
1855 struct xfs_btree_block *left; /* left btree block */
1856 int lrecs; /* left record count */
1857 struct xfs_buf *rbp; /* right buffer pointer */
1858 struct xfs_btree_block *right; /* right btree block */
1859 int rrecs; /* right record count */
1860 union xfs_btree_ptr lptr; /* left btree pointer */
1861 union xfs_btree_key *rkp = NULL; /* right btree key */
1862 union xfs_btree_ptr *rpp = NULL; /* right address pointer */
1863 union xfs_btree_rec *rrp = NULL; /* right record pointer */
1864 int error; /* error return value */
1865
1866 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
1867 XFS_BTREE_TRACE_ARGI(cur, level);
1868
1869 if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) &&
1870 level == cur->bc_nlevels - 1)
1871 goto out0;
1872
1873 /* Set up variables for this block as "right". */
1874 right = xfs_btree_get_block(cur, level, &rbp);
1875
1876#ifdef DEBUG
1877 error = xfs_btree_check_block(cur, right, level, rbp);
1878 if (error)
1879 goto error0;
1880#endif
1881
1882 /* If we've got no left sibling then we can't shift an entry left. */
1883 xfs_btree_get_sibling(cur, right, &lptr, XFS_BB_LEFTSIB);
1884 if (xfs_btree_ptr_is_null(cur, &lptr))
1885 goto out0;
1886
1887 /*
1888 * If the cursor entry is the one that would be moved, don't
1889 * do it... it's too complicated.
1890 */
1891 if (cur->bc_ptrs[level] <= 1)
1892 goto out0;
1893
1894 /* Set up the left neighbor as "left". */
1895 error = xfs_btree_read_buf_block(cur, &lptr, level, 0, &left, &lbp);
1896 if (error)
1897 goto error0;
1898
1899 /* If it's full, it can't take another entry. */
1900 lrecs = xfs_btree_get_numrecs(left);
1901 if (lrecs == cur->bc_ops->get_maxrecs(cur, level))
1902 goto out0;
1903
1904 rrecs = xfs_btree_get_numrecs(right);
1905
1906 /*
1907 * We add one entry to the left side and remove one for the right side.
1908 * Accout for it here, the changes will be updated on disk and logged
1909 * later.
1910 */
1911 lrecs++;
1912 rrecs--;
1913
1914 XFS_BTREE_STATS_INC(cur, lshift);
1915 XFS_BTREE_STATS_ADD(cur, moves, 1);
1916
1917 /*
1918 * If non-leaf, copy a key and a ptr to the left block.
1919 * Log the changes to the left block.
1920 */
1921 if (level > 0) {
1922 /* It's a non-leaf. Move keys and pointers. */
1923 union xfs_btree_key *lkp; /* left btree key */
1924 union xfs_btree_ptr *lpp; /* left address pointer */
1925
1926 lkp = xfs_btree_key_addr(cur, lrecs, left);
1927 rkp = xfs_btree_key_addr(cur, 1, right);
1928
1929 lpp = xfs_btree_ptr_addr(cur, lrecs, left);
1930 rpp = xfs_btree_ptr_addr(cur, 1, right);
1931#ifdef DEBUG
1932 error = xfs_btree_check_ptr(cur, rpp, 0, level);
1933 if (error)
1934 goto error0;
1935#endif
1936 xfs_btree_copy_keys(cur, lkp, rkp, 1);
1937 xfs_btree_copy_ptrs(cur, lpp, rpp, 1);
1938
1939 xfs_btree_log_keys(cur, lbp, lrecs, lrecs);
1940 xfs_btree_log_ptrs(cur, lbp, lrecs, lrecs);
1941
1942 xfs_btree_check_key(cur->bc_btnum,
1943 xfs_btree_key_addr(cur, lrecs - 1, left),
1944 lkp);
1945 } else {
1946 /* It's a leaf. Move records. */
1947 union xfs_btree_rec *lrp; /* left record pointer */
1948
1949 lrp = xfs_btree_rec_addr(cur, lrecs, left);
1950 rrp = xfs_btree_rec_addr(cur, 1, right);
1951
1952 xfs_btree_copy_recs(cur, lrp, rrp, 1);
1953 xfs_btree_log_recs(cur, lbp, lrecs, lrecs);
1954
1955 xfs_btree_check_rec(cur->bc_btnum,
1956 xfs_btree_rec_addr(cur, lrecs - 1, left),
1957 lrp);
1958 }
1959
1960 xfs_btree_set_numrecs(left, lrecs);
1961 xfs_btree_log_block(cur, lbp, XFS_BB_NUMRECS);
1962
1963 xfs_btree_set_numrecs(right, rrecs);
1964 xfs_btree_log_block(cur, rbp, XFS_BB_NUMRECS);
1965
1966 /*
1967 * Slide the contents of right down one entry.
1968 */
1969 XFS_BTREE_STATS_ADD(cur, moves, rrecs - 1);
1970 if (level > 0) {
1971 /* It's a nonleaf. operate on keys and ptrs */
1972#ifdef DEBUG
1973 int i; /* loop index */
1974
1975 for (i = 0; i < rrecs; i++) {
1976 error = xfs_btree_check_ptr(cur, rpp, i + 1, level);
1977 if (error)
1978 goto error0;
1979 }
1980#endif
1981 xfs_btree_shift_keys(cur,
1982 xfs_btree_key_addr(cur, 2, right),
1983 -1, rrecs);
1984 xfs_btree_shift_ptrs(cur,
1985 xfs_btree_ptr_addr(cur, 2, right),
1986 -1, rrecs);
1987
1988 xfs_btree_log_keys(cur, rbp, 1, rrecs);
1989 xfs_btree_log_ptrs(cur, rbp, 1, rrecs);
1990 } else {
1991 /* It's a leaf. operate on records */
1992 xfs_btree_shift_recs(cur,
1993 xfs_btree_rec_addr(cur, 2, right),
1994 -1, rrecs);
1995 xfs_btree_log_recs(cur, rbp, 1, rrecs);
1996
1997 /*
1998 * If it's the first record in the block, we'll need a key
1999 * structure to pass up to the next level (updkey).
2000 */
2001 cur->bc_ops->init_key_from_rec(&key,
2002 xfs_btree_rec_addr(cur, 1, right));
2003 rkp = &key;
2004 }
2005
2006 /* Update the parent key values of right. */
2007 error = xfs_btree_updkey(cur, rkp, level + 1);
2008 if (error)
2009 goto error0;
2010
2011 /* Slide the cursor value left one. */
2012 cur->bc_ptrs[level]--;
2013
2014 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
2015 *stat = 1;
2016 return 0;
2017
2018out0:
2019 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
2020 *stat = 0;
2021 return 0;
2022
2023error0:
2024 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
2025 return error;
2026}
2027
2028/*
1844 * Move 1 record right from cur/level if possible. 2029 * Move 1 record right from cur/level if possible.
1845 * Update cur to reflect the new path. 2030 * Update cur to reflect the new path.
1846 */ 2031 */