diff options
author | Christoph Hellwig <hch@infradead.org> | 2011-08-24 01:59:25 -0400 |
---|---|---|
committer | Alex Elder <aelder@sgi.com> | 2011-10-11 22:15:01 -0400 |
commit | 04f658ee229f60dbb9a0dc2f3d6871b12b758051 (patch) | |
tree | eee3e17cf4af0f5c6cbb8393f247dfb6d823615a /fs/xfs/xfs_aops.c | |
parent | c58cb165bd44de8aaee9755a144136ae743be116 (diff) |
xfs: improve ioend error handling
Return unwritten extent conversion errors to aio_complete.
Skip both unwritten extent conversion and size updates if we had an
I/O error or the filesystem has been shut down.
Return -EIO to the aio/buffer completion handlers in case of a
forced shutdown.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_aops.c')
-rw-r--r-- | fs/xfs/xfs_aops.c | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 46bba3e0af47..22aadf667862 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c | |||
@@ -88,8 +88,10 @@ xfs_destroy_ioend( | |||
88 | } | 88 | } |
89 | 89 | ||
90 | if (ioend->io_iocb) { | 90 | if (ioend->io_iocb) { |
91 | if (ioend->io_isasync) | 91 | if (ioend->io_isasync) { |
92 | aio_complete(ioend->io_iocb, ioend->io_result, 0); | 92 | aio_complete(ioend->io_iocb, ioend->io_error ? |
93 | ioend->io_error : ioend->io_result, 0); | ||
94 | } | ||
93 | inode_dio_done(ioend->io_inode); | 95 | inode_dio_done(ioend->io_inode); |
94 | } | 96 | } |
95 | 97 | ||
@@ -141,9 +143,6 @@ xfs_setfilesize( | |||
141 | xfs_inode_t *ip = XFS_I(ioend->io_inode); | 143 | xfs_inode_t *ip = XFS_I(ioend->io_inode); |
142 | xfs_fsize_t isize; | 144 | xfs_fsize_t isize; |
143 | 145 | ||
144 | if (unlikely(ioend->io_error)) | ||
145 | return 0; | ||
146 | |||
147 | if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) | 146 | if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) |
148 | return EAGAIN; | 147 | return EAGAIN; |
149 | 148 | ||
@@ -189,17 +188,24 @@ xfs_end_io( | |||
189 | struct xfs_inode *ip = XFS_I(ioend->io_inode); | 188 | struct xfs_inode *ip = XFS_I(ioend->io_inode); |
190 | int error = 0; | 189 | int error = 0; |
191 | 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 | |||
192 | /* | 198 | /* |
193 | * For unwritten extents we need to issue transactions to convert a | 199 | * For unwritten extents we need to issue transactions to convert a |
194 | * 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. |
195 | */ | 201 | */ |
196 | if (ioend->io_type == IO_UNWRITTEN && | 202 | if (ioend->io_type == IO_UNWRITTEN) { |
197 | likely(!ioend->io_error && !XFS_FORCED_SHUTDOWN(ip->i_mount))) { | ||
198 | |||
199 | error = xfs_iomap_write_unwritten(ip, ioend->io_offset, | 203 | error = xfs_iomap_write_unwritten(ip, ioend->io_offset, |
200 | ioend->io_size); | 204 | ioend->io_size); |
201 | if (error) | 205 | if (error) { |
202 | ioend->io_error = error; | 206 | ioend->io_error = -error; |
207 | goto done; | ||
208 | } | ||
203 | } | 209 | } |
204 | 210 | ||
205 | /* | 211 | /* |
@@ -209,6 +215,7 @@ xfs_end_io( | |||
209 | error = xfs_setfilesize(ioend); | 215 | error = xfs_setfilesize(ioend); |
210 | ASSERT(!error || error == EAGAIN); | 216 | ASSERT(!error || error == EAGAIN); |
211 | 217 | ||
218 | done: | ||
212 | /* | 219 | /* |
213 | * 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 |
214 | * tail of the workqueue for another attempt later. Otherwise destroy | 221 | * tail of the workqueue for another attempt later. Otherwise destroy |