From beeec582a54e86052560b75440562028cd6a7d0a Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 12 Jul 2016 14:18:10 +0200 Subject: quotaon: Improve reporting of quota state quotactl Q_XFS_GETQSTAT is able to report whether only accounting or also quota enforcement is turned on. This works for XFS and GFS2 for ages and since kernel 4.1 also for other filesystems. Use this quotactl when it is supported and report more details in verbose mode. Signed-off-by: Jan Kara --- quotaon.c | 34 +++++++++++++++++++++++++--------- quotasys.c | 34 ++++++++++++++++++++++++---------- quotasys.h | 6 ++++++ 3 files changed, 55 insertions(+), 19 deletions(-) diff --git a/quotaon.c b/quotaon.c index b9cc841..fe19224 100644 --- a/quotaon.c +++ b/quotaon.c @@ -332,23 +332,39 @@ static int newstate(struct mount_entry *mnt, int type, char *extra) static int print_state(struct mount_entry *mnt, int type) { int on = 0; - - if (!strcmp(mnt->me_type, MNTTYPE_XFS) || - !strcmp(mnt->me_type, MNTTYPE_GFS2)) { - if (kern_qfmt_supp(QF_XFS)) - on = kern_quota_on(mnt, type, QF_XFS) != -1; + char *state; + + if (kern_qfmt_supp(QF_XFS)) { + on = kern_quota_state_xfs(mnt->me_devname, type); + if (!strcmp(mnt->me_type, MNTTYPE_XFS) || + !strcmp(mnt->me_type, MNTTYPE_GFS2) || on >= 0) { + if (on < 0) + on = 0; + if (!(flags & FL_VERBOSE)) + goto print_state; + if (on == 0) + state = _("off"); + else if (on == 1) + state = _("on (accounting)"); + else + state = _("on (enforced)"); + goto print; + } } - else if (kernel_iface == IFACE_GENERIC) + if (kernel_iface == IFACE_GENERIC) on = kern_quota_on(mnt, type, -1) != -1; else if (kern_qfmt_supp(QF_VFSV0)) on = kern_quota_on(mnt, type, QF_VFSV0) != -1; else if (kern_qfmt_supp(QF_VFSOLD)) on = kern_quota_on(mnt, type, QF_VFSOLD) != -1; - printf(_("%s quota on %s (%s) is %s\n"), _(type2name(type)), mnt->me_dir, mnt->me_devname, - on ? _("on") : _("off")); +print_state: + state = on ? _("on") : _("off"); +print: + printf(_("%s quota on %s (%s) is %s\n"), _(type2name(type)), + mnt->me_dir, mnt->me_devname, state); - return on; + return on > 0; } int main(int argc, char **argv) diff --git a/quotasys.c b/quotasys.c index d04f25a..48368a5 100644 --- a/quotasys.c +++ b/quotasys.c @@ -1114,20 +1114,34 @@ static int v2_kern_quota_on(const char *dev, int type) return 0; } -/* Check whether XFS quota is turned on on given device */ -static int xfs_kern_quota_on(const char *dev, int type) +/* + * Check whether quota is turned on on given device. This quotactl always + * worked for XFS and it works even for VFS quotas for kernel 4.1 and newer. + * + * We return 0 when quota is not turned on, 1 when only accounting is turned + * on, and 2 when both accounting and enforcement is turned on. We return -1 + * on error. + */ +int kern_quota_state_xfs(const char *dev, int type) { struct xfs_mem_dqinfo info; if (!quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, 0, (void *)&info)) { - if (type == USRQUOTA && (info.qs_flags & XFS_QUOTA_UDQ_ACCT)) - return 1; - if (type == GRPQUOTA && (info.qs_flags & XFS_QUOTA_GDQ_ACCT)) - return 1; - if (type == PRJQUOTA && (info.qs_flags & XFS_QUOTA_PDQ_ACCT)) - return 1; + if (type == USRQUOTA) { + return !!(info.qs_flags & XFS_QUOTA_UDQ_ACCT) + + !!(info.qs_flags & XFS_QUOTA_UDQ_ENFD); + } + if (type == GRPQUOTA) { + return !!(info.qs_flags & XFS_QUOTA_GDQ_ACCT) + + !!(info.qs_flags & XFS_QUOTA_GDQ_ENFD); + } + if (type == PRJQUOTA) { + return !!(info.qs_flags & XFS_QUOTA_PDQ_ACCT) + + !!(info.qs_flags & XFS_QUOTA_PDQ_ENFD); + } + return 0; } - return 0; + return -1; } /* @@ -1141,7 +1155,7 @@ int kern_quota_on(struct mount_entry *mnt, int type, int fmt) return -1; if (mnt->me_qfmt[type] == QF_XFS) { if ((fmt == -1 || fmt == QF_XFS) && - xfs_kern_quota_on(mnt->me_devname, type)) /* XFS quota format */ + kern_quota_state_xfs(mnt->me_devname, type) > 0) return QF_XFS; return -1; } diff --git a/quotasys.h b/quotasys.h index f19b00e..cb1f22f 100644 --- a/quotasys.h +++ b/quotasys.h @@ -173,6 +173,12 @@ int devcmp_handles(struct quota_handle *a, struct quota_handle *b); /* Check kernel supported quotafile format */ void init_kernel_interface(void); +/* + * Check whether is quota turned on on given device for given type. This + * works for XFS for all kernels and for other filesystems since kernel 4.1. + */ +int kern_quota_state_xfs(const char *dev, int type); + /* Check whether is quota turned on on given device for given type */ int kern_quota_on(struct mount_entry *mnt, int type, int fmt); -- cgit v1.2.3