diff options
Diffstat (limited to 'fs/xfs/xfs_trans_buf.c')
-rw-r--r-- | fs/xfs/xfs_trans_buf.c | 99 |
1 files changed, 24 insertions, 75 deletions
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index 15919f67a88f..286a287ac57a 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c | |||
@@ -322,49 +322,38 @@ xfs_trans_read_buf_map( | |||
322 | } | 322 | } |
323 | 323 | ||
324 | /* | 324 | /* |
325 | * Release the buffer bp which was previously acquired with one of the | 325 | * Release a buffer previously joined to the transaction. If the buffer is |
326 | * xfs_trans_... buffer allocation routines if the buffer has not | 326 | * modified within this transaction, decrement the recursion count but do not |
327 | * been modified within this transaction. If the buffer is modified | 327 | * release the buffer even if the count goes to 0. If the buffer is not modified |
328 | * within this transaction, do decrement the recursion count but do | 328 | * within the transaction, decrement the recursion count and release the buffer |
329 | * not release the buffer even if the count goes to 0. If the buffer is not | 329 | * if the recursion count goes to 0. |
330 | * modified within the transaction, decrement the recursion count and | ||
331 | * release the buffer if the recursion count goes to 0. | ||
332 | * | 330 | * |
333 | * If the buffer is to be released and it was not modified before | 331 | * If the buffer is to be released and it was not already dirty before this |
334 | * this transaction began, then free the buf_log_item associated with it. | 332 | * transaction began, then also free the buf_log_item associated with it. |
335 | * | 333 | * |
336 | * If the transaction pointer is NULL, make this just a normal | 334 | * If the transaction pointer is NULL, this is a normal xfs_buf_relse() call. |
337 | * brelse() call. | ||
338 | */ | 335 | */ |
339 | void | 336 | void |
340 | xfs_trans_brelse( | 337 | xfs_trans_brelse( |
341 | xfs_trans_t *tp, | 338 | struct xfs_trans *tp, |
342 | xfs_buf_t *bp) | 339 | struct xfs_buf *bp) |
343 | { | 340 | { |
344 | struct xfs_buf_log_item *bip; | 341 | struct xfs_buf_log_item *bip = bp->b_log_item; |
345 | int freed; | ||
346 | 342 | ||
347 | /* | 343 | ASSERT(bp->b_transp == tp); |
348 | * Default to a normal brelse() call if the tp is NULL. | 344 | |
349 | */ | 345 | if (!tp) { |
350 | if (tp == NULL) { | ||
351 | ASSERT(bp->b_transp == NULL); | ||
352 | xfs_buf_relse(bp); | 346 | xfs_buf_relse(bp); |
353 | return; | 347 | return; |
354 | } | 348 | } |
355 | 349 | ||
356 | ASSERT(bp->b_transp == tp); | 350 | trace_xfs_trans_brelse(bip); |
357 | bip = bp->b_log_item; | ||
358 | ASSERT(bip->bli_item.li_type == XFS_LI_BUF); | 351 | ASSERT(bip->bli_item.li_type == XFS_LI_BUF); |
359 | ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); | ||
360 | ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL)); | ||
361 | ASSERT(atomic_read(&bip->bli_refcount) > 0); | 352 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
362 | 353 | ||
363 | trace_xfs_trans_brelse(bip); | ||
364 | |||
365 | /* | 354 | /* |
366 | * If the release is just for a recursive lock, | 355 | * If the release is for a recursive lookup, then decrement the count |
367 | * then decrement the count and return. | 356 | * and return. |
368 | */ | 357 | */ |
369 | if (bip->bli_recur > 0) { | 358 | if (bip->bli_recur > 0) { |
370 | bip->bli_recur--; | 359 | bip->bli_recur--; |
@@ -372,64 +361,24 @@ xfs_trans_brelse( | |||
372 | } | 361 | } |
373 | 362 | ||
374 | /* | 363 | /* |
375 | * If the buffer is dirty within this transaction, we can't | 364 | * If the buffer is invalidated or dirty in this transaction, we can't |
376 | * release it until we commit. | 365 | * release it until we commit. |
377 | */ | 366 | */ |
378 | if (test_bit(XFS_LI_DIRTY, &bip->bli_item.li_flags)) | 367 | if (test_bit(XFS_LI_DIRTY, &bip->bli_item.li_flags)) |
379 | return; | 368 | return; |
380 | |||
381 | /* | ||
382 | * If the buffer has been invalidated, then we can't release | ||
383 | * it until the transaction commits to disk unless it is re-dirtied | ||
384 | * as part of this transaction. This prevents us from pulling | ||
385 | * the item from the AIL before we should. | ||
386 | */ | ||
387 | if (bip->bli_flags & XFS_BLI_STALE) | 369 | if (bip->bli_flags & XFS_BLI_STALE) |
388 | return; | 370 | return; |
389 | 371 | ||
390 | ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED)); | ||
391 | |||
392 | /* | 372 | /* |
393 | * Free up the log item descriptor tracking the released item. | 373 | * Unlink the log item from the transaction and clear the hold flag, if |
374 | * set. We wouldn't want the next user of the buffer to get confused. | ||
394 | */ | 375 | */ |
376 | ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED)); | ||
395 | xfs_trans_del_item(&bip->bli_item); | 377 | xfs_trans_del_item(&bip->bli_item); |
378 | bip->bli_flags &= ~XFS_BLI_HOLD; | ||
396 | 379 | ||
397 | /* | 380 | /* drop the reference to the bli */ |
398 | * Clear the hold flag in the buf log item if it is set. | 381 | xfs_buf_item_put(bip); |
399 | * We wouldn't want the next user of the buffer to | ||
400 | * get confused. | ||
401 | */ | ||
402 | if (bip->bli_flags & XFS_BLI_HOLD) { | ||
403 | bip->bli_flags &= ~XFS_BLI_HOLD; | ||
404 | } | ||
405 | |||
406 | /* | ||
407 | * Drop our reference to the buf log item. | ||
408 | */ | ||
409 | freed = atomic_dec_and_test(&bip->bli_refcount); | ||
410 | |||
411 | /* | ||
412 | * If the buf item is not tracking data in the log, then we must free it | ||
413 | * before releasing the buffer back to the free pool. | ||
414 | * | ||
415 | * If the fs has shutdown and we dropped the last reference, it may fall | ||
416 | * on us to release a (possibly dirty) bli if it never made it to the | ||
417 | * AIL (e.g., the aborted unpin already happened and didn't release it | ||
418 | * due to our reference). Since we're already shutdown and need | ||
419 | * ail_lock, just force remove from the AIL and release the bli here. | ||
420 | */ | ||
421 | if (XFS_FORCED_SHUTDOWN(tp->t_mountp) && freed) { | ||
422 | xfs_trans_ail_remove(&bip->bli_item, SHUTDOWN_LOG_IO_ERROR); | ||
423 | xfs_buf_item_relse(bp); | ||
424 | } else if (!(bip->bli_flags & XFS_BLI_DIRTY)) { | ||
425 | /*** | ||
426 | ASSERT(bp->b_pincount == 0); | ||
427 | ***/ | ||
428 | ASSERT(atomic_read(&bip->bli_refcount) == 0); | ||
429 | ASSERT(!test_bit(XFS_LI_IN_AIL, &bip->bli_item.li_flags)); | ||
430 | ASSERT(!(bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF)); | ||
431 | xfs_buf_item_relse(bp); | ||
432 | } | ||
433 | 382 | ||
434 | bp->b_transp = NULL; | 383 | bp->b_transp = NULL; |
435 | xfs_buf_relse(bp); | 384 | xfs_buf_relse(bp); |