mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
xfs: make inode unlinked bucket recovery work with quotacheck
Teach quotacheck to reload the unlinked inode lists when walking the inode table. This requires extra state handling, since it's possible that a reloaded inode will get inactivated before quotacheck tries to scan it; in this case, we need to ensure that the reloaded inode does not have dquots attached when it is freed. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
This commit is contained in:
parent
83771c50e4
commit
49813a21ed
@ -333,7 +333,6 @@ xfs_attr_inactive(
|
||||
int error = 0;
|
||||
|
||||
mp = dp->i_mount;
|
||||
ASSERT(! XFS_NOT_DQATTACHED(mp, dp));
|
||||
|
||||
xfs_ilock(dp, lock_mode);
|
||||
if (!xfs_inode_has_attr_fork(dp))
|
||||
|
@ -1742,9 +1742,13 @@ xfs_inactive(
|
||||
ip->i_df.if_nextents > 0 || ip->i_delayed_blks > 0))
|
||||
truncate = 1;
|
||||
|
||||
error = xfs_qm_dqattach(ip);
|
||||
if (error)
|
||||
goto out;
|
||||
if (xfs_iflags_test(ip, XFS_IQUOTAUNCHECKED)) {
|
||||
xfs_qm_dqdetach(ip);
|
||||
} else {
|
||||
error = xfs_qm_dqattach(ip);
|
||||
if (error)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (S_ISLNK(VFS_I(ip)->i_mode))
|
||||
error = xfs_inactive_symlink(ip);
|
||||
@ -1962,6 +1966,8 @@ xfs_iunlink_reload_next(
|
||||
trace_xfs_iunlink_reload_next(next_ip);
|
||||
rele:
|
||||
ASSERT(!(VFS_I(next_ip)->i_state & I_DONTCACHE));
|
||||
if (xfs_is_quotacheck_running(mp) && next_ip)
|
||||
xfs_iflags_set(next_ip, XFS_IQUOTAUNCHECKED);
|
||||
xfs_irele(next_ip);
|
||||
return error;
|
||||
}
|
||||
|
@ -344,6 +344,9 @@ static inline bool xfs_inode_has_large_extent_counts(struct xfs_inode *ip)
|
||||
*/
|
||||
#define XFS_INACTIVATING (1 << 13)
|
||||
|
||||
/* Quotacheck is running but inode has not been added to quota counts. */
|
||||
#define XFS_IQUOTAUNCHECKED (1 << 14)
|
||||
|
||||
/* All inode state flags related to inode reclaim. */
|
||||
#define XFS_ALL_IRECLAIM_FLAGS (XFS_IRECLAIMABLE | \
|
||||
XFS_IRECLAIM | \
|
||||
@ -358,7 +361,7 @@ static inline bool xfs_inode_has_large_extent_counts(struct xfs_inode *ip)
|
||||
#define XFS_IRECLAIM_RESET_FLAGS \
|
||||
(XFS_IRECLAIMABLE | XFS_IRECLAIM | \
|
||||
XFS_IDIRTY_RELEASE | XFS_ITRUNCATED | XFS_NEED_INACTIVE | \
|
||||
XFS_INACTIVATING)
|
||||
XFS_INACTIVATING | XFS_IQUOTAUNCHECKED)
|
||||
|
||||
/*
|
||||
* Flags for inode locking.
|
||||
|
@ -405,6 +405,8 @@ __XFS_HAS_FEAT(nouuid, NOUUID)
|
||||
#define XFS_OPSTATE_WARNED_SHRINK 8
|
||||
/* Kernel has logged a warning about logged xattr updates being used. */
|
||||
#define XFS_OPSTATE_WARNED_LARP 9
|
||||
/* Mount time quotacheck is running */
|
||||
#define XFS_OPSTATE_QUOTACHECK_RUNNING 10
|
||||
|
||||
#define __XFS_IS_OPSTATE(name, NAME) \
|
||||
static inline bool xfs_is_ ## name (struct xfs_mount *mp) \
|
||||
@ -427,6 +429,11 @@ __XFS_IS_OPSTATE(inode32, INODE32)
|
||||
__XFS_IS_OPSTATE(readonly, READONLY)
|
||||
__XFS_IS_OPSTATE(inodegc_enabled, INODEGC_ENABLED)
|
||||
__XFS_IS_OPSTATE(blockgc_enabled, BLOCKGC_ENABLED)
|
||||
#ifdef CONFIG_XFS_QUOTA
|
||||
__XFS_IS_OPSTATE(quotacheck_running, QUOTACHECK_RUNNING)
|
||||
#else
|
||||
# define xfs_is_quotacheck_running(mp) (false)
|
||||
#endif
|
||||
|
||||
static inline bool
|
||||
xfs_should_warn(struct xfs_mount *mp, long nr)
|
||||
@ -444,7 +451,8 @@ xfs_should_warn(struct xfs_mount *mp, long nr)
|
||||
{ (1UL << XFS_OPSTATE_BLOCKGC_ENABLED), "blockgc" }, \
|
||||
{ (1UL << XFS_OPSTATE_WARNED_SCRUB), "wscrub" }, \
|
||||
{ (1UL << XFS_OPSTATE_WARNED_SHRINK), "wshrink" }, \
|
||||
{ (1UL << XFS_OPSTATE_WARNED_LARP), "wlarp" }
|
||||
{ (1UL << XFS_OPSTATE_WARNED_LARP), "wlarp" }, \
|
||||
{ (1UL << XFS_OPSTATE_QUOTACHECK_RUNNING), "quotacheck" }
|
||||
|
||||
/*
|
||||
* Max and min values for mount-option defined I/O
|
||||
|
@ -1160,6 +1160,10 @@ xfs_qm_dqusage_adjust(
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = xfs_inode_reload_unlinked(ip);
|
||||
if (error)
|
||||
goto error0;
|
||||
|
||||
ASSERT(ip->i_delayed_blks == 0);
|
||||
|
||||
if (XFS_IS_REALTIME_INODE(ip)) {
|
||||
@ -1173,6 +1177,7 @@ xfs_qm_dqusage_adjust(
|
||||
}
|
||||
|
||||
nblks = (xfs_qcnt_t)ip->i_nblocks - rtblks;
|
||||
xfs_iflags_clear(ip, XFS_IQUOTAUNCHECKED);
|
||||
|
||||
/*
|
||||
* Add the (disk blocks and inode) resources occupied by this
|
||||
@ -1319,8 +1324,10 @@ xfs_qm_quotacheck(
|
||||
flags |= XFS_PQUOTA_CHKD;
|
||||
}
|
||||
|
||||
xfs_set_quotacheck_running(mp);
|
||||
error = xfs_iwalk_threaded(mp, 0, 0, xfs_qm_dqusage_adjust, 0, true,
|
||||
NULL);
|
||||
xfs_clear_quotacheck_running(mp);
|
||||
|
||||
/*
|
||||
* On error, the inode walk may have partially populated the dquot
|
||||
|
Loading…
Reference in New Issue
Block a user