aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2010-05-06 21:04:34 -0400
committerAlex Elder <aelder@sgi.com>2010-05-24 11:33:31 -0400
commit64fc35de60da3b1fe970168d10914bf1cf34a3e3 (patch)
tree150216a336bbb3a0f7066763b675fb6a0e6f3061
parent3383ca5780f88bb2c119174045ed77d5ece08072 (diff)
xfs: modify buffer item reference counting
The buffer log item reference counts used to take referenceѕ for every transaction, similar to the pin counting. This is symmetric (like the pin/unpin) with respect to transaction completion, but with dleayed logging becomes assymetric as the pinning becomes assymetric w.r.t. transaction completion. To make both cases the same, allow the buffer pinning to take a reference to the buffer log item and always drop the reference the transaction has on it when being unlocked. This is balanced correctly because the unpin operation always drops a reference to the log item. Hence reference counting becomes symmetric w.r.t. item pinning as well as w.r.t active transactions and as a result the reference counting model remain consistent between normal and delayed logging. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Alex Elder <aelder@sgi.com>
-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/*