diff options
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_buf_item.c | 75 | ||||
-rw-r--r-- | fs/xfs/xfs_buf_item.h | 4 | ||||
-rw-r--r-- | fs/xfs/xfs_trace.h | 4 | ||||
-rw-r--r-- | fs/xfs/xfs_trans.h | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_trans_buf.c | 34 |
5 files changed, 87 insertions, 31 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; |
diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h index 2573d2a75fc8..0f1c247dc680 100644 --- a/fs/xfs/xfs_buf_item.h +++ b/fs/xfs/xfs_buf_item.h | |||
@@ -120,6 +120,7 @@ xfs_blft_from_flags(struct xfs_buf_log_format *blf) | |||
120 | #define XFS_BLI_INODE_ALLOC_BUF 0x10 | 120 | #define XFS_BLI_INODE_ALLOC_BUF 0x10 |
121 | #define XFS_BLI_STALE_INODE 0x20 | 121 | #define XFS_BLI_STALE_INODE 0x20 |
122 | #define XFS_BLI_INODE_BUF 0x40 | 122 | #define XFS_BLI_INODE_BUF 0x40 |
123 | #define XFS_BLI_ORDERED 0x80 | ||
123 | 124 | ||
124 | #define XFS_BLI_FLAGS \ | 125 | #define XFS_BLI_FLAGS \ |
125 | { XFS_BLI_HOLD, "HOLD" }, \ | 126 | { XFS_BLI_HOLD, "HOLD" }, \ |
@@ -128,7 +129,8 @@ xfs_blft_from_flags(struct xfs_buf_log_format *blf) | |||
128 | { XFS_BLI_LOGGED, "LOGGED" }, \ | 129 | { XFS_BLI_LOGGED, "LOGGED" }, \ |
129 | { XFS_BLI_INODE_ALLOC_BUF, "INODE_ALLOC" }, \ | 130 | { XFS_BLI_INODE_ALLOC_BUF, "INODE_ALLOC" }, \ |
130 | { XFS_BLI_STALE_INODE, "STALE_INODE" }, \ | 131 | { XFS_BLI_STALE_INODE, "STALE_INODE" }, \ |
131 | { XFS_BLI_INODE_BUF, "INODE_BUF" } | 132 | { XFS_BLI_INODE_BUF, "INODE_BUF" }, \ |
133 | { XFS_BLI_ORDERED, "ORDERED" } | ||
132 | 134 | ||
133 | 135 | ||
134 | #ifdef __KERNEL__ | 136 | #ifdef __KERNEL__ |
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index e31867270077..ee8b3a3b5d65 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h | |||
@@ -486,9 +486,12 @@ DEFINE_EVENT(xfs_buf_item_class, name, \ | |||
486 | TP_PROTO(struct xfs_buf_log_item *bip), \ | 486 | TP_PROTO(struct xfs_buf_log_item *bip), \ |
487 | TP_ARGS(bip)) | 487 | TP_ARGS(bip)) |
488 | DEFINE_BUF_ITEM_EVENT(xfs_buf_item_size); | 488 | DEFINE_BUF_ITEM_EVENT(xfs_buf_item_size); |
489 | DEFINE_BUF_ITEM_EVENT(xfs_buf_item_size_ordered); | ||
489 | DEFINE_BUF_ITEM_EVENT(xfs_buf_item_size_stale); | 490 | DEFINE_BUF_ITEM_EVENT(xfs_buf_item_size_stale); |
490 | DEFINE_BUF_ITEM_EVENT(xfs_buf_item_format); | 491 | DEFINE_BUF_ITEM_EVENT(xfs_buf_item_format); |
492 | DEFINE_BUF_ITEM_EVENT(xfs_buf_item_format_ordered); | ||
491 | DEFINE_BUF_ITEM_EVENT(xfs_buf_item_format_stale); | 493 | DEFINE_BUF_ITEM_EVENT(xfs_buf_item_format_stale); |
494 | DEFINE_BUF_ITEM_EVENT(xfs_buf_item_ordered); | ||
492 | DEFINE_BUF_ITEM_EVENT(xfs_buf_item_pin); | 495 | DEFINE_BUF_ITEM_EVENT(xfs_buf_item_pin); |
493 | DEFINE_BUF_ITEM_EVENT(xfs_buf_item_unpin); | 496 | DEFINE_BUF_ITEM_EVENT(xfs_buf_item_unpin); |
494 | DEFINE_BUF_ITEM_EVENT(xfs_buf_item_unpin_stale); | 497 | DEFINE_BUF_ITEM_EVENT(xfs_buf_item_unpin_stale); |
@@ -508,6 +511,7 @@ DEFINE_BUF_ITEM_EVENT(xfs_trans_bjoin); | |||
508 | DEFINE_BUF_ITEM_EVENT(xfs_trans_bhold); | 511 | DEFINE_BUF_ITEM_EVENT(xfs_trans_bhold); |
509 | DEFINE_BUF_ITEM_EVENT(xfs_trans_bhold_release); | 512 | DEFINE_BUF_ITEM_EVENT(xfs_trans_bhold_release); |
510 | DEFINE_BUF_ITEM_EVENT(xfs_trans_binval); | 513 | DEFINE_BUF_ITEM_EVENT(xfs_trans_binval); |
514 | DEFINE_BUF_ITEM_EVENT(xfs_trans_buf_ordered); | ||
511 | 515 | ||
512 | DECLARE_EVENT_CLASS(xfs_lock_class, | 516 | DECLARE_EVENT_CLASS(xfs_lock_class, |
513 | TP_PROTO(struct xfs_inode *ip, unsigned lock_flags, | 517 | TP_PROTO(struct xfs_inode *ip, unsigned lock_flags, |
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 6d526569820c..822570ec605a 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h | |||
@@ -498,6 +498,7 @@ void xfs_trans_bhold_release(xfs_trans_t *, struct xfs_buf *); | |||
498 | void xfs_trans_binval(xfs_trans_t *, struct xfs_buf *); | 498 | void xfs_trans_binval(xfs_trans_t *, struct xfs_buf *); |
499 | void xfs_trans_inode_buf(xfs_trans_t *, struct xfs_buf *); | 499 | void xfs_trans_inode_buf(xfs_trans_t *, struct xfs_buf *); |
500 | void xfs_trans_stale_inode_buf(xfs_trans_t *, struct xfs_buf *); | 500 | void xfs_trans_stale_inode_buf(xfs_trans_t *, struct xfs_buf *); |
501 | void xfs_trans_ordered_buf(xfs_trans_t *, struct xfs_buf *); | ||
501 | void xfs_trans_dquot_buf(xfs_trans_t *, struct xfs_buf *, uint); | 502 | void xfs_trans_dquot_buf(xfs_trans_t *, struct xfs_buf *, uint); |
502 | void xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *); | 503 | void xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *); |
503 | void xfs_trans_ichgtime(struct xfs_trans *, struct xfs_inode *, int); | 504 | void xfs_trans_ichgtime(struct xfs_trans *, struct xfs_inode *, int); |
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index 73a5fa457e16..aa5a04b844d6 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c | |||
@@ -397,7 +397,6 @@ shutdown_abort: | |||
397 | return XFS_ERROR(EIO); | 397 | return XFS_ERROR(EIO); |
398 | } | 398 | } |
399 | 399 | ||
400 | |||
401 | /* | 400 | /* |
402 | * Release the buffer bp which was previously acquired with one of the | 401 | * Release the buffer bp which was previously acquired with one of the |
403 | * xfs_trans_... buffer allocation routines if the buffer has not | 402 | * xfs_trans_... buffer allocation routines if the buffer has not |
@@ -603,8 +602,14 @@ xfs_trans_log_buf(xfs_trans_t *tp, | |||
603 | 602 | ||
604 | tp->t_flags |= XFS_TRANS_DIRTY; | 603 | tp->t_flags |= XFS_TRANS_DIRTY; |
605 | bip->bli_item.li_desc->lid_flags |= XFS_LID_DIRTY; | 604 | bip->bli_item.li_desc->lid_flags |= XFS_LID_DIRTY; |
606 | bip->bli_flags |= XFS_BLI_LOGGED; | 605 | |
607 | xfs_buf_item_log(bip, first, last); | 606 | /* |
607 | * If we have an ordered buffer we are not logging any dirty range but | ||
608 | * it still needs to be marked dirty and that it has been logged. | ||
609 | */ | ||
610 | bip->bli_flags |= XFS_BLI_DIRTY | XFS_BLI_LOGGED; | ||
611 | if (!(bip->bli_flags & XFS_BLI_ORDERED)) | ||
612 | xfs_buf_item_log(bip, first, last); | ||
608 | } | 613 | } |
609 | 614 | ||
610 | 615 | ||
@@ -757,6 +762,29 @@ xfs_trans_inode_alloc_buf( | |||
757 | } | 762 | } |
758 | 763 | ||
759 | /* | 764 | /* |
765 | * Mark the buffer as ordered for this transaction. This means | ||
766 | * that the contents of the buffer are not recorded in the transaction | ||
767 | * but it is tracked in the AIL as though it was. This allows us | ||
768 | * to record logical changes in transactions rather than the physical | ||
769 | * changes we make to the buffer without changing writeback ordering | ||
770 | * constraints of metadata buffers. | ||
771 | */ | ||
772 | void | ||
773 | xfs_trans_ordered_buf( | ||
774 | struct xfs_trans *tp, | ||
775 | struct xfs_buf *bp) | ||
776 | { | ||
777 | struct xfs_buf_log_item *bip = bp->b_fspriv; | ||
778 | |||
779 | ASSERT(bp->b_transp == tp); | ||
780 | ASSERT(bip != NULL); | ||
781 | ASSERT(atomic_read(&bip->bli_refcount) > 0); | ||
782 | |||
783 | bip->bli_flags |= XFS_BLI_ORDERED; | ||
784 | trace_xfs_buf_item_ordered(bip); | ||
785 | } | ||
786 | |||
787 | /* | ||
760 | * Set the type of the buffer for log recovery so that it can correctly identify | 788 | * Set the type of the buffer for log recovery so that it can correctly identify |
761 | * and hence attach the correct buffer ops to the buffer after replay. | 789 | * and hence attach the correct buffer ops to the buffer after replay. |
762 | */ | 790 | */ |