aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_bmap_btree.c
diff options
context:
space:
mode:
authorLachlan McIlroy <lachlan@sgi.com>2008-06-22 23:25:53 -0400
committerNiv Sardi <xaiki@debian.org>2008-07-28 02:59:03 -0400
commitddea2d5246b4ffbe49bbfb700aa3dbe717eb0915 (patch)
tree9b3041590c9a6f2a15ab15682605d796d7ba9d19 /fs/xfs/xfs_bmap_btree.c
parent6bd8fc8a55cba263bab0b1c24786e95c5a2dc720 (diff)
[XFS] Always reset btree cursor after an insert
After a btree insert operation a cursor can be invalid due to block splits and a maybe a new root block. We reset the cursor in xfs_bmbt_insert() in the cases where we think we need to but it isn't enough as we still see assertions. Just do what we do elsewhere and reset the cursor unconditionally. Also remove the fix to revalidate the original cursor in xfs_bmbt_insert(). SGI-PV: 983336 SGI-Modid: xfs-linux-melb:xfs-kern:31342a Signed-off-by: Lachlan McIlroy <lachlan@sgi.com> Signed-off-by: David Chinner <dgc@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_bmap_btree.c')
-rw-r--r--fs/xfs/xfs_bmap_btree.c38
1 files changed, 4 insertions, 34 deletions
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index 4f0e849d973e..4aa2f11ba563 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -2029,22 +2029,8 @@ xfs_bmbt_increment(
2029 * Insert the current record at the point referenced by cur. 2029 * Insert the current record at the point referenced by cur.
2030 * 2030 *
2031 * A multi-level split of the tree on insert will invalidate the original 2031 * A multi-level split of the tree on insert will invalidate the original
2032 * cursor. It appears, however, that some callers assume that the cursor is 2032 * cursor. All callers of this function should assume that the cursor is
2033 * always valid. Hence if we do a multi-level split we need to revalidate the 2033 * no longer valid and revalidate it.
2034 * cursor.
2035 *
2036 * When a split occurs, we will see a new cursor returned. Use that as a
2037 * trigger to determine if we need to revalidate the original cursor. If we get
2038 * a split, then use the original irec to lookup up the path of the record we
2039 * just inserted.
2040 *
2041 * Note that the fact that the btree root is in the inode means that we can
2042 * have the level of the tree change without a "split" occurring at the root
2043 * level. What happens is that the root is migrated to an allocated block and
2044 * the inode root is pointed to it. This means a single split can change the
2045 * level of the tree (level 2 -> level 3) and invalidate the old cursor. Hence
2046 * the level change should be accounted as a split so as to correctly trigger a
2047 * revalidation of the old cursor.
2048 */ 2034 */
2049int /* error */ 2035int /* error */
2050xfs_bmbt_insert( 2036xfs_bmbt_insert(
@@ -2057,14 +2043,11 @@ xfs_bmbt_insert(
2057 xfs_fsblock_t nbno; 2043 xfs_fsblock_t nbno;
2058 xfs_btree_cur_t *ncur; 2044 xfs_btree_cur_t *ncur;
2059 xfs_bmbt_rec_t nrec; 2045 xfs_bmbt_rec_t nrec;
2060 xfs_bmbt_irec_t oirec; /* original irec */
2061 xfs_btree_cur_t *pcur; 2046 xfs_btree_cur_t *pcur;
2062 int splits = 0;
2063 2047
2064 XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 2048 XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
2065 level = 0; 2049 level = 0;
2066 nbno = NULLFSBLOCK; 2050 nbno = NULLFSBLOCK;
2067 oirec = cur->bc_rec.b;
2068 xfs_bmbt_disk_set_all(&nrec, &cur->bc_rec.b); 2051 xfs_bmbt_disk_set_all(&nrec, &cur->bc_rec.b);
2069 ncur = NULL; 2052 ncur = NULL;
2070 pcur = cur; 2053 pcur = cur;
@@ -2073,13 +2056,11 @@ xfs_bmbt_insert(
2073 &i))) { 2056 &i))) {
2074 if (pcur != cur) 2057 if (pcur != cur)
2075 xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); 2058 xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR);
2076 goto error0; 2059 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2060 return error;
2077 } 2061 }
2078 XFS_WANT_CORRUPTED_GOTO(i == 1, error0); 2062 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
2079 if (pcur != cur && (ncur || nbno == NULLFSBLOCK)) { 2063 if (pcur != cur && (ncur || nbno == NULLFSBLOCK)) {
2080 /* allocating a new root is effectively a split */
2081 if (cur->bc_nlevels != pcur->bc_nlevels)
2082 splits++;
2083 cur->bc_nlevels = pcur->bc_nlevels; 2064 cur->bc_nlevels = pcur->bc_nlevels;
2084 cur->bc_private.b.allocated += 2065 cur->bc_private.b.allocated +=
2085 pcur->bc_private.b.allocated; 2066 pcur->bc_private.b.allocated;
@@ -2093,21 +2074,10 @@ xfs_bmbt_insert(
2093 xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR); 2074 xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR);
2094 } 2075 }
2095 if (ncur) { 2076 if (ncur) {
2096 splits++;
2097 pcur = ncur; 2077 pcur = ncur;
2098 ncur = NULL; 2078 ncur = NULL;
2099 } 2079 }
2100 } while (nbno != NULLFSBLOCK); 2080 } while (nbno != NULLFSBLOCK);
2101
2102 if (splits > 1) {
2103 /* revalidate the old cursor as we had a multi-level split */
2104 error = xfs_bmbt_lookup_eq(cur, oirec.br_startoff,
2105 oirec.br_startblock, oirec.br_blockcount, &i);
2106 if (error)
2107 goto error0;
2108 ASSERT(i == 1);
2109 }
2110
2111 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 2081 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2112 *stat = i; 2082 *stat = i;
2113 return 0; 2083 return 0;