Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

xfs: ensure dquot item is deleted from AIL only after log shutdown

In xfs_qm_dqflush(), when a dquot flush fails due to corruption
(the out_abort error path), the original code removed the dquot log
item from the AIL before calling xfs_force_shutdown(). This ordering
introduces a subtle race condition that can lead to data loss after
a crash.

The AIL tracks the oldest dirty metadata in the journal. The position
of the tail item in the AIL determines the log tail LSN, which is the
oldest LSN that must be preserved for crash recovery. When an item is
removed from the AIL, the log tail can advance past the LSN of that item.

The race window is as follows: if the dquot item happens to be at
the tail of the log, removing it from the AIL allows the log tail
to advance. If a concurrent log write is sampling the tail LSN at
the same time and subsequently writes a complete checkpoint (i.e.,
one containing a commit record) to disk before the shutdown takes
effect, the journal will no longer protect the dquot's last
modification. On the next mount, log recovery will not replay the
dquot changes, even though they were never written back to disk,
resulting in silent data loss.

Fix this by calling xfs_force_shutdown() before xfs_trans_ail_delete()
in the out_abort path. Once the log is shut down, no new log writes
can complete with an updated tail LSN, making it safe to remove the
dquot item from the AIL.

Cc: stable@vger.kernel.org
Fixes: b707fffda6a3 ("xfs: abort consistently on dquot flush failure")
Signed-off-by: Long Li <leo.lilong@huawei.com>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>

authored by

Long Li and committed by
Carlos Maiolino
186ac39b f1d77b86

+7 -1
+7 -1
fs/xfs/xfs_dquot.c
··· 1439 1439 return 0; 1440 1440 1441 1441 out_abort: 1442 + /* 1443 + * Shut down the log before removing the dquot item from the AIL. 1444 + * Otherwise, the log tail may advance past this item's LSN while 1445 + * log writes are still in progress, making these unflushed changes 1446 + * unrecoverable on the next mount. 1447 + */ 1448 + xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); 1442 1449 dqp->q_flags &= ~XFS_DQFLAG_DIRTY; 1443 1450 xfs_trans_ail_delete(lip, 0); 1444 - xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); 1445 1451 xfs_dqfunlock(dqp); 1446 1452 return error; 1447 1453 }