diff options
Diffstat (limited to 'fs/xfs/xfs_buf_item.c')
-rw-r--r-- | fs/xfs/xfs_buf_item.c | 75 |
1 files changed, 48 insertions, 27 deletions
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 4ec431777048..61f68768ee84 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c | |||
@@ -140,6 +140,16 @@ xfs_buf_item_size( | |||
140 | 140 | ||
141 | ASSERT(bip->bli_flags & XFS_BLI_LOGGED); | 141 | ASSERT(bip->bli_flags & XFS_BLI_LOGGED); |
142 | 142 | ||
143 | if (bip->bli_flags & XFS_BLI_ORDERED) { | ||
144 | /* | ||
145 | * The buffer has been logged just to order it. | ||
146 | * It is not being included in the transaction | ||
147 | * commit, so no vectors are used at all. | ||
148 | */ | ||
149 | trace_xfs_buf_item_size_ordered(bip); | ||
150 | return XFS_LOG_VEC_ORDERED; | ||
151 | } | ||
152 | |||
143 | /* | 153 | /* |
144 | * the vector count is based on the number of buffer vectors we have | 154 | * the vector count is based on the number of buffer vectors we have |
145 | * dirty bits in. This will only be greater than one when we have a | 155 | * dirty bits in. This will only be greater than one when we have a |
@@ -212,6 +222,7 @@ xfs_buf_item_format_segment( | |||
212 | goto out; | 222 | goto out; |
213 | } | 223 | } |
214 | 224 | ||
225 | |||
215 | /* | 226 | /* |
216 | * Fill in an iovec for each set of contiguous chunks. | 227 | * Fill in an iovec for each set of contiguous chunks. |
217 | */ | 228 | */ |
@@ -311,6 +322,16 @@ xfs_buf_item_format( | |||
311 | bip->bli_flags &= ~XFS_BLI_INODE_BUF; | 322 | bip->bli_flags &= ~XFS_BLI_INODE_BUF; |
312 | } | 323 | } |
313 | 324 | ||
325 | if ((bip->bli_flags & (XFS_BLI_ORDERED|XFS_BLI_STALE)) == | ||
326 | XFS_BLI_ORDERED) { | ||
327 | /* | ||
328 | * The buffer has been logged just to order it. It is not being | ||
329 | * included in the transaction commit, so don't format it. | ||
330 | */ | ||
331 | trace_xfs_buf_item_format_ordered(bip); | ||
332 | return; | ||
333 | } | ||
334 | |||
314 | for (i = 0; i < bip->bli_format_count; i++) { | 335 | for (i = 0; i < bip->bli_format_count; i++) { |
315 | vecp = xfs_buf_item_format_segment(bip, vecp, offset, | 336 | vecp = xfs_buf_item_format_segment(bip, vecp, offset, |
316 | &bip->bli_formats[i]); | 337 | &bip->bli_formats[i]); |
@@ -340,6 +361,7 @@ xfs_buf_item_pin( | |||
340 | 361 | ||
341 | ASSERT(atomic_read(&bip->bli_refcount) > 0); | 362 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
342 | ASSERT((bip->bli_flags & XFS_BLI_LOGGED) || | 363 | ASSERT((bip->bli_flags & XFS_BLI_LOGGED) || |
364 | (bip->bli_flags & XFS_BLI_ORDERED) || | ||
343 | (bip->bli_flags & XFS_BLI_STALE)); | 365 | (bip->bli_flags & XFS_BLI_STALE)); |
344 | 366 | ||
345 | trace_xfs_buf_item_pin(bip); | 367 | trace_xfs_buf_item_pin(bip); |
@@ -512,8 +534,9 @@ xfs_buf_item_unlock( | |||
512 | { | 534 | { |
513 | struct xfs_buf_log_item *bip = BUF_ITEM(lip); | 535 | struct xfs_buf_log_item *bip = BUF_ITEM(lip); |
514 | struct xfs_buf *bp = bip->bli_buf; | 536 | struct xfs_buf *bp = bip->bli_buf; |
515 | int aborted, clean, i; | 537 | bool clean; |
516 | uint hold; | 538 | bool aborted; |
539 | int flags; | ||
517 | 540 | ||
518 | /* Clear the buffer's association with this transaction. */ | 541 | /* Clear the buffer's association with this transaction. */ |
519 | bp->b_transp = NULL; | 542 | bp->b_transp = NULL; |
@@ -524,23 +547,21 @@ xfs_buf_item_unlock( | |||
524 | * (cancelled) buffers at unpin time, but we'll never go through the | 547 | * (cancelled) buffers at unpin time, but we'll never go through the |
525 | * pin/unpin cycle if we abort inside commit. | 548 | * pin/unpin cycle if we abort inside commit. |
526 | */ | 549 | */ |
527 | aborted = (lip->li_flags & XFS_LI_ABORTED) != 0; | 550 | aborted = (lip->li_flags & XFS_LI_ABORTED) ? true : false; |
528 | |||
529 | /* | 551 | /* |
530 | * Before possibly freeing the buf item, determine if we should | 552 | * Before possibly freeing the buf item, copy the per-transaction state |
531 | * release the buffer at the end of this routine. | 553 | * so we can reference it safely later after clearing it from the |
554 | * buffer log item. | ||
532 | */ | 555 | */ |
533 | hold = bip->bli_flags & XFS_BLI_HOLD; | 556 | flags = bip->bli_flags; |
534 | 557 | bip->bli_flags &= ~(XFS_BLI_LOGGED | XFS_BLI_HOLD | XFS_BLI_ORDERED); | |
535 | /* Clear the per transaction state. */ | ||
536 | bip->bli_flags &= ~(XFS_BLI_LOGGED | XFS_BLI_HOLD); | ||
537 | 558 | ||
538 | /* | 559 | /* |
539 | * If the buf item is marked stale, then don't do anything. We'll | 560 | * If the buf item is marked stale, then don't do anything. We'll |
540 | * unlock the buffer and free the buf item when the buffer is unpinned | 561 | * unlock the buffer and free the buf item when the buffer is unpinned |
541 | * for the last time. | 562 | * for the last time. |
542 | */ | 563 | */ |
543 | if (bip->bli_flags & XFS_BLI_STALE) { | 564 | if (flags & XFS_BLI_STALE) { |
544 | trace_xfs_buf_item_unlock_stale(bip); | 565 | trace_xfs_buf_item_unlock_stale(bip); |
545 | ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); | 566 | ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); |
546 | if (!aborted) { | 567 | if (!aborted) { |
@@ -557,13 +578,19 @@ xfs_buf_item_unlock( | |||
557 | * be the only reference to the buf item, so we free it anyway | 578 | * be the only reference to the buf item, so we free it anyway |
558 | * regardless of whether it is dirty or not. A dirty abort implies a | 579 | * regardless of whether it is dirty or not. A dirty abort implies a |
559 | * shutdown, anyway. | 580 | * shutdown, anyway. |
581 | * | ||
582 | * Ordered buffers are dirty but may have no recorded changes, so ensure | ||
583 | * we only release clean items here. | ||
560 | */ | 584 | */ |
561 | clean = 1; | 585 | clean = (flags & XFS_BLI_DIRTY) ? false : true; |
562 | for (i = 0; i < bip->bli_format_count; i++) { | 586 | if (clean) { |
563 | if (!xfs_bitmap_empty(bip->bli_formats[i].blf_data_map, | 587 | int i; |
564 | bip->bli_formats[i].blf_map_size)) { | 588 | for (i = 0; i < bip->bli_format_count; i++) { |
565 | clean = 0; | 589 | if (!xfs_bitmap_empty(bip->bli_formats[i].blf_data_map, |
566 | break; | 590 | bip->bli_formats[i].blf_map_size)) { |
591 | clean = false; | ||
592 | break; | ||
593 | } | ||
567 | } | 594 | } |
568 | } | 595 | } |
569 | if (clean) | 596 | if (clean) |
@@ -576,7 +603,7 @@ xfs_buf_item_unlock( | |||
576 | } else | 603 | } else |
577 | atomic_dec(&bip->bli_refcount); | 604 | atomic_dec(&bip->bli_refcount); |
578 | 605 | ||
579 | if (!hold) | 606 | if (!(flags & XFS_BLI_HOLD)) |
580 | xfs_buf_relse(bp); | 607 | xfs_buf_relse(bp); |
581 | } | 608 | } |
582 | 609 | ||
@@ -842,12 +869,6 @@ xfs_buf_item_log( | |||
842 | struct xfs_buf *bp = bip->bli_buf; | 869 | struct xfs_buf *bp = bip->bli_buf; |
843 | 870 | ||
844 | /* | 871 | /* |
845 | * Mark the item as having some dirty data for | ||
846 | * quick reference in xfs_buf_item_dirty. | ||
847 | */ | ||
848 | bip->bli_flags |= XFS_BLI_DIRTY; | ||
849 | |||
850 | /* | ||
851 | * walk each buffer segment and mark them dirty appropriately. | 872 | * walk each buffer segment and mark them dirty appropriately. |
852 | */ | 873 | */ |
853 | start = 0; | 874 | start = 0; |
@@ -873,7 +894,7 @@ xfs_buf_item_log( | |||
873 | 894 | ||
874 | 895 | ||
875 | /* | 896 | /* |
876 | * Return 1 if the buffer has some data that has been logged (at any | 897 | * Return 1 if the buffer has been logged or ordered in a transaction (at any |
877 | * point, not just the current transaction) and 0 if not. | 898 | * point, not just the current transaction) and 0 if not. |
878 | */ | 899 | */ |
879 | uint | 900 | uint |
@@ -907,11 +928,11 @@ void | |||
907 | xfs_buf_item_relse( | 928 | xfs_buf_item_relse( |
908 | xfs_buf_t *bp) | 929 | xfs_buf_t *bp) |
909 | { | 930 | { |
910 | xfs_buf_log_item_t *bip; | 931 | xfs_buf_log_item_t *bip = bp->b_fspriv; |
911 | 932 | ||
912 | trace_xfs_buf_item_relse(bp, _RET_IP_); | 933 | trace_xfs_buf_item_relse(bp, _RET_IP_); |
934 | ASSERT(!(bip->bli_item.li_flags & XFS_LI_IN_AIL)); | ||
913 | 935 | ||
914 | bip = bp->b_fspriv; | ||
915 | bp->b_fspriv = bip->bli_item.li_bio_list; | 936 | bp->b_fspriv = bip->bli_item.li_bio_list; |
916 | if (bp->b_fspriv == NULL) | 937 | if (bp->b_fspriv == NULL) |
917 | bp->b_iodone = NULL; | 938 | bp->b_iodone = NULL; |