Skip to content

Commit 49813a2

Browse files
author
Darrick J. Wong
committed
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>
1 parent 83771c5 commit 49813a2

File tree

5 files changed

+29
-6
lines changed

5 files changed

+29
-6
lines changed

fs/xfs/xfs_attr_inactive.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,6 @@ xfs_attr_inactive(
333333
int error = 0;
334334

335335
mp = dp->i_mount;
336-
ASSERT(! XFS_NOT_DQATTACHED(mp, dp));
337336

338337
xfs_ilock(dp, lock_mode);
339338
if (!xfs_inode_has_attr_fork(dp))

fs/xfs/xfs_inode.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1742,9 +1742,13 @@ xfs_inactive(
17421742
ip->i_df.if_nextents > 0 || ip->i_delayed_blks > 0))
17431743
truncate = 1;
17441744

1745-
error = xfs_qm_dqattach(ip);
1746-
if (error)
1747-
goto out;
1745+
if (xfs_iflags_test(ip, XFS_IQUOTAUNCHECKED)) {
1746+
xfs_qm_dqdetach(ip);
1747+
} else {
1748+
error = xfs_qm_dqattach(ip);
1749+
if (error)
1750+
goto out;
1751+
}
17481752

17491753
if (S_ISLNK(VFS_I(ip)->i_mode))
17501754
error = xfs_inactive_symlink(ip);
@@ -1962,6 +1966,8 @@ xfs_iunlink_reload_next(
19621966
trace_xfs_iunlink_reload_next(next_ip);
19631967
rele:
19641968
ASSERT(!(VFS_I(next_ip)->i_state & I_DONTCACHE));
1969+
if (xfs_is_quotacheck_running(mp) && next_ip)
1970+
xfs_iflags_set(next_ip, XFS_IQUOTAUNCHECKED);
19651971
xfs_irele(next_ip);
19661972
return error;
19671973
}

fs/xfs/xfs_inode.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,9 @@ static inline bool xfs_inode_has_large_extent_counts(struct xfs_inode *ip)
344344
*/
345345
#define XFS_INACTIVATING (1 << 13)
346346

347+
/* Quotacheck is running but inode has not been added to quota counts. */
348+
#define XFS_IQUOTAUNCHECKED (1 << 14)
349+
347350
/* All inode state flags related to inode reclaim. */
348351
#define XFS_ALL_IRECLAIM_FLAGS (XFS_IRECLAIMABLE | \
349352
XFS_IRECLAIM | \
@@ -358,7 +361,7 @@ static inline bool xfs_inode_has_large_extent_counts(struct xfs_inode *ip)
358361
#define XFS_IRECLAIM_RESET_FLAGS \
359362
(XFS_IRECLAIMABLE | XFS_IRECLAIM | \
360363
XFS_IDIRTY_RELEASE | XFS_ITRUNCATED | XFS_NEED_INACTIVE | \
361-
XFS_INACTIVATING)
364+
XFS_INACTIVATING | XFS_IQUOTAUNCHECKED)
362365

363366
/*
364367
* Flags for inode locking.

fs/xfs/xfs_mount.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,8 @@ __XFS_HAS_FEAT(nouuid, NOUUID)
405405
#define XFS_OPSTATE_WARNED_SHRINK 8
406406
/* Kernel has logged a warning about logged xattr updates being used. */
407407
#define XFS_OPSTATE_WARNED_LARP 9
408+
/* Mount time quotacheck is running */
409+
#define XFS_OPSTATE_QUOTACHECK_RUNNING 10
408410

409411
#define __XFS_IS_OPSTATE(name, NAME) \
410412
static inline bool xfs_is_ ## name (struct xfs_mount *mp) \
@@ -427,6 +429,11 @@ __XFS_IS_OPSTATE(inode32, INODE32)
427429
__XFS_IS_OPSTATE(readonly, READONLY)
428430
__XFS_IS_OPSTATE(inodegc_enabled, INODEGC_ENABLED)
429431
__XFS_IS_OPSTATE(blockgc_enabled, BLOCKGC_ENABLED)
432+
#ifdef CONFIG_XFS_QUOTA
433+
__XFS_IS_OPSTATE(quotacheck_running, QUOTACHECK_RUNNING)
434+
#else
435+
# define xfs_is_quotacheck_running(mp) (false)
436+
#endif
430437

431438
static inline bool
432439
xfs_should_warn(struct xfs_mount *mp, long nr)
@@ -444,7 +451,8 @@ xfs_should_warn(struct xfs_mount *mp, long nr)
444451
{ (1UL << XFS_OPSTATE_BLOCKGC_ENABLED), "blockgc" }, \
445452
{ (1UL << XFS_OPSTATE_WARNED_SCRUB), "wscrub" }, \
446453
{ (1UL << XFS_OPSTATE_WARNED_SHRINK), "wshrink" }, \
447-
{ (1UL << XFS_OPSTATE_WARNED_LARP), "wlarp" }
454+
{ (1UL << XFS_OPSTATE_WARNED_LARP), "wlarp" }, \
455+
{ (1UL << XFS_OPSTATE_QUOTACHECK_RUNNING), "quotacheck" }
448456

449457
/*
450458
* Max and min values for mount-option defined I/O

fs/xfs/xfs_qm.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,6 +1160,10 @@ xfs_qm_dqusage_adjust(
11601160
if (error)
11611161
return error;
11621162

1163+
error = xfs_inode_reload_unlinked(ip);
1164+
if (error)
1165+
goto error0;
1166+
11631167
ASSERT(ip->i_delayed_blks == 0);
11641168

11651169
if (XFS_IS_REALTIME_INODE(ip)) {
@@ -1173,6 +1177,7 @@ xfs_qm_dqusage_adjust(
11731177
}
11741178

11751179
nblks = (xfs_qcnt_t)ip->i_nblocks - rtblks;
1180+
xfs_iflags_clear(ip, XFS_IQUOTAUNCHECKED);
11761181

11771182
/*
11781183
* Add the (disk blocks and inode) resources occupied by this
@@ -1319,8 +1324,10 @@ xfs_qm_quotacheck(
13191324
flags |= XFS_PQUOTA_CHKD;
13201325
}
13211326

1327+
xfs_set_quotacheck_running(mp);
13221328
error = xfs_iwalk_threaded(mp, 0, 0, xfs_qm_dqusage_adjust, 0, true,
13231329
NULL);
1330+
xfs_clear_quotacheck_running(mp);
13241331

13251332
/*
13261333
* On error, the inode walk may have partially populated the dquot

0 commit comments

Comments
 (0)