Query kernel for next quota on XFS or file system with hidden quota files
This commit is contained in:
parent
8c6725d6b5
commit
774297a4e8
@ -0,0 +1,92 @@
|
||||
From 7367f5d511ec4555fbb7a87c1c1853fd4fd01712 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Kara <jack@suse.cz>
|
||||
Date: Tue, 26 Jan 2016 14:06:59 +0100
|
||||
Subject: [PATCH 2/2] Add support for scanning using Q_XGETNEXTQUOTA
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Add support for scanning of all available quota structures using
|
||||
Q_XGETNEXTQUOTA quotactl.
|
||||
|
||||
Signed-off-by: Jan Kara <jack@suse.cz>
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
quotaio_xfs.c | 42 +++++++++++++++++++++++++++++++++++++++---
|
||||
quotaio_xfs.h | 1 +
|
||||
2 files changed, 40 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/quotaio_xfs.c b/quotaio_xfs.c
|
||||
index 903c03e..9d90a3e 100644
|
||||
--- a/quotaio_xfs.c
|
||||
+++ b/quotaio_xfs.c
|
||||
@@ -191,15 +191,51 @@ static int xfs_get_dquot(struct dquot *dq)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int xfs_kernel_scan_dquots(struct quota_handle *h,
|
||||
+ int (*process_dquot)(struct dquot *dquot, char *dqname))
|
||||
+{
|
||||
+ struct dquot *dquot = get_empty_dquot();
|
||||
+ qid_t id = 0;
|
||||
+ struct xfs_kern_dqblk xdqblk;
|
||||
+ int ret;
|
||||
+
|
||||
+ dquot->dq_h = h;
|
||||
+ while (1) {
|
||||
+ ret = quotactl(QCMD(Q_XGETNEXTQUOTA, h->qh_type),
|
||||
+ h->qh_quotadev, id, (void *)&xdqblk);
|
||||
+ if (ret < 0)
|
||||
+ break;
|
||||
+
|
||||
+ xfs_kern2utildqblk(&dquot->dq_dqb, &xdqblk);
|
||||
+ dquot->dq_id = xdqblk.d_id;
|
||||
+ ret = process_dquot(dquot, NULL);
|
||||
+ if (ret < 0)
|
||||
+ break;
|
||||
+ id = xdqblk.d_id + 1;
|
||||
+ }
|
||||
+ free(dquot);
|
||||
+
|
||||
+ if (errno == ENOENT)
|
||||
+ return 0;
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Scan all known dquots and call callback on each
|
||||
*/
|
||||
static int xfs_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct dquot *dquot, char *dqname))
|
||||
{
|
||||
- if (!XFS_USRQUOTA(h) && !XFS_GRPQUOTA(h))
|
||||
- return 0;
|
||||
+ int ret;
|
||||
+ struct xfs_kern_dqblk xdqblk;
|
||||
|
||||
- return generic_scan_dquots(h, process_dquot, xfs_get_dquot);
|
||||
+ ret = quotactl(QCMD(Q_XGETNEXTQUOTA, h->qh_type), h->qh_quotadev, 0,
|
||||
+ (void *)&xdqblk);
|
||||
+ if (ret < 0 && (errno == ENOSYS || errno == EINVAL)) {
|
||||
+ if (!XFS_USRQUOTA(h) && !XFS_GRPQUOTA(h))
|
||||
+ return 0;
|
||||
+ return generic_scan_dquots(h, process_dquot, xfs_get_dquot);
|
||||
+ }
|
||||
+ return xfs_kernel_scan_dquots(h, process_dquot);
|
||||
}
|
||||
|
||||
/*
|
||||
diff --git a/quotaio_xfs.h b/quotaio_xfs.h
|
||||
index 54725b0..2236da4 100644
|
||||
--- a/quotaio_xfs.h
|
||||
+++ b/quotaio_xfs.h
|
||||
@@ -46,6 +46,7 @@
|
||||
#define Q_XSETQLIM XQM_CMD(0x4) /* set disk limits only */
|
||||
#define Q_XGETQSTAT XQM_CMD(0x5) /* returns fs_quota_stat_t struct */
|
||||
#define Q_XQUOTARM XQM_CMD(0x6) /* free quota files' space */
|
||||
+#define Q_XGETNEXTQUOTA XQM_CMD(0x9) /* get disk limits and usage >= ID */
|
||||
|
||||
/*
|
||||
* fs_disk_quota structure:
|
||||
--
|
||||
2.5.0
|
||||
|
||||
142
quota-4.03-Scan-dquots-using-Q_GETNEXTQUOTA.patch
Normal file
142
quota-4.03-Scan-dquots-using-Q_GETNEXTQUOTA.patch
Normal file
@ -0,0 +1,142 @@
|
||||
From 85687833434d50e3f5fd4b849e543eb505bf5a20 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Kara <jack@suse.cz>
|
||||
Date: Tue, 26 Jan 2016 13:10:59 +0100
|
||||
Subject: [PATCH 1/2] Scan dquots using Q_GETNEXTQUOTA
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Check for new kernel quotactl Q_GETNEXTQUOTA and if available use it for
|
||||
scanning all dquot structures.
|
||||
|
||||
Signed-off-by: Jan Kara <jack@suse.cz>
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
quota.h | 14 ++++++++++++++
|
||||
quotaio_generic.c | 34 ++++++++++++++++++++++++++++++++++
|
||||
quotaio_generic.h | 4 ++++
|
||||
quotaio_meta.c | 14 +++++++++++++-
|
||||
4 files changed, 65 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/quota.h b/quota.h
|
||||
index 0c38427..0607e04 100644
|
||||
--- a/quota.h
|
||||
+++ b/quota.h
|
||||
@@ -63,6 +63,7 @@ typedef int64_t qsize_t; /* Type in which we store size limitations */
|
||||
#define Q_SETINFO 0x800006 /* set information about quota files */
|
||||
#define Q_GETQUOTA 0x800007 /* get user quota structure */
|
||||
#define Q_SETQUOTA 0x800008 /* set user quota structure */
|
||||
+#define Q_GETNEXTQUOTA 0x800009 /* get disk limits and usage >= ID */
|
||||
|
||||
/*
|
||||
* Quota structure used for communication with userspace via quotactl
|
||||
@@ -91,6 +92,19 @@ struct if_dqblk {
|
||||
u_int32_t dqb_valid;
|
||||
};
|
||||
|
||||
+struct if_nextdqblk {
|
||||
+ u_int64_t dqb_bhardlimit;
|
||||
+ u_int64_t dqb_bsoftlimit;
|
||||
+ u_int64_t dqb_curspace;
|
||||
+ u_int64_t dqb_ihardlimit;
|
||||
+ u_int64_t dqb_isoftlimit;
|
||||
+ u_int64_t dqb_curinodes;
|
||||
+ u_int64_t dqb_btime;
|
||||
+ u_int64_t dqb_itime;
|
||||
+ u_int32_t dqb_valid;
|
||||
+ u_int32_t dqb_id;
|
||||
+};
|
||||
+
|
||||
/*
|
||||
* Structure used for setting quota information about file via quotactl
|
||||
* Following flags are used to specify which fields are valid
|
||||
diff --git a/quotaio_generic.c b/quotaio_generic.c
|
||||
index 5001a56..4bdf380 100644
|
||||
--- a/quotaio_generic.c
|
||||
+++ b/quotaio_generic.c
|
||||
@@ -161,3 +161,37 @@ int generic_scan_dquots(struct quota_handle *h,
|
||||
free(dquot);
|
||||
return ret;
|
||||
}
|
||||
+
|
||||
+int vfs_scan_dquots(struct quota_handle *h,
|
||||
+ int (*process_dquot)(struct dquot *dquot, char *dqname))
|
||||
+{
|
||||
+ struct dquot *dquot = get_empty_dquot();
|
||||
+ qid_t id = 0;
|
||||
+ struct if_nextdqblk kdqblk;
|
||||
+ int ret;
|
||||
+
|
||||
+ dquot->dq_h = h;
|
||||
+ while (1) {
|
||||
+ ret = quotactl(QCMD(Q_GETNEXTQUOTA, h->qh_type),
|
||||
+ h->qh_quotadev, id, (void *)&kdqblk);
|
||||
+ if (ret < 0)
|
||||
+ break;
|
||||
+
|
||||
+ /*
|
||||
+ * This is a slight hack but we know struct if_dqblk is a
|
||||
+ * subset of struct if_nextdqblk
|
||||
+ */
|
||||
+ generic_kern2utildqblk(&dquot->dq_dqb,
|
||||
+ (struct if_dqblk *)&kdqblk);
|
||||
+ dquot->dq_id = kdqblk.dqb_id;
|
||||
+ ret = process_dquot(dquot, NULL);
|
||||
+ if (ret < 0)
|
||||
+ break;
|
||||
+ id = kdqblk.dqb_id + 1;
|
||||
+ }
|
||||
+ free(dquot);
|
||||
+
|
||||
+ if (errno == ENOENT)
|
||||
+ return 0;
|
||||
+ return ret;
|
||||
+}
|
||||
diff --git a/quotaio_generic.h b/quotaio_generic.h
|
||||
index 5edc11c..a7930f0 100644
|
||||
--- a/quotaio_generic.h
|
||||
+++ b/quotaio_generic.h
|
||||
@@ -27,4 +27,8 @@ int generic_scan_dquots(struct quota_handle *h,
|
||||
int (*process_dquot)(struct dquot *dquot, char *dqname),
|
||||
int (*get_dquot)(struct dquot *dquot));
|
||||
|
||||
+/* Scan all dquots using kernel quotactl to get existing ids */
|
||||
+int vfs_scan_dquots(struct quota_handle *h,
|
||||
+ int (*process_dquot)(struct dquot *dquot, char *dqname));
|
||||
+
|
||||
#endif
|
||||
diff --git a/quotaio_meta.c b/quotaio_meta.c
|
||||
index e52b4f4..ad6ff7a 100644
|
||||
--- a/quotaio_meta.c
|
||||
+++ b/quotaio_meta.c
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
+#include <errno.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -55,7 +56,18 @@ static int meta_commit_dquot(struct dquot *dquot, int flags)
|
||||
|
||||
static int meta_scan_dquots(struct quota_handle *h, int (*process_dquot)(struct dquot *dquot, char *dqname))
|
||||
{
|
||||
- return generic_scan_dquots(h, process_dquot, vfs_get_dquot);
|
||||
+ struct if_nextdqblk kdqblk;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = quotactl(QCMD(Q_GETNEXTQUOTA, h->qh_type), h->qh_quotadev, 0,
|
||||
+ (void *)&kdqblk);
|
||||
+ /*
|
||||
+ * Fall back to scanning using passwd if Q_GETNEXTQUOTA is not
|
||||
+ * supported
|
||||
+ */
|
||||
+ if (ret < 0 && (errno == ENOSYS || errno == EINVAL))
|
||||
+ return generic_scan_dquots(h, process_dquot, vfs_get_dquot);
|
||||
+ return vfs_scan_dquots(h, process_dquot);
|
||||
}
|
||||
|
||||
struct quotafile_ops quotafile_ops_meta = {
|
||||
--
|
||||
2.5.0
|
||||
|
||||
13
quota.spec
13
quota.spec
@ -4,7 +4,7 @@
|
||||
Name: quota
|
||||
Epoch: 1
|
||||
Version: 4.03
|
||||
Release: 2%{?dist}
|
||||
Release: 3%{?dist}
|
||||
Summary: System administration tools for monitoring users' disk usage
|
||||
# quota_nld.c, quotaio_xfs.h: GPLv2
|
||||
# bylabel.c copied from util-linux: GPLv2+
|
||||
@ -44,6 +44,11 @@ Patch3: quota-4.03-Respect-enviroment-CFLAGS.patch
|
||||
# bug #1296455, reported to upstream
|
||||
# <https://sourceforge.net/p/linuxquota/bugs/122/>
|
||||
Patch4: quota-4.03-Work-around-an-AC_CHECK_LIB-bug-in-Autoconf.patch
|
||||
# Query kernel for next quota on file system with hiden quota files,
|
||||
# bug #1306195, in upstream after 4.03
|
||||
Patch5: quota-4.03-Scan-dquots-using-Q_GETNEXTQUOTA.patch
|
||||
# Query kernel for next XFS quota, bug #1306195, in upstream after 4.03
|
||||
Patch6: quota-4.03-Add-support-for-scanning-using-Q_XGETNEXTQUOTA.patch
|
||||
BuildRequires: autoconf
|
||||
BuildRequires: automake
|
||||
BuildRequires: bash
|
||||
@ -154,6 +159,8 @@ Linux/UNIX environment.
|
||||
%patch2 -p1
|
||||
%patch3 -p1
|
||||
%patch4 -p1
|
||||
%patch5 -p1
|
||||
%patch6 -p1
|
||||
# Unpack forgotten LDAP scripts
|
||||
tar -xzkf %{SOURCE5}
|
||||
# Regenerate build scripts, also because of Respect-enviroment-CFLAGS.patch
|
||||
@ -266,6 +273,10 @@ make check
|
||||
|
||||
|
||||
%changelog
|
||||
* Mon Feb 22 2016 Petr Pisar <ppisar@redhat.com> - 1:4.03-3
|
||||
- Query kernel for next quota on XFS or file system with hidden quota files
|
||||
(bug #1306195)
|
||||
|
||||
* Thu Feb 04 2016 Fedora Release Engineering <releng@fedoraproject.org> - 1:4.03-2
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user