diff options
Diffstat (limited to 'fs/xfs/xfs_buf_item.c')
-rw-r--r-- | fs/xfs/xfs_buf_item.c | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 2686d0d54c5b..ed2b65f3f8b9 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c | |||
@@ -142,7 +142,7 @@ xfs_buf_item_log_check( | |||
142 | #endif | 142 | #endif |
143 | 143 | ||
144 | STATIC void xfs_buf_error_relse(xfs_buf_t *bp); | 144 | STATIC void xfs_buf_error_relse(xfs_buf_t *bp); |
145 | STATIC void xfs_buf_do_callbacks(xfs_buf_t *bp, xfs_log_item_t *lip); | 145 | STATIC void xfs_buf_do_callbacks(struct xfs_buf *bp); |
146 | 146 | ||
147 | /* | 147 | /* |
148 | * This returns the number of log iovecs needed to log the | 148 | * This returns the number of log iovecs needed to log the |
@@ -450,7 +450,7 @@ xfs_buf_item_unpin( | |||
450 | * xfs_trans_ail_delete() drops the AIL lock. | 450 | * xfs_trans_ail_delete() drops the AIL lock. |
451 | */ | 451 | */ |
452 | if (bip->bli_flags & XFS_BLI_STALE_INODE) { | 452 | if (bip->bli_flags & XFS_BLI_STALE_INODE) { |
453 | xfs_buf_do_callbacks(bp, (xfs_log_item_t *)bip); | 453 | xfs_buf_do_callbacks(bp); |
454 | XFS_BUF_SET_FSPRIVATE(bp, NULL); | 454 | XFS_BUF_SET_FSPRIVATE(bp, NULL); |
455 | XFS_BUF_CLR_IODONE_FUNC(bp); | 455 | XFS_BUF_CLR_IODONE_FUNC(bp); |
456 | } else { | 456 | } else { |
@@ -918,15 +918,26 @@ xfs_buf_attach_iodone( | |||
918 | XFS_BUF_SET_IODONE_FUNC(bp, xfs_buf_iodone_callbacks); | 918 | XFS_BUF_SET_IODONE_FUNC(bp, xfs_buf_iodone_callbacks); |
919 | } | 919 | } |
920 | 920 | ||
921 | /* | ||
922 | * We can have many callbacks on a buffer. Running the callbacks individually | ||
923 | * can cause a lot of contention on the AIL lock, so we allow for a single | ||
924 | * callback to be able to scan the remaining lip->li_bio_list for other items | ||
925 | * of the same type and callback to be processed in the first call. | ||
926 | * | ||
927 | * As a result, the loop walking the callback list below will also modify the | ||
928 | * list. it removes the first item from the list and then runs the callback. | ||
929 | * The loop then restarts from the new head of the list. This allows the | ||
930 | * callback to scan and modify the list attached to the buffer and we don't | ||
931 | * have to care about maintaining a next item pointer. | ||
932 | */ | ||
921 | STATIC void | 933 | STATIC void |
922 | xfs_buf_do_callbacks( | 934 | xfs_buf_do_callbacks( |
923 | xfs_buf_t *bp, | 935 | struct xfs_buf *bp) |
924 | xfs_log_item_t *lip) | ||
925 | { | 936 | { |
926 | xfs_log_item_t *nlip; | 937 | struct xfs_log_item *lip; |
927 | 938 | ||
928 | while (lip != NULL) { | 939 | while ((lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *)) != NULL) { |
929 | nlip = lip->li_bio_list; | 940 | XFS_BUF_SET_FSPRIVATE(bp, lip->li_bio_list); |
930 | ASSERT(lip->li_cb != NULL); | 941 | ASSERT(lip->li_cb != NULL); |
931 | /* | 942 | /* |
932 | * Clear the next pointer so we don't have any | 943 | * Clear the next pointer so we don't have any |
@@ -936,7 +947,6 @@ xfs_buf_do_callbacks( | |||
936 | */ | 947 | */ |
937 | lip->li_bio_list = NULL; | 948 | lip->li_bio_list = NULL; |
938 | lip->li_cb(bp, lip); | 949 | lip->li_cb(bp, lip); |
939 | lip = nlip; | ||
940 | } | 950 | } |
941 | } | 951 | } |
942 | 952 | ||
@@ -970,7 +980,7 @@ xfs_buf_iodone_callbacks( | |||
970 | ASSERT(XFS_BUF_TARGET(bp) == mp->m_ddev_targp); | 980 | ASSERT(XFS_BUF_TARGET(bp) == mp->m_ddev_targp); |
971 | XFS_BUF_SUPER_STALE(bp); | 981 | XFS_BUF_SUPER_STALE(bp); |
972 | trace_xfs_buf_item_iodone(bp, _RET_IP_); | 982 | trace_xfs_buf_item_iodone(bp, _RET_IP_); |
973 | xfs_buf_do_callbacks(bp, lip); | 983 | xfs_buf_do_callbacks(bp); |
974 | XFS_BUF_SET_FSPRIVATE(bp, NULL); | 984 | XFS_BUF_SET_FSPRIVATE(bp, NULL); |
975 | XFS_BUF_CLR_IODONE_FUNC(bp); | 985 | XFS_BUF_CLR_IODONE_FUNC(bp); |
976 | xfs_buf_ioend(bp, 0); | 986 | xfs_buf_ioend(bp, 0); |
@@ -1029,7 +1039,7 @@ xfs_buf_iodone_callbacks( | |||
1029 | return; | 1039 | return; |
1030 | } | 1040 | } |
1031 | 1041 | ||
1032 | xfs_buf_do_callbacks(bp, lip); | 1042 | xfs_buf_do_callbacks(bp); |
1033 | XFS_BUF_SET_FSPRIVATE(bp, NULL); | 1043 | XFS_BUF_SET_FSPRIVATE(bp, NULL); |
1034 | XFS_BUF_CLR_IODONE_FUNC(bp); | 1044 | XFS_BUF_CLR_IODONE_FUNC(bp); |
1035 | xfs_buf_ioend(bp, 0); | 1045 | xfs_buf_ioend(bp, 0); |
@@ -1063,7 +1073,7 @@ xfs_buf_error_relse( | |||
1063 | * We have to unpin the pinned buffers so do the | 1073 | * We have to unpin the pinned buffers so do the |
1064 | * callbacks. | 1074 | * callbacks. |
1065 | */ | 1075 | */ |
1066 | xfs_buf_do_callbacks(bp, lip); | 1076 | xfs_buf_do_callbacks(bp); |
1067 | XFS_BUF_SET_FSPRIVATE(bp, NULL); | 1077 | XFS_BUF_SET_FSPRIVATE(bp, NULL); |
1068 | XFS_BUF_CLR_IODONE_FUNC(bp); | 1078 | XFS_BUF_CLR_IODONE_FUNC(bp); |
1069 | XFS_BUF_SET_BRELSE_FUNC(bp,NULL); | 1079 | XFS_BUF_SET_BRELSE_FUNC(bp,NULL); |