diff options
Diffstat (limited to 'fs/xfs/xfs_buf_item.c')
-rw-r--r-- | fs/xfs/xfs_buf_item.c | 87 |
1 files changed, 58 insertions, 29 deletions
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 4ec431777048..bfc4e0c26fd3 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 | */ |
@@ -299,18 +310,36 @@ xfs_buf_item_format( | |||
299 | 310 | ||
300 | /* | 311 | /* |
301 | * If it is an inode buffer, transfer the in-memory state to the | 312 | * If it is an inode buffer, transfer the in-memory state to the |
302 | * format flags and clear the in-memory state. We do not transfer | 313 | * format flags and clear the in-memory state. |
314 | * | ||
315 | * For buffer based inode allocation, we do not transfer | ||
303 | * this state if the inode buffer allocation has not yet been committed | 316 | * this state if the inode buffer allocation has not yet been committed |
304 | * to the log as setting the XFS_BLI_INODE_BUF flag will prevent | 317 | * to the log as setting the XFS_BLI_INODE_BUF flag will prevent |
305 | * correct replay of the inode allocation. | 318 | * correct replay of the inode allocation. |
319 | * | ||
320 | * For icreate item based inode allocation, the buffers aren't written | ||
321 | * to the journal during allocation, and hence we should always tag the | ||
322 | * buffer as an inode buffer so that the correct unlinked list replay | ||
323 | * occurs during recovery. | ||
306 | */ | 324 | */ |
307 | if (bip->bli_flags & XFS_BLI_INODE_BUF) { | 325 | if (bip->bli_flags & XFS_BLI_INODE_BUF) { |
308 | if (!((bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF) && | 326 | if (xfs_sb_version_hascrc(&lip->li_mountp->m_sb) || |
327 | !((bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF) && | ||
309 | xfs_log_item_in_current_chkpt(lip))) | 328 | xfs_log_item_in_current_chkpt(lip))) |
310 | bip->__bli_format.blf_flags |= XFS_BLF_INODE_BUF; | 329 | bip->__bli_format.blf_flags |= XFS_BLF_INODE_BUF; |
311 | bip->bli_flags &= ~XFS_BLI_INODE_BUF; | 330 | bip->bli_flags &= ~XFS_BLI_INODE_BUF; |
312 | } | 331 | } |
313 | 332 | ||
333 | if ((bip->bli_flags & (XFS_BLI_ORDERED|XFS_BLI_STALE)) == | ||
334 | XFS_BLI_ORDERED) { | ||
335 | /* | ||
336 | * The buffer has been logged just to order it. It is not being | ||
337 | * included in the transaction commit, so don't format it. | ||
338 | */ | ||
339 | trace_xfs_buf_item_format_ordered(bip); | ||
340 | return; | ||
341 | } | ||
342 | |||
314 | for (i = 0; i < bip->bli_format_count; i++) { | 343 | for (i = 0; i < bip->bli_format_count; i++) { |
315 | vecp = xfs_buf_item_format_segment(bip, vecp, offset, | 344 | vecp = xfs_buf_item_format_segment(bip, vecp, offset, |
316 | &bip->bli_formats[i]); | 345 | &bip->bli_formats[i]); |
@@ -340,6 +369,7 @@ xfs_buf_item_pin( | |||
340 | 369 | ||
341 | ASSERT(atomic_read(&bip->bli_refcount) > 0); | 370 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
342 | ASSERT((bip->bli_flags & XFS_BLI_LOGGED) || | 371 | ASSERT((bip->bli_flags & XFS_BLI_LOGGED) || |
372 | (bip->bli_flags & XFS_BLI_ORDERED) || | ||
343 | (bip->bli_flags & XFS_BLI_STALE)); | 373 | (bip->bli_flags & XFS_BLI_STALE)); |
344 | 374 | ||
345 | trace_xfs_buf_item_pin(bip); | 375 | trace_xfs_buf_item_pin(bip); |
@@ -512,8 +542,9 @@ xfs_buf_item_unlock( | |||
512 | { | 542 | { |
513 | struct xfs_buf_log_item *bip = BUF_ITEM(lip); | 543 | struct xfs_buf_log_item *bip = BUF_ITEM(lip); |
514 | struct xfs_buf *bp = bip->bli_buf; | 544 | struct xfs_buf *bp = bip->bli_buf; |
515 | int aborted, clean, i; | 545 | bool clean; |
516 | uint hold; | 546 | bool aborted; |
547 | int flags; | ||
517 | 548 | ||
518 | /* Clear the buffer's association with this transaction. */ | 549 | /* Clear the buffer's association with this transaction. */ |
519 | bp->b_transp = NULL; | 550 | bp->b_transp = NULL; |
@@ -524,23 +555,21 @@ xfs_buf_item_unlock( | |||
524 | * (cancelled) buffers at unpin time, but we'll never go through the | 555 | * (cancelled) buffers at unpin time, but we'll never go through the |
525 | * pin/unpin cycle if we abort inside commit. | 556 | * pin/unpin cycle if we abort inside commit. |
526 | */ | 557 | */ |
527 | aborted = (lip->li_flags & XFS_LI_ABORTED) != 0; | 558 | aborted = (lip->li_flags & XFS_LI_ABORTED) ? true : false; |
528 | |||
529 | /* | 559 | /* |
530 | * Before possibly freeing the buf item, determine if we should | 560 | * Before possibly freeing the buf item, copy the per-transaction state |
531 | * release the buffer at the end of this routine. | 561 | * so we can reference it safely later after clearing it from the |
562 | * buffer log item. | ||
532 | */ | 563 | */ |
533 | hold = bip->bli_flags & XFS_BLI_HOLD; | 564 | flags = bip->bli_flags; |
534 | 565 | 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 | 566 | ||
538 | /* | 567 | /* |
539 | * If the buf item is marked stale, then don't do anything. We'll | 568 | * 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 | 569 | * unlock the buffer and free the buf item when the buffer is unpinned |
541 | * for the last time. | 570 | * for the last time. |
542 | */ | 571 | */ |
543 | if (bip->bli_flags & XFS_BLI_STALE) { | 572 | if (flags & XFS_BLI_STALE) { |
544 | trace_xfs_buf_item_unlock_stale(bip); | 573 | trace_xfs_buf_item_unlock_stale(bip); |
545 | ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); | 574 | ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); |
546 | if (!aborted) { | 575 | if (!aborted) { |
@@ -557,13 +586,19 @@ xfs_buf_item_unlock( | |||
557 | * be the only reference to the buf item, so we free it anyway | 586 | * 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 | 587 | * regardless of whether it is dirty or not. A dirty abort implies a |
559 | * shutdown, anyway. | 588 | * shutdown, anyway. |
589 | * | ||
590 | * Ordered buffers are dirty but may have no recorded changes, so ensure | ||
591 | * we only release clean items here. | ||
560 | */ | 592 | */ |
561 | clean = 1; | 593 | clean = (flags & XFS_BLI_DIRTY) ? false : true; |
562 | for (i = 0; i < bip->bli_format_count; i++) { | 594 | if (clean) { |
563 | if (!xfs_bitmap_empty(bip->bli_formats[i].blf_data_map, | 595 | int i; |
564 | bip->bli_formats[i].blf_map_size)) { | 596 | for (i = 0; i < bip->bli_format_count; i++) { |
565 | clean = 0; | 597 | if (!xfs_bitmap_empty(bip->bli_formats[i].blf_data_map, |
566 | break; | 598 | bip->bli_formats[i].blf_map_size)) { |
599 | clean = false; | ||
600 | break; | ||
601 | } | ||
567 | } | 602 | } |
568 | } | 603 | } |
569 | if (clean) | 604 | if (clean) |
@@ -576,7 +611,7 @@ xfs_buf_item_unlock( | |||
576 | } else | 611 | } else |
577 | atomic_dec(&bip->bli_refcount); | 612 | atomic_dec(&bip->bli_refcount); |
578 | 613 | ||
579 | if (!hold) | 614 | if (!(flags & XFS_BLI_HOLD)) |
580 | xfs_buf_relse(bp); | 615 | xfs_buf_relse(bp); |
581 | } | 616 | } |
582 | 617 | ||
@@ -842,12 +877,6 @@ xfs_buf_item_log( | |||
842 | struct xfs_buf *bp = bip->bli_buf; | 877 | struct xfs_buf *bp = bip->bli_buf; |
843 | 878 | ||
844 | /* | 879 | /* |
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. | 880 | * walk each buffer segment and mark them dirty appropriately. |
852 | */ | 881 | */ |
853 | start = 0; | 882 | start = 0; |
@@ -873,7 +902,7 @@ xfs_buf_item_log( | |||
873 | 902 | ||
874 | 903 | ||
875 | /* | 904 | /* |
876 | * Return 1 if the buffer has some data that has been logged (at any | 905 | * 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. | 906 | * point, not just the current transaction) and 0 if not. |
878 | */ | 907 | */ |
879 | uint | 908 | uint |
@@ -907,11 +936,11 @@ void | |||
907 | xfs_buf_item_relse( | 936 | xfs_buf_item_relse( |
908 | xfs_buf_t *bp) | 937 | xfs_buf_t *bp) |
909 | { | 938 | { |
910 | xfs_buf_log_item_t *bip; | 939 | xfs_buf_log_item_t *bip = bp->b_fspriv; |
911 | 940 | ||
912 | trace_xfs_buf_item_relse(bp, _RET_IP_); | 941 | trace_xfs_buf_item_relse(bp, _RET_IP_); |
942 | ASSERT(!(bip->bli_item.li_flags & XFS_LI_IN_AIL)); | ||
913 | 943 | ||
914 | bip = bp->b_fspriv; | ||
915 | bp->b_fspriv = bip->bli_item.li_bio_list; | 944 | bp->b_fspriv = bip->bli_item.li_bio_list; |
916 | if (bp->b_fspriv == NULL) | 945 | if (bp->b_fspriv == NULL) |
917 | bp->b_iodone = NULL; | 946 | bp->b_iodone = NULL; |