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@xxxxxxxxxxx > >> http://oss.sgi.com/mailman/listinfo/xfs > > > > _______________________________________________ > > xfs mailing list > > xfs@xxxxxxxxxxx > > http://oss.sgi.com/mailman/listinfo/xfs > > > > _______________________________________________ > xfs mailing list > xfs@xxxxxxxxxxx > http://oss.sgi.com/mailman/listinfo/xfs _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs