aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2012-04-23 01:58:33 -0400
committerBen Myers <bpm@sgi.com>2012-05-14 17:20:26 -0400
commit1c30462542bac8abffb4823638b6b1659c1cfcf5 (patch)
treeb86f1fc14eb0f41e224833128ecc81163227d044 /fs/xfs
parent32ce90a4b79155a155de2b284d8b69023e5e8fea (diff)
xfs: allow assigning the tail lsn with the AIL lock held
Provide a variant of xlog_assign_tail_lsn that has the AIL lock already held. By doing so we do an additional atomic_read + atomic_set under the lock, which comes down to two instructions. Switch xfs_trans_ail_update_bulk and xfs_trans_ail_delete_bulk to the new version to reduce the number of lock roundtrips, and prepare for a new addition that would require a third lock roundtrip in xfs_trans_ail_delete_bulk. This addition is also the reason for slightly rearranging the conditionals and relying on xfs_log_space_wake for checking that the filesystem has been shut down internally. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Mark Tinguely <tinguely@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_log.c31
-rw-r--r--fs/xfs/xfs_log.h1
-rw-r--r--fs/xfs/xfs_trans_ail.c22
-rw-r--r--fs/xfs/xfs_trans_priv.h1
4 files changed, 40 insertions, 15 deletions
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 6db1fef38bf..418d5d7bc52 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -916,27 +916,42 @@ xfs_log_need_covered(xfs_mount_t *mp)
916 * We may be holding the log iclog lock upon entering this routine. 916 * We may be holding the log iclog lock upon entering this routine.
917 */ 917 */
918xfs_lsn_t 918xfs_lsn_t
919xlog_assign_tail_lsn( 919xlog_assign_tail_lsn_locked(
920 struct xfs_mount *mp) 920 struct xfs_mount *mp)
921{ 921{
922 xfs_lsn_t tail_lsn;
923 struct log *log = mp->m_log; 922 struct log *log = mp->m_log;
923 struct xfs_log_item *lip;
924 xfs_lsn_t tail_lsn;
925
926 assert_spin_locked(&mp->m_ail->xa_lock);
924 927
925 /* 928 /*
926 * To make sure we always have a valid LSN for the log tail we keep 929 * To make sure we always have a valid LSN for the log tail we keep
927 * track of the last LSN which was committed in log->l_last_sync_lsn, 930 * track of the last LSN which was committed in log->l_last_sync_lsn,
928 * and use that when the AIL was empty and xfs_ail_min_lsn returns 0. 931 * and use that when the AIL was empty.
929 *
930 * If the AIL has been emptied we also need to wake any process
931 * waiting for this condition.
932 */ 932 */
933 tail_lsn = xfs_ail_min_lsn(mp->m_ail); 933 lip = xfs_ail_min(mp->m_ail);
934 if (!tail_lsn) 934 if (lip)
935 tail_lsn = lip->li_lsn;
936 else
935 tail_lsn = atomic64_read(&log->l_last_sync_lsn); 937 tail_lsn = atomic64_read(&log->l_last_sync_lsn);
936 atomic64_set(&log->l_tail_lsn, tail_lsn); 938 atomic64_set(&log->l_tail_lsn, tail_lsn);
937 return tail_lsn; 939 return tail_lsn;
938} 940}
939 941
942xfs_lsn_t
943xlog_assign_tail_lsn(
944 struct xfs_mount *mp)
945{
946 xfs_lsn_t tail_lsn;
947
948 spin_lock(&mp->m_ail->xa_lock);
949 tail_lsn = xlog_assign_tail_lsn_locked(mp);
950 spin_unlock(&mp->m_ail->xa_lock);
951
952 return tail_lsn;
953}
954
940/* 955/*
941 * Return the space in the log between the tail and the head. The head 956 * Return the space in the log between the tail and the head. The head
942 * is passed in the cycle/bytes formal parms. In the special case where 957 * is passed in the cycle/bytes formal parms. In the special case where
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
index 2c622bedb30..748d312850e 100644
--- a/fs/xfs/xfs_log.h
+++ b/fs/xfs/xfs_log.h
@@ -152,6 +152,7 @@ int xfs_log_mount(struct xfs_mount *mp,
152 int num_bblocks); 152 int num_bblocks);
153int xfs_log_mount_finish(struct xfs_mount *mp); 153int xfs_log_mount_finish(struct xfs_mount *mp);
154xfs_lsn_t xlog_assign_tail_lsn(struct xfs_mount *mp); 154xfs_lsn_t xlog_assign_tail_lsn(struct xfs_mount *mp);
155xfs_lsn_t xlog_assign_tail_lsn_locked(struct xfs_mount *mp);
155void xfs_log_space_wake(struct xfs_mount *mp); 156void xfs_log_space_wake(struct xfs_mount *mp);
156int xfs_log_notify(struct xfs_mount *mp, 157int xfs_log_notify(struct xfs_mount *mp,
157 struct xlog_in_core *iclog, 158 struct xlog_in_core *iclog,
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index 1dead07f092..77acc53f2f3 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -79,7 +79,7 @@ xfs_ail_check(
79 * Return a pointer to the first item in the AIL. If the AIL is empty, then 79 * Return a pointer to the first item in the AIL. If the AIL is empty, then
80 * return NULL. 80 * return NULL.
81 */ 81 */
82static xfs_log_item_t * 82xfs_log_item_t *
83xfs_ail_min( 83xfs_ail_min(
84 struct xfs_ail *ailp) 84 struct xfs_ail *ailp)
85{ 85{
@@ -667,11 +667,15 @@ xfs_trans_ail_update_bulk(
667 667
668 if (!list_empty(&tmp)) 668 if (!list_empty(&tmp))
669 xfs_ail_splice(ailp, cur, &tmp, lsn); 669 xfs_ail_splice(ailp, cur, &tmp, lsn);
670 spin_unlock(&ailp->xa_lock);
671 670
672 if (mlip_changed && !XFS_FORCED_SHUTDOWN(ailp->xa_mount)) { 671 if (mlip_changed) {
673 xlog_assign_tail_lsn(ailp->xa_mount); 672 if (!XFS_FORCED_SHUTDOWN(ailp->xa_mount))
673 xlog_assign_tail_lsn_locked(ailp->xa_mount);
674 spin_unlock(&ailp->xa_lock);
675
674 xfs_log_space_wake(ailp->xa_mount); 676 xfs_log_space_wake(ailp->xa_mount);
677 } else {
678 spin_unlock(&ailp->xa_lock);
675 } 679 }
676} 680}
677 681
@@ -729,11 +733,15 @@ xfs_trans_ail_delete_bulk(
729 if (mlip == lip) 733 if (mlip == lip)
730 mlip_changed = 1; 734 mlip_changed = 1;
731 } 735 }
732 spin_unlock(&ailp->xa_lock);
733 736
734 if (mlip_changed && !XFS_FORCED_SHUTDOWN(ailp->xa_mount)) { 737 if (mlip_changed) {
735 xlog_assign_tail_lsn(ailp->xa_mount); 738 if (!XFS_FORCED_SHUTDOWN(ailp->xa_mount))
739 xlog_assign_tail_lsn_locked(ailp->xa_mount);
740 spin_unlock(&ailp->xa_lock);
741
736 xfs_log_space_wake(ailp->xa_mount); 742 xfs_log_space_wake(ailp->xa_mount);
743 } else {
744 spin_unlock(&ailp->xa_lock);
737 } 745 }
738} 746}
739 747
diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h
index 8ab2ced415f..46a1ebd4a7a 100644
--- a/fs/xfs/xfs_trans_priv.h
+++ b/fs/xfs/xfs_trans_priv.h
@@ -102,6 +102,7 @@ xfs_trans_ail_delete(
102 102
103void xfs_ail_push(struct xfs_ail *, xfs_lsn_t); 103void xfs_ail_push(struct xfs_ail *, xfs_lsn_t);
104void xfs_ail_push_all(struct xfs_ail *); 104void xfs_ail_push_all(struct xfs_ail *);
105struct xfs_log_item *xfs_ail_min(struct xfs_ail *ailp);
105xfs_lsn_t xfs_ail_min_lsn(struct xfs_ail *ailp); 106xfs_lsn_t xfs_ail_min_lsn(struct xfs_ail *ailp);
106 107
107struct xfs_log_item * xfs_trans_ail_cursor_first(struct xfs_ail *ailp, 108struct xfs_log_item * xfs_trans_ail_cursor_first(struct xfs_ail *ailp,