aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2014-12-03 17:43:13 -0500
committerDave Chinner <david@fromorbit.com>2014-12-03 17:43:13 -0500
commit2d3d0c53df99587e1d58759f805c3aae79fac453 (patch)
tree0ee91663769ac5c8b3e67d833a596efa1a15b72d /fs/xfs
parentcdc9cec7c0ff521edf8c0e9c9432bf8fdccfc702 (diff)
xfs: lobotomise xfs_trans_read_buf_map()
There's a case in that code where it checks for a buffer match in a transaction where the buffer is not marked done. i.e. trying to catch a buffer we have locked in the transaction but have not completed IO on. The only way we can find a buffer that has not had IO completed on it is if it had readahead issued on it, but we never do readahead on buffers that we have already joined into a transaction. Hence this condition cannot occur, and buffers locked and joined into a transaction should always be marked done and not under IO. Remove this code and re-order xfs_trans_read_buf_map() to remove duplicated IO dispatch and error handling code. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_trans_buf.c135
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
233xfs_buftarg_t *xfs_error_target;
234int xfs_do_error;
235int xfs_req_num;
236int 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
402shutdown_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/*