diff options
author | Christoph Hellwig <hch@infradead.org> | 2012-04-23 01:58:33 -0400 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2012-05-14 17:20:26 -0400 |
commit | 1c30462542bac8abffb4823638b6b1659c1cfcf5 (patch) | |
tree | b86f1fc14eb0f41e224833128ecc81163227d044 | |
parent | 32ce90a4b79155a155de2b284d8b69023e5e8fea (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>
-rw-r--r-- | fs/xfs/xfs_log.c | 31 | ||||
-rw-r--r-- | fs/xfs/xfs_log.h | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_trans_ail.c | 22 | ||||
-rw-r--r-- | fs/xfs/xfs_trans_priv.h | 1 |
4 files changed, 40 insertions, 15 deletions
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 6db1fef38bff..418d5d7bc52b 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 | */ |
918 | xfs_lsn_t | 918 | xfs_lsn_t |
919 | xlog_assign_tail_lsn( | 919 | xlog_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 | ||
942 | xfs_lsn_t | ||
943 | xlog_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 2c622bedb302..748d312850e2 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); |
153 | int xfs_log_mount_finish(struct xfs_mount *mp); | 153 | int xfs_log_mount_finish(struct xfs_mount *mp); |
154 | xfs_lsn_t xlog_assign_tail_lsn(struct xfs_mount *mp); | 154 | xfs_lsn_t xlog_assign_tail_lsn(struct xfs_mount *mp); |
155 | xfs_lsn_t xlog_assign_tail_lsn_locked(struct xfs_mount *mp); | ||
155 | void xfs_log_space_wake(struct xfs_mount *mp); | 156 | void xfs_log_space_wake(struct xfs_mount *mp); |
156 | int xfs_log_notify(struct xfs_mount *mp, | 157 | int 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 1dead07f092c..77acc53f2f31 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 | */ |
82 | static xfs_log_item_t * | 82 | xfs_log_item_t * |
83 | xfs_ail_min( | 83 | xfs_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 8ab2ced415f1..46a1ebd4a7a2 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 | ||
103 | void xfs_ail_push(struct xfs_ail *, xfs_lsn_t); | 103 | void xfs_ail_push(struct xfs_ail *, xfs_lsn_t); |
104 | void xfs_ail_push_all(struct xfs_ail *); | 104 | void xfs_ail_push_all(struct xfs_ail *); |
105 | struct xfs_log_item *xfs_ail_min(struct xfs_ail *ailp); | ||
105 | xfs_lsn_t xfs_ail_min_lsn(struct xfs_ail *ailp); | 106 | xfs_lsn_t xfs_ail_min_lsn(struct xfs_ail *ailp); |
106 | 107 | ||
107 | struct xfs_log_item * xfs_trans_ail_cursor_first(struct xfs_ail *ailp, | 108 | struct xfs_log_item * xfs_trans_ail_cursor_first(struct xfs_ail *ailp, |