diff options
| -rw-r--r-- | fs/xfs/xfs_trans_buf.c | 135 |
1 files changed, 33 insertions, 102 deletions
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index e2b2216b1635..2f363cdd1e14 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c | |||
| @@ -229,13 +229,6 @@ xfs_trans_getsb(xfs_trans_t *tp, | |||
| 229 | return bp; | 229 | return bp; |
| 230 | } | 230 | } |
| 231 | 231 | ||
| 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 | /* | 232 | /* |
| 240 | * Get and lock the buffer for the caller if it is not already | 233 | * 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 | 234 | * locked within the given transaction. If it has not yet been |
| @@ -257,46 +250,11 @@ xfs_trans_read_buf_map( | |||
| 257 | struct xfs_buf **bpp, | 250 | struct xfs_buf **bpp, |
| 258 | const struct xfs_buf_ops *ops) | 251 | const struct xfs_buf_ops *ops) |
| 259 | { | 252 | { |
| 260 | xfs_buf_t *bp; | 253 | struct xfs_buf *bp = NULL; |
| 261 | xfs_buf_log_item_t *bip; | 254 | struct xfs_buf_log_item *bip; |
| 262 | int error; | 255 | int error; |
| 263 | 256 | ||
| 264 | *bpp = NULL; | 257 | *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 | /* | 258 | /* |
| 301 | * If we find the buffer in the cache with this transaction | 259 | * If we find the buffer in the cache with this transaction |
| 302 | * pointer in its b_fsprivate2 field, then we know we already | 260 | * pointer in its b_fsprivate2 field, then we know we already |
| @@ -305,49 +263,24 @@ xfs_trans_read_buf_map( | |||
| 305 | * If the buffer is not yet read in, then we read it in, increment | 263 | * 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. | 264 | * the lock recursion count, and return it to the caller. |
| 307 | */ | 265 | */ |
| 308 | bp = xfs_trans_buf_item_match(tp, target, map, nmaps); | 266 | if (tp) |
| 309 | if (bp != NULL) { | 267 | bp = xfs_trans_buf_item_match(tp, target, map, nmaps); |
| 268 | if (bp) { | ||
| 310 | ASSERT(xfs_buf_islocked(bp)); | 269 | ASSERT(xfs_buf_islocked(bp)); |
| 311 | ASSERT(bp->b_transp == tp); | 270 | ASSERT(bp->b_transp == tp); |
| 312 | ASSERT(bp->b_fspriv != NULL); | 271 | ASSERT(bp->b_fspriv != NULL); |
| 313 | ASSERT(!bp->b_error); | 272 | ASSERT(!bp->b_error); |
| 314 | if (!(XFS_BUF_ISDONE(bp))) { | 273 | ASSERT(bp->b_flags & XBF_DONE); |
| 315 | trace_xfs_trans_read_buf_io(bp, _RET_IP_); | 274 | |
| 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 | /* | 275 | /* |
| 341 | * We never locked this buf ourselves, so we shouldn't | 276 | * We never locked this buf ourselves, so we shouldn't |
| 342 | * brelse it either. Just get out. | 277 | * brelse it either. Just get out. |
| 343 | */ | 278 | */ |
| 344 | if (XFS_FORCED_SHUTDOWN(mp)) { | 279 | if (XFS_FORCED_SHUTDOWN(mp)) { |
| 345 | trace_xfs_trans_read_buf_shut(bp, _RET_IP_); | 280 | trace_xfs_trans_read_buf_shut(bp, _RET_IP_); |
| 346 | *bpp = NULL; | ||
| 347 | return -EIO; | 281 | return -EIO; |
| 348 | } | 282 | } |
| 349 | 283 | ||
| 350 | |||
| 351 | bip = bp->b_fspriv; | 284 | bip = bp->b_fspriv; |
| 352 | bip->bli_recur++; | 285 | bip->bli_recur++; |
| 353 | 286 | ||
| @@ -358,17 +291,29 @@ xfs_trans_read_buf_map( | |||
| 358 | } | 291 | } |
| 359 | 292 | ||
| 360 | bp = xfs_buf_read_map(target, map, nmaps, flags, ops); | 293 | bp = xfs_buf_read_map(target, map, nmaps, flags, ops); |
| 361 | if (bp == NULL) { | 294 | if (!bp) { |
| 362 | *bpp = NULL; | 295 | if (!(flags & XBF_TRYLOCK)) |
| 363 | return (flags & XBF_TRYLOCK) ? | 296 | return -ENOMEM; |
| 364 | 0 : -ENOMEM; | 297 | return tp ? 0 : -EAGAIN; |
| 365 | } | 298 | } |
| 299 | |||
| 300 | /* | ||
| 301 | * If we've had a read error, then the contents of the buffer are | ||
| 302 | * invalid and should not be used. To ensure that a followup read tries | ||
| 303 | * to pull the buffer from disk again, we clear the XBF_DONE flag and | ||
| 304 | * mark the buffer stale. This ensures that anyone who has a current | ||
| 305 | * reference to the buffer will interpret it's contents correctly and | ||
| 306 | * future cache lookups will also treat it as an empty, uninitialised | ||
| 307 | * buffer. | ||
| 308 | */ | ||
| 366 | if (bp->b_error) { | 309 | if (bp->b_error) { |
| 367 | error = bp->b_error; | 310 | error = bp->b_error; |
| 311 | if (!XFS_FORCED_SHUTDOWN(mp)) | ||
| 312 | xfs_buf_ioerror_alert(bp, __func__); | ||
| 313 | bp->b_flags &= ~XBF_DONE; | ||
| 368 | xfs_buf_stale(bp); | 314 | xfs_buf_stale(bp); |
| 369 | XFS_BUF_DONE(bp); | 315 | |
| 370 | xfs_buf_ioerror_alert(bp, __func__); | 316 | 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); | 317 | xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR); |
| 373 | xfs_buf_relse(bp); | 318 | xfs_buf_relse(bp); |
| 374 | 319 | ||
| @@ -377,33 +322,19 @@ xfs_trans_read_buf_map( | |||
| 377 | error = -EFSCORRUPTED; | 322 | error = -EFSCORRUPTED; |
| 378 | return error; | 323 | return error; |
| 379 | } | 324 | } |
| 380 | #ifdef DEBUG | 325 | |
| 381 | if (xfs_do_error && !(tp->t_flags & XFS_TRANS_DIRTY)) { | 326 | if (XFS_FORCED_SHUTDOWN(mp)) { |
| 382 | if (xfs_error_target == target) { | 327 | xfs_buf_relse(bp); |
| 383 | if (((xfs_req_num++) % xfs_error_mod) == 0) { | 328 | trace_xfs_trans_read_buf_shut(bp, _RET_IP_); |
| 384 | xfs_force_shutdown(tp->t_mountp, | 329 | 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 | } | 330 | } |
| 392 | #endif | ||
| 393 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
| 394 | goto shutdown_abort; | ||
| 395 | 331 | ||
| 396 | _xfs_trans_bjoin(tp, bp, 1); | 332 | if (tp) |
| 333 | _xfs_trans_bjoin(tp, bp, 1); | ||
| 397 | trace_xfs_trans_read_buf(bp->b_fspriv); | 334 | trace_xfs_trans_read_buf(bp->b_fspriv); |
| 398 | |||
| 399 | *bpp = bp; | 335 | *bpp = bp; |
| 400 | return 0; | 336 | return 0; |
| 401 | 337 | ||
| 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 | } | 338 | } |
| 408 | 339 | ||
| 409 | /* | 340 | /* |
