| From c95b9d4dbefd14220985ed47955ba0bc70d7b9d2 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 7 Oct 2020 13:55:16 -0700 |
| Subject: xfs: fix realtime bitmap/summary file truncation when growing rt |
| volume |
| |
| From: Darrick J. Wong <darrick.wong@oracle.com> |
| |
| [ Upstream commit f4c32e87de7d66074d5612567c5eac7325024428 ] |
| |
| The realtime bitmap and summary files are regular files that are hidden |
| away from the directory tree. Since they're regular files, inode |
| inactivation will try to purge what it thinks are speculative |
| preallocations beyond the incore size of the file. Unfortunately, |
| xfs_growfs_rt forgets to update the incore size when it resizes the |
| inodes, with the result that inactivating the rt inodes at unmount time |
| will cause their contents to be truncated. |
| |
| Fix this by updating the incore size when we change the ondisk size as |
| part of updating the superblock. Note that we don't do this when we're |
| allocating blocks to the rt inodes because we actually want those blocks |
| to get purged if the growfs fails. |
| |
| This fixes corruption complaints from the online rtsummary checker when |
| running xfs/233. Since that test requires rmap, one can also trigger |
| this by growing an rt volume, cycling the mount, and creating rt files. |
| |
| Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> |
| Reviewed-by: Chandan Babu R <chandanrlinux@gmail.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| fs/xfs/xfs_rtalloc.c | 10 ++++++++-- |
| 1 file changed, 8 insertions(+), 2 deletions(-) |
| |
| diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c |
| index 0753b1dfd0750..be01bfbc3ad93 100644 |
| --- a/fs/xfs/xfs_rtalloc.c |
| +++ b/fs/xfs/xfs_rtalloc.c |
| @@ -1027,10 +1027,13 @@ xfs_growfs_rt( |
| xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL); |
| xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL); |
| /* |
| - * Update the bitmap inode's size. |
| + * Update the bitmap inode's size ondisk and incore. We need |
| + * to update the incore size so that inode inactivation won't |
| + * punch what it thinks are "posteof" blocks. |
| */ |
| mp->m_rbmip->i_d.di_size = |
| nsbp->sb_rbmblocks * nsbp->sb_blocksize; |
| + i_size_write(VFS_I(mp->m_rbmip), mp->m_rbmip->i_d.di_size); |
| xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE); |
| /* |
| * Get the summary inode into the transaction. |
| @@ -1038,9 +1041,12 @@ xfs_growfs_rt( |
| xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL); |
| xfs_trans_ijoin(tp, mp->m_rsumip, XFS_ILOCK_EXCL); |
| /* |
| - * Update the summary inode's size. |
| + * Update the summary inode's size. We need to update the |
| + * incore size so that inode inactivation won't punch what it |
| + * thinks are "posteof" blocks. |
| */ |
| mp->m_rsumip->i_d.di_size = nmp->m_rsumsize; |
| + i_size_write(VFS_I(mp->m_rsumip), mp->m_rsumip->i_d.di_size); |
| xfs_trans_log_inode(tp, mp->m_rsumip, XFS_ILOG_CORE); |
| /* |
| * Copy summary data from old to new sizes. |
| -- |
| 2.27.0 |
| |