mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-06 14:05:39 +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;
|
int error = 0;
|
||||||
|
|
||||||
mp = dp->i_mount;
|
mp = dp->i_mount;
|
||||||
ASSERT(! XFS_NOT_DQATTACHED(mp, dp));
|
|
||||||
|
|
||||||
xfs_ilock(dp, lock_mode);
|
xfs_ilock(dp, lock_mode);
|
||||||
if (!xfs_inode_has_attr_fork(dp))
|
if (!xfs_inode_has_attr_fork(dp))
|
||||||
|
@ -1742,9 +1742,13 @@ xfs_inactive(
|
|||||||
ip->i_df.if_nextents > 0 || ip->i_delayed_blks > 0))
|
ip->i_df.if_nextents > 0 || ip->i_delayed_blks > 0))
|
||||||
truncate = 1;
|
truncate = 1;
|
||||||
|
|
||||||
error = xfs_qm_dqattach(ip);
|
if (xfs_iflags_test(ip, XFS_IQUOTAUNCHECKED)) {
|
||||||
if (error)
|
xfs_qm_dqdetach(ip);
|
||||||
goto out;
|
} else {
|
||||||
|
error = xfs_qm_dqattach(ip);
|
||||||
|
if (error)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (S_ISLNK(VFS_I(ip)->i_mode))
|
if (S_ISLNK(VFS_I(ip)->i_mode))
|
||||||
error = xfs_inactive_symlink(ip);
|
error = xfs_inactive_symlink(ip);
|
||||||
@ -1962,6 +1966,8 @@ xfs_iunlink_reload_next(
|
|||||||
trace_xfs_iunlink_reload_next(next_ip);
|
trace_xfs_iunlink_reload_next(next_ip);
|
||||||
rele:
|
rele:
|
||||||
ASSERT(!(VFS_I(next_ip)->i_state & I_DONTCACHE));
|
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);
|
xfs_irele(next_ip);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -344,6 +344,9 @@ static inline bool xfs_inode_has_large_extent_counts(struct xfs_inode *ip)
|
|||||||
*/
|
*/
|
||||||
#define XFS_INACTIVATING (1 << 13)
|
#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. */
|
/* All inode state flags related to inode reclaim. */
|
||||||
#define XFS_ALL_IRECLAIM_FLAGS (XFS_IRECLAIMABLE | \
|
#define XFS_ALL_IRECLAIM_FLAGS (XFS_IRECLAIMABLE | \
|
||||||
XFS_IRECLAIM | \
|
XFS_IRECLAIM | \
|
||||||
@ -358,7 +361,7 @@ static inline bool xfs_inode_has_large_extent_counts(struct xfs_inode *ip)
|
|||||||
#define XFS_IRECLAIM_RESET_FLAGS \
|
#define XFS_IRECLAIM_RESET_FLAGS \
|
||||||
(XFS_IRECLAIMABLE | XFS_IRECLAIM | \
|
(XFS_IRECLAIMABLE | XFS_IRECLAIM | \
|
||||||
XFS_IDIRTY_RELEASE | XFS_ITRUNCATED | XFS_NEED_INACTIVE | \
|
XFS_IDIRTY_RELEASE | XFS_ITRUNCATED | XFS_NEED_INACTIVE | \
|
||||||
XFS_INACTIVATING)
|
XFS_INACTIVATING | XFS_IQUOTAUNCHECKED)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flags for inode locking.
|
* Flags for inode locking.
|
||||||
|
@ -405,6 +405,8 @@ __XFS_HAS_FEAT(nouuid, NOUUID)
|
|||||||
#define XFS_OPSTATE_WARNED_SHRINK 8
|
#define XFS_OPSTATE_WARNED_SHRINK 8
|
||||||
/* Kernel has logged a warning about logged xattr updates being used. */
|
/* Kernel has logged a warning about logged xattr updates being used. */
|
||||||
#define XFS_OPSTATE_WARNED_LARP 9
|
#define XFS_OPSTATE_WARNED_LARP 9
|
||||||
|
/* Mount time quotacheck is running */
|
||||||
|
#define XFS_OPSTATE_QUOTACHECK_RUNNING 10
|
||||||
|
|
||||||
#define __XFS_IS_OPSTATE(name, NAME) \
|
#define __XFS_IS_OPSTATE(name, NAME) \
|
||||||
static inline bool xfs_is_ ## name (struct xfs_mount *mp) \
|
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(readonly, READONLY)
|
||||||
__XFS_IS_OPSTATE(inodegc_enabled, INODEGC_ENABLED)
|
__XFS_IS_OPSTATE(inodegc_enabled, INODEGC_ENABLED)
|
||||||
__XFS_IS_OPSTATE(blockgc_enabled, BLOCKGC_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
|
static inline bool
|
||||||
xfs_should_warn(struct xfs_mount *mp, long nr)
|
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_BLOCKGC_ENABLED), "blockgc" }, \
|
||||||
{ (1UL << XFS_OPSTATE_WARNED_SCRUB), "wscrub" }, \
|
{ (1UL << XFS_OPSTATE_WARNED_SCRUB), "wscrub" }, \
|
||||||
{ (1UL << XFS_OPSTATE_WARNED_SHRINK), "wshrink" }, \
|
{ (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
|
* Max and min values for mount-option defined I/O
|
||||||
|
@ -1160,6 +1160,10 @@ xfs_qm_dqusage_adjust(
|
|||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
error = xfs_inode_reload_unlinked(ip);
|
||||||
|
if (error)
|
||||||
|
goto error0;
|
||||||
|
|
||||||
ASSERT(ip->i_delayed_blks == 0);
|
ASSERT(ip->i_delayed_blks == 0);
|
||||||
|
|
||||||
if (XFS_IS_REALTIME_INODE(ip)) {
|
if (XFS_IS_REALTIME_INODE(ip)) {
|
||||||
@ -1173,6 +1177,7 @@ xfs_qm_dqusage_adjust(
|
|||||||
}
|
}
|
||||||
|
|
||||||
nblks = (xfs_qcnt_t)ip->i_nblocks - rtblks;
|
nblks = (xfs_qcnt_t)ip->i_nblocks - rtblks;
|
||||||
|
xfs_iflags_clear(ip, XFS_IQUOTAUNCHECKED);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add the (disk blocks and inode) resources occupied by this
|
* Add the (disk blocks and inode) resources occupied by this
|
||||||
@ -1319,8 +1324,10 @@ xfs_qm_quotacheck(
|
|||||||
flags |= XFS_PQUOTA_CHKD;
|
flags |= XFS_PQUOTA_CHKD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xfs_set_quotacheck_running(mp);
|
||||||
error = xfs_iwalk_threaded(mp, 0, 0, xfs_qm_dqusage_adjust, 0, true,
|
error = xfs_iwalk_threaded(mp, 0, 0, xfs_qm_dqusage_adjust, 0, true,
|
||||||
NULL);
|
NULL);
|
||||||
|
xfs_clear_quotacheck_running(mp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On error, the inode walk may have partially populated the dquot
|
* On error, the inode walk may have partially populated the dquot
|
||||||
|
Loading…
Reference in New Issue
Block a user