aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_buf_item.c110
1 files changed, 50 insertions, 60 deletions
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 240340a4727b..4cd5f615371d 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -341,10 +341,15 @@ xfs_buf_item_format(
341} 341}
342 342
343/* 343/*
344 * This is called to pin the buffer associated with the buf log 344 * This is called to pin the buffer associated with the buf log item in memory
345 * item in memory so it cannot be written out. Simply call bpin() 345 * so it cannot be written out. Simply call bpin() on the buffer to do this.
346 * on the buffer to do this. 346 *
347 * We also always take a reference to the buffer log item here so that the bli
348 * is held while the item is pinned in memory. This means that we can
349 * unconditionally drop the reference count a transaction holds when the
350 * transaction is completed.
347 */ 351 */
352
348STATIC void 353STATIC void
349xfs_buf_item_pin( 354xfs_buf_item_pin(
350 xfs_buf_log_item_t *bip) 355 xfs_buf_log_item_t *bip)
@@ -356,6 +361,7 @@ xfs_buf_item_pin(
356 ASSERT(atomic_read(&bip->bli_refcount) > 0); 361 ASSERT(atomic_read(&bip->bli_refcount) > 0);
357 ASSERT((bip->bli_flags & XFS_BLI_LOGGED) || 362 ASSERT((bip->bli_flags & XFS_BLI_LOGGED) ||
358 (bip->bli_flags & XFS_BLI_STALE)); 363 (bip->bli_flags & XFS_BLI_STALE));
364 atomic_inc(&bip->bli_refcount);
359 trace_xfs_buf_item_pin(bip); 365 trace_xfs_buf_item_pin(bip);
360 xfs_bpin(bp); 366 xfs_bpin(bp);
361} 367}
@@ -489,20 +495,23 @@ xfs_buf_item_trylock(
489} 495}
490 496
491/* 497/*
492 * Release the buffer associated with the buf log item. 498 * Release the buffer associated with the buf log item. If there is no dirty
493 * If there is no dirty logged data associated with the 499 * logged data associated with the buffer recorded in the buf log item, then
494 * buffer recorded in the buf log item, then free the 500 * free the buf log item and remove the reference to it in the buffer.
495 * buf log item and remove the reference to it in the
496 * buffer.
497 * 501 *
498 * This call ignores the recursion count. It is only called 502 * This call ignores the recursion count. It is only called when the buffer
499 * when the buffer should REALLY be unlocked, regardless 503 * should REALLY be unlocked, regardless of the recursion count.
500 * of the recursion count.
501 * 504 *
502 * If the XFS_BLI_HOLD flag is set in the buf log item, then 505 * We unconditionally drop the transaction's reference to the log item. If the
503 * free the log item if necessary but do not unlock the buffer. 506 * item was logged, then another reference was taken when it was pinned, so we
504 * This is for support of xfs_trans_bhold(). Make sure the 507 * can safely drop the transaction reference now. This also allows us to avoid
505 * XFS_BLI_HOLD field is cleared if we don't free the item. 508 * potential races with the unpin code freeing the bli by not referencing the
509 * bli after we've dropped the reference count.
510 *
511 * If the XFS_BLI_HOLD flag is set in the buf log item, then free the log item
512 * if necessary but do not unlock the buffer. This is for support of
513 * xfs_trans_bhold(). Make sure the XFS_BLI_HOLD field is cleared if we don't
514 * free the item.
506 */ 515 */
507STATIC void 516STATIC void
508xfs_buf_item_unlock( 517xfs_buf_item_unlock(
@@ -514,73 +523,54 @@ xfs_buf_item_unlock(
514 523
515 bp = bip->bli_buf; 524 bp = bip->bli_buf;
516 525
517 /* 526 /* Clear the buffer's association with this transaction. */
518 * Clear the buffer's association with this transaction.
519 */
520 XFS_BUF_SET_FSPRIVATE2(bp, NULL); 527 XFS_BUF_SET_FSPRIVATE2(bp, NULL);
521 528
522 /* 529 /*
523 * If this is a transaction abort, don't return early. 530 * If this is a transaction abort, don't return early. Instead, allow
524 * Instead, allow the brelse to happen. 531 * the brelse to happen. Normally it would be done for stale
525 * Normally it would be done for stale (cancelled) buffers 532 * (cancelled) buffers at unpin time, but we'll never go through the
526 * at unpin time, but we'll never go through the pin/unpin 533 * pin/unpin cycle if we abort inside commit.
527 * cycle if we abort inside commit.
528 */ 534 */
529 aborted = (bip->bli_item.li_flags & XFS_LI_ABORTED) != 0; 535 aborted = (bip->bli_item.li_flags & XFS_LI_ABORTED) != 0;
530 536
531 /* 537 /*
532 * If the buf item is marked stale, then don't do anything. 538 * Before possibly freeing the buf item, determine if we should
533 * We'll unlock the buffer and free the buf item when the 539 * release the buffer at the end of this routine.
534 * buffer is unpinned for the last time. 540 */
541 hold = bip->bli_flags & XFS_BLI_HOLD;
542
543 /* Clear the per transaction state. */
544 bip->bli_flags &= ~(XFS_BLI_LOGGED | XFS_BLI_HOLD);
545
546 /*
547 * If the buf item is marked stale, then don't do anything. We'll
548 * unlock the buffer and free the buf item when the buffer is unpinned
549 * for the last time.
535 */ 550 */
536 if (bip->bli_flags & XFS_BLI_STALE) { 551 if (bip->bli_flags & XFS_BLI_STALE) {
537 bip->bli_flags &= ~XFS_BLI_LOGGED;
538 trace_xfs_buf_item_unlock_stale(bip); 552 trace_xfs_buf_item_unlock_stale(bip);
539 ASSERT(bip->bli_format.blf_flags & XFS_BLI_CANCEL); 553 ASSERT(bip->bli_format.blf_flags & XFS_BLI_CANCEL);
540 if (!aborted) 554 if (!aborted) {
555 atomic_dec(&bip->bli_refcount);
541 return; 556 return;
557 }
542 } 558 }
543 559
544 /*
545 * Drop the transaction's reference to the log item if
546 * it was not logged as part of the transaction. Otherwise
547 * we'll drop the reference in xfs_buf_item_unpin() when
548 * the transaction is really through with the buffer.
549 */
550 if (!(bip->bli_flags & XFS_BLI_LOGGED)) {
551 atomic_dec(&bip->bli_refcount);
552 } else {
553 /*
554 * Clear the logged flag since this is per
555 * transaction state.
556 */
557 bip->bli_flags &= ~XFS_BLI_LOGGED;
558 }
559
560 /*
561 * Before possibly freeing the buf item, determine if we should
562 * release the buffer at the end of this routine.
563 */
564 hold = bip->bli_flags & XFS_BLI_HOLD;
565 trace_xfs_buf_item_unlock(bip); 560 trace_xfs_buf_item_unlock(bip);
566 561
567 /* 562 /*
568 * If the buf item isn't tracking any data, free it. 563 * If the buf item isn't tracking any data, free it, otherwise drop the
569 * Otherwise, if XFS_BLI_HOLD is set clear it. 564 * reference we hold to it.
570 */ 565 */
571 if (xfs_bitmap_empty(bip->bli_format.blf_data_map, 566 if (xfs_bitmap_empty(bip->bli_format.blf_data_map,
572 bip->bli_format.blf_map_size)) { 567 bip->bli_format.blf_map_size))
573 xfs_buf_item_relse(bp); 568 xfs_buf_item_relse(bp);
574 } else if (hold) { 569 else
575 bip->bli_flags &= ~XFS_BLI_HOLD; 570 atomic_dec(&bip->bli_refcount);
576 }
577 571
578 /* 572 if (!hold)
579 * Release the buffer if XFS_BLI_HOLD was not set.
580 */
581 if (!hold) {
582 xfs_buf_relse(bp); 573 xfs_buf_relse(bp);
583 }
584} 574}
585 575
586/* 576/*