xfs: use current->journal_info for detecting transaction recursion
[linux-2.6-microblaze.git] / fs / xfs / libxfs / xfs_btree.c
index 2d25bab..5b6fcb9 100644 (file)
@@ -353,20 +353,17 @@ xfs_btree_free_block(
  */
 void
 xfs_btree_del_cursor(
-       xfs_btree_cur_t *cur,           /* btree cursor */
-       int             error)          /* del because of error */
+       struct xfs_btree_cur    *cur,           /* btree cursor */
+       int                     error)          /* del because of error */
 {
-       int             i;              /* btree level */
+       int                     i;              /* btree level */
 
        /*
-        * Clear the buffer pointers, and release the buffers.
-        * If we're doing this in the face of an error, we
-        * need to make sure to inspect all of the entries
-        * in the bc_bufs array for buffers to be unlocked.
-        * This is because some of the btree code works from
-        * level n down to 0, and if we get an error along
-        * the way we won't have initialized all the entries
-        * down to 0.
+        * Clear the buffer pointers and release the buffers. If we're doing
+        * this because of an error, inspect all of the entries in the bc_bufs
+        * array for buffers to be unlocked. This is because some of the btree
+        * code works from level n down to 0, and if we get an error along the
+        * way we won't have initialized all the entries down to 0.
         */
        for (i = 0; i < cur->bc_nlevels; i++) {
                if (cur->bc_bufs[i])
@@ -374,17 +371,11 @@ xfs_btree_del_cursor(
                else if (!error)
                        break;
        }
-       /*
-        * Can't free a bmap cursor without having dealt with the
-        * allocated indirect blocks' accounting.
-        */
-       ASSERT(cur->bc_btnum != XFS_BTNUM_BMAP ||
-              cur->bc_ino.allocated == 0);
-       /*
-        * Free the cursor.
-        */
+
+       ASSERT(cur->bc_btnum != XFS_BTNUM_BMAP || cur->bc_ino.allocated == 0 ||
+              XFS_FORCED_SHUTDOWN(cur->bc_mp));
        if (unlikely(cur->bc_flags & XFS_BTREE_STAGING))
-               kmem_free((void *)cur->bc_ops);
+               kmem_free(cur->bc_ops);
        kmem_cache_free(xfs_btree_cur_zone, cur);
 }
 
@@ -397,7 +388,7 @@ xfs_btree_dup_cursor(
        xfs_btree_cur_t *cur,           /* input cursor */
        xfs_btree_cur_t **ncur)         /* output cursor */
 {
-       xfs_buf_t       *bp;            /* btree block's buffer pointer */
+       struct xfs_buf  *bp;            /* btree block's buffer pointer */
        int             error;          /* error return value */
        int             i;              /* level number of btree block */
        xfs_mount_t     *mp;            /* mount structure for filesystem */
@@ -701,7 +692,7 @@ xfs_btree_firstrec(
        int                     level)  /* level to change */
 {
        struct xfs_btree_block  *block; /* generic btree block pointer */
-       xfs_buf_t               *bp;    /* buffer containing block */
+       struct xfs_buf          *bp;    /* buffer containing block */
 
        /*
         * Get the block pointer for this level.
@@ -731,7 +722,7 @@ xfs_btree_lastrec(
        int                     level)  /* level to change */
 {
        struct xfs_btree_block  *block; /* generic btree block pointer */
-       xfs_buf_t               *bp;    /* buffer containing block */
+       struct xfs_buf          *bp;    /* buffer containing block */
 
        /*
         * Get the block pointer for this level.
@@ -993,7 +984,7 @@ STATIC void
 xfs_btree_setbuf(
        xfs_btree_cur_t         *cur,   /* btree cursor */
        int                     lev,    /* level in btree */
-       xfs_buf_t               *bp)    /* new buffer to set */
+       struct xfs_buf          *bp)    /* new buffer to set */
 {
        struct xfs_btree_block  *b;     /* btree block */
 
@@ -1636,7 +1627,7 @@ xfs_btree_decrement(
        int                     *stat)          /* success/failure */
 {
        struct xfs_btree_block  *block;
-       xfs_buf_t               *bp;
+       struct xfs_buf          *bp;
        int                     error;          /* error return value */
        int                     lev;
        union xfs_btree_ptr     ptr;
@@ -2814,7 +2805,7 @@ xfs_btree_split_worker(
        struct xfs_btree_split_args     *args = container_of(work,
                                                struct xfs_btree_split_args, work);
        unsigned long           pflags;
-       unsigned long           new_pflags = PF_MEMALLOC_NOFS;
+       unsigned long           new_pflags = 0;
 
        /*
         * we are in a transaction context here, but may also be doing work
@@ -2826,12 +2817,20 @@ xfs_btree_split_worker(
                new_pflags |= PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD;
 
        current_set_flags_nested(&pflags, new_pflags);
+       xfs_trans_set_context(args->cur->bc_tp);
 
        args->result = __xfs_btree_split(args->cur, args->level, args->ptrp,
                                         args->key, args->curp, args->stat);
-       complete(args->done);
 
+       xfs_trans_clear_context(args->cur->bc_tp);
        current_restore_flags_nested(&pflags, new_pflags);
+
+       /*
+        * Do not access args after complete() has run here. We don't own args
+        * and the owner may run and free args before we return here.
+        */
+       complete(args->done);
+
 }
 
 /*
@@ -4070,7 +4069,7 @@ xfs_btree_delrec(
         * surviving block, and log it.
         */
        xfs_btree_set_numrecs(left, lrecs + rrecs);
-       xfs_btree_get_sibling(cur, right, &cptr, XFS_BB_RIGHTSIB),
+       xfs_btree_get_sibling(cur, right, &cptr, XFS_BB_RIGHTSIB);
        xfs_btree_set_sibling(cur, left, &cptr, XFS_BB_RIGHTSIB);
        xfs_btree_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB);