Linux XFS filesystem development
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <djwong@kernel.org>
To: aalbersh@kernel.org
Cc: linux-xfs@vger.kernel.org
Subject: Re: [PATCH 5/8] makecfg: handle metadir quota options
Date: Thu, 3 Sep 2026 20:29:38 -0700	[thread overview]
Message-ID: <20260904032938.GX1933798@frogsfrogsfrogs> (raw)
In-Reply-To: <178848534949.1052910.5093950459218799636.stgit@frogsfrogsfrogs>

On Thu, Sep 03, 2026 at 06:31:04PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> A different LOLLM pointed out that the mkfs configuration file generator
> should generate config file lines for the quota accounting/enforcement
> mkfs options for metadir filesystems, because those quota flags persist
> across mounts.  Add the necessary pieces to do that.
> 
> Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
> ---
>  libfrog/fsgeom.h |   11 ++++++++-
>  db/info.c        |    3 ++
>  libfrog/fsgeom.c |   69 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  mkfs/xfs_mkfs.c  |    4 ++-
>  spaceman/info.c  |   51 ++++++++++++++++++++++++++++++++++++++--
>  5 files changed, 131 insertions(+), 7 deletions(-)
> 
> 
> diff --git a/libfrog/fsgeom.h b/libfrog/fsgeom.h
> index 1109dd2bcdb4cc..c3d865f0783e52 100644
> --- a/libfrog/fsgeom.h
> +++ b/libfrog/fsgeom.h
> @@ -217,7 +217,16 @@ bytes_per_rtgroup(
>  		fsgeo->blocksize;
>  }
>  
> +/* These should correspond to XFS_[UGP]UOTA_{ACCT,ENFD} */
> +#define MAKECFG_UQUOTA_ACCT	0x0001 /* user quota accounting ON */
> +#define MAKECFG_UQUOTA_ENFD	0x0002 /* user quota limits enforced */
> +#define MAKECFG_GQUOTA_ACCT	0x0040 /* group quota accounting ON */
> +#define MAKECFG_GQUOTA_ENFD	0x0080 /* group quota limits enforced */
> +#define MAKECFG_PQUOTA_ACCT	0x0008 /* project quota accounting ON */
> +#define MAKECFG_PQUOTA_ENFD	0x0200 /* project quota limits enforced */
> +
>  int xfrog_write_mkfs_config(const struct xfs_fsop_geom *fsgeo,
> -		const struct fsxattr *fsx, int autofsck, FILE *fp);
> +		unsigned int qflags, const struct fsxattr *fsx, int autofsck,
> +		FILE *fp);
>  
>  #endif /* __LIBFROG_FSGEOM_H__ */
> diff --git a/db/info.c b/db/info.c
> index 3621f0b53e031b..ad1933a2e7dedb 100644
> --- a/db/info.c
> +++ b/db/info.c
> @@ -440,7 +440,8 @@ makecfg_f(
>  		close_fp = true;
>  	}
>  
> -	error = xfrog_write_mkfs_config(&geo, &fsx, autofsck, fp);
> +	error = xfrog_write_mkfs_config(&geo, mp->m_sb.sb_qflags, &fsx,
> +			autofsck, fp);
>  	if (error) {
>  		if (close_fp)
>  			perror(argv[optind]);
> diff --git a/libfrog/fsgeom.c b/libfrog/fsgeom.c
> index fdb7b96e06b246..f1ca7e73df638a 100644
> --- a/libfrog/fsgeom.c
> +++ b/libfrog/fsgeom.c
> @@ -262,6 +262,12 @@ enum {
>  	M_BIGTIME,
>  	M_METADIR,
>  	M_AUTOFSCK,
> +	M_UQUOTA,
> +	M_GQUOTA,
> +	M_PQUOTA,
> +	M_UQNOENFORCE,
> +	M_GQNOENFORCE,
> +	M_PQNOENFORCE,
>  	M_MAX_OPTS,
>  };
>  
> @@ -298,6 +304,7 @@ struct mkfs_config_opt;
>  struct mkfs_config_data {
>  	const struct xfs_fsop_geom	*fsgeo;
>  	const struct fsxattr		*fsx;
> +	unsigned int			qflags;
>  	enum fsprop_autofsck		autofsck;
>  };
>  
> @@ -307,9 +314,11 @@ typedef int (*opt_print_fn)(const struct mkfs_config_opt *opt,
>  
>  struct mkfs_config_opt {
>  	const char		*name;
> +	opt_print_fn		print_fn;
>  	uint64_t		fsgeom_flag;
>  	uint64_t		xflags_flag;
> -	opt_print_fn		print_fn;
> +	unsigned int		qflags_mask;
> +	unsigned int		qflags;
>  };
>  
>  struct mkfs_config_section {
> @@ -351,6 +360,26 @@ print_xflag(
>  	return 0;
>  }
>  
> +static int
> +print_qflags(
> +	const struct mkfs_config_opt	*opt,
> +	const struct mkfs_config_data	*data,
> +	FILE				*fp)
> +{
> +	int				ret;
> +
> +	/* quota flags are only persisted on metadir filesystems */
> +	if (!(data->fsgeo->flags & XFS_FSOP_GEOM_FLAGS_METADIR))
> +		return 0;
> +	if ((data->qflags & opt->qflags_mask) != opt->qflags)
> +		return 0;
> +
> +	ret = fprintf(fp, "%s=1\n", opt->name);
> +	if (ret <= 0)
> +		return ret;
> +	return 0;
> +}
> +
>  static int
>  print_projinherit(
>  	const struct mkfs_config_opt	*opt,
> @@ -497,6 +526,42 @@ static const struct mkfs_config_section config_sections[] = {
>  				.name		= "autofsck",
>  				.print_fn	= print_autofsck,
>  			},
> +			[M_UQUOTA] = {
> +				.name		= "uquota",
> +				.qflags		= MAKECFG_UQUOTA_ACCT | MAKECFG_UQUOTA_ENFD,
> +				.qflags_mask	= MAKECFG_UQUOTA_ACCT | MAKECFG_UQUOTA_ENFD,
> +				.print_fn	= print_qflags,
> +			},
> +			[M_GQUOTA] = {
> +				.name		= "gquota",
> +				.qflags		= MAKECFG_GQUOTA_ACCT | MAKECFG_GQUOTA_ENFD,
> +				.qflags_mask	= MAKECFG_GQUOTA_ACCT | MAKECFG_GQUOTA_ENFD,
> +				.print_fn	= print_qflags,
> +			},
> +			[M_PQUOTA] = {
> +				.name		= "pquota",
> +				.qflags		= MAKECFG_PQUOTA_ACCT | MAKECFG_PQUOTA_ENFD,
> +				.qflags_mask	= MAKECFG_PQUOTA_ACCT | MAKECFG_PQUOTA_ENFD,
> +				.print_fn	= print_qflags,
> +			},
> +			[M_UQNOENFORCE] = {
> +				.name		= "uqnoenforce",
> +				.qflags		= MAKECFG_UQUOTA_ACCT,
> +				.qflags_mask	= MAKECFG_UQUOTA_ACCT | MAKECFG_UQUOTA_ENFD,
> +				.print_fn	= print_qflags,
> +			},
> +			[M_GQNOENFORCE] = {
> +				.name		= "gqnoenforce",
> +				.qflags		= MAKECFG_GQUOTA_ACCT,
> +				.qflags_mask	= MAKECFG_GQUOTA_ACCT | MAKECFG_GQUOTA_ENFD,
> +				.print_fn	= print_qflags,
> +			},
> +			[M_PQNOENFORCE] = {
> +				.name		= "pqnoenforce",
> +				.qflags		= MAKECFG_PQUOTA_ACCT,
> +				.qflags_mask	= MAKECFG_PQUOTA_ACCT | MAKECFG_PQUOTA_ENFD,
> +				.print_fn	= print_qflags,
> +			},
>  			[M_MAX_OPTS] = { },
>  		},
>  	},
> @@ -584,6 +649,7 @@ static const struct mkfs_config_section config_sections[] = {
>  int
>  xfrog_write_mkfs_config(
>  	const struct xfs_fsop_geom		*fsgeo,
> +	unsigned int				qflags,
>  	const struct fsxattr			*fsx,
>  	int					autofsck,
>  	FILE					*fp)
> @@ -592,6 +658,7 @@ xfrog_write_mkfs_config(
>  		.fsgeo				= fsgeo,
>  		.fsx				= fsx,
>  		.autofsck			= autofsck,
> +		.qflags				= qflags,
>  	};
>  	const struct mkfs_config_section	*section = config_sections;
>  	const struct mkfs_config_opt		*opt;
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index 5b6dabb76fabfe..5c45e0248d1de6 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -6229,8 +6229,8 @@ main(
>  		}
>  
>  		libxfs_fs_geometry(mp, &geo, XFS_FS_GEOM_MAX_STRUCT_VER);
> -		error = xfrog_write_mkfs_config(&geo, &cli.fsx, cli.autofsck,
> -				fp);
> +		error = xfrog_write_mkfs_config(&geo, cli.sb_feat.qflags,
> +				&cli.fsx, cli.autofsck, fp);
>  		if (error) {
>  			perror(cli.makecfg);
>  			exit(1);
> diff --git a/spaceman/info.c b/spaceman/info.c
> index 653b8ff98f5c3f..121556e6bd9909 100644
> --- a/spaceman/info.c
> +++ b/spaceman/info.c
> @@ -3,6 +3,7 @@
>   * Copyright (C) 2018 Oracle.  All Rights Reserved.
>   * Author: Darrick J. Wong <darrick.wong@oracle.com>
>   */
> +#include <sys/quota.h>
>  #include "libxfs.h"
>  #include "command.h"
>  #include "init.h"
> @@ -11,6 +12,7 @@
>  #include "libfrog/fsproperties.h"
>  #include "libfrog/fsprops.h"
>  #include "space.h"
> +#include "include/xqm.h"
>  
>  static void
>  info_help(void)
> @@ -88,7 +90,7 @@ get_autofsck(
>  		ret = 0;
>  		goto out_fph;
>  	}
> -	if (ret)
> +	if (ret || !valuelen)
>  		goto out_fph;
>  
>  	*autofsck = fsprop_autofsck_read(valuebuf);
> @@ -98,6 +100,43 @@ get_autofsck(
>  	return ret;
>  }
>  
> +struct qflags_xlate {
> +	unsigned int	qs_flag;
> +	unsigned int	mkcfg_qflag;
> +};
> +
> +static const struct qflags_xlate qsflags_xlate[] = {
> +	{ .qs_flag = XFS_QUOTA_UDQ_ACCT, .mkcfg_qflag = MAKECFG_UQUOTA_ACCT },
> +	{ .qs_flag = XFS_QUOTA_UDQ_ENFD, .mkcfg_qflag = MAKECFG_UQUOTA_ENFD },
> +	{ .qs_flag = XFS_QUOTA_GDQ_ACCT, .mkcfg_qflag = MAKECFG_GQUOTA_ACCT },
> +	{ .qs_flag = XFS_QUOTA_GDQ_ENFD, .mkcfg_qflag = MAKECFG_GQUOTA_ENFD },
> +	{ .qs_flag = XFS_QUOTA_PDQ_ACCT, .mkcfg_qflag = MAKECFG_PQUOTA_ACCT },
> +	{ .qs_flag = XFS_QUOTA_PDQ_ENFD, .mkcfg_qflag = MAKECFG_PQUOTA_ENFD },
> +};
> +
> +static int
> +get_qflags(
> +	struct fileio		*f,
> +	unsigned int		*qflags)
> +{
> +	struct fs_quota_stat	qstat;
> +	int			i;
> +	int			ret;
> +
> +	*qflags = 0;
> +
> +	ret = quotactl(QCMD(Q_XGETQSTAT, 0), f->fs_path.fs_name, 0,
> +			(void *)&qstat);
> +	if (ret)
> +		return ret;

This needs to handle the kernel returning ENOSYS, which means either
that quota wasn't compiled into the kernel or it wasn't enabled.  In
this case it's sufficient to set qflags to 0.

	if (ret) {
		if (errno == ENOSYS)
			return 0;
		return ret;
	}

Will fix that for the next version.

--D

> +	for (i = 0; i < ARRAY_SIZE(qsflags_xlate); i++)
> +		if (qstat.qs_flags & qsflags_xlate[i].qs_flag)
> +			*qflags |= qsflags_xlate[i].mkcfg_qflag;
> +
> +	return 0;
> +}
> +
>  static int makecfg_usage(void);
>  
>  static int
> @@ -109,6 +148,7 @@ makecfg_f(
>  	FILE			*fp;
>  	bool			close_fp = false;
>  	enum fsprop_autofsck	autofsck;
> +	unsigned int		qflags;
>  	int			c;
>  	int			ret;
>  
> @@ -145,6 +185,12 @@ makecfg_f(
>  		return 1;
>  	}
>  
> +	ret = get_qflags(file, &qflags);
> +	if (ret) {
> +		perror("quotactl");
> +		return 1;
> +	}
> +
>  	if (optind == argc) {
>  		fp = stdout;
>  	} else {
> @@ -156,7 +202,8 @@ makecfg_f(
>  		close_fp = true;
>  	}
>  
> -	ret = xfrog_write_mkfs_config(&file->xfd.fsgeom, &fsx, autofsck, fp);
> +	ret = xfrog_write_mkfs_config(&file->xfd.fsgeom, qflags, &fsx,
> +			autofsck, fp);
>  	if (ret) {
>  		if (close_fp)
>  			perror(argv[optind]);
> 
> 

  reply	other threads:[~2026-09-04  3:29 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-04  1:29 [PATCHSET v2] xfsprogs: generate mkfs.xfs config files Darrick J. Wong
2026-09-04  1:30 ` [PATCH 1/8] mkfs: automatically upgrade autofsck earlier Darrick J. Wong
2026-09-04  1:30 ` [PATCH 2/8] mkfs: print config file for a given mkfs configuration Darrick J. Wong
2026-09-04  1:30 ` [PATCH 3/8] xfs_db: print configuration file for mounted filesystems Darrick J. Wong
2026-09-04  1:30 ` [PATCH 4/8] xfs_spaceman: " Darrick J. Wong
2026-09-04  1:31 ` [PATCH 5/8] makecfg: handle metadir quota options Darrick J. Wong
2026-09-04  3:29   ` Darrick J. Wong [this message]
2026-09-04  1:31 ` [PATCH 6/8] makecfg: handle old V4 options that are almost always on by default Darrick J. Wong
2026-09-04  1:31 ` [PATCH 7/8] xfs_admin: print configuration file for mounted filesystems Darrick J. Wong
2026-09-04  1:31 ` [PATCH 8/8] mkfs: allow specification of default options via configuration file Darrick J. Wong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260904032938.GX1933798@frogsfrogsfrogs \
    --to=djwong@kernel.org \
    --cc=aalbersh@kernel.org \
    --cc=linux-xfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox