diff options
Diffstat (limited to 'fs/xfs/xfs_trans_buf.c')
| -rw-r--r-- | fs/xfs/xfs_trans_buf.c | 243 |
1 files changed, 80 insertions, 163 deletions
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index 49130628d5ef..fb586360d1c9 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c | |||
| @@ -46,6 +46,65 @@ STATIC xfs_buf_t *xfs_trans_buf_item_match(xfs_trans_t *, xfs_buftarg_t *, | |||
| 46 | STATIC xfs_buf_t *xfs_trans_buf_item_match_all(xfs_trans_t *, xfs_buftarg_t *, | 46 | STATIC xfs_buf_t *xfs_trans_buf_item_match_all(xfs_trans_t *, xfs_buftarg_t *, |
| 47 | xfs_daddr_t, int); | 47 | xfs_daddr_t, int); |
| 48 | 48 | ||
| 49 | /* | ||
| 50 | * Add the locked buffer to the transaction. | ||
| 51 | * | ||
| 52 | * The buffer must be locked, and it cannot be associated with any | ||
| 53 | * transaction. | ||
| 54 | * | ||
| 55 | * If the buffer does not yet have a buf log item associated with it, | ||
| 56 | * then allocate one for it. Then add the buf item to the transaction. | ||
| 57 | */ | ||
| 58 | STATIC void | ||
| 59 | _xfs_trans_bjoin( | ||
| 60 | struct xfs_trans *tp, | ||
| 61 | struct xfs_buf *bp, | ||
| 62 | int reset_recur) | ||
| 63 | { | ||
| 64 | struct xfs_buf_log_item *bip; | ||
| 65 | |||
| 66 | ASSERT(XFS_BUF_ISBUSY(bp)); | ||
| 67 | ASSERT(XFS_BUF_FSPRIVATE2(bp, void *) == NULL); | ||
| 68 | |||
| 69 | /* | ||
| 70 | * The xfs_buf_log_item pointer is stored in b_fsprivate. If | ||
| 71 | * it doesn't have one yet, then allocate one and initialize it. | ||
| 72 | * The checks to see if one is there are in xfs_buf_item_init(). | ||
| 73 | */ | ||
| 74 | xfs_buf_item_init(bp, tp->t_mountp); | ||
| 75 | bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); | ||
| 76 | ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); | ||
| 77 | ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL)); | ||
| 78 | ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED)); | ||
| 79 | if (reset_recur) | ||
| 80 | bip->bli_recur = 0; | ||
| 81 | |||
| 82 | /* | ||
| 83 | * Take a reference for this transaction on the buf item. | ||
| 84 | */ | ||
| 85 | atomic_inc(&bip->bli_refcount); | ||
| 86 | |||
| 87 | /* | ||
| 88 | * Get a log_item_desc to point at the new item. | ||
| 89 | */ | ||
| 90 | (void) xfs_trans_add_item(tp, (xfs_log_item_t *)bip); | ||
| 91 | |||
| 92 | /* | ||
| 93 | * Initialize b_fsprivate2 so we can find it with incore_match() | ||
| 94 | * in xfs_trans_get_buf() and friends above. | ||
| 95 | */ | ||
| 96 | XFS_BUF_SET_FSPRIVATE2(bp, tp); | ||
| 97 | |||
| 98 | } | ||
| 99 | |||
| 100 | void | ||
| 101 | xfs_trans_bjoin( | ||
| 102 | struct xfs_trans *tp, | ||
| 103 | struct xfs_buf *bp) | ||
| 104 | { | ||
| 105 | _xfs_trans_bjoin(tp, bp, 0); | ||
| 106 | trace_xfs_trans_bjoin(bp->b_fspriv); | ||
| 107 | } | ||
| 49 | 108 | ||
| 50 | /* | 109 | /* |
| 51 | * Get and lock the buffer for the caller if it is not already | 110 | * Get and lock the buffer for the caller if it is not already |
| @@ -75,13 +134,14 @@ xfs_trans_get_buf(xfs_trans_t *tp, | |||
| 75 | xfs_buf_log_item_t *bip; | 134 | xfs_buf_log_item_t *bip; |
| 76 | 135 | ||
| 77 | if (flags == 0) | 136 | if (flags == 0) |
| 78 | flags = XFS_BUF_LOCK | XFS_BUF_MAPPED; | 137 | flags = XBF_LOCK | XBF_MAPPED; |
| 79 | 138 | ||
| 80 | /* | 139 | /* |
| 81 | * Default to a normal get_buf() call if the tp is NULL. | 140 | * Default to a normal get_buf() call if the tp is NULL. |
| 82 | */ | 141 | */ |
| 83 | if (tp == NULL) | 142 | if (tp == NULL) |
| 84 | return xfs_buf_get(target_dev, blkno, len, flags | BUF_BUSY); | 143 | return xfs_buf_get(target_dev, blkno, len, |
| 144 | flags | XBF_DONT_BLOCK); | ||
| 85 | 145 | ||
| 86 | /* | 146 | /* |
| 87 | * If we find the buffer in the cache with this transaction | 147 | * If we find the buffer in the cache with this transaction |
| @@ -117,54 +177,22 @@ xfs_trans_get_buf(xfs_trans_t *tp, | |||
| 117 | } | 177 | } |
| 118 | 178 | ||
| 119 | /* | 179 | /* |
| 120 | * We always specify the BUF_BUSY flag within a transaction so | 180 | * We always specify the XBF_DONT_BLOCK flag within a transaction |
| 121 | * that get_buf does not try to push out a delayed write buffer | 181 | * so that get_buf does not try to push out a delayed write buffer |
| 122 | * which might cause another transaction to take place (if the | 182 | * which might cause another transaction to take place (if the |
| 123 | * buffer was delayed alloc). Such recursive transactions can | 183 | * buffer was delayed alloc). Such recursive transactions can |
| 124 | * easily deadlock with our current transaction as well as cause | 184 | * easily deadlock with our current transaction as well as cause |
| 125 | * us to run out of stack space. | 185 | * us to run out of stack space. |
| 126 | */ | 186 | */ |
| 127 | bp = xfs_buf_get(target_dev, blkno, len, flags | BUF_BUSY); | 187 | bp = xfs_buf_get(target_dev, blkno, len, flags | XBF_DONT_BLOCK); |
| 128 | if (bp == NULL) { | 188 | if (bp == NULL) { |
| 129 | return NULL; | 189 | return NULL; |
| 130 | } | 190 | } |
| 131 | 191 | ||
| 132 | ASSERT(!XFS_BUF_GETERROR(bp)); | 192 | ASSERT(!XFS_BUF_GETERROR(bp)); |
| 133 | 193 | ||
| 134 | /* | 194 | _xfs_trans_bjoin(tp, bp, 1); |
| 135 | * The xfs_buf_log_item pointer is stored in b_fsprivate. If | 195 | trace_xfs_trans_get_buf(bp->b_fspriv); |
| 136 | * it doesn't have one yet, then allocate one and initialize it. | ||
| 137 | * The checks to see if one is there are in xfs_buf_item_init(). | ||
| 138 | */ | ||
| 139 | xfs_buf_item_init(bp, tp->t_mountp); | ||
| 140 | |||
| 141 | /* | ||
| 142 | * Set the recursion count for the buffer within this transaction | ||
| 143 | * to 0. | ||
| 144 | */ | ||
| 145 | bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*); | ||
| 146 | ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); | ||
| 147 | ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL)); | ||
| 148 | ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED)); | ||
| 149 | bip->bli_recur = 0; | ||
| 150 | |||
| 151 | /* | ||
| 152 | * Take a reference for this transaction on the buf item. | ||
| 153 | */ | ||
| 154 | atomic_inc(&bip->bli_refcount); | ||
| 155 | |||
| 156 | /* | ||
| 157 | * Get a log_item_desc to point at the new item. | ||
| 158 | */ | ||
| 159 | (void) xfs_trans_add_item(tp, (xfs_log_item_t*)bip); | ||
| 160 | |||
| 161 | /* | ||
| 162 | * Initialize b_fsprivate2 so we can find it with incore_match() | ||
| 163 | * above. | ||
| 164 | */ | ||
| 165 | XFS_BUF_SET_FSPRIVATE2(bp, tp); | ||
| 166 | |||
| 167 | trace_xfs_trans_get_buf(bip); | ||
| 168 | return (bp); | 196 | return (bp); |
| 169 | } | 197 | } |
| 170 | 198 | ||
| @@ -209,44 +237,11 @@ xfs_trans_getsb(xfs_trans_t *tp, | |||
| 209 | } | 237 | } |
| 210 | 238 | ||
| 211 | bp = xfs_getsb(mp, flags); | 239 | bp = xfs_getsb(mp, flags); |
| 212 | if (bp == NULL) { | 240 | if (bp == NULL) |
| 213 | return NULL; | 241 | return NULL; |
| 214 | } | ||
| 215 | |||
| 216 | /* | ||
| 217 | * The xfs_buf_log_item pointer is stored in b_fsprivate. If | ||
| 218 | * it doesn't have one yet, then allocate one and initialize it. | ||
| 219 | * The checks to see if one is there are in xfs_buf_item_init(). | ||
| 220 | */ | ||
| 221 | xfs_buf_item_init(bp, mp); | ||
| 222 | |||
| 223 | /* | ||
| 224 | * Set the recursion count for the buffer within this transaction | ||
| 225 | * to 0. | ||
| 226 | */ | ||
| 227 | bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*); | ||
| 228 | ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); | ||
| 229 | ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL)); | ||
| 230 | ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED)); | ||
| 231 | bip->bli_recur = 0; | ||
| 232 | |||
| 233 | /* | ||
| 234 | * Take a reference for this transaction on the buf item. | ||
| 235 | */ | ||
| 236 | atomic_inc(&bip->bli_refcount); | ||
| 237 | |||
| 238 | /* | ||
| 239 | * Get a log_item_desc to point at the new item. | ||
| 240 | */ | ||
| 241 | (void) xfs_trans_add_item(tp, (xfs_log_item_t*)bip); | ||
| 242 | |||
| 243 | /* | ||
| 244 | * Initialize b_fsprivate2 so we can find it with incore_match() | ||
| 245 | * above. | ||
| 246 | */ | ||
| 247 | XFS_BUF_SET_FSPRIVATE2(bp, tp); | ||
| 248 | 242 | ||
| 249 | trace_xfs_trans_getsb(bip); | 243 | _xfs_trans_bjoin(tp, bp, 1); |
| 244 | trace_xfs_trans_getsb(bp->b_fspriv); | ||
| 250 | return (bp); | 245 | return (bp); |
| 251 | } | 246 | } |
| 252 | 247 | ||
| @@ -290,15 +285,15 @@ xfs_trans_read_buf( | |||
| 290 | int error; | 285 | int error; |
| 291 | 286 | ||
| 292 | if (flags == 0) | 287 | if (flags == 0) |
| 293 | flags = XFS_BUF_LOCK | XFS_BUF_MAPPED; | 288 | flags = XBF_LOCK | XBF_MAPPED; |
| 294 | 289 | ||
| 295 | /* | 290 | /* |
| 296 | * Default to a normal get_buf() call if the tp is NULL. | 291 | * Default to a normal get_buf() call if the tp is NULL. |
| 297 | */ | 292 | */ |
| 298 | if (tp == NULL) { | 293 | if (tp == NULL) { |
| 299 | bp = xfs_buf_read(target, blkno, len, flags | BUF_BUSY); | 294 | bp = xfs_buf_read(target, blkno, len, flags | XBF_DONT_BLOCK); |
| 300 | if (!bp) | 295 | if (!bp) |
| 301 | return (flags & XFS_BUF_TRYLOCK) ? | 296 | return (flags & XBF_TRYLOCK) ? |
| 302 | EAGAIN : XFS_ERROR(ENOMEM); | 297 | EAGAIN : XFS_ERROR(ENOMEM); |
| 303 | 298 | ||
| 304 | if (XFS_BUF_GETERROR(bp) != 0) { | 299 | if (XFS_BUF_GETERROR(bp) != 0) { |
| @@ -385,14 +380,14 @@ xfs_trans_read_buf( | |||
| 385 | } | 380 | } |
| 386 | 381 | ||
| 387 | /* | 382 | /* |
| 388 | * We always specify the BUF_BUSY flag within a transaction so | 383 | * We always specify the XBF_DONT_BLOCK flag within a transaction |
| 389 | * that get_buf does not try to push out a delayed write buffer | 384 | * so that get_buf does not try to push out a delayed write buffer |
| 390 | * which might cause another transaction to take place (if the | 385 | * which might cause another transaction to take place (if the |
| 391 | * buffer was delayed alloc). Such recursive transactions can | 386 | * buffer was delayed alloc). Such recursive transactions can |
| 392 | * easily deadlock with our current transaction as well as cause | 387 | * easily deadlock with our current transaction as well as cause |
| 393 | * us to run out of stack space. | 388 | * us to run out of stack space. |
| 394 | */ | 389 | */ |
| 395 | bp = xfs_buf_read(target, blkno, len, flags | BUF_BUSY); | 390 | bp = xfs_buf_read(target, blkno, len, flags | XBF_DONT_BLOCK); |
| 396 | if (bp == NULL) { | 391 | if (bp == NULL) { |
| 397 | *bpp = NULL; | 392 | *bpp = NULL; |
| 398 | return 0; | 393 | return 0; |
| @@ -424,40 +419,9 @@ xfs_trans_read_buf( | |||
| 424 | if (XFS_FORCED_SHUTDOWN(mp)) | 419 | if (XFS_FORCED_SHUTDOWN(mp)) |
| 425 | goto shutdown_abort; | 420 | goto shutdown_abort; |
| 426 | 421 | ||
| 427 | /* | 422 | _xfs_trans_bjoin(tp, bp, 1); |
| 428 | * The xfs_buf_log_item pointer is stored in b_fsprivate. If | 423 | trace_xfs_trans_read_buf(bp->b_fspriv); |
| 429 | * it doesn't have one yet, then allocate one and initialize it. | ||
| 430 | * The checks to see if one is there are in xfs_buf_item_init(). | ||
| 431 | */ | ||
| 432 | xfs_buf_item_init(bp, tp->t_mountp); | ||
| 433 | 424 | ||
| 434 | /* | ||
| 435 | * Set the recursion count for the buffer within this transaction | ||
| 436 | * to 0. | ||
| 437 | */ | ||
| 438 | bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*); | ||
| 439 | ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); | ||
| 440 | ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL)); | ||
| 441 | ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED)); | ||
| 442 | bip->bli_recur = 0; | ||
| 443 | |||
| 444 | /* | ||
| 445 | * Take a reference for this transaction on the buf item. | ||
| 446 | */ | ||
| 447 | atomic_inc(&bip->bli_refcount); | ||
| 448 | |||
| 449 | /* | ||
| 450 | * Get a log_item_desc to point at the new item. | ||
| 451 | */ | ||
| 452 | (void) xfs_trans_add_item(tp, (xfs_log_item_t*)bip); | ||
| 453 | |||
| 454 | /* | ||
| 455 | * Initialize b_fsprivate2 so we can find it with incore_match() | ||
| 456 | * above. | ||
| 457 | */ | ||
| 458 | XFS_BUF_SET_FSPRIVATE2(bp, tp); | ||
| 459 | |||
| 460 | trace_xfs_trans_read_buf(bip); | ||
| 461 | *bpp = bp; | 425 | *bpp = bp; |
| 462 | return 0; | 426 | return 0; |
| 463 | 427 | ||
| @@ -472,8 +436,8 @@ shutdown_abort: | |||
| 472 | if (XFS_BUF_ISSTALE(bp) && XFS_BUF_ISDELAYWRITE(bp)) | 436 | if (XFS_BUF_ISSTALE(bp) && XFS_BUF_ISDELAYWRITE(bp)) |
| 473 | cmn_err(CE_NOTE, "about to pop assert, bp == 0x%p", bp); | 437 | cmn_err(CE_NOTE, "about to pop assert, bp == 0x%p", bp); |
| 474 | #endif | 438 | #endif |
| 475 | ASSERT((XFS_BUF_BFLAGS(bp) & (XFS_B_STALE|XFS_B_DELWRI)) != | 439 | ASSERT((XFS_BUF_BFLAGS(bp) & (XBF_STALE|XBF_DELWRI)) != |
| 476 | (XFS_B_STALE|XFS_B_DELWRI)); | 440 | (XBF_STALE|XBF_DELWRI)); |
| 477 | 441 | ||
| 478 | trace_xfs_trans_read_buf_shut(bp, _RET_IP_); | 442 | trace_xfs_trans_read_buf_shut(bp, _RET_IP_); |
| 479 | xfs_buf_relse(bp); | 443 | xfs_buf_relse(bp); |
| @@ -622,53 +586,6 @@ xfs_trans_brelse(xfs_trans_t *tp, | |||
| 622 | } | 586 | } |
| 623 | 587 | ||
| 624 | /* | 588 | /* |
| 625 | * Add the locked buffer to the transaction. | ||
| 626 | * The buffer must be locked, and it cannot be associated with any | ||
| 627 | * transaction. | ||
| 628 | * | ||
| 629 | * If the buffer does not yet have a buf log item associated with it, | ||
| 630 | * then allocate one for it. Then add the buf item to the transaction. | ||
| 631 | */ | ||
| 632 | void | ||
| 633 | xfs_trans_bjoin(xfs_trans_t *tp, | ||
| 634 | xfs_buf_t *bp) | ||
| 635 | { | ||
| 636 | xfs_buf_log_item_t *bip; | ||
| 637 | |||
| 638 | ASSERT(XFS_BUF_ISBUSY(bp)); | ||
| 639 | ASSERT(XFS_BUF_FSPRIVATE2(bp, void *) == NULL); | ||
| 640 | |||
| 641 | /* | ||
| 642 | * The xfs_buf_log_item pointer is stored in b_fsprivate. If | ||
| 643 | * it doesn't have one yet, then allocate one and initialize it. | ||
| 644 | * The checks to see if one is there are in xfs_buf_item_init(). | ||
| 645 | */ | ||
| 646 | xfs_buf_item_init(bp, tp->t_mountp); | ||
| 647 | bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); | ||
| 648 | ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); | ||
| 649 | ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL)); | ||
| 650 | ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED)); | ||
| 651 | |||
| 652 | /* | ||
| 653 | * Take a reference for this transaction on the buf item. | ||
| 654 | */ | ||
| 655 | atomic_inc(&bip->bli_refcount); | ||
| 656 | |||
| 657 | /* | ||
| 658 | * Get a log_item_desc to point at the new item. | ||
| 659 | */ | ||
| 660 | (void) xfs_trans_add_item(tp, (xfs_log_item_t *)bip); | ||
| 661 | |||
| 662 | /* | ||
| 663 | * Initialize b_fsprivate2 so we can find it with incore_match() | ||
| 664 | * in xfs_trans_get_buf() and friends above. | ||
| 665 | */ | ||
| 666 | XFS_BUF_SET_FSPRIVATE2(bp, tp); | ||
| 667 | |||
| 668 | trace_xfs_trans_bjoin(bip); | ||
| 669 | } | ||
| 670 | |||
| 671 | /* | ||
| 672 | * Mark the buffer as not needing to be unlocked when the buf item's | 589 | * Mark the buffer as not needing to be unlocked when the buf item's |
| 673 | * IOP_UNLOCK() routine is called. The buffer must already be locked | 590 | * IOP_UNLOCK() routine is called. The buffer must already be locked |
| 674 | * and associated with the given transaction. | 591 | * and associated with the given transaction. |
