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.c99
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 */
339void 336void
340xfs_trans_brelse( 337xfs_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);