diff options
Diffstat (limited to 'fs/xfs/xfs_aops.c')
-rw-r--r-- | fs/xfs/xfs_aops.c | 119 |
1 files changed, 42 insertions, 77 deletions
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 8c37dde4c521..11b2aad982d4 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c | |||
@@ -38,40 +38,6 @@ | |||
38 | #include <linux/pagevec.h> | 38 | #include <linux/pagevec.h> |
39 | #include <linux/writeback.h> | 39 | #include <linux/writeback.h> |
40 | 40 | ||
41 | |||
42 | /* | ||
43 | * Prime number of hash buckets since address is used as the key. | ||
44 | */ | ||
45 | #define NVSYNC 37 | ||
46 | #define to_ioend_wq(v) (&xfs_ioend_wq[((unsigned long)v) % NVSYNC]) | ||
47 | static wait_queue_head_t xfs_ioend_wq[NVSYNC]; | ||
48 | |||
49 | void __init | ||
50 | xfs_ioend_init(void) | ||
51 | { | ||
52 | int i; | ||
53 | |||
54 | for (i = 0; i < NVSYNC; i++) | ||
55 | init_waitqueue_head(&xfs_ioend_wq[i]); | ||
56 | } | ||
57 | |||
58 | void | ||
59 | xfs_ioend_wait( | ||
60 | xfs_inode_t *ip) | ||
61 | { | ||
62 | wait_queue_head_t *wq = to_ioend_wq(ip); | ||
63 | |||
64 | wait_event(*wq, (atomic_read(&ip->i_iocount) == 0)); | ||
65 | } | ||
66 | |||
67 | STATIC void | ||
68 | xfs_ioend_wake( | ||
69 | xfs_inode_t *ip) | ||
70 | { | ||
71 | if (atomic_dec_and_test(&ip->i_iocount)) | ||
72 | wake_up(to_ioend_wq(ip)); | ||
73 | } | ||
74 | |||
75 | void | 41 | void |
76 | xfs_count_page_state( | 42 | xfs_count_page_state( |
77 | struct page *page, | 43 | struct page *page, |
@@ -115,25 +81,20 @@ xfs_destroy_ioend( | |||
115 | xfs_ioend_t *ioend) | 81 | xfs_ioend_t *ioend) |
116 | { | 82 | { |
117 | struct buffer_head *bh, *next; | 83 | struct buffer_head *bh, *next; |
118 | struct xfs_inode *ip = XFS_I(ioend->io_inode); | ||
119 | 84 | ||
120 | for (bh = ioend->io_buffer_head; bh; bh = next) { | 85 | for (bh = ioend->io_buffer_head; bh; bh = next) { |
121 | next = bh->b_private; | 86 | next = bh->b_private; |
122 | bh->b_end_io(bh, !ioend->io_error); | 87 | bh->b_end_io(bh, !ioend->io_error); |
123 | } | 88 | } |
124 | 89 | ||
125 | /* | 90 | if (ioend->io_iocb) { |
126 | * Volume managers supporting multiple paths can send back ENODEV | 91 | if (ioend->io_isasync) { |
127 | * when the final path disappears. In this case continuing to fill | 92 | aio_complete(ioend->io_iocb, ioend->io_error ? |
128 | * the page cache with dirty data which cannot be written out is | 93 | ioend->io_error : ioend->io_result, 0); |
129 | * evil, so prevent that. | 94 | } |
130 | */ | 95 | inode_dio_done(ioend->io_inode); |
131 | if (unlikely(ioend->io_error == -ENODEV)) { | ||
132 | xfs_do_force_shutdown(ip->i_mount, SHUTDOWN_DEVICE_REQ, | ||
133 | __FILE__, __LINE__); | ||
134 | } | 96 | } |
135 | 97 | ||
136 | xfs_ioend_wake(ip); | ||
137 | mempool_free(ioend, xfs_ioend_pool); | 98 | mempool_free(ioend, xfs_ioend_pool); |
138 | } | 99 | } |
139 | 100 | ||
@@ -156,6 +117,15 @@ xfs_ioend_new_eof( | |||
156 | } | 117 | } |
157 | 118 | ||
158 | /* | 119 | /* |
120 | * Fast and loose check if this write could update the on-disk inode size. | ||
121 | */ | ||
122 | static inline bool xfs_ioend_is_append(struct xfs_ioend *ioend) | ||
123 | { | ||
124 | return ioend->io_offset + ioend->io_size > | ||
125 | XFS_I(ioend->io_inode)->i_d.di_size; | ||
126 | } | ||
127 | |||
128 | /* | ||
159 | * Update on-disk file size now that data has been written to disk. The | 129 | * Update on-disk file size now that data has been written to disk. The |
160 | * current in-memory file size is i_size. If a write is beyond eof i_new_size | 130 | * current in-memory file size is i_size. If a write is beyond eof i_new_size |
161 | * will be the intended file size until i_size is updated. If this write does | 131 | * will be the intended file size until i_size is updated. If this write does |
@@ -173,9 +143,6 @@ xfs_setfilesize( | |||
173 | xfs_inode_t *ip = XFS_I(ioend->io_inode); | 143 | xfs_inode_t *ip = XFS_I(ioend->io_inode); |
174 | xfs_fsize_t isize; | 144 | xfs_fsize_t isize; |
175 | 145 | ||
176 | if (unlikely(ioend->io_error)) | ||
177 | return 0; | ||
178 | |||
179 | if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) | 146 | if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) |
180 | return EAGAIN; | 147 | return EAGAIN; |
181 | 148 | ||
@@ -192,6 +159,9 @@ xfs_setfilesize( | |||
192 | 159 | ||
193 | /* | 160 | /* |
194 | * Schedule IO completion handling on the final put of an ioend. | 161 | * Schedule IO completion handling on the final put of an ioend. |
162 | * | ||
163 | * If there is no work to do we might as well call it a day and free the | ||
164 | * ioend right now. | ||
195 | */ | 165 | */ |
196 | STATIC void | 166 | STATIC void |
197 | xfs_finish_ioend( | 167 | xfs_finish_ioend( |
@@ -200,8 +170,10 @@ xfs_finish_ioend( | |||
200 | if (atomic_dec_and_test(&ioend->io_remaining)) { | 170 | if (atomic_dec_and_test(&ioend->io_remaining)) { |
201 | if (ioend->io_type == IO_UNWRITTEN) | 171 | if (ioend->io_type == IO_UNWRITTEN) |
202 | queue_work(xfsconvertd_workqueue, &ioend->io_work); | 172 | queue_work(xfsconvertd_workqueue, &ioend->io_work); |
203 | else | 173 | else if (xfs_ioend_is_append(ioend)) |
204 | queue_work(xfsdatad_workqueue, &ioend->io_work); | 174 | queue_work(xfsdatad_workqueue, &ioend->io_work); |
175 | else | ||
176 | xfs_destroy_ioend(ioend); | ||
205 | } | 177 | } |
206 | } | 178 | } |
207 | 179 | ||
@@ -216,17 +188,24 @@ xfs_end_io( | |||
216 | struct xfs_inode *ip = XFS_I(ioend->io_inode); | 188 | struct xfs_inode *ip = XFS_I(ioend->io_inode); |
217 | int error = 0; | 189 | int error = 0; |
218 | 190 | ||
191 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) { | ||
192 | error = -EIO; | ||
193 | goto done; | ||
194 | } | ||
195 | if (ioend->io_error) | ||
196 | goto done; | ||
197 | |||
219 | /* | 198 | /* |
220 | * For unwritten extents we need to issue transactions to convert a | 199 | * For unwritten extents we need to issue transactions to convert a |
221 | * range to normal written extens after the data I/O has finished. | 200 | * range to normal written extens after the data I/O has finished. |
222 | */ | 201 | */ |
223 | if (ioend->io_type == IO_UNWRITTEN && | 202 | if (ioend->io_type == IO_UNWRITTEN) { |
224 | likely(!ioend->io_error && !XFS_FORCED_SHUTDOWN(ip->i_mount))) { | ||
225 | |||
226 | error = xfs_iomap_write_unwritten(ip, ioend->io_offset, | 203 | error = xfs_iomap_write_unwritten(ip, ioend->io_offset, |
227 | ioend->io_size); | 204 | ioend->io_size); |
228 | if (error) | 205 | if (error) { |
229 | ioend->io_error = error; | 206 | ioend->io_error = -error; |
207 | goto done; | ||
208 | } | ||
230 | } | 209 | } |
231 | 210 | ||
232 | /* | 211 | /* |
@@ -236,6 +215,7 @@ xfs_end_io( | |||
236 | error = xfs_setfilesize(ioend); | 215 | error = xfs_setfilesize(ioend); |
237 | ASSERT(!error || error == EAGAIN); | 216 | ASSERT(!error || error == EAGAIN); |
238 | 217 | ||
218 | done: | ||
239 | /* | 219 | /* |
240 | * If we didn't complete processing of the ioend, requeue it to the | 220 | * If we didn't complete processing of the ioend, requeue it to the |
241 | * tail of the workqueue for another attempt later. Otherwise destroy | 221 | * tail of the workqueue for another attempt later. Otherwise destroy |
@@ -247,8 +227,6 @@ xfs_end_io( | |||
247 | /* ensure we don't spin on blocked ioends */ | 227 | /* ensure we don't spin on blocked ioends */ |
248 | delay(1); | 228 | delay(1); |
249 | } else { | 229 | } else { |
250 | if (ioend->io_iocb) | ||
251 | aio_complete(ioend->io_iocb, ioend->io_result, 0); | ||
252 | xfs_destroy_ioend(ioend); | 230 | xfs_destroy_ioend(ioend); |
253 | } | 231 | } |
254 | } | 232 | } |
@@ -285,13 +263,13 @@ xfs_alloc_ioend( | |||
285 | * all the I/O from calling the completion routine too early. | 263 | * all the I/O from calling the completion routine too early. |
286 | */ | 264 | */ |
287 | atomic_set(&ioend->io_remaining, 1); | 265 | atomic_set(&ioend->io_remaining, 1); |
266 | ioend->io_isasync = 0; | ||
288 | ioend->io_error = 0; | 267 | ioend->io_error = 0; |
289 | ioend->io_list = NULL; | 268 | ioend->io_list = NULL; |
290 | ioend->io_type = type; | 269 | ioend->io_type = type; |
291 | ioend->io_inode = inode; | 270 | ioend->io_inode = inode; |
292 | ioend->io_buffer_head = NULL; | 271 | ioend->io_buffer_head = NULL; |
293 | ioend->io_buffer_tail = NULL; | 272 | ioend->io_buffer_tail = NULL; |
294 | atomic_inc(&XFS_I(ioend->io_inode)->i_iocount); | ||
295 | ioend->io_offset = 0; | 273 | ioend->io_offset = 0; |
296 | ioend->io_size = 0; | 274 | ioend->io_size = 0; |
297 | ioend->io_iocb = NULL; | 275 | ioend->io_iocb = NULL; |
@@ -337,8 +315,8 @@ xfs_map_blocks( | |||
337 | count = mp->m_maxioffset - offset; | 315 | count = mp->m_maxioffset - offset; |
338 | end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); | 316 | end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); |
339 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | 317 | offset_fsb = XFS_B_TO_FSBT(mp, offset); |
340 | error = xfs_bmapi(NULL, ip, offset_fsb, end_fsb - offset_fsb, | 318 | error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, |
341 | bmapi_flags, NULL, 0, imap, &nimaps, NULL); | 319 | imap, &nimaps, bmapi_flags); |
342 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 320 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
343 | 321 | ||
344 | if (error) | 322 | if (error) |
@@ -551,7 +529,6 @@ xfs_cancel_ioend( | |||
551 | unlock_buffer(bh); | 529 | unlock_buffer(bh); |
552 | } while ((bh = next_bh) != NULL); | 530 | } while ((bh = next_bh) != NULL); |
553 | 531 | ||
554 | xfs_ioend_wake(XFS_I(ioend->io_inode)); | ||
555 | mempool_free(ioend, xfs_ioend_pool); | 532 | mempool_free(ioend, xfs_ioend_pool); |
556 | } while ((ioend = next) != NULL); | 533 | } while ((ioend = next) != NULL); |
557 | } | 534 | } |
@@ -1161,8 +1138,8 @@ __xfs_get_blocks( | |||
1161 | end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size); | 1138 | end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size); |
1162 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | 1139 | offset_fsb = XFS_B_TO_FSBT(mp, offset); |
1163 | 1140 | ||
1164 | error = xfs_bmapi(NULL, ip, offset_fsb, end_fsb - offset_fsb, | 1141 | error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, |
1165 | XFS_BMAPI_ENTIRE, NULL, 0, &imap, &nimaps, NULL); | 1142 | &imap, &nimaps, XFS_BMAPI_ENTIRE); |
1166 | if (error) | 1143 | if (error) |
1167 | goto out_unlock; | 1144 | goto out_unlock; |
1168 | 1145 | ||
@@ -1300,7 +1277,6 @@ xfs_end_io_direct_write( | |||
1300 | bool is_async) | 1277 | bool is_async) |
1301 | { | 1278 | { |
1302 | struct xfs_ioend *ioend = iocb->private; | 1279 | struct xfs_ioend *ioend = iocb->private; |
1303 | struct inode *inode = ioend->io_inode; | ||
1304 | 1280 | ||
1305 | /* | 1281 | /* |
1306 | * blockdev_direct_IO can return an error even after the I/O | 1282 | * blockdev_direct_IO can return an error even after the I/O |
@@ -1311,28 +1287,17 @@ xfs_end_io_direct_write( | |||
1311 | 1287 | ||
1312 | ioend->io_offset = offset; | 1288 | ioend->io_offset = offset; |
1313 | ioend->io_size = size; | 1289 | ioend->io_size = size; |
1290 | ioend->io_iocb = iocb; | ||
1291 | ioend->io_result = ret; | ||
1314 | if (private && size > 0) | 1292 | if (private && size > 0) |
1315 | ioend->io_type = IO_UNWRITTEN; | 1293 | ioend->io_type = IO_UNWRITTEN; |
1316 | 1294 | ||
1317 | if (is_async) { | 1295 | if (is_async) { |
1318 | /* | 1296 | ioend->io_isasync = 1; |
1319 | * If we are converting an unwritten extent we need to delay | ||
1320 | * the AIO completion until after the unwrittent extent | ||
1321 | * conversion has completed, otherwise do it ASAP. | ||
1322 | */ | ||
1323 | if (ioend->io_type == IO_UNWRITTEN) { | ||
1324 | ioend->io_iocb = iocb; | ||
1325 | ioend->io_result = ret; | ||
1326 | } else { | ||
1327 | aio_complete(iocb, ret, 0); | ||
1328 | } | ||
1329 | xfs_finish_ioend(ioend); | 1297 | xfs_finish_ioend(ioend); |
1330 | } else { | 1298 | } else { |
1331 | xfs_finish_ioend_sync(ioend); | 1299 | xfs_finish_ioend_sync(ioend); |
1332 | } | 1300 | } |
1333 | |||
1334 | /* XXX: probably should move into the real I/O completion handler */ | ||
1335 | inode_dio_done(inode); | ||
1336 | } | 1301 | } |
1337 | 1302 | ||
1338 | STATIC ssize_t | 1303 | STATIC ssize_t |