aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_inode_item.c90
-rw-r--r--fs/xfs/xfs_trans_ail.c73
-rw-r--r--fs/xfs/xfs_trans_priv.h4
3 files changed, 151 insertions, 16 deletions
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 7c8d30c453c3..fd4f398bd6f1 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -842,15 +842,64 @@ xfs_inode_item_destroy(
842 * flushed to disk. It is responsible for removing the inode item 842 * flushed to disk. It is responsible for removing the inode item
843 * from the AIL if it has not been re-logged, and unlocking the inode's 843 * from the AIL if it has not been re-logged, and unlocking the inode's
844 * flush lock. 844 * flush lock.
845 *
846 * To reduce AIL lock traffic as much as possible, we scan the buffer log item
847 * list for other inodes that will run this function. We remove them from the
848 * buffer list so we can process all the inode IO completions in one AIL lock
849 * traversal.
845 */ 850 */
846void 851void
847xfs_iflush_done( 852xfs_iflush_done(
848 struct xfs_buf *bp, 853 struct xfs_buf *bp,
849 struct xfs_log_item *lip) 854 struct xfs_log_item *lip)
850{ 855{
851 struct xfs_inode_log_item *iip = INODE_ITEM(lip); 856 struct xfs_inode_log_item *iip;
852 xfs_inode_t *ip = iip->ili_inode; 857 struct xfs_log_item *blip;
858 struct xfs_log_item *next;
859 struct xfs_log_item *prev;
853 struct xfs_ail *ailp = lip->li_ailp; 860 struct xfs_ail *ailp = lip->li_ailp;
861 int need_ail = 0;
862
863 /*
864 * Scan the buffer IO completions for other inodes being completed and
865 * attach them to the current inode log item.
866 */
867 blip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);
868 prev = NULL;
869 while (blip != NULL) {
870 if (lip->li_cb != xfs_iflush_done) {
871 prev = blip;
872 blip = blip->li_bio_list;
873 continue;
874 }
875
876 /* remove from list */
877 next = blip->li_bio_list;
878 if (!prev) {
879 XFS_BUF_SET_FSPRIVATE(bp, next);
880 } else {
881 prev->li_bio_list = next;
882 }
883
884 /* add to current list */
885 blip->li_bio_list = lip->li_bio_list;
886 lip->li_bio_list = blip;
887
888 /*
889 * while we have the item, do the unlocked check for needing
890 * the AIL lock.
891 */
892 iip = INODE_ITEM(blip);
893 if (iip->ili_logged && blip->li_lsn == iip->ili_flush_lsn)
894 need_ail++;
895
896 blip = next;
897 }
898
899 /* make sure we capture the state of the initial inode. */
900 iip = INODE_ITEM(lip);
901 if (iip->ili_logged && lip->li_lsn == iip->ili_flush_lsn)
902 need_ail++;
854 903
855 /* 904 /*
856 * We only want to pull the item from the AIL if it is 905 * We only want to pull the item from the AIL if it is
@@ -861,28 +910,37 @@ xfs_iflush_done(
861 * the lock since it's cheaper, and then we recheck while 910 * the lock since it's cheaper, and then we recheck while
862 * holding the lock before removing the inode from the AIL. 911 * holding the lock before removing the inode from the AIL.
863 */ 912 */
864 if (iip->ili_logged && lip->li_lsn == iip->ili_flush_lsn) { 913 if (need_ail) {
914 struct xfs_log_item *log_items[need_ail];
915 int i = 0;
865 spin_lock(&ailp->xa_lock); 916 spin_lock(&ailp->xa_lock);
866 if (lip->li_lsn == iip->ili_flush_lsn) { 917 for (blip = lip; blip; blip = blip->li_bio_list) {
867 /* xfs_trans_ail_delete() drops the AIL lock. */ 918 iip = INODE_ITEM(blip);
868 xfs_trans_ail_delete(ailp, lip); 919 if (iip->ili_logged &&
869 } else { 920 blip->li_lsn == iip->ili_flush_lsn) {
870 spin_unlock(&ailp->xa_lock); 921 log_items[i++] = blip;
922 }
923 ASSERT(i <= need_ail);
871 } 924 }
925 /* xfs_trans_ail_delete_bulk() drops the AIL lock. */
926 xfs_trans_ail_delete_bulk(ailp, log_items, i);
872 } 927 }
873 928
874 iip->ili_logged = 0;
875 929
876 /* 930 /*
877 * Clear the ili_last_fields bits now that we know that the 931 * clean up and unlock the flush lock now we are done. We can clear the
878 * data corresponding to them is safely on disk. 932 * ili_last_fields bits now that we know that the data corresponding to
933 * them is safely on disk.
879 */ 934 */
880 iip->ili_last_fields = 0; 935 for (blip = lip; blip; blip = next) {
936 next = blip->li_bio_list;
937 blip->li_bio_list = NULL;
881 938
882 /* 939 iip = INODE_ITEM(blip);
883 * Release the inode's flush lock since we're done with it. 940 iip->ili_logged = 0;
884 */ 941 iip->ili_last_fields = 0;
885 xfs_ifunlock(ip); 942 xfs_ifunlock(iip->ili_inode);
943 }
886} 944}
887 945
888/* 946/*
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index fe991a76bf14..218f96861c80 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -639,6 +639,79 @@ xfs_trans_ail_delete(
639 } 639 }
640} 640}
641 641
642/*
643 * xfs_trans_ail_delete_bulk - remove multiple log items from the AIL
644 *
645 * @xfs_trans_ail_delete_bulk takes an array of log items that all need to
646 * removed from the AIL. The caller is already holding the AIL lock, and done
647 * all the checks necessary to ensure the items passed in via @log_items are
648 * ready for deletion. This includes checking that the items are in the AIL.
649 *
650 * For each log item to be removed, unlink it from the AIL, clear the IN_AIL
651 * flag from the item and reset the item's lsn to 0. If we remove the first
652 * item in the AIL, update the log tail to match the new minimum LSN in the
653 * AIL.
654 *
655 * This function will not drop the AIL lock until all items are removed from
656 * the AIL to minimise the amount of lock traffic on the AIL. This does not
657 * greatly increase the AIL hold time, but does significantly reduce the amount
658 * of traffic on the lock, especially during IO completion.
659 *
660 * This function must be called with the AIL lock held. The lock is dropped
661 * before returning.
662 */
663void
664xfs_trans_ail_delete_bulk(
665 struct xfs_ail *ailp,
666 struct xfs_log_item **log_items,
667 int nr_items) __releases(ailp->xa_lock)
668{
669 xfs_log_item_t *mlip;
670 xfs_lsn_t tail_lsn;
671 int mlip_changed = 0;
672 int i;
673
674 mlip = xfs_ail_min(ailp);
675
676 for (i = 0; i < nr_items; i++) {
677 struct xfs_log_item *lip = log_items[i];
678 if (!(lip->li_flags & XFS_LI_IN_AIL)) {
679 struct xfs_mount *mp = ailp->xa_mount;
680
681 spin_unlock(&ailp->xa_lock);
682 if (!XFS_FORCED_SHUTDOWN(mp)) {
683 xfs_cmn_err(XFS_PTAG_AILDELETE, CE_ALERT, mp,
684 "%s: attempting to delete a log item that is not in the AIL",
685 __func__);
686 xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
687 }
688 return;
689 }
690
691 xfs_ail_delete(ailp, lip);
692 lip->li_flags &= ~XFS_LI_IN_AIL;
693 lip->li_lsn = 0;
694 if (mlip == lip)
695 mlip_changed = 1;
696 }
697
698 if (!mlip_changed) {
699 spin_unlock(&ailp->xa_lock);
700 return;
701 }
702
703 /*
704 * It is not safe to access mlip after the AIL lock is dropped, so we
705 * must get a copy of li_lsn before we do so. This is especially
706 * important on 32-bit platforms where accessing and updating 64-bit
707 * values like li_lsn is not atomic. It is possible we've emptied the
708 * AIL here, so if that is the case, pass an LSN of 0 to the tail move.
709 */
710 mlip = xfs_ail_min(ailp);
711 tail_lsn = mlip ? mlip->li_lsn : 0;
712 spin_unlock(&ailp->xa_lock);
713 xfs_log_move_tail(ailp->xa_mount, tail_lsn);
714}
642 715
643 716
644/* 717/*
diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h
index e039729186e9..246ca4dcb5c4 100644
--- a/fs/xfs/xfs_trans_priv.h
+++ b/fs/xfs/xfs_trans_priv.h
@@ -85,6 +85,10 @@ void xfs_trans_ail_update_bulk(struct xfs_ail *ailp,
85void xfs_trans_ail_delete(struct xfs_ail *ailp, 85void xfs_trans_ail_delete(struct xfs_ail *ailp,
86 struct xfs_log_item *lip) 86 struct xfs_log_item *lip)
87 __releases(ailp->xa_lock); 87 __releases(ailp->xa_lock);
88void xfs_trans_ail_delete_bulk(struct xfs_ail *ailp,
89 struct xfs_log_item **log_items,
90 int nr_items)
91 __releases(ailp->xa_lock);
88void xfs_trans_ail_push(struct xfs_ail *, xfs_lsn_t); 92void xfs_trans_ail_push(struct xfs_ail *, xfs_lsn_t);
89void xfs_trans_unlocked_item(struct xfs_ail *, 93void xfs_trans_unlocked_item(struct xfs_ail *,
90 xfs_log_item_t *); 94 xfs_log_item_t *);