|
14 | 14 | #include "xfs_trace.h" |
15 | 15 | #include "xfs_log.h" |
16 | 16 | #include "xfs_log_recover.h" |
| 17 | +#include "xfs_log_priv.h" |
17 | 18 | #include "xfs_trans.h" |
18 | 19 | #include "xfs_buf_item.h" |
19 | 20 | #include "xfs_errortag.h" |
@@ -813,7 +814,15 @@ xfs_buf_read_map( |
813 | 814 | * buffer. |
814 | 815 | */ |
815 | 816 | if (error) { |
816 | | - if (!xfs_is_shutdown(target->bt_mount)) |
| 817 | + /* |
| 818 | + * Check against log shutdown for error reporting because |
| 819 | + * metadata writeback may require a read first and we need to |
| 820 | + * report errors in metadata writeback until the log is shut |
| 821 | + * down. High level transaction read functions already check |
| 822 | + * against mount shutdown, anyway, so we only need to be |
| 823 | + * concerned about low level IO interactions here. |
| 824 | + */ |
| 825 | + if (!xlog_is_shutdown(target->bt_mount->m_log)) |
817 | 826 | xfs_buf_ioerror_alert(bp, fa); |
818 | 827 |
|
819 | 828 | bp->b_flags &= ~XBF_DONE; |
@@ -1174,10 +1183,10 @@ xfs_buf_ioend_handle_error( |
1174 | 1183 | struct xfs_error_cfg *cfg; |
1175 | 1184 |
|
1176 | 1185 | /* |
1177 | | - * If we've already decided to shutdown the filesystem because of I/O |
1178 | | - * errors, there's no point in giving this a retry. |
| 1186 | + * If we've already shutdown the journal because of I/O errors, there's |
| 1187 | + * no point in giving this a retry. |
1179 | 1188 | */ |
1180 | | - if (xfs_is_shutdown(mp)) |
| 1189 | + if (xlog_is_shutdown(mp->m_log)) |
1181 | 1190 | goto out_stale; |
1182 | 1191 |
|
1183 | 1192 | xfs_buf_ioerror_alert_ratelimited(bp); |
@@ -1588,8 +1597,23 @@ __xfs_buf_submit( |
1588 | 1597 |
|
1589 | 1598 | ASSERT(!(bp->b_flags & _XBF_DELWRI_Q)); |
1590 | 1599 |
|
1591 | | - /* on shutdown we stale and complete the buffer immediately */ |
1592 | | - if (xfs_is_shutdown(bp->b_mount)) { |
| 1600 | + /* |
| 1601 | + * On log shutdown we stale and complete the buffer immediately. We can |
| 1602 | + * be called to read the superblock before the log has been set up, so |
| 1603 | + * be careful checking the log state. |
| 1604 | + * |
| 1605 | + * Checking the mount shutdown state here can result in the log tail |
| 1606 | + * moving inappropriately on disk as the log may not yet be shut down. |
| 1607 | + * i.e. failing this buffer on mount shutdown can remove it from the AIL |
| 1608 | + * and move the tail of the log forwards without having written this |
| 1609 | + * buffer to disk. This corrupts the log tail state in memory, and |
| 1610 | + * because the log may not be shut down yet, it can then be propagated |
| 1611 | + * to disk before the log is shutdown. Hence we check log shutdown |
| 1612 | + * state here rather than mount state to avoid corrupting the log tail |
| 1613 | + * on shutdown. |
| 1614 | + */ |
| 1615 | + if (bp->b_mount->m_log && |
| 1616 | + xlog_is_shutdown(bp->b_mount->m_log)) { |
1593 | 1617 | xfs_buf_ioend_fail(bp); |
1594 | 1618 | return -EIO; |
1595 | 1619 | } |
@@ -1803,10 +1827,10 @@ xfs_buftarg_drain( |
1803 | 1827 | * If one or more failed buffers were freed, that means dirty metadata |
1804 | 1828 | * was thrown away. This should only ever happen after I/O completion |
1805 | 1829 | * handling has elevated I/O error(s) to permanent failures and shuts |
1806 | | - * down the fs. |
| 1830 | + * down the journal. |
1807 | 1831 | */ |
1808 | 1832 | if (write_fail) { |
1809 | | - ASSERT(xfs_is_shutdown(btp->bt_mount)); |
| 1833 | + ASSERT(xlog_is_shutdown(btp->bt_mount->m_log)); |
1810 | 1834 | xfs_alert(btp->bt_mount, |
1811 | 1835 | "Please run xfs_repair to determine the extent of the problem."); |
1812 | 1836 | } |
@@ -2089,12 +2113,13 @@ xfs_buf_delwri_submit_buffers( |
2089 | 2113 | blk_start_plug(&plug); |
2090 | 2114 | list_for_each_entry_safe(bp, n, buffer_list, b_list) { |
2091 | 2115 | if (!wait_list) { |
| 2116 | + if (!xfs_buf_trylock(bp)) |
| 2117 | + continue; |
2092 | 2118 | if (xfs_buf_ispinned(bp)) { |
| 2119 | + xfs_buf_unlock(bp); |
2093 | 2120 | pinned++; |
2094 | 2121 | continue; |
2095 | 2122 | } |
2096 | | - if (!xfs_buf_trylock(bp)) |
2097 | | - continue; |
2098 | 2123 | } else { |
2099 | 2124 | xfs_buf_lock(bp); |
2100 | 2125 | } |
|
0 commit comments