Skip to content

Commit d5d9dd5

Browse files
author
Darrick J. Wong
committed
xfs: persist quota flags with metadir
It's annoying that one has to keep reminding XFS about what quota options it should mount with, since the quota flags recording the previous state are sitting right there in the primary superblock. Even more strangely, there exists a noquota option to disable quotas completely, so it's odder still that providing no options is the same as noquota. Starting with metadir, let's change the behavior so that if the user does not specify any quota-related mount options at all, the ondisk quota flags will be used to bring up quota. In other words, the filesystem will mount in the same state and with the same functionality as it had during the last mount. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
1 parent 128a055 commit d5d9dd5

File tree

5 files changed

+78
-3
lines changed

5 files changed

+78
-3
lines changed

fs/xfs/xfs_mount.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,13 @@ xfs_mountfs(
852852
if (error)
853853
goto out_fail_wait;
854854

855+
/*
856+
* If we're resuming quota status, pick up the preliminary qflags from
857+
* the ondisk superblock so that we know if we should recover dquots.
858+
*/
859+
if (xfs_is_resuming_quotaon(mp))
860+
xfs_qm_resume_quotaon(mp);
861+
855862
/*
856863
* Log's mount-time initialization. The first part of recovery can place
857864
* some items on the AIL, to be handled when recovery is finished or
@@ -865,6 +872,14 @@ xfs_mountfs(
865872
goto out_inodegc_shrinker;
866873
}
867874

875+
/*
876+
* If we're resuming quota status and recovered the log, re-sample the
877+
* qflags from the ondisk superblock now that we've recovered it, just
878+
* in case someone shut down enforcement just before a crash.
879+
*/
880+
if (xfs_clear_resuming_quotaon(mp) && xlog_recovery_needed(mp->m_log))
881+
xfs_qm_resume_quotaon(mp);
882+
868883
/*
869884
* If logged xattrs are still enabled after log recovery finishes, then
870885
* they'll be available until unmount. Otherwise, turn them off.

fs/xfs/xfs_mount.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,8 @@ __XFS_HAS_FEAT(nouuid, NOUUID)
499499
#define XFS_OPSTATE_WARNED_PPTR 16
500500
/* Kernel has logged a warning about metadata dirs being used on this fs. */
501501
#define XFS_OPSTATE_WARNED_METADIR 17
502+
/* Filesystem should use qflags to determine quotaon status */
503+
#define XFS_OPSTATE_RESUMING_QUOTAON 18
502504

503505
#define __XFS_IS_OPSTATE(name, NAME) \
504506
static inline bool xfs_is_ ## name (struct xfs_mount *mp) \
@@ -523,9 +525,24 @@ __XFS_IS_OPSTATE(inodegc_enabled, INODEGC_ENABLED)
523525
__XFS_IS_OPSTATE(blockgc_enabled, BLOCKGC_ENABLED)
524526
#ifdef CONFIG_XFS_QUOTA
525527
__XFS_IS_OPSTATE(quotacheck_running, QUOTACHECK_RUNNING)
528+
__XFS_IS_OPSTATE(resuming_quotaon, RESUMING_QUOTAON)
526529
#else
527-
# define xfs_is_quotacheck_running(mp) (false)
528-
#endif
530+
static inline bool xfs_is_quotacheck_running(struct xfs_mount *mp)
531+
{
532+
return false;
533+
}
534+
static inline bool xfs_is_resuming_quotaon(struct xfs_mount *mp)
535+
{
536+
return false;
537+
}
538+
static inline void xfs_set_resuming_quotaon(struct xfs_mount *m)
539+
{
540+
}
541+
static inline bool xfs_clear_resuming_quotaon(struct xfs_mount *mp)
542+
{
543+
return false;
544+
}
545+
#endif /* CONFIG_XFS_QUOTA */
529546
__XFS_IS_OPSTATE(done_with_log_incompat, UNSET_LOG_INCOMPAT)
530547
__XFS_IS_OPSTATE(using_logged_xattrs, USE_LARP)
531548

fs/xfs/xfs_qm_bhv.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,21 @@ xfs_qm_newmount(
135135

136136
return 0;
137137
}
138+
139+
/*
140+
* If the sysadmin didn't provide any quota mount options, restore the quota
141+
* accounting and enforcement state from the ondisk superblock. Only do this
142+
* for metadir filesystems because this is a behavior change.
143+
*/
144+
void
145+
xfs_qm_resume_quotaon(
146+
struct xfs_mount *mp)
147+
{
148+
if (!xfs_has_metadir(mp))
149+
return;
150+
if (xfs_has_norecovery(mp))
151+
return;
152+
153+
mp->m_qflags = mp->m_sb.sb_qflags & (XFS_ALL_QUOTA_ACCT |
154+
XFS_ALL_QUOTA_ENFD);
155+
}

fs/xfs/xfs_quota.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ extern void xfs_qm_dqdetach(struct xfs_inode *);
125125
extern void xfs_qm_dqrele(struct xfs_dquot *);
126126
extern void xfs_qm_statvfs(struct xfs_inode *, struct kstatfs *);
127127
extern int xfs_qm_newmount(struct xfs_mount *, uint *, uint *);
128+
void xfs_qm_resume_quotaon(struct xfs_mount *mp);
128129
extern void xfs_qm_mount_quotas(struct xfs_mount *);
129130
extern void xfs_qm_unmount(struct xfs_mount *);
130131
extern void xfs_qm_unmount_quotas(struct xfs_mount *);
@@ -202,6 +203,7 @@ xfs_trans_reserve_quota_icreate(struct xfs_trans *tp, struct xfs_dquot *udqp,
202203
#define xfs_qm_dqrele(d) do { (d) = (d); } while(0)
203204
#define xfs_qm_statvfs(ip, s) do { } while(0)
204205
#define xfs_qm_newmount(mp, a, b) (0)
206+
#define xfs_qm_resume_quotaon(mp) ((void)0)
205207
#define xfs_qm_mount_quotas(mp)
206208
#define xfs_qm_unmount(mp)
207209
#define xfs_qm_unmount_quotas(mp)

fs/xfs/xfs_super.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ enum xfs_dax_mode {
6767
XFS_DAX_NEVER = 2,
6868
};
6969

70+
/* Were quota mount options provided? Must use the upper 16 bits of qflags. */
71+
#define XFS_QFLAGS_MNTOPTS (1U << 31)
72+
7073
static void
7174
xfs_mount_set_dax_mode(
7275
struct xfs_mount *mp,
@@ -1264,6 +1267,8 @@ xfs_fs_parse_param(
12641267
int size = 0;
12651268
int opt;
12661269

1270+
BUILD_BUG_ON(XFS_QFLAGS_MNTOPTS & XFS_MOUNT_QUOTA_ALL);
1271+
12671272
opt = fs_parse(fc, xfs_fs_parameters, param, &result);
12681273
if (opt < 0)
12691274
return opt;
@@ -1341,32 +1346,39 @@ xfs_fs_parse_param(
13411346
case Opt_noquota:
13421347
parsing_mp->m_qflags &= ~XFS_ALL_QUOTA_ACCT;
13431348
parsing_mp->m_qflags &= ~XFS_ALL_QUOTA_ENFD;
1349+
parsing_mp->m_qflags |= XFS_QFLAGS_MNTOPTS;
13441350
return 0;
13451351
case Opt_quota:
13461352
case Opt_uquota:
13471353
case Opt_usrquota:
13481354
parsing_mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ENFD);
1355+
parsing_mp->m_qflags |= XFS_QFLAGS_MNTOPTS;
13491356
return 0;
13501357
case Opt_qnoenforce:
13511358
case Opt_uqnoenforce:
13521359
parsing_mp->m_qflags |= XFS_UQUOTA_ACCT;
13531360
parsing_mp->m_qflags &= ~XFS_UQUOTA_ENFD;
1361+
parsing_mp->m_qflags |= XFS_QFLAGS_MNTOPTS;
13541362
return 0;
13551363
case Opt_pquota:
13561364
case Opt_prjquota:
13571365
parsing_mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ENFD);
1366+
parsing_mp->m_qflags |= XFS_QFLAGS_MNTOPTS;
13581367
return 0;
13591368
case Opt_pqnoenforce:
13601369
parsing_mp->m_qflags |= XFS_PQUOTA_ACCT;
13611370
parsing_mp->m_qflags &= ~XFS_PQUOTA_ENFD;
1371+
parsing_mp->m_qflags |= XFS_QFLAGS_MNTOPTS;
13621372
return 0;
13631373
case Opt_gquota:
13641374
case Opt_grpquota:
13651375
parsing_mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ENFD);
1376+
parsing_mp->m_qflags |= XFS_QFLAGS_MNTOPTS;
13661377
return 0;
13671378
case Opt_gqnoenforce:
13681379
parsing_mp->m_qflags |= XFS_GQUOTA_ACCT;
13691380
parsing_mp->m_qflags &= ~XFS_GQUOTA_ENFD;
1381+
parsing_mp->m_qflags |= XFS_QFLAGS_MNTOPTS;
13701382
return 0;
13711383
case Opt_discard:
13721384
parsing_mp->m_features |= XFS_FEAT_DISCARD;
@@ -1433,7 +1445,8 @@ xfs_fs_validate_params(
14331445
return -EINVAL;
14341446
}
14351447

1436-
if (!IS_ENABLED(CONFIG_XFS_QUOTA) && mp->m_qflags != 0) {
1448+
if (!IS_ENABLED(CONFIG_XFS_QUOTA) &&
1449+
(mp->m_qflags & ~XFS_QFLAGS_MNTOPTS)) {
14371450
xfs_warn(mp, "quota support not available in this kernel.");
14381451
return -EINVAL;
14391452
}
@@ -1768,6 +1781,14 @@ xfs_fs_fill_super(
17681781
if (xfs_has_parent(mp))
17691782
xfs_warn_experimental(mp, XFS_EXPERIMENTAL_PPTR);
17701783

1784+
/*
1785+
* If no quota mount options were provided, maybe we'll try to pick
1786+
* up the quota accounting and enforcement flags from the ondisk sb.
1787+
*/
1788+
if (!(mp->m_qflags & XFS_QFLAGS_MNTOPTS))
1789+
xfs_set_resuming_quotaon(mp);
1790+
mp->m_qflags &= ~XFS_QFLAGS_MNTOPTS;
1791+
17711792
error = xfs_mountfs(mp);
17721793
if (error)
17731794
goto out_filestream_unmount;
@@ -1954,6 +1975,8 @@ xfs_fs_reconfigure(
19541975
int flags = fc->sb_flags;
19551976
int error;
19561977

1978+
new_mp->m_qflags &= ~XFS_QFLAGS_MNTOPTS;
1979+
19571980
/* version 5 superblocks always support version counters. */
19581981
if (xfs_has_crc(mp))
19591982
fc->sb_flags |= SB_I_VERSION;

0 commit comments

Comments
 (0)