diff options
author | Christoph Hellwig <hch@infradead.org> | 2010-06-23 04:11:15 -0400 |
---|---|---|
committer | Alex Elder <aelder@sgi.com> | 2010-07-26 14:16:34 -0400 |
commit | 9412e3181c0ef82efc3d8e88d73e583ec10c34e9 (patch) | |
tree | 10ed24cdebd9922e7cd9414941e5c59e9e5fafab /fs/xfs/xfs_buf_item.c | |
parent | e98c414f9a3134fe7efc56ef8f1d394b54bfd40e (diff) |
xfs: merge iop_unpin_remove into iop_unpin
The unpin_remove item operation instances always share most of the
implementation with the respective unpin implementation. So instead
of keeping two different entry points add a remove flag to the unpin
operation and share the code more easily.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Diffstat (limited to 'fs/xfs/xfs_buf_item.c')
-rw-r--r-- | fs/xfs/xfs_buf_item.c | 74 |
1 files changed, 28 insertions, 46 deletions
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 711f69abbbe4..93899953c603 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c | |||
@@ -388,20 +388,25 @@ xfs_buf_item_pin( | |||
388 | * Also drop the reference to the buf item for the current transaction. | 388 | * Also drop the reference to the buf item for the current transaction. |
389 | * If the XFS_BLI_STALE flag is set and we are the last reference, | 389 | * If the XFS_BLI_STALE flag is set and we are the last reference, |
390 | * then free up the buf log item and unlock the buffer. | 390 | * then free up the buf log item and unlock the buffer. |
391 | * | ||
392 | * If the remove flag is set we are called from uncommit in the | ||
393 | * forced-shutdown path. If that is true and the reference count on | ||
394 | * the log item is going to drop to zero we need to free the item's | ||
395 | * descriptor in the transaction. | ||
391 | */ | 396 | */ |
392 | STATIC void | 397 | STATIC void |
393 | xfs_buf_item_unpin( | 398 | xfs_buf_item_unpin( |
394 | xfs_buf_log_item_t *bip) | 399 | xfs_buf_log_item_t *bip, |
400 | int remove) | ||
395 | { | 401 | { |
396 | struct xfs_ail *ailp; | 402 | struct xfs_ail *ailp; |
397 | xfs_buf_t *bp; | 403 | xfs_buf_t *bp = bip->bli_buf; |
398 | int freed; | 404 | int freed; |
399 | int stale = bip->bli_flags & XFS_BLI_STALE; | 405 | int stale = bip->bli_flags & XFS_BLI_STALE; |
400 | 406 | ||
401 | bp = bip->bli_buf; | ||
402 | ASSERT(bp != NULL); | ||
403 | ASSERT(XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *) == bip); | 407 | ASSERT(XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *) == bip); |
404 | ASSERT(atomic_read(&bip->bli_refcount) > 0); | 408 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
409 | |||
405 | trace_xfs_buf_item_unpin(bip); | 410 | trace_xfs_buf_item_unpin(bip); |
406 | 411 | ||
407 | freed = atomic_dec_and_test(&bip->bli_refcount); | 412 | freed = atomic_dec_and_test(&bip->bli_refcount); |
@@ -413,8 +418,26 @@ xfs_buf_item_unpin( | |||
413 | ASSERT(!(XFS_BUF_ISDELAYWRITE(bp))); | 418 | ASSERT(!(XFS_BUF_ISDELAYWRITE(bp))); |
414 | ASSERT(XFS_BUF_ISSTALE(bp)); | 419 | ASSERT(XFS_BUF_ISSTALE(bp)); |
415 | ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL); | 420 | ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL); |
421 | |||
416 | trace_xfs_buf_item_unpin_stale(bip); | 422 | trace_xfs_buf_item_unpin_stale(bip); |
417 | 423 | ||
424 | if (remove) { | ||
425 | /* | ||
426 | * We have to remove the log item from the transaction | ||
427 | * as we are about to release our reference to the | ||
428 | * buffer. If we don't, the unlock that occurs later | ||
429 | * in xfs_trans_uncommit() will ry to reference the | ||
430 | * buffer which we no longer have a hold on. | ||
431 | */ | ||
432 | xfs_trans_del_item(&bip->bli_item); | ||
433 | |||
434 | /* | ||
435 | * Since the transaction no longer refers to the buffer, | ||
436 | * the buffer should no longer refer to the transaction. | ||
437 | */ | ||
438 | XFS_BUF_SET_FSPRIVATE2(bp, NULL); | ||
439 | } | ||
440 | |||
418 | /* | 441 | /* |
419 | * If we get called here because of an IO error, we may | 442 | * If we get called here because of an IO error, we may |
420 | * or may not have the item on the AIL. xfs_trans_ail_delete() | 443 | * or may not have the item on the AIL. xfs_trans_ail_delete() |
@@ -436,45 +459,6 @@ xfs_buf_item_unpin( | |||
436 | } | 459 | } |
437 | 460 | ||
438 | /* | 461 | /* |
439 | * this is called from uncommit in the forced-shutdown path. | ||
440 | * we need to check to see if the reference count on the log item | ||
441 | * is going to drop to zero. If so, unpin will free the log item | ||
442 | * so we need to free the item's descriptor (that points to the item) | ||
443 | * in the transaction. | ||
444 | */ | ||
445 | STATIC void | ||
446 | xfs_buf_item_unpin_remove( | ||
447 | xfs_buf_log_item_t *bip, | ||
448 | xfs_trans_t *tp) | ||
449 | { | ||
450 | /* will xfs_buf_item_unpin() call xfs_buf_item_relse()? */ | ||
451 | if ((atomic_read(&bip->bli_refcount) == 1) && | ||
452 | (bip->bli_flags & XFS_BLI_STALE)) { | ||
453 | /* | ||
454 | * yes -- We can safely do some work here and then call | ||
455 | * buf_item_unpin to do the rest because we are | ||
456 | * are holding the buffer locked so no one else will be | ||
457 | * able to bump up the refcount. We have to remove the | ||
458 | * log item from the transaction as we are about to release | ||
459 | * our reference to the buffer. If we don't, the unlock that | ||
460 | * occurs later in the xfs_trans_uncommit() will try to | ||
461 | * reference the buffer which we no longer have a hold on. | ||
462 | */ | ||
463 | ASSERT(XFS_BUF_VALUSEMA(bip->bli_buf) <= 0); | ||
464 | trace_xfs_buf_item_unpin_stale(bip); | ||
465 | |||
466 | xfs_trans_del_item(&bip->bli_item); | ||
467 | |||
468 | /* | ||
469 | * Since the transaction no longer refers to the buffer, the | ||
470 | * buffer should no longer refer to the transaction. | ||
471 | */ | ||
472 | XFS_BUF_SET_FSPRIVATE2(bip->bli_buf, NULL); | ||
473 | } | ||
474 | xfs_buf_item_unpin(bip); | ||
475 | } | ||
476 | |||
477 | /* | ||
478 | * This is called to attempt to lock the buffer associated with this | 462 | * This is called to attempt to lock the buffer associated with this |
479 | * buf log item. Don't sleep on the buffer lock. If we can't get | 463 | * buf log item. Don't sleep on the buffer lock. If we can't get |
480 | * the lock right away, return 0. If we can get the lock, take a | 464 | * the lock right away, return 0. If we can get the lock, take a |
@@ -669,9 +653,7 @@ static struct xfs_item_ops xfs_buf_item_ops = { | |||
669 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) | 653 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) |
670 | xfs_buf_item_format, | 654 | xfs_buf_item_format, |
671 | .iop_pin = (void(*)(xfs_log_item_t*))xfs_buf_item_pin, | 655 | .iop_pin = (void(*)(xfs_log_item_t*))xfs_buf_item_pin, |
672 | .iop_unpin = (void(*)(xfs_log_item_t*))xfs_buf_item_unpin, | 656 | .iop_unpin = (void(*)(xfs_log_item_t*, int))xfs_buf_item_unpin, |
673 | .iop_unpin_remove = (void(*)(xfs_log_item_t*, xfs_trans_t *)) | ||
674 | xfs_buf_item_unpin_remove, | ||
675 | .iop_trylock = (uint(*)(xfs_log_item_t*))xfs_buf_item_trylock, | 657 | .iop_trylock = (uint(*)(xfs_log_item_t*))xfs_buf_item_trylock, |
676 | .iop_unlock = (void(*)(xfs_log_item_t*))xfs_buf_item_unlock, | 658 | .iop_unlock = (void(*)(xfs_log_item_t*))xfs_buf_item_unlock, |
677 | .iop_committed = (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t)) | 659 | .iop_committed = (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t)) |