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 22:58:10 +0800 [thread overview]
Message-ID: <20160817145810.GD7193@zlang.usersys.redhat.com> (raw)
In-Reply-To: <82f3c5f9-204d-845f-16cf-c267085242ac@sandeen.net>
On Wed, Aug 17, 2016 at 09:43:36AM -0500, Eric Sandeen wrote:
> On 8/17/16 3:33 AM, Zorro Lang wrote:
>
> > 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]
>
> And that's all correct, right.
>
> > [root@dhcp-13-149 xfsprogs-dev]# umount /mnt/scratch
> > [root@dhcp-13-149 xfsprogs-dev]# mount /dev/mapper/testvg-scratchdev /mnt/scratch -o pquota
>
> Now you have only 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]
>
> And pquota is properly shown, but user and group show inode 0.
>
> > [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.
>
> *nod*
>
> > 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?
>
> This is a bug in the kernel, because it does not fill in inode information
> for inactive quota types, and fills in 0 instead (so we don't even
> get NULLFSINO).
>
> I did send a patch for this,
>
> [PATCH] quota: fill in Q_XGETQSTAT inode information for inactive quotas
>
> to the linux-fsdevel list (it is in common vfs quota code, but I probably
> should have cc'd the xfs list as well). Jan has indicated that he has
> merged it.
>
> With that patch and this one, it should all work as expected.
Wow, sorry I didn't notice that patch(It's not in xfs cc list). So now
everything works well, I have no objection with this patch now. Please
allow me to ack this patch:)
I'll test both patches together later.
Thanks,
Zorro
>
> Thanks,
> -Eric
>
> > 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
> >
>
> _______________________________________________
> 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
next prev parent reply other threads:[~2016-08-17 14:58 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
2016-08-17 14:43 ` Eric Sandeen
2016-08-17 14:58 ` Zorro Lang [this message]
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=20160817145810.GD7193@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.