diff options
author | David S. Miller <davem@davemloft.net> | 2011-01-24 16:17:06 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-01-24 16:17:06 -0500 |
commit | e92427b289d252cfbd4cb5282d92f4ce1a5bb1fb (patch) | |
tree | 6d30e5e7b7f8e9aaa51d43b7128ac56860fa03bb /fs/xfs/xfs_buf_item.c | |
parent | c506653d35249bb4738bb139c24362e1ae724bc1 (diff) | |
parent | ec30f343d61391ab23705e50a525da1d55395780 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'fs/xfs/xfs_buf_item.c')
-rw-r--r-- | fs/xfs/xfs_buf_item.c | 179 |
1 files changed, 68 insertions, 111 deletions
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 2686d0d54c5b..98c6f73b6752 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c | |||
@@ -141,8 +141,7 @@ xfs_buf_item_log_check( | |||
141 | #define xfs_buf_item_log_check(x) | 141 | #define xfs_buf_item_log_check(x) |
142 | #endif | 142 | #endif |
143 | 143 | ||
144 | STATIC void xfs_buf_error_relse(xfs_buf_t *bp); | 144 | STATIC void xfs_buf_do_callbacks(struct xfs_buf *bp); |
145 | STATIC void xfs_buf_do_callbacks(xfs_buf_t *bp, xfs_log_item_t *lip); | ||
146 | 145 | ||
147 | /* | 146 | /* |
148 | * This returns the number of log iovecs needed to log the | 147 | * This returns the number of log iovecs needed to log the |
@@ -450,7 +449,7 @@ xfs_buf_item_unpin( | |||
450 | * xfs_trans_ail_delete() drops the AIL lock. | 449 | * xfs_trans_ail_delete() drops the AIL lock. |
451 | */ | 450 | */ |
452 | if (bip->bli_flags & XFS_BLI_STALE_INODE) { | 451 | if (bip->bli_flags & XFS_BLI_STALE_INODE) { |
453 | xfs_buf_do_callbacks(bp, (xfs_log_item_t *)bip); | 452 | xfs_buf_do_callbacks(bp); |
454 | XFS_BUF_SET_FSPRIVATE(bp, NULL); | 453 | XFS_BUF_SET_FSPRIVATE(bp, NULL); |
455 | XFS_BUF_CLR_IODONE_FUNC(bp); | 454 | XFS_BUF_CLR_IODONE_FUNC(bp); |
456 | } else { | 455 | } else { |
@@ -918,15 +917,26 @@ xfs_buf_attach_iodone( | |||
918 | XFS_BUF_SET_IODONE_FUNC(bp, xfs_buf_iodone_callbacks); | 917 | XFS_BUF_SET_IODONE_FUNC(bp, xfs_buf_iodone_callbacks); |
919 | } | 918 | } |
920 | 919 | ||
920 | /* | ||
921 | * We can have many callbacks on a buffer. Running the callbacks individually | ||
922 | * can cause a lot of contention on the AIL lock, so we allow for a single | ||
923 | * callback to be able to scan the remaining lip->li_bio_list for other items | ||
924 | * of the same type and callback to be processed in the first call. | ||
925 | * | ||
926 | * As a result, the loop walking the callback list below will also modify the | ||
927 | * list. it removes the first item from the list and then runs the callback. | ||
928 | * The loop then restarts from the new head of the list. This allows the | ||
929 | * callback to scan and modify the list attached to the buffer and we don't | ||
930 | * have to care about maintaining a next item pointer. | ||
931 | */ | ||
921 | STATIC void | 932 | STATIC void |
922 | xfs_buf_do_callbacks( | 933 | xfs_buf_do_callbacks( |
923 | xfs_buf_t *bp, | 934 | struct xfs_buf *bp) |
924 | xfs_log_item_t *lip) | ||
925 | { | 935 | { |
926 | xfs_log_item_t *nlip; | 936 | struct xfs_log_item *lip; |
927 | 937 | ||
928 | while (lip != NULL) { | 938 | while ((lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *)) != NULL) { |
929 | nlip = lip->li_bio_list; | 939 | XFS_BUF_SET_FSPRIVATE(bp, lip->li_bio_list); |
930 | ASSERT(lip->li_cb != NULL); | 940 | ASSERT(lip->li_cb != NULL); |
931 | /* | 941 | /* |
932 | * Clear the next pointer so we don't have any | 942 | * Clear the next pointer so we don't have any |
@@ -936,7 +946,6 @@ xfs_buf_do_callbacks( | |||
936 | */ | 946 | */ |
937 | lip->li_bio_list = NULL; | 947 | lip->li_bio_list = NULL; |
938 | lip->li_cb(bp, lip); | 948 | lip->li_cb(bp, lip); |
939 | lip = nlip; | ||
940 | } | 949 | } |
941 | } | 950 | } |
942 | 951 | ||
@@ -949,128 +958,76 @@ xfs_buf_do_callbacks( | |||
949 | */ | 958 | */ |
950 | void | 959 | void |
951 | xfs_buf_iodone_callbacks( | 960 | xfs_buf_iodone_callbacks( |
952 | xfs_buf_t *bp) | 961 | struct xfs_buf *bp) |
953 | { | 962 | { |
954 | xfs_log_item_t *lip; | 963 | struct xfs_log_item *lip = bp->b_fspriv; |
955 | static ulong lasttime; | 964 | struct xfs_mount *mp = lip->li_mountp; |
956 | static xfs_buftarg_t *lasttarg; | 965 | static ulong lasttime; |
957 | xfs_mount_t *mp; | 966 | static xfs_buftarg_t *lasttarg; |
958 | 967 | ||
959 | ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); | 968 | if (likely(!XFS_BUF_GETERROR(bp))) |
960 | lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *); | 969 | goto do_callbacks; |
961 | 970 | ||
962 | if (XFS_BUF_GETERROR(bp) != 0) { | 971 | /* |
963 | /* | 972 | * If we've already decided to shutdown the filesystem because of |
964 | * If we've already decided to shutdown the filesystem | 973 | * I/O errors, there's no point in giving this a retry. |
965 | * because of IO errors, there's no point in giving this | 974 | */ |
966 | * a retry. | 975 | if (XFS_FORCED_SHUTDOWN(mp)) { |
967 | */ | 976 | XFS_BUF_SUPER_STALE(bp); |
968 | mp = lip->li_mountp; | 977 | trace_xfs_buf_item_iodone(bp, _RET_IP_); |
969 | if (XFS_FORCED_SHUTDOWN(mp)) { | 978 | goto do_callbacks; |
970 | ASSERT(XFS_BUF_TARGET(bp) == mp->m_ddev_targp); | 979 | } |
971 | XFS_BUF_SUPER_STALE(bp); | ||
972 | trace_xfs_buf_item_iodone(bp, _RET_IP_); | ||
973 | xfs_buf_do_callbacks(bp, lip); | ||
974 | XFS_BUF_SET_FSPRIVATE(bp, NULL); | ||
975 | XFS_BUF_CLR_IODONE_FUNC(bp); | ||
976 | xfs_buf_ioend(bp, 0); | ||
977 | return; | ||
978 | } | ||
979 | 980 | ||
980 | if ((XFS_BUF_TARGET(bp) != lasttarg) || | 981 | if (XFS_BUF_TARGET(bp) != lasttarg || |
981 | (time_after(jiffies, (lasttime + 5*HZ)))) { | 982 | time_after(jiffies, (lasttime + 5*HZ))) { |
982 | lasttime = jiffies; | 983 | lasttime = jiffies; |
983 | cmn_err(CE_ALERT, "Device %s, XFS metadata write error" | 984 | cmn_err(CE_ALERT, "Device %s, XFS metadata write error" |
984 | " block 0x%llx in %s", | 985 | " block 0x%llx in %s", |
985 | XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)), | 986 | XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)), |
986 | (__uint64_t)XFS_BUF_ADDR(bp), mp->m_fsname); | 987 | (__uint64_t)XFS_BUF_ADDR(bp), mp->m_fsname); |
987 | } | 988 | } |
988 | lasttarg = XFS_BUF_TARGET(bp); | 989 | lasttarg = XFS_BUF_TARGET(bp); |
989 | 990 | ||
990 | if (XFS_BUF_ISASYNC(bp)) { | 991 | /* |
991 | /* | 992 | * If the write was asynchronous then noone will be looking for the |
992 | * If the write was asynchronous then noone will be | 993 | * error. Clear the error state and write the buffer out again. |
993 | * looking for the error. Clear the error state | 994 | * |
994 | * and write the buffer out again delayed write. | 995 | * During sync or umount we'll write all pending buffers again |
995 | * | 996 | * synchronous, which will catch these errors if they keep hanging |
996 | * XXXsup This is OK, so long as we catch these | 997 | * around. |
997 | * before we start the umount; we don't want these | 998 | */ |
998 | * DELWRI metadata bufs to be hanging around. | 999 | if (XFS_BUF_ISASYNC(bp)) { |
999 | */ | 1000 | XFS_BUF_ERROR(bp, 0); /* errno of 0 unsets the flag */ |
1000 | XFS_BUF_ERROR(bp,0); /* errno of 0 unsets the flag */ | 1001 | |
1001 | 1002 | if (!XFS_BUF_ISSTALE(bp)) { | |
1002 | if (!(XFS_BUF_ISSTALE(bp))) { | 1003 | XFS_BUF_DELAYWRITE(bp); |
1003 | XFS_BUF_DELAYWRITE(bp); | ||
1004 | XFS_BUF_DONE(bp); | ||
1005 | XFS_BUF_SET_START(bp); | ||
1006 | } | ||
1007 | ASSERT(XFS_BUF_IODONE_FUNC(bp)); | ||
1008 | trace_xfs_buf_item_iodone_async(bp, _RET_IP_); | ||
1009 | xfs_buf_relse(bp); | ||
1010 | } else { | ||
1011 | /* | ||
1012 | * If the write of the buffer was not asynchronous, | ||
1013 | * then we want to make sure to return the error | ||
1014 | * to the caller of bwrite(). Because of this we | ||
1015 | * cannot clear the B_ERROR state at this point. | ||
1016 | * Instead we install a callback function that | ||
1017 | * will be called when the buffer is released, and | ||
1018 | * that routine will clear the error state and | ||
1019 | * set the buffer to be written out again after | ||
1020 | * some delay. | ||
1021 | */ | ||
1022 | /* We actually overwrite the existing b-relse | ||
1023 | function at times, but we're gonna be shutting down | ||
1024 | anyway. */ | ||
1025 | XFS_BUF_SET_BRELSE_FUNC(bp,xfs_buf_error_relse); | ||
1026 | XFS_BUF_DONE(bp); | 1004 | XFS_BUF_DONE(bp); |
1027 | XFS_BUF_FINISH_IOWAIT(bp); | 1005 | XFS_BUF_SET_START(bp); |
1028 | } | 1006 | } |
1007 | ASSERT(XFS_BUF_IODONE_FUNC(bp)); | ||
1008 | trace_xfs_buf_item_iodone_async(bp, _RET_IP_); | ||
1009 | xfs_buf_relse(bp); | ||
1029 | return; | 1010 | return; |
1030 | } | 1011 | } |
1031 | 1012 | ||
1032 | xfs_buf_do_callbacks(bp, lip); | 1013 | /* |
1033 | XFS_BUF_SET_FSPRIVATE(bp, NULL); | 1014 | * If the write of the buffer was synchronous, we want to make |
1034 | XFS_BUF_CLR_IODONE_FUNC(bp); | 1015 | * sure to return the error to the caller of xfs_bwrite(). |
1035 | xfs_buf_ioend(bp, 0); | 1016 | */ |
1036 | } | ||
1037 | |||
1038 | /* | ||
1039 | * This is a callback routine attached to a buffer which gets an error | ||
1040 | * when being written out synchronously. | ||
1041 | */ | ||
1042 | STATIC void | ||
1043 | xfs_buf_error_relse( | ||
1044 | xfs_buf_t *bp) | ||
1045 | { | ||
1046 | xfs_log_item_t *lip; | ||
1047 | xfs_mount_t *mp; | ||
1048 | |||
1049 | lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *); | ||
1050 | mp = (xfs_mount_t *)lip->li_mountp; | ||
1051 | ASSERT(XFS_BUF_TARGET(bp) == mp->m_ddev_targp); | ||
1052 | |||
1053 | XFS_BUF_STALE(bp); | 1017 | XFS_BUF_STALE(bp); |
1054 | XFS_BUF_DONE(bp); | 1018 | XFS_BUF_DONE(bp); |
1055 | XFS_BUF_UNDELAYWRITE(bp); | 1019 | XFS_BUF_UNDELAYWRITE(bp); |
1056 | XFS_BUF_ERROR(bp,0); | ||
1057 | 1020 | ||
1058 | trace_xfs_buf_error_relse(bp, _RET_IP_); | 1021 | trace_xfs_buf_error_relse(bp, _RET_IP_); |
1022 | xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR); | ||
1059 | 1023 | ||
1060 | if (! XFS_FORCED_SHUTDOWN(mp)) | 1024 | do_callbacks: |
1061 | xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR); | 1025 | xfs_buf_do_callbacks(bp); |
1062 | /* | ||
1063 | * We have to unpin the pinned buffers so do the | ||
1064 | * callbacks. | ||
1065 | */ | ||
1066 | xfs_buf_do_callbacks(bp, lip); | ||
1067 | XFS_BUF_SET_FSPRIVATE(bp, NULL); | 1026 | XFS_BUF_SET_FSPRIVATE(bp, NULL); |
1068 | XFS_BUF_CLR_IODONE_FUNC(bp); | 1027 | XFS_BUF_CLR_IODONE_FUNC(bp); |
1069 | XFS_BUF_SET_BRELSE_FUNC(bp,NULL); | 1028 | xfs_buf_ioend(bp, 0); |
1070 | xfs_buf_relse(bp); | ||
1071 | } | 1029 | } |
1072 | 1030 | ||
1073 | |||
1074 | /* | 1031 | /* |
1075 | * This is the iodone() function for buffers which have been | 1032 | * This is the iodone() function for buffers which have been |
1076 | * logged. It is called when they are eventually flushed out. | 1033 | * logged. It is called when they are eventually flushed out. |