Blame SOURCES/quota-4.03-Scan-dquots-using-Q_GETNEXTQUOTA.patch

7c06a3
From 85687833434d50e3f5fd4b849e543eb505bf5a20 Mon Sep 17 00:00:00 2001
7c06a3
From: Jan Kara <jack@suse.cz>
7c06a3
Date: Tue, 26 Jan 2016 13:10:59 +0100
7c06a3
Subject: [PATCH 1/2] Scan dquots using Q_GETNEXTQUOTA
7c06a3
MIME-Version: 1.0
7c06a3
Content-Type: text/plain; charset=UTF-8
7c06a3
Content-Transfer-Encoding: 8bit
7c06a3
7c06a3
Check for new kernel quotactl Q_GETNEXTQUOTA and if available use it for
7c06a3
scanning all dquot structures.
7c06a3
7c06a3
Signed-off-by: Jan Kara <jack@suse.cz>
7c06a3
Signed-off-by: Petr Písař <ppisar@redhat.com>
7c06a3
---
7c06a3
 quota.h           | 14 ++++++++++++++
7c06a3
 quotaio_generic.c | 34 ++++++++++++++++++++++++++++++++++
7c06a3
 quotaio_generic.h |  4 ++++
7c06a3
 quotaio_meta.c    | 14 +++++++++++++-
7c06a3
 4 files changed, 65 insertions(+), 1 deletion(-)
7c06a3
7c06a3
diff --git a/quota.h b/quota.h
7c06a3
index 0c38427..0607e04 100644
7c06a3
--- a/quota.h
7c06a3
+++ b/quota.h
7c06a3
@@ -63,6 +63,7 @@ typedef int64_t qsize_t;	/* Type in which we store size limitations */
7c06a3
 #define Q_SETINFO  0x800006	/* set information about quota files */
7c06a3
 #define Q_GETQUOTA 0x800007	/* get user quota structure */
7c06a3
 #define Q_SETQUOTA 0x800008	/* set user quota structure */
7c06a3
+#define Q_GETNEXTQUOTA 0x800009	/* get disk limits and usage >= ID */
7c06a3
 
7c06a3
 /*
7c06a3
  * Quota structure used for communication with userspace via quotactl
7c06a3
@@ -91,6 +92,19 @@ struct if_dqblk {
7c06a3
 	u_int32_t dqb_valid;
7c06a3
 };
7c06a3
 
7c06a3
+struct if_nextdqblk {
7c06a3
+	u_int64_t dqb_bhardlimit;
7c06a3
+	u_int64_t dqb_bsoftlimit;
7c06a3
+	u_int64_t dqb_curspace;
7c06a3
+	u_int64_t dqb_ihardlimit;
7c06a3
+	u_int64_t dqb_isoftlimit;
7c06a3
+	u_int64_t dqb_curinodes;
7c06a3
+	u_int64_t dqb_btime;
7c06a3
+	u_int64_t dqb_itime;
7c06a3
+	u_int32_t dqb_valid;
7c06a3
+	u_int32_t dqb_id;
7c06a3
+};
7c06a3
+
7c06a3
 /*
7c06a3
  * Structure used for setting quota information about file via quotactl
7c06a3
  * Following flags are used to specify which fields are valid
7c06a3
diff --git a/quotaio_generic.c b/quotaio_generic.c
7c06a3
index 5001a56..4bdf380 100644
7c06a3
--- a/quotaio_generic.c
7c06a3
+++ b/quotaio_generic.c
7c06a3
@@ -161,3 +161,37 @@ int generic_scan_dquots(struct quota_handle *h,
7c06a3
 	free(dquot);
7c06a3
 	return ret;
7c06a3
 }
7c06a3
+
7c06a3
+int vfs_scan_dquots(struct quota_handle *h,
7c06a3
+		    int (*process_dquot)(struct dquot *dquot, char *dqname))
7c06a3
+{
7c06a3
+	struct dquot *dquot = get_empty_dquot();
7c06a3
+	qid_t id = 0;
7c06a3
+	struct if_nextdqblk kdqblk;
7c06a3
+	int ret;
7c06a3
+
7c06a3
+	dquot->dq_h = h;
7c06a3
+	while (1) {
7c06a3
+		ret = quotactl(QCMD(Q_GETNEXTQUOTA, h->qh_type),
7c06a3
+			       h->qh_quotadev, id, (void *)&kdqblk);
7c06a3
+		if (ret < 0)
7c06a3
+			break;
7c06a3
+
7c06a3
+		/*
7c06a3
+		 * This is a slight hack but we know struct if_dqblk is a
7c06a3
+		 * subset of struct if_nextdqblk
7c06a3
+		 */
7c06a3
+		generic_kern2utildqblk(&dquot->dq_dqb,
7c06a3
+				       (struct if_dqblk *)&kdqblk);
7c06a3
+		dquot->dq_id = kdqblk.dqb_id;
7c06a3
+		ret = process_dquot(dquot, NULL);
7c06a3
+		if (ret < 0)
7c06a3
+			break;
7c06a3
+		id = kdqblk.dqb_id + 1;
7c06a3
+	}
7c06a3
+	free(dquot);
7c06a3
+
7c06a3
+	if (errno == ENOENT)
7c06a3
+		return 0;
7c06a3
+	return ret;
7c06a3
+}
7c06a3
diff --git a/quotaio_generic.h b/quotaio_generic.h
7c06a3
index 5edc11c..a7930f0 100644
7c06a3
--- a/quotaio_generic.h
7c06a3
+++ b/quotaio_generic.h
7c06a3
@@ -27,4 +27,8 @@ int generic_scan_dquots(struct quota_handle *h,
7c06a3
 			int (*process_dquot)(struct dquot *dquot, char *dqname),
7c06a3
 			int (*get_dquot)(struct dquot *dquot));
7c06a3
 
7c06a3
+/* Scan all dquots using kernel quotactl to get existing ids */
7c06a3
+int vfs_scan_dquots(struct quota_handle *h,
7c06a3
+		    int (*process_dquot)(struct dquot *dquot, char *dqname));
7c06a3
+
7c06a3
 #endif
7c06a3
diff --git a/quotaio_meta.c b/quotaio_meta.c
7c06a3
index e52b4f4..ad6ff7a 100644
7c06a3
--- a/quotaio_meta.c
7c06a3
+++ b/quotaio_meta.c
7c06a3
@@ -8,6 +8,7 @@
7c06a3
 
7c06a3
 #include <string.h>
7c06a3
 #include <stdlib.h>
7c06a3
+#include <errno.h>
7c06a3
 
7c06a3
 #include <sys/types.h>
7c06a3
 
7c06a3
@@ -55,7 +56,18 @@ static int meta_commit_dquot(struct dquot *dquot, int flags)
7c06a3
 
7c06a3
 static int meta_scan_dquots(struct quota_handle *h, int (*process_dquot)(struct dquot *dquot, char *dqname))
7c06a3
 {
7c06a3
-	return generic_scan_dquots(h, process_dquot, vfs_get_dquot);
7c06a3
+	struct if_nextdqblk kdqblk;
7c06a3
+	int ret;
7c06a3
+
7c06a3
+	ret = quotactl(QCMD(Q_GETNEXTQUOTA, h->qh_type), h->qh_quotadev, 0,
7c06a3
+		       (void *)&kdqblk);
7c06a3
+	/*
7c06a3
+	 * Fall back to scanning using passwd if Q_GETNEXTQUOTA is not
7c06a3
+	 * supported
7c06a3
+	 */
7c06a3
+	if (ret < 0 && (errno == ENOSYS || errno == EINVAL))
7c06a3
+		return generic_scan_dquots(h, process_dquot, vfs_get_dquot);
7c06a3
+	return vfs_scan_dquots(h, process_dquot);
7c06a3
 }
7c06a3
 
7c06a3
 struct quotafile_ops quotafile_ops_meta = {
7c06a3
-- 
7c06a3
2.5.0
7c06a3