aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_bmap.c13
-rw-r--r--fs/xfs/xfs_bmap_btree.c38
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 */
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;