aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_trans_buf.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_trans_buf.c')
-rw-r--r--fs/xfs/xfs_trans_buf.c137
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
233xfs_buftarg_t *xfs_error_target;
234int xfs_do_error;
235int xfs_req_num;
236int 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
402shutdown_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/*