mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2024-12-29 17:23:36 +00:00
Fixes for 6.3-rc1:
* Fix a crash if mount time quotacheck fails when there are inodes queued for garbage collection. * Fix an off by one error when discarding folios after writeback failure. Signed-off-by: Darrick J. Wong <djwong@kernel.org> -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQ2qTKExjcn+O1o2YRKO3ySh0YRpgUCZAYvQwAKCRBKO3ySh0YR pjMXAP9X9HozNYESlg/cMq6nY2XfbHIR2qvNOfopiRpWby5xQAEAqBiEhafIJ0A1 mTt+0TqQxDsH+uxr/QEUm76Q7F3f1gE= =0zU0 -----END PGP SIGNATURE----- Merge tag 'xfs-6.3-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux Pull xfs fixes from Darrick Wong: - Fix a crash if mount time quotacheck fails when there are inodes queued for garbage collection. - Fix an off by one error when discarding folios after writeback failure. * tag 'xfs-6.3-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: xfs: fix off-by-one-block in xfs_discard_folio() xfs: quotacheck failure can race with background inode inactivation
This commit is contained in:
commit
2e545d69bd
@ -449,15 +449,17 @@ xfs_prepare_ioend(
|
||||
}
|
||||
|
||||
/*
|
||||
* If the page has delalloc blocks on it, we need to punch them out before we
|
||||
* invalidate the page. If we don't, we leave a stale delalloc mapping on the
|
||||
* inode that can trip up a later direct I/O read operation on the same region.
|
||||
* If the folio has delalloc blocks on it, the caller is asking us to punch them
|
||||
* out. If we don't, we can leave a stale delalloc mapping covered by a clean
|
||||
* page that needs to be dirtied again before the delalloc mapping can be
|
||||
* converted. This stale delalloc mapping can trip up a later direct I/O read
|
||||
* operation on the same region.
|
||||
*
|
||||
* We prevent this by truncating away the delalloc regions on the page. Because
|
||||
* We prevent this by truncating away the delalloc regions on the folio. Because
|
||||
* they are delalloc, we can do this without needing a transaction. Indeed - if
|
||||
* we get ENOSPC errors, we have to be able to do this truncation without a
|
||||
* transaction as there is no space left for block reservation (typically why we
|
||||
* see a ENOSPC in writeback).
|
||||
* transaction as there is no space left for block reservation (typically why
|
||||
* we see a ENOSPC in writeback).
|
||||
*/
|
||||
static void
|
||||
xfs_discard_folio(
|
||||
@ -475,8 +477,13 @@ xfs_discard_folio(
|
||||
"page discard on page "PTR_FMT", inode 0x%llx, pos %llu.",
|
||||
folio, ip->i_ino, pos);
|
||||
|
||||
/*
|
||||
* The end of the punch range is always the offset of the the first
|
||||
* byte of the next folio. Hence the end offset is only dependent on the
|
||||
* folio itself and not the start offset that is passed in.
|
||||
*/
|
||||
error = xfs_bmap_punch_delalloc_range(ip, pos,
|
||||
round_up(pos, folio_size(folio)));
|
||||
folio_pos(folio) + folio_size(folio));
|
||||
|
||||
if (error && !xfs_is_shutdown(mp))
|
||||
xfs_alert(mp, "page discard unable to remove delalloc mapping.");
|
||||
|
@ -1321,15 +1321,14 @@ xfs_qm_quotacheck(
|
||||
|
||||
error = xfs_iwalk_threaded(mp, 0, 0, xfs_qm_dqusage_adjust, 0, true,
|
||||
NULL);
|
||||
if (error) {
|
||||
/*
|
||||
* The inode walk may have partially populated the dquot
|
||||
* caches. We must purge them before disabling quota and
|
||||
* tearing down the quotainfo, or else the dquots will leak.
|
||||
*/
|
||||
xfs_qm_dqpurge_all(mp);
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
/*
|
||||
* On error, the inode walk may have partially populated the dquot
|
||||
* caches. We must purge them before disabling quota and tearing down
|
||||
* the quotainfo, or else the dquots will leak.
|
||||
*/
|
||||
if (error)
|
||||
goto error_purge;
|
||||
|
||||
/*
|
||||
* We've made all the changes that we need to make incore. Flush them
|
||||
@ -1363,10 +1362,8 @@ xfs_qm_quotacheck(
|
||||
* and turn quotaoff. The dquots won't be attached to any of the inodes
|
||||
* at this point (because we intentionally didn't in dqget_noattach).
|
||||
*/
|
||||
if (error) {
|
||||
xfs_qm_dqpurge_all(mp);
|
||||
goto error_return;
|
||||
}
|
||||
if (error)
|
||||
goto error_purge;
|
||||
|
||||
/*
|
||||
* If one type of quotas is off, then it will lose its
|
||||
@ -1376,7 +1373,7 @@ xfs_qm_quotacheck(
|
||||
mp->m_qflags &= ~XFS_ALL_QUOTA_CHKD;
|
||||
mp->m_qflags |= flags;
|
||||
|
||||
error_return:
|
||||
error_return:
|
||||
xfs_buf_delwri_cancel(&buffer_list);
|
||||
|
||||
if (error) {
|
||||
@ -1395,6 +1392,21 @@ xfs_qm_quotacheck(
|
||||
} else
|
||||
xfs_notice(mp, "Quotacheck: Done.");
|
||||
return error;
|
||||
|
||||
error_purge:
|
||||
/*
|
||||
* On error, we may have inodes queued for inactivation. This may try
|
||||
* to attach dquots to the inode before running cleanup operations on
|
||||
* the inode and this can race with the xfs_qm_destroy_quotainfo() call
|
||||
* below that frees mp->m_quotainfo. To avoid this race, flush all the
|
||||
* pending inodegc operations before we purge the dquots from memory,
|
||||
* ensuring that background inactivation is idle whilst we turn off
|
||||
* quotas.
|
||||
*/
|
||||
xfs_inodegc_flush(mp);
|
||||
xfs_qm_dqpurge_all(mp);
|
||||
goto error_return;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user