diff options
author | Lachlan McIlroy <lachlan@sgi.com> | 2008-06-22 23:25:53 -0400 |
---|---|---|
committer | Niv Sardi <xaiki@debian.org> | 2008-07-28 02:59:03 -0400 |
commit | ddea2d5246b4ffbe49bbfb700aa3dbe717eb0915 (patch) | |
tree | 9b3041590c9a6f2a15ab15682605d796d7ba9d19 /fs/xfs | |
parent | 6bd8fc8a55cba263bab0b1c24786e95c5a2dc720 (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')
-rw-r--r-- | fs/xfs/xfs_bmap.c | 13 | ||||
-rw-r--r-- | fs/xfs/xfs_bmap_btree.c | 38 |
2 files changed, 14 insertions, 37 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index c21e01a9b2dd..cf4dee01983a 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -1746,11 +1746,18 @@ xfs_bmap_add_extent_unwritten_real( | |||
1746 | if ((error = xfs_bmbt_insert(cur, &i))) | 1746 | if ((error = xfs_bmbt_insert(cur, &i))) |
1747 | goto done; | 1747 | goto done; |
1748 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 1748 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1749 | if ((error = xfs_bmbt_increment(cur, 0, &i))) | 1749 | /* |
1750 | * Reset the cursor to the position of the new extent | ||
1751 | * we are about to insert as we can't trust it after | ||
1752 | * the previous insert. | ||
1753 | */ | ||
1754 | if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff, | ||
1755 | new->br_startblock, new->br_blockcount, | ||
1756 | &i))) | ||
1750 | goto done; | 1757 | goto done; |
1751 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 1758 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); |
1752 | /* new middle extent - newext */ | 1759 | /* new middle extent - newext */ |
1753 | cur->bc_rec.b = *new; | 1760 | cur->bc_rec.b.br_state = new->br_state; |
1754 | if ((error = xfs_bmbt_insert(cur, &i))) | 1761 | if ((error = xfs_bmbt_insert(cur, &i))) |
1755 | goto done; | 1762 | goto done; |
1756 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 1763 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
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 | */ |
2049 | int /* error */ | 2035 | int /* error */ |
2050 | xfs_bmbt_insert( | 2036 | xfs_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; |