diff options
Diffstat (limited to 'fs/xfs/xfs_trans_buf.c')
-rw-r--r-- | fs/xfs/xfs_trans_buf.c | 137 |
1 files changed, 33 insertions, 104 deletions
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index e2b2216b1635..0a4d4ab6d9a9 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c | |||
@@ -21,8 +21,6 @@ | |||
21 | #include "xfs_format.h" | 21 | #include "xfs_format.h" |
22 | #include "xfs_log_format.h" | 22 | #include "xfs_log_format.h" |
23 | #include "xfs_trans_resv.h" | 23 | #include "xfs_trans_resv.h" |
24 | #include "xfs_sb.h" | ||
25 | #include "xfs_ag.h" | ||
26 | #include "xfs_mount.h" | 24 | #include "xfs_mount.h" |
27 | #include "xfs_inode.h" | 25 | #include "xfs_inode.h" |
28 | #include "xfs_trans.h" | 26 | #include "xfs_trans.h" |
@@ -229,13 +227,6 @@ xfs_trans_getsb(xfs_trans_t *tp, | |||
229 | return bp; | 227 | return bp; |
230 | } | 228 | } |
231 | 229 | ||
232 | #ifdef DEBUG | ||
233 | xfs_buftarg_t *xfs_error_target; | ||
234 | int xfs_do_error; | ||
235 | int xfs_req_num; | ||
236 | int xfs_error_mod = 33; | ||
237 | #endif | ||
238 | |||
239 | /* | 230 | /* |
240 | * Get and lock the buffer for the caller if it is not already | 231 | * Get and lock the buffer for the caller if it is not already |
241 | * locked within the given transaction. If it has not yet been | 232 | * locked within the given transaction. If it has not yet been |
@@ -257,46 +248,11 @@ xfs_trans_read_buf_map( | |||
257 | struct xfs_buf **bpp, | 248 | struct xfs_buf **bpp, |
258 | const struct xfs_buf_ops *ops) | 249 | const struct xfs_buf_ops *ops) |
259 | { | 250 | { |
260 | xfs_buf_t *bp; | 251 | struct xfs_buf *bp = NULL; |
261 | xfs_buf_log_item_t *bip; | 252 | struct xfs_buf_log_item *bip; |
262 | int error; | 253 | int error; |
263 | 254 | ||
264 | *bpp = NULL; | 255 | *bpp = NULL; |
265 | if (!tp) { | ||
266 | bp = xfs_buf_read_map(target, map, nmaps, flags, ops); | ||
267 | if (!bp) | ||
268 | return (flags & XBF_TRYLOCK) ? | ||
269 | -EAGAIN : -ENOMEM; | ||
270 | |||
271 | if (bp->b_error) { | ||
272 | error = bp->b_error; | ||
273 | xfs_buf_ioerror_alert(bp, __func__); | ||
274 | XFS_BUF_UNDONE(bp); | ||
275 | xfs_buf_stale(bp); | ||
276 | xfs_buf_relse(bp); | ||
277 | |||
278 | /* bad CRC means corrupted metadata */ | ||
279 | if (error == -EFSBADCRC) | ||
280 | error = -EFSCORRUPTED; | ||
281 | return error; | ||
282 | } | ||
283 | #ifdef DEBUG | ||
284 | if (xfs_do_error) { | ||
285 | if (xfs_error_target == target) { | ||
286 | if (((xfs_req_num++) % xfs_error_mod) == 0) { | ||
287 | xfs_buf_relse(bp); | ||
288 | xfs_debug(mp, "Returning error!"); | ||
289 | return -EIO; | ||
290 | } | ||
291 | } | ||
292 | } | ||
293 | #endif | ||
294 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
295 | goto shutdown_abort; | ||
296 | *bpp = bp; | ||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | /* | 256 | /* |
301 | * If we find the buffer in the cache with this transaction | 257 | * If we find the buffer in the cache with this transaction |
302 | * pointer in its b_fsprivate2 field, then we know we already | 258 | * pointer in its b_fsprivate2 field, then we know we already |
@@ -305,49 +261,24 @@ xfs_trans_read_buf_map( | |||
305 | * If the buffer is not yet read in, then we read it in, increment | 261 | * If the buffer is not yet read in, then we read it in, increment |
306 | * the lock recursion count, and return it to the caller. | 262 | * the lock recursion count, and return it to the caller. |
307 | */ | 263 | */ |
308 | bp = xfs_trans_buf_item_match(tp, target, map, nmaps); | 264 | if (tp) |
309 | if (bp != NULL) { | 265 | bp = xfs_trans_buf_item_match(tp, target, map, nmaps); |
266 | if (bp) { | ||
310 | ASSERT(xfs_buf_islocked(bp)); | 267 | ASSERT(xfs_buf_islocked(bp)); |
311 | ASSERT(bp->b_transp == tp); | 268 | ASSERT(bp->b_transp == tp); |
312 | ASSERT(bp->b_fspriv != NULL); | 269 | ASSERT(bp->b_fspriv != NULL); |
313 | ASSERT(!bp->b_error); | 270 | ASSERT(!bp->b_error); |
314 | if (!(XFS_BUF_ISDONE(bp))) { | 271 | ASSERT(bp->b_flags & XBF_DONE); |
315 | trace_xfs_trans_read_buf_io(bp, _RET_IP_); | 272 | |
316 | ASSERT(!XFS_BUF_ISASYNC(bp)); | ||
317 | ASSERT(bp->b_iodone == NULL); | ||
318 | XFS_BUF_READ(bp); | ||
319 | bp->b_ops = ops; | ||
320 | |||
321 | error = xfs_buf_submit_wait(bp); | ||
322 | if (error) { | ||
323 | if (!XFS_FORCED_SHUTDOWN(mp)) | ||
324 | xfs_buf_ioerror_alert(bp, __func__); | ||
325 | xfs_buf_relse(bp); | ||
326 | /* | ||
327 | * We can gracefully recover from most read | ||
328 | * errors. Ones we can't are those that happen | ||
329 | * after the transaction's already dirty. | ||
330 | */ | ||
331 | if (tp->t_flags & XFS_TRANS_DIRTY) | ||
332 | xfs_force_shutdown(tp->t_mountp, | ||
333 | SHUTDOWN_META_IO_ERROR); | ||
334 | /* bad CRC means corrupted metadata */ | ||
335 | if (error == -EFSBADCRC) | ||
336 | error = -EFSCORRUPTED; | ||
337 | return error; | ||
338 | } | ||
339 | } | ||
340 | /* | 273 | /* |
341 | * We never locked this buf ourselves, so we shouldn't | 274 | * We never locked this buf ourselves, so we shouldn't |
342 | * brelse it either. Just get out. | 275 | * brelse it either. Just get out. |
343 | */ | 276 | */ |
344 | if (XFS_FORCED_SHUTDOWN(mp)) { | 277 | if (XFS_FORCED_SHUTDOWN(mp)) { |
345 | trace_xfs_trans_read_buf_shut(bp, _RET_IP_); | 278 | trace_xfs_trans_read_buf_shut(bp, _RET_IP_); |
346 | *bpp = NULL; | ||
347 | return -EIO; | 279 | return -EIO; |
348 | } | 280 | } |
349 | 281 | ||
350 | |||
351 | bip = bp->b_fspriv; | 282 | bip = bp->b_fspriv; |
352 | bip->bli_recur++; | 283 | bip->bli_recur++; |
353 | 284 | ||
@@ -358,17 +289,29 @@ xfs_trans_read_buf_map( | |||
358 | } | 289 | } |
359 | 290 | ||
360 | bp = xfs_buf_read_map(target, map, nmaps, flags, ops); | 291 | bp = xfs_buf_read_map(target, map, nmaps, flags, ops); |
361 | if (bp == NULL) { | 292 | if (!bp) { |
362 | *bpp = NULL; | 293 | if (!(flags & XBF_TRYLOCK)) |
363 | return (flags & XBF_TRYLOCK) ? | 294 | return -ENOMEM; |
364 | 0 : -ENOMEM; | 295 | return tp ? 0 : -EAGAIN; |
365 | } | 296 | } |
297 | |||
298 | /* | ||
299 | * If we've had a read error, then the contents of the buffer are | ||
300 | * invalid and should not be used. To ensure that a followup read tries | ||
301 | * to pull the buffer from disk again, we clear the XBF_DONE flag and | ||
302 | * mark the buffer stale. This ensures that anyone who has a current | ||
303 | * reference to the buffer will interpret it's contents correctly and | ||
304 | * future cache lookups will also treat it as an empty, uninitialised | ||
305 | * buffer. | ||
306 | */ | ||
366 | if (bp->b_error) { | 307 | if (bp->b_error) { |
367 | error = bp->b_error; | 308 | error = bp->b_error; |
309 | if (!XFS_FORCED_SHUTDOWN(mp)) | ||
310 | xfs_buf_ioerror_alert(bp, __func__); | ||
311 | bp->b_flags &= ~XBF_DONE; | ||
368 | xfs_buf_stale(bp); | 312 | xfs_buf_stale(bp); |
369 | XFS_BUF_DONE(bp); | 313 | |
370 | xfs_buf_ioerror_alert(bp, __func__); | 314 | if (tp && (tp->t_flags & XFS_TRANS_DIRTY)) |
371 | if (tp->t_flags & XFS_TRANS_DIRTY) | ||
372 | xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR); | 315 | xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR); |
373 | xfs_buf_relse(bp); | 316 | xfs_buf_relse(bp); |
374 | 317 | ||
@@ -377,33 +320,19 @@ xfs_trans_read_buf_map( | |||
377 | error = -EFSCORRUPTED; | 320 | error = -EFSCORRUPTED; |
378 | return error; | 321 | return error; |
379 | } | 322 | } |
380 | #ifdef DEBUG | 323 | |
381 | if (xfs_do_error && !(tp->t_flags & XFS_TRANS_DIRTY)) { | 324 | if (XFS_FORCED_SHUTDOWN(mp)) { |
382 | if (xfs_error_target == target) { | 325 | xfs_buf_relse(bp); |
383 | if (((xfs_req_num++) % xfs_error_mod) == 0) { | 326 | trace_xfs_trans_read_buf_shut(bp, _RET_IP_); |
384 | xfs_force_shutdown(tp->t_mountp, | 327 | return -EIO; |
385 | SHUTDOWN_META_IO_ERROR); | ||
386 | xfs_buf_relse(bp); | ||
387 | xfs_debug(mp, "Returning trans error!"); | ||
388 | return -EIO; | ||
389 | } | ||
390 | } | ||
391 | } | 328 | } |
392 | #endif | ||
393 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
394 | goto shutdown_abort; | ||
395 | 329 | ||
396 | _xfs_trans_bjoin(tp, bp, 1); | 330 | if (tp) |
331 | _xfs_trans_bjoin(tp, bp, 1); | ||
397 | trace_xfs_trans_read_buf(bp->b_fspriv); | 332 | trace_xfs_trans_read_buf(bp->b_fspriv); |
398 | |||
399 | *bpp = bp; | 333 | *bpp = bp; |
400 | return 0; | 334 | return 0; |
401 | 335 | ||
402 | shutdown_abort: | ||
403 | trace_xfs_trans_read_buf_shut(bp, _RET_IP_); | ||
404 | xfs_buf_relse(bp); | ||
405 | *bpp = NULL; | ||
406 | return -EIO; | ||
407 | } | 336 | } |
408 | 337 | ||
409 | /* | 338 | /* |