aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_bmap_btree.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_bmap_btree.c')
-rw-r--r--fs/xfs/xfs_bmap_btree.c54
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 */
2031int /* error */ 2049int /* error */
2032xfs_bmbt_insert( 2050xfs_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;