Skip to content

Commit 373b058

Browse files
cmaiolinodjwong
authored andcommitted
xfs: Properly retry failed dquot items in case of error during buffer writeback
Once the inode item writeback errors is already fixed, it's time to fix the same problem in dquot code. Although there were no reports of users hitting this bug in dquot code (at least none I've seen), the bug is there and I was already planning to fix it when the correct approach to fix the inodes part was decided. This patch aims to fix the same problem in dquot code, regarding failed buffers being unable to be resubmitted once they are flush locked. Tested with the recently test-case sent to fstests list by Hou Tao. Reviewed-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
1 parent 3b42d38 commit 373b058

File tree

2 files changed

+49
-5
lines changed

2 files changed

+49
-5
lines changed

fs/xfs/xfs_dquot.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -970,14 +970,22 @@ xfs_qm_dqflush_done(
970970
* holding the lock before removing the dquot from the AIL.
971971
*/
972972
if ((lip->li_flags & XFS_LI_IN_AIL) &&
973-
lip->li_lsn == qip->qli_flush_lsn) {
973+
((lip->li_lsn == qip->qli_flush_lsn) ||
974+
(lip->li_flags & XFS_LI_FAILED))) {
974975

975976
/* xfs_trans_ail_delete() drops the AIL lock. */
976977
spin_lock(&ailp->xa_lock);
977-
if (lip->li_lsn == qip->qli_flush_lsn)
978+
if (lip->li_lsn == qip->qli_flush_lsn) {
978979
xfs_trans_ail_delete(ailp, lip, SHUTDOWN_CORRUPT_INCORE);
979-
else
980+
} else {
981+
/*
982+
* Clear the failed state since we are about to drop the
983+
* flush lock
984+
*/
985+
if (lip->li_flags & XFS_LI_FAILED)
986+
xfs_clear_li_failed(lip);
980987
spin_unlock(&ailp->xa_lock);
988+
}
981989
}
982990

983991
/*

fs/xfs/xfs_dquot_item.c

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,20 +137,55 @@ xfs_qm_dqunpin_wait(
137137
wait_event(dqp->q_pinwait, (atomic_read(&dqp->q_pincount) == 0));
138138
}
139139

140+
/*
141+
* Callback used to mark a buffer with XFS_LI_FAILED when items in the buffer
142+
* have been failed during writeback
143+
*
144+
* this informs the AIL that the dquot is already flush locked on the next push,
145+
* and acquires a hold on the buffer to ensure that it isn't reclaimed before
146+
* dirty data makes it to disk.
147+
*/
148+
STATIC void
149+
xfs_dquot_item_error(
150+
struct xfs_log_item *lip,
151+
struct xfs_buf *bp)
152+
{
153+
struct xfs_dquot *dqp;
154+
155+
dqp = DQUOT_ITEM(lip)->qli_dquot;
156+
ASSERT(!completion_done(&dqp->q_flush));
157+
xfs_set_li_failed(lip, bp);
158+
}
159+
140160
STATIC uint
141161
xfs_qm_dquot_logitem_push(
142162
struct xfs_log_item *lip,
143163
struct list_head *buffer_list) __releases(&lip->li_ailp->xa_lock)
144164
__acquires(&lip->li_ailp->xa_lock)
145165
{
146166
struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot;
147-
struct xfs_buf *bp = NULL;
167+
struct xfs_buf *bp = lip->li_buf;
148168
uint rval = XFS_ITEM_SUCCESS;
149169
int error;
150170

151171
if (atomic_read(&dqp->q_pincount) > 0)
152172
return XFS_ITEM_PINNED;
153173

174+
/*
175+
* The buffer containing this item failed to be written back
176+
* previously. Resubmit the buffer for IO
177+
*/
178+
if (lip->li_flags & XFS_LI_FAILED) {
179+
if (!xfs_buf_trylock(bp))
180+
return XFS_ITEM_LOCKED;
181+
182+
if (!xfs_buf_resubmit_failed_buffers(bp, lip, buffer_list))
183+
rval = XFS_ITEM_FLUSHING;
184+
185+
xfs_buf_unlock(bp);
186+
return rval;
187+
}
188+
154189
if (!xfs_dqlock_nowait(dqp))
155190
return XFS_ITEM_LOCKED;
156191

@@ -242,7 +277,8 @@ static const struct xfs_item_ops xfs_dquot_item_ops = {
242277
.iop_unlock = xfs_qm_dquot_logitem_unlock,
243278
.iop_committed = xfs_qm_dquot_logitem_committed,
244279
.iop_push = xfs_qm_dquot_logitem_push,
245-
.iop_committing = xfs_qm_dquot_logitem_committing
280+
.iop_committing = xfs_qm_dquot_logitem_committing,
281+
.iop_error = xfs_dquot_item_error
246282
};
247283

248284
/*

0 commit comments

Comments
 (0)