dovecot: Support for rquota with NFS mounts. Patch by HTK NetCom...

dovecot at dovecot.org dovecot at dovecot.org
Thu Aug 2 17:05:36 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/078d9dde99c8
changeset: 6159:078d9dde99c8
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Aug 02 17:05:26 2007 +0300
description:
Support for rquota with NFS mounts. Patch by HTK NetCommunication Oy.

diffstat:

3 files changed, 123 insertions(+)
configure.in                  |    7 ++
src/plugins/quota/Makefile.am |    5 +
src/plugins/quota/quota-fs.c  |  111 +++++++++++++++++++++++++++++++++++++++++

diffs (167 lines):

diff -r 6e9b6468398f -r 078d9dde99c8 configure.in
--- a/configure.in	Thu Aug 02 15:56:47 2007 +0300
+++ b/configure.in	Thu Aug 02 17:05:26 2007 +0300
@@ -1921,6 +1921,13 @@ AC_CHECK_HEADER(zlib.h, [
 ])
 AM_CONDITIONAL(BUILD_ZLIB, test "$have_zlib" = "yes")
 
+have_rquota=no
+AC_CHECK_HEADER(rpcsvc/rquota.h, [
+  AC_DEFINE(HAVE_RQUOTA,, Define if you wish to retrieve quota of NFS mounted mailboxes)
+  have_rquota=yes
+])
+AM_CONDITIONAL(HAVE_RQUOTA, test "$have_rquota" = "yes")
+
 dnl **
 dnl ** capabilities
 dnl **
diff -r 6e9b6468398f -r 078d9dde99c8 src/plugins/quota/Makefile.am
--- a/src/plugins/quota/Makefile.am	Thu Aug 02 15:56:47 2007 +0300
+++ b/src/plugins/quota/Makefile.am	Thu Aug 02 17:05:26 2007 +0300
@@ -11,6 +11,11 @@ lib10_quota_plugin_la_LDFLAGS = -module 
 
 module_LTLIBRARIES = \
 	lib10_quota_plugin.la
+
+if HAVE_RQUOTA
+lib10_quota_plugin_la_LIBADD = \
+	-lrpcsvc
+endif
 
 lib10_quota_plugin_la_SOURCES = \
 	quota.c \
diff -r 6e9b6468398f -r 078d9dde99c8 src/plugins/quota/quota-fs.c
--- a/src/plugins/quota/quota-fs.c	Thu Aug 02 15:56:47 2007 +0300
+++ b/src/plugins/quota/quota-fs.c	Thu Aug 02 17:05:26 2007 +0300
@@ -24,6 +24,11 @@
 #  define HAVE_XFS_QUOTA
 #endif
 
+#ifdef HAVE_RQUOTA
+#  include <rpcsvc/rquota.h>
+#  define RQUOTA_GETQUOTA_TIMEOUT_SECS 10
+#endif
+
 #ifndef DEV_BSIZE
 #  define DEV_BSIZE 512
 #endif
@@ -189,6 +194,101 @@ fs_quota_root_get_resources(struct quota
 	return resources;
 }
 
+#ifdef HAVE_RQUOTA
+/* retrieve user quota from a remote host */
+static int do_rquota(struct fs_quota_root *root, uint64_t *value_r,
+		     uint64_t *limit_r)
+{
+	struct getquota_rslt result;
+	struct getquota_args args;
+	struct timeval timeout;
+	enum clnt_stat call_status;
+	CLIENT *cl;
+	struct fs_quota_mountpoint *mount = root->mount;
+	const char *host;
+	char *path;
+
+	path = strchr(mount->device_path, ':');
+	if (path == NULL) {
+		i_error("quota-fs: %s is not a valid NFS device path",
+			mount->device_path);
+		return -1;
+	}
+
+	host = t_strdup_until(mount->device_path, path);
+	path++;
+
+	if (getenv("DEBUG") != NULL) {
+		i_info("quota-fs: host=%s, path=%s, uid=%s",
+			host, path, dec2str(root->uid));
+	}
+
+	/* clnt_create() polls for a while to establish a connection */
+	cl = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp");
+	if (cl == NULL) {
+		i_error("quota-fs: could not contact RPC service on %s",
+			host);
+		return -1;
+	}
+
+	/* make the rquota call on the remote host */
+	args.gqa_pathp = path;
+	args.gqa_uid = root->uid;
+
+	timeout.tv_sec = RQUOTA_GETQUOTA_TIMEOUT_SECS;
+	timeout.tv_usec = 0;
+	call_status = clnt_call(cl, RQUOTAPROC_GETQUOTA,
+				(xdrproc_t)xdr_getquota_args, (char *)&args,
+				(xdrproc_t)xdr_getquota_rslt, (char *)&result,
+				timeout);
+	
+	/* the result has been deserialized, let the client go */
+	clnt_destroy(cl);
+
+	if (call_status != RPC_SUCCESS) {
+		const char *rpc_error_msg = clnt_sperrno(call_status);
+
+		i_error("quota-fs: remote rquota call failed: %s",
+			rpc_error_msg);
+		return -1;
+	}
+
+	switch (result.status) {
+	case Q_OK: {
+		/* convert the results from blocks to bytes */
+		rquota *rq = &result.getquota_rslt_u.gqr_rquota;
+
+		if (rq->rq_active) {
+			*value_r = (uint64_t)rq->rq_curblocks *
+				(uint64_t)rq->rq_bsize;
+			*limit_r = (uint64_t)rq->rq_bsoftlimit *
+				(uint64_t)rq->rq_bsize;
+		}
+		if (getenv("DEBUG") != NULL) {
+			i_info("quota-fs: uid=%s, value=%llu, "
+			       "limit=%llu, active=%d", dec2str(root->uid),
+			       (unsigned long long)*value_r,
+			       (unsigned long long)*limit_r, rq->rq_active);
+		}
+		return 1;
+	}
+	case Q_NOQUOTA:
+		if (getenv("DEBUG") != NULL) {
+			i_info("quota-fs: uid=%s, limit=unlimited",
+			       dec2str(root->uid));
+		}
+		return 1;
+	case Q_EPERM:
+		i_error("quota-fs: permission denied to rquota service");
+		return -1;
+	default:
+		i_error("quota-fs: unrecognized status code (%d) "
+			"from rquota service", result.status);
+		return -1;
+	}
+}
+#endif
+
 static int
 fs_quota_get_resource(struct quota_root *_root, const char *name,
 		      uint64_t *value_r, uint64_t *limit_r)
@@ -205,6 +305,17 @@ fs_quota_get_resource(struct quota_root 
 	if (strcasecmp(name, QUOTA_NAME_STORAGE_BYTES) != 0 ||
 	    root->mount == NULL)
 		return 0;
+
+#ifdef HAVE_RQUOTA
+	if (strcmp(root->mount->type, "nfs") == 0) {
+		int ret;
+
+		t_push();
+		ret = do_rquota(root, value_r, limit_r);
+		t_pop();
+		return ret;
+	}
+#endif
 
 #if defined (HAVE_QUOTACTL) && defined(HAVE_SYS_QUOTA_H)
 	/* Linux */


More information about the dovecot-cvs mailing list