Commit 03b1293edad462ad1ad62bcc5160c76758e450d5

Authored by Dave Chinner
Committed by Ben Myers
1 parent 4b62acfe99

xfs: fix buffer shudown reference count mismatch

When we shut down the filesystem, we have to unpin and free all the
buffers currently active in the CIL. To do this we unpin and remove
them in one operation as a result of a failed iclogbuf write. For
buffers, we do this removal via a simultated IO completion of after
marking the buffer stale.

At the time we do this, we have two references to the buffer - the
active LRU reference and the buf log item.  The LRU reference is
removed by marking the buffer stale, and the active CIL reference is
by the xfs_buf_iodone() callback that is run by
xfs_buf_do_callbacks() during ioend processing (via the bp->b_iodone
callback).

However, ioend processing requires one more reference - that of the
IO that it is completing. We don't have this reference, so we free
the buffer prematurely and use it after it is freed. For buffers
marked with XBF_ASYNC, this leads to assert failures in
xfs_buf_rele() on debug kernels because the b_hold count is zero.

Fix this by making sure we take the necessary IO reference before
starting IO completion processing on the stale buffer, and set the
XBF_ASYNC flag to ensure that IO completion processing removes all
the active references from the buffer to ensure it is fully torn
down.

Cc: <stable@vger.kernel.org>
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Mark Tinguely <tinguely@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>

Showing 1 changed file with 18 additions and 0 deletions Side-by-side Diff

fs/xfs/xfs_buf_item.c
... ... @@ -526,7 +526,25 @@
526 526 }
527 527 xfs_buf_relse(bp);
528 528 } else if (freed && remove) {
  529 + /*
  530 + * There are currently two references to the buffer - the active
  531 + * LRU reference and the buf log item. What we are about to do
  532 + * here - simulate a failed IO completion - requires 3
  533 + * references.
  534 + *
  535 + * The LRU reference is removed by the xfs_buf_stale() call. The
  536 + * buf item reference is removed by the xfs_buf_iodone()
  537 + * callback that is run by xfs_buf_do_callbacks() during ioend
  538 + * processing (via the bp->b_iodone callback), and then finally
  539 + * the ioend processing will drop the IO reference if the buffer
  540 + * is marked XBF_ASYNC.
  541 + *
  542 + * Hence we need to take an additional reference here so that IO
  543 + * completion processing doesn't free the buffer prematurely.
  544 + */
529 545 xfs_buf_lock(bp);
  546 + xfs_buf_hold(bp);
  547 + bp->b_flags |= XBF_ASYNC;
530 548 xfs_buf_ioerror(bp, EIO);
531 549 XFS_BUF_UNDONE(bp);
532 550 xfs_buf_stale(bp);