aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_trans_ail.c
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2010-12-19 20:03:17 -0500
committerDave Chinner <david@fromorbit.com>2010-12-19 20:03:17 -0500
commit3013683253ad04f67d8cfaa25be708353686b90a (patch)
treeeadc35b70c0169096a7dbaf4eb9966be7630db04 /fs/xfs/xfs_trans_ail.c
parentc90821a26a8c90ad1e3116393b8a8260ab46bffb (diff)
xfs: remove all the inodes on a buffer from the AIL in bulk
When inode buffer IO completes, usually all of the inodes are removed from the AIL. This involves processing them one at a time and taking the AIL lock once for every inode. When all CPUs are processing inode IO completions, this causes excessive amount sof contention on the AIL lock. Instead, change the way we process inode IO completion in the buffer IO done callback. Allow the inode IO done callback to walk the list of IO done callbacks and pull all the inodes off the buffer in one go and then process them as a batch. Once all the inodes for removal are collected, take the AIL lock once and do a bulk removal operation to minimise traffic on the AIL lock. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/xfs/xfs_trans_ail.c')
-rw-r--r--fs/xfs/xfs_trans_ail.c73
1 files changed, 73 insertions, 0 deletions
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/*