linux-xfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Zorro Lang <zlang@redhat.com>
To: Eric Sandeen <sandeen@sandeen.net>
Cc: xfs@oss.sgi.com
Subject: Re: [PATCH V2] xfs_quota: wire up XFS_GETQSTATV
Date: Wed, 17 Aug 2016 16:33:40 +0800	[thread overview]
Message-ID: <20160817083340.GB7193@zlang.usersys.redhat.com> (raw)
In-Reply-To: <2ca2dc3b-53d2-0791-644f-c9cd5abef89f@sandeen.net>

On Mon, Aug 15, 2016 at 10:17:19PM -0500, Eric Sandeen wrote:
> The new XFS_GETQSTATV quotactl, available since kernel v3.12,
> was never implemented in xfs_quota, and the "state" command
> continues to use XFS_GETQSTAT, which cannot report both
> group & project quota on newer formats.
> 
> The new call has room for all 3 quota types (user, group, and
> quota), vs just two, where previously project and quota
> overlapped.
> 
> So:
> 
> First, try XFS_GETQSTATV.
> If it passes, we have all the information we need, and we print
> it. state_qfilestat() is modified to take the newer structure.
> 
> If it fails, try XFS_GETQSTAT.  If that passes, we are on an
> older kernel with neither XFS_GETQSTATV nor the on-disk project
> quota inode.  We copy the available information into the newer
> statv structure, carefully determining wither group or project
> (or neither) is actually active, and print it with the same
> state_qfilestat routine.
> 
> Signed-off-by: Eric Sandeen <sandeen@redhat.com>
> ---

Hi Eric,

This's what I tried to explain to you:

  [root@dhcp-13-149 ~]# mount /dev/mapper/testvg-scratchdev /mnt/scratch -o pquota,gquota,uquota
  [root@dhcp-13-149 xfsprogs-dev]# xfs_quota -xc "limit bsoft=100m bhard=200m fsgqa" /mnt/scratch
  [root@dhcp-13-149 xfsprogs-dev]# xfs_quota -xc "limit -g bsoft=100m bhard=200m fsgqa" /mnt/scratch
  [root@dhcp-13-149 xfsprogs-dev]# xfs_quota -xc "state" /mnt/scratch
  User quota state on /mnt/scratch (/dev/mapper/testvg-scratchdev)
    Accounting: ON
    Enforcement: ON
    Inode: #101 (2 blocks, 2 extents)
  Group quota state on /mnt/scratch (/dev/mapper/testvg-scratchdev)
    Accounting: ON
    Enforcement: ON
    Inode: #99 (2 blocks, 2 extents)
  Project quota state on /mnt/scratch (/dev/mapper/testvg-scratchdev)
    Accounting: ON
    Enforcement: ON
    Inode: #100 (1 blocks, 1 extents)
  Blocks grace time: [7 days]
  Inodes grace time: [7 days]
  Realtime Blocks grace time: [7 days]
  [root@dhcp-13-149 xfsprogs-dev]# umount /mnt/scratch
  [root@dhcp-13-149 xfsprogs-dev]# mount /dev/mapper/testvg-scratchdev /mnt/scratch -o pquota
  [root@dhcp-13-149 xfsprogs-dev]# xfs_quota -xc "state" /mnt/scratch
  User quota state on /mnt/scratch (/dev/mapper/testvg-scratchdev)
    Accounting: OFF
    Enforcement: OFF
    Inode: #0 (0 blocks, 0 extents)
  Group quota state on /mnt/scratch (/dev/mapper/testvg-scratchdev)
    Accounting: OFF
    Enforcement: OFF
    Inode: #0 (0 blocks, 0 extents)
  Project quota state on /mnt/scratch (/dev/mapper/testvg-scratchdev)
    Accounting: ON
    Enforcement: ON
    Inode: #100 (1 blocks, 1 extents)
  Blocks grace time: [7 days]
  Inodes grace time: [7 days]
  Realtime Blocks grace time: [7 days]
  [root@dhcp-13-149 ~]# xfs_db -r -c "sb 0" -c "p" /dev/mapper/testvg-scratchdev|grep quot
  uquotino = 101
  gquotino = 99
  pquotino = 100


If I someone quota isn't enable, "state" command will print that inode
number, blocks and extents as 0.

Do you think this's a problem should be fixed?
If it's a bug, maybe we can fix it on another patch later, because
it's another bug?

Thanks,
Zorro

> 
> I probably could have done some memcpy()'s in 
> state_stat_to_statv(), but opted for the explicit copy-out;
> the structures aren't identical, although the newer one 
> only differs by padding on the end.  If memcpy() is preferable
> I could send a V2...
> 
> V2: set sv.qs_version = FS_QSTATV_VERSION1; before calling
> the quotactl (thanks Zorro!)
> 
> diff --git a/include/xqm.h b/include/xqm.h
> index c084b2d..5b6934a 100644
> --- a/include/xqm.h
> +++ b/include/xqm.h
> @@ -32,6 +32,7 @@
>  #define Q_XGETQSTAT	XQM_CMD(5)	/* get quota subsystem status */
>  #define Q_XQUOTARM	XQM_CMD(6)	/* free disk space used by dquots */
>  #define Q_XQUOTASYNC	XQM_CMD(7)	/* delalloc flush, updates dquots */
> +#define Q_XGETQSTATV	XQM_CMD(8)	/* newer version of get quota */
>  #define Q_XGETNEXTQUOTA	XQM_CMD(9)	/* get disk limits and usage */
>  
>  /*
> @@ -149,4 +150,35 @@ typedef struct fs_quota_stat {
>  	__u16		qs_iwarnlimit;	/* limit for num warnings */
>  } fs_quota_stat_t;
>  
> +
> +#ifndef FS_QSTATV_VERSION1
> +#define FS_QSTATV_VERSION1	1	/* fs_quota_statv.qs_version */
> +#endif
> +
> +/*
> + * Some basic information about 'quota files' for Q_XGETQSTATV command
> + */
> +struct fs_qfilestatv {
> +	__u64		qfs_ino;	/* inode number */
> +	__u64		qfs_nblks;	/* number of BBs 512-byte-blks */
> +	__u32		qfs_nextents;	/* number of extents */
> +	__u32		qfs_pad;	/* pad for 8-byte alignment */
> +};
> +
> +struct fs_quota_statv {
> +	__s8			qs_version;	/* version for future changes */
> +	__u8			qs_pad1;	/* pad for 16bit alignment */
> +	__u16			qs_flags;	/* FS_QUOTA_.* flags */
> +	__u32			qs_incoredqs;	/* number of dquots incore */
> +	struct fs_qfilestatv	qs_uquota;	/* user quota information */
> +	struct fs_qfilestatv	qs_gquota;	/* group quota information */
> +	struct fs_qfilestatv	qs_pquota;	/* project quota information */
> +	__s32			qs_btimelimit;	/* limit for blks timer */
> +	__s32			qs_itimelimit;	/* limit for inodes timer */
> +	__s32			qs_rtbtimelimit;/* limit for rt blks timer */
> +	__u16			qs_bwarnlimit;	/* limit for num warnings */
> +	__u16			qs_iwarnlimit;	/* limit for num warnings */
> +	__u64			qs_pad2[8];	/* for future proofing */
> +};
> +
>  #endif	/* __XQM_H__ */
> diff --git a/quota/linux.c b/quota/linux.c
> index 74dba01..4f1f3c4 100644
> --- a/quota/linux.c
> +++ b/quota/linux.c
> @@ -55,6 +55,8 @@ xcommand_to_qcommand(
>  		return Q_XSETQLIM;
>  	case XFS_GETQSTAT:
>  		return Q_XGETQSTAT;
> +	case XFS_GETQSTATV:
> +		return Q_XGETQSTATV;
>  	case XFS_QUOTARM:
>  		return Q_XQUOTARM;
>  	case XFS_QSYNC:
> diff --git a/quota/state.c b/quota/state.c
> index 8186762..9f6616e 100644
> --- a/quota/state.c
> +++ b/quota/state.c
> @@ -111,12 +111,12 @@ remove_help(void)
>  
>  static void
>  state_qfilestat(
> -	FILE		*fp,
> -	fs_path_t	*mount,
> -	uint		type,
> -	fs_qfilestat_t	*qfs,
> -	int		accounting,
> -	int		enforcing)
> +	FILE			*fp,
> +	struct fs_path		*mount,
> +	uint			type,
> +	struct fs_qfilestatv	*qfs,
> +	int			accounting,
> +	int			enforcing)
>  {
>  	fprintf(fp, _("%s quota state on %s (%s)\n"), type_to_string(type),
>  		mount->fs_dir, mount->fs_name);
> @@ -142,39 +142,96 @@ state_timelimit(
>  		time_to_string(timelimit, VERBOSE_FLAG | ABSOLUTE_FLAG));
>  }
>  
> +/*
> + * fs_quota_stat holds a subset of fs_quota_statv; this copies
> + * the smaller into the larger, leaving any not-present fields
> + * empty.  This is so the same reporting function can be used
> + * for both XFS_GETQSTAT and XFS_GETQSTATV results.
> + */
>  static void
> -state_quotafile_mount(
> -	FILE		*fp,
> -	uint		type,
> -	fs_path_t	*mount,
> -	uint		flags)
> +state_stat_to_statv(
> +	struct fs_quota_stat	*s,
> +	struct fs_quota_statv	*sv)
>  {
> -	fs_quota_stat_t	s;
> -	char		*dev = mount->fs_name;
> +	memset(sv, 0, sizeof(struct fs_quota_statv));
> +
> +	/* shared information */
> +	sv->qs_version = s->qs_version;
> +	sv->qs_flags = s->qs_flags;
> +	sv->qs_incoredqs = s->qs_incoredqs;
> +	sv->qs_btimelimit = s->qs_btimelimit;
> +	sv->qs_itimelimit = s->qs_itimelimit;
> +	sv->qs_rtbtimelimit = s->qs_rtbtimelimit;
> +	sv->qs_bwarnlimit = s->qs_bwarnlimit;
> +	sv->qs_iwarnlimit = s->qs_iwarnlimit;
> +
> +	/* Always room for uquota */
> +	sv->qs_uquota.qfs_ino = s->qs_uquota.qfs_ino;
> +	sv->qs_uquota.qfs_nblks = s->qs_uquota.qfs_nblks;
> +	sv->qs_uquota.qfs_nextents = s->qs_uquota.qfs_nextents;
> +
> +	/*
> +	 * If we are here, XFS_GETQSTATV failed and XFS_GETQSTAT passed;
> +	 * that is a very strong hint that we're on a kernel which predates
> +	 * the on-disk pquota inode; both were added in v3.12.  So, we do
> +	 * some tricksy determination here.
> +	 * gs_gquota may hold either group quota inode info, or project
> +	 * quota if that is used instead; which one it actually holds depends
> +	 * on the quota flags.  (If neither is set, neither is used)
> +	 */
> +	if (s->qs_flags & XFS_QUOTA_GDQ_ACCT) {
> +		/* gs_gquota holds group quota info */
> +		sv->qs_gquota.qfs_ino = s->qs_gquota.qfs_ino;
> +		sv->qs_gquota.qfs_nblks = s->qs_gquota.qfs_nblks;
> +		sv->qs_gquota.qfs_nextents = s->qs_gquota.qfs_nextents;
> +	} else if (s->qs_flags & XFS_QUOTA_PDQ_ACCT) {
> +		/* gs_gquota actually holds project quota info */
> +		sv->qs_pquota.qfs_ino = s->qs_gquota.qfs_ino;
> +		sv->qs_pquota.qfs_nblks = s->qs_gquota.qfs_nblks;
> +		sv->qs_pquota.qfs_nextents = s->qs_gquota.qfs_nextents;
> +	}
> +}
>  
> -	if (xfsquotactl(XFS_GETQSTAT, dev, type, 0, (void *)&s) < 0) {
> -		if (flags & VERBOSE_FLAG)
> -			fprintf(fp, _("%s quota are not enabled on %s\n"),
> -				type_to_string(type), dev);
> -		return;
> +static void
> +state_quotafile_mount(
> +	FILE			*fp,
> +	uint			type,
> +	struct fs_path		*mount,
> +	uint			flags)
> +{
> +	struct fs_quota_stat	s;
> +	struct fs_quota_statv	sv;
> +	char			*dev = mount->fs_name;
> +
> +	sv.qs_version = FS_QSTATV_VERSION1;
> +
> +	if (xfsquotactl(XFS_GETQSTATV, dev, type, 0, (void *)&sv) < 0) {
> +		if (xfsquotactl(XFS_GETQSTAT, dev, type, 0, (void *)&s) < 0) {
> +			if (flags & VERBOSE_FLAG)
> +				fprintf(fp,
> +					_("%s quota are not enabled on %s\n"),
> +					type_to_string(type), dev);
> +			return;
> +		}
> +		state_stat_to_statv(&s, &sv);
>  	}
>  
>  	if (type & XFS_USER_QUOTA)
> -		state_qfilestat(fp, mount, XFS_USER_QUOTA, &s.qs_uquota,
> -				s.qs_flags & XFS_QUOTA_UDQ_ACCT,
> -				s.qs_flags & XFS_QUOTA_UDQ_ENFD);
> +		state_qfilestat(fp, mount, XFS_USER_QUOTA, &sv.qs_uquota,
> +				sv.qs_flags & XFS_QUOTA_UDQ_ACCT,
> +				sv.qs_flags & XFS_QUOTA_UDQ_ENFD);
>  	if (type & XFS_GROUP_QUOTA)
> -		state_qfilestat(fp, mount, XFS_GROUP_QUOTA, &s.qs_gquota,
> -				s.qs_flags & XFS_QUOTA_GDQ_ACCT,
> -				s.qs_flags & XFS_QUOTA_GDQ_ENFD);
> +		state_qfilestat(fp, mount, XFS_GROUP_QUOTA, &sv.qs_gquota,
> +				sv.qs_flags & XFS_QUOTA_GDQ_ACCT,
> +				sv.qs_flags & XFS_QUOTA_GDQ_ENFD);
>  	if (type & XFS_PROJ_QUOTA)
> -		state_qfilestat(fp, mount, XFS_PROJ_QUOTA, &s.qs_gquota,
> -				s.qs_flags & XFS_QUOTA_PDQ_ACCT,
> -				s.qs_flags & XFS_QUOTA_PDQ_ENFD);
> +		state_qfilestat(fp, mount, XFS_PROJ_QUOTA, &sv.qs_pquota,
> +				sv.qs_flags & XFS_QUOTA_PDQ_ACCT,
> +				sv.qs_flags & XFS_QUOTA_PDQ_ENFD);
>  
> -	state_timelimit(fp, XFS_BLOCK_QUOTA, s.qs_btimelimit);
> -	state_timelimit(fp, XFS_INODE_QUOTA, s.qs_itimelimit);
> -	state_timelimit(fp, XFS_RTBLOCK_QUOTA, s.qs_rtbtimelimit);
> +	state_timelimit(fp, XFS_BLOCK_QUOTA, sv.qs_btimelimit);
> +	state_timelimit(fp, XFS_INODE_QUOTA, sv.qs_itimelimit);
> +	state_timelimit(fp, XFS_RTBLOCK_QUOTA, sv.qs_rtbtimelimit);
>  }
>  
>  static void
> 
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

  reply	other threads:[~2016-08-17  8:33 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-08-12 23:07 [PATCH] xfs_quota: wire up XFS_GETQSTATV Eric Sandeen
2016-08-15 13:44 ` Bill O'Donnell
2016-08-15 16:38 ` Zorro Lang
2016-08-15 16:43   ` Eric Sandeen
2016-08-16  3:17 ` [PATCH V2] " Eric Sandeen
2016-08-17  8:33   ` Zorro Lang [this message]
2016-08-17 14:43     ` Eric Sandeen
2016-08-17 14:58       ` Zorro Lang
2016-08-17 15:02   ` Zorro Lang

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=20160817083340.GB7193@zlang.usersys.redhat.com \
    --to=zlang@redhat.com \
    --cc=sandeen@sandeen.net \
    --cc=xfs@oss.sgi.com \
    /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;
as well as URLs for NNTP newsgroup(s).