diff options
Diffstat (limited to 'fs/xfs/xfs_bmap_btree.c')
-rw-r--r-- | fs/xfs/xfs_bmap_btree.c | 54 |
1 files changed, 44 insertions, 10 deletions
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c index bd18987326a3..4f0e849d973e 100644 --- a/fs/xfs/xfs_bmap_btree.c +++ b/fs/xfs/xfs_bmap_btree.c | |||
@@ -275,21 +275,21 @@ xfs_bmbt_trace_cursor( | |||
275 | } | 275 | } |
276 | 276 | ||
277 | #define XFS_BMBT_TRACE_ARGBI(c,b,i) \ | 277 | #define XFS_BMBT_TRACE_ARGBI(c,b,i) \ |
278 | xfs_bmbt_trace_argbi(__FUNCTION__, c, b, i, __LINE__) | 278 | xfs_bmbt_trace_argbi(__func__, c, b, i, __LINE__) |
279 | #define XFS_BMBT_TRACE_ARGBII(c,b,i,j) \ | 279 | #define XFS_BMBT_TRACE_ARGBII(c,b,i,j) \ |
280 | xfs_bmbt_trace_argbii(__FUNCTION__, c, b, i, j, __LINE__) | 280 | xfs_bmbt_trace_argbii(__func__, c, b, i, j, __LINE__) |
281 | #define XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j) \ | 281 | #define XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j) \ |
282 | xfs_bmbt_trace_argfffi(__FUNCTION__, c, o, b, i, j, __LINE__) | 282 | xfs_bmbt_trace_argfffi(__func__, c, o, b, i, j, __LINE__) |
283 | #define XFS_BMBT_TRACE_ARGI(c,i) \ | 283 | #define XFS_BMBT_TRACE_ARGI(c,i) \ |
284 | xfs_bmbt_trace_argi(__FUNCTION__, c, i, __LINE__) | 284 | xfs_bmbt_trace_argi(__func__, c, i, __LINE__) |
285 | #define XFS_BMBT_TRACE_ARGIFK(c,i,f,s) \ | 285 | #define XFS_BMBT_TRACE_ARGIFK(c,i,f,s) \ |
286 | xfs_bmbt_trace_argifk(__FUNCTION__, c, i, f, s, __LINE__) | 286 | xfs_bmbt_trace_argifk(__func__, c, i, f, s, __LINE__) |
287 | #define XFS_BMBT_TRACE_ARGIFR(c,i,f,r) \ | 287 | #define XFS_BMBT_TRACE_ARGIFR(c,i,f,r) \ |
288 | xfs_bmbt_trace_argifr(__FUNCTION__, c, i, f, r, __LINE__) | 288 | xfs_bmbt_trace_argifr(__func__, c, i, f, r, __LINE__) |
289 | #define XFS_BMBT_TRACE_ARGIK(c,i,k) \ | 289 | #define XFS_BMBT_TRACE_ARGIK(c,i,k) \ |
290 | xfs_bmbt_trace_argik(__FUNCTION__, c, i, k, __LINE__) | 290 | xfs_bmbt_trace_argik(__func__, c, i, k, __LINE__) |
291 | #define XFS_BMBT_TRACE_CURSOR(c,s) \ | 291 | #define XFS_BMBT_TRACE_CURSOR(c,s) \ |
292 | xfs_bmbt_trace_cursor(__FUNCTION__, c, s, __LINE__) | 292 | xfs_bmbt_trace_cursor(__func__, c, s, __LINE__) |
293 | #else | 293 | #else |
294 | #define XFS_BMBT_TRACE_ARGBI(c,b,i) | 294 | #define XFS_BMBT_TRACE_ARGBI(c,b,i) |
295 | #define XFS_BMBT_TRACE_ARGBII(c,b,i,j) | 295 | #define XFS_BMBT_TRACE_ARGBII(c,b,i,j) |
@@ -2027,6 +2027,24 @@ xfs_bmbt_increment( | |||
2027 | 2027 | ||
2028 | /* | 2028 | /* |
2029 | * Insert the current record at the point referenced by cur. | 2029 | * Insert the current record at the point referenced by cur. |
2030 | * | ||
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 | ||
2033 | * always valid. Hence if we do a multi-level split we need to revalidate the | ||
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. | ||
2030 | */ | 2048 | */ |
2031 | int /* error */ | 2049 | int /* error */ |
2032 | xfs_bmbt_insert( | 2050 | xfs_bmbt_insert( |
@@ -2039,11 +2057,14 @@ xfs_bmbt_insert( | |||
2039 | xfs_fsblock_t nbno; | 2057 | xfs_fsblock_t nbno; |
2040 | xfs_btree_cur_t *ncur; | 2058 | xfs_btree_cur_t *ncur; |
2041 | xfs_bmbt_rec_t nrec; | 2059 | xfs_bmbt_rec_t nrec; |
2060 | xfs_bmbt_irec_t oirec; /* original irec */ | ||
2042 | xfs_btree_cur_t *pcur; | 2061 | xfs_btree_cur_t *pcur; |
2062 | int splits = 0; | ||
2043 | 2063 | ||
2044 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | 2064 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); |
2045 | level = 0; | 2065 | level = 0; |
2046 | nbno = NULLFSBLOCK; | 2066 | nbno = NULLFSBLOCK; |
2067 | oirec = cur->bc_rec.b; | ||
2047 | xfs_bmbt_disk_set_all(&nrec, &cur->bc_rec.b); | 2068 | xfs_bmbt_disk_set_all(&nrec, &cur->bc_rec.b); |
2048 | ncur = NULL; | 2069 | ncur = NULL; |
2049 | pcur = cur; | 2070 | pcur = cur; |
@@ -2052,11 +2073,13 @@ xfs_bmbt_insert( | |||
2052 | &i))) { | 2073 | &i))) { |
2053 | if (pcur != cur) | 2074 | if (pcur != cur) |
2054 | xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); | 2075 | xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); |
2055 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 2076 | goto error0; |
2056 | return error; | ||
2057 | } | 2077 | } |
2058 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 2078 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
2059 | if (pcur != cur && (ncur || nbno == NULLFSBLOCK)) { | 2079 | 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++; | ||
2060 | cur->bc_nlevels = pcur->bc_nlevels; | 2083 | cur->bc_nlevels = pcur->bc_nlevels; |
2061 | cur->bc_private.b.allocated += | 2084 | cur->bc_private.b.allocated += |
2062 | pcur->bc_private.b.allocated; | 2085 | pcur->bc_private.b.allocated; |
@@ -2070,10 +2093,21 @@ xfs_bmbt_insert( | |||
2070 | xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR); | 2093 | xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR); |
2071 | } | 2094 | } |
2072 | if (ncur) { | 2095 | if (ncur) { |
2096 | splits++; | ||
2073 | pcur = ncur; | 2097 | pcur = ncur; |
2074 | ncur = NULL; | 2098 | ncur = NULL; |
2075 | } | 2099 | } |
2076 | } while (nbno != NULLFSBLOCK); | 2100 | } 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 | |||
2077 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | 2111 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
2078 | *stat = i; | 2112 | *stat = i; |
2079 | return 0; | 2113 | return 0; |