]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/xfs/xfs_bmap_btree.c
ACPI: check a return value correctly in acpi_power_get_context()
[linux-2.6-omap-h63xx.git] / fs / xfs / xfs_bmap_btree.c
index c4181d85605cb646e94c55afd5d4bb49d43f1dd3..4f0e849d973edda419fb75980b62f5e4f159419a 100644 (file)
@@ -275,21 +275,21 @@ xfs_bmbt_trace_cursor(
 }
 
 #define        XFS_BMBT_TRACE_ARGBI(c,b,i)     \
-       xfs_bmbt_trace_argbi(__FUNCTION__, c, b, i, __LINE__)
+       xfs_bmbt_trace_argbi(__func__, c, b, i, __LINE__)
 #define        XFS_BMBT_TRACE_ARGBII(c,b,i,j)  \
-       xfs_bmbt_trace_argbii(__FUNCTION__, c, b, i, j, __LINE__)
+       xfs_bmbt_trace_argbii(__func__, c, b, i, j, __LINE__)
 #define        XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j)       \
-       xfs_bmbt_trace_argfffi(__FUNCTION__, c, o, b, i, j, __LINE__)
+       xfs_bmbt_trace_argfffi(__func__, c, o, b, i, j, __LINE__)
 #define        XFS_BMBT_TRACE_ARGI(c,i)        \
-       xfs_bmbt_trace_argi(__FUNCTION__, c, i, __LINE__)
+       xfs_bmbt_trace_argi(__func__, c, i, __LINE__)
 #define        XFS_BMBT_TRACE_ARGIFK(c,i,f,s)  \
-       xfs_bmbt_trace_argifk(__FUNCTION__, c, i, f, s, __LINE__)
+       xfs_bmbt_trace_argifk(__func__, c, i, f, s, __LINE__)
 #define        XFS_BMBT_TRACE_ARGIFR(c,i,f,r)  \
-       xfs_bmbt_trace_argifr(__FUNCTION__, c, i, f, r, __LINE__)
+       xfs_bmbt_trace_argifr(__func__, c, i, f, r, __LINE__)
 #define        XFS_BMBT_TRACE_ARGIK(c,i,k)     \
-       xfs_bmbt_trace_argik(__FUNCTION__, c, i, k, __LINE__)
+       xfs_bmbt_trace_argik(__func__, c, i, k, __LINE__)
 #define        XFS_BMBT_TRACE_CURSOR(c,s)      \
-       xfs_bmbt_trace_cursor(__FUNCTION__, c, s, __LINE__)
+       xfs_bmbt_trace_cursor(__func__, c, s, __LINE__)
 #else
 #define        XFS_BMBT_TRACE_ARGBI(c,b,i)
 #define        XFS_BMBT_TRACE_ARGBII(c,b,i,j)
@@ -631,7 +631,7 @@ xfs_bmbt_delrec(
                memcpy(lrp, rrp, numrrecs * sizeof(*lrp));
                xfs_bmbt_log_recs(cur, lbp, numlrecs + 1, numlrecs + numrrecs);
        }
-       be16_add(&left->bb_numrecs, numrrecs);
+       be16_add_cpu(&left->bb_numrecs, numrrecs);
        left->bb_rightsib = right->bb_rightsib;
        xfs_bmbt_log_block(cur, lbp, XFS_BB_RIGHTSIB | XFS_BB_NUMRECS);
        if (be64_to_cpu(left->bb_rightsib) != NULLDFSBNO) {
@@ -924,7 +924,7 @@ xfs_bmbt_killroot(
                xfs_iroot_realloc(ip, i, cur->bc_private.b.whichfork);
                block = ifp->if_broot;
        }
-       be16_add(&block->bb_numrecs, i);
+       be16_add_cpu(&block->bb_numrecs, i);
        ASSERT(block->bb_numrecs == cblock->bb_numrecs);
        kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
        ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur);
@@ -947,7 +947,7 @@ xfs_bmbt_killroot(
                        XFS_TRANS_DQ_BCOUNT, -1L);
        xfs_trans_binval(cur->bc_tp, cbp);
        cur->bc_bufs[level - 1] = NULL;
-       be16_add(&block->bb_level, -1);
+       be16_add_cpu(&block->bb_level, -1);
        xfs_trans_log_inode(cur->bc_tp, ip,
                XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork));
        cur->bc_nlevels--;
@@ -1401,9 +1401,9 @@ xfs_bmbt_rshift(
                key.br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(rrp));
                rkp = &key;
        }
-       be16_add(&left->bb_numrecs, -1);
+       be16_add_cpu(&left->bb_numrecs, -1);
        xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS);
-       be16_add(&right->bb_numrecs, 1);
+       be16_add_cpu(&right->bb_numrecs, 1);
 #ifdef DEBUG
        if (level > 0)
                xfs_btree_check_key(XFS_BTNUM_BMAP, rkp, rkp + 1);
@@ -1535,7 +1535,7 @@ xfs_bmbt_split(
        right->bb_numrecs = cpu_to_be16(be16_to_cpu(left->bb_numrecs) / 2);
        if ((be16_to_cpu(left->bb_numrecs) & 1) &&
            cur->bc_ptrs[level] <= be16_to_cpu(right->bb_numrecs) + 1)
-               be16_add(&right->bb_numrecs, 1);
+               be16_add_cpu(&right->bb_numrecs, 1);
        i = be16_to_cpu(left->bb_numrecs) - be16_to_cpu(right->bb_numrecs) + 1;
        if (level > 0) {
                lkp = XFS_BMAP_KEY_IADDR(left, i, cur);
@@ -1562,7 +1562,7 @@ xfs_bmbt_split(
                xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
                *startoff = xfs_bmbt_disk_get_startoff(rrp);
        }
-       be16_add(&left->bb_numrecs, -(be16_to_cpu(right->bb_numrecs)));
+       be16_add_cpu(&left->bb_numrecs, -(be16_to_cpu(right->bb_numrecs)));
        right->bb_rightsib = left->bb_rightsib;
        left->bb_rightsib = cpu_to_be64(args.fsbno);
        right->bb_leftsib = cpu_to_be64(lbno);
@@ -2027,6 +2027,24 @@ xfs_bmbt_increment(
 
 /*
  * Insert the current record at the point referenced by cur.
+ *
+ * A multi-level split of the tree on insert will invalidate the original
+ * cursor. It appears, however, that some callers assume that the cursor is
+ * always valid. Hence if we do a multi-level split we need to revalidate the
+ * cursor.
+ *
+ * When a split occurs, we will see a new cursor returned. Use that as a
+ * trigger to determine if we need to revalidate the original cursor. If we get
+ * a split, then use the original irec to lookup up the path of the record we
+ * just inserted.
+ *
+ * Note that the fact that the btree root is in the inode means that we can
+ * have the level of the tree change without a "split" occurring at the root
+ * level. What happens is that the root is migrated to an allocated block and
+ * the inode root is pointed to it. This means a single split can change the
+ * level of the tree (level 2 -> level 3) and invalidate the old cursor. Hence
+ * the level change should be accounted as a split so as to correctly trigger a
+ * revalidation of the old cursor.
  */
 int                                    /* error */
 xfs_bmbt_insert(
@@ -2039,11 +2057,14 @@ xfs_bmbt_insert(
        xfs_fsblock_t   nbno;
        xfs_btree_cur_t *ncur;
        xfs_bmbt_rec_t  nrec;
+       xfs_bmbt_irec_t oirec;          /* original irec */
        xfs_btree_cur_t *pcur;
+       int             splits = 0;
 
        XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
        level = 0;
        nbno = NULLFSBLOCK;
+       oirec = cur->bc_rec.b;
        xfs_bmbt_disk_set_all(&nrec, &cur->bc_rec.b);
        ncur = NULL;
        pcur = cur;
@@ -2052,11 +2073,13 @@ xfs_bmbt_insert(
                                &i))) {
                        if (pcur != cur)
                                xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR);
-                       XFS_BMBT_TRACE_CURSOR(cur, ERROR);
-                       return error;
+                       goto error0;
                }
                XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
                if (pcur != cur && (ncur || nbno == NULLFSBLOCK)) {
+                       /* allocating a new root is effectively a split */
+                       if (cur->bc_nlevels != pcur->bc_nlevels)
+                               splits++;
                        cur->bc_nlevels = pcur->bc_nlevels;
                        cur->bc_private.b.allocated +=
                                pcur->bc_private.b.allocated;
@@ -2070,10 +2093,21 @@ xfs_bmbt_insert(
                        xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR);
                }
                if (ncur) {
+                       splits++;
                        pcur = ncur;
                        ncur = NULL;
                }
        } while (nbno != NULLFSBLOCK);
+
+       if (splits > 1) {
+               /* revalidate the old cursor as we had a multi-level split */
+               error = xfs_bmbt_lookup_eq(cur, oirec.br_startoff,
+                               oirec.br_startblock, oirec.br_blockcount, &i);
+               if (error)
+                       goto error0;
+               ASSERT(i == 1);
+       }
+
        XFS_BMBT_TRACE_CURSOR(cur, EXIT);
        *stat = i;
        return 0;
@@ -2240,7 +2274,7 @@ xfs_bmbt_newroot(
        bp = xfs_btree_get_bufl(args.mp, cur->bc_tp, args.fsbno, 0);
        cblock = XFS_BUF_TO_BMBT_BLOCK(bp);
        *cblock = *block;
-       be16_add(&block->bb_level, 1);
+       be16_add_cpu(&block->bb_level, 1);
        block->bb_numrecs = cpu_to_be16(1);
        cur->bc_nlevels++;
        cur->bc_ptrs[level + 1] = 1;