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:
Linus Torvalds 2023-03-12 09:47:08 -07:00
commit 2e545d69bd
2 changed files with 40 additions and 21 deletions

View File

@ -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.");

View File

@ -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;
}
/*