Timo Sirainen wrote:
On Tue, 2009-02-17 at 11:14 +0300, [email protected] wrote:
Hi all. Unfortunately, the existing quota-fs does not know how to get
GROUP quota with NFS storage. But there is a tool for Linux quota-tools
(http://slackware.rol.ru/slackware/slackware-12.2/source/a/quota/). This
patch is made on the basis quota-tools. The patch was successful alpha
testing. Suggestions and comments are welcome.
There's a bit too much copy&pasted code. For example the i_info() calls
are duplicated. And I think you could keep the clnt open when
fallbacking to the non-ext lookup instead of having to recreate it in
the middle. It would also need to have some #ifdef EXT_RQUOTAPROG checks
so that the code would compile with other systems than Linux too. And it
should probably remember if the non-ext lookup failed the previous time,
so it wouldn't waste time every time doing it twice.
Hi. Thanks for your comments. I made a new version of the patch for
GROUP quota with NFS storage.
But I do not know how better to define EXT_RQUOTAPROG: automatically or
using option for configure script.
What do you think? Are you interested in this patch for the basic
version of the dovecot?
diff -ruN -bE dovecot-1.1.11.orig/src/plugins/quota/quota-fs.c
dovecot-1.1.11/src/plugins/quota/quota-fs.c
--- dovecot-1.1.11.orig/src/plugins/quota/quota-fs.c 2009-01-06
17:33:51.000000000 +0300
+++ dovecot-1.1.11/src/plugins/quota/quota-fs.c 2009-02-27 15:56:24.000000000
+0300
@@ -288,17 +288,25 @@
#ifdef HAVE_RQUOTA
/* retrieve user quota from a remote host */
-static int do_rquota(struct fs_quota_root *root, bool bytes,
+static int do_rquota(struct fs_quota_root *root, bool group, bool bytes,
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;
+ int type, id;
+
+ union {
+ getquota_args arg;
+ ext_getquota_args ext_arg;
+ } args;
+
+ type = group ? GRPQUOTA : USRQUOTA;
+ id = group ? root->gid : root->uid;
path = strchr(mount->device_path, ':');
if (path == NULL) {
@@ -311,10 +319,40 @@
path++;
if (getenv("DEBUG") != NULL) {
- i_info("quota-fs: host=%s, path=%s, uid=%s",
- host, path, dec2str(root->uid));
+ i_info("quota-fs: host=%s, path=%s, %cid=%s",
+ host, path, group ? 'g' : 'u', dec2str(id));
+ }
+
+ if (group) {
+ /* clnt_create() polls for a while to establish a connection */
+ cl = clnt_create(host, RQUOTAPROG, EXT_RQUOTAVERS, "udp");
+ if (cl == NULL) {
+ i_error("quota-fs: could not contact RPC service on %s",
+ host);
+ return -1;
}
+ /* Establish some RPC credentials */
+ auth_destroy(cl->cl_auth);
+ cl->cl_auth = authunix_create_default();
+
+ /* make the rquota call on the remote host */
+ args.ext_arg.gqa_pathp = path;
+ args.ext_arg.gqa_id = id;
+ args.ext_arg.gqa_type = type;
+
+ timeout.tv_sec = RQUOTA_GETQUOTA_TIMEOUT_SECS;
+ timeout.tv_usec = 0;
+
+ call_status = clnt_call(cl, RQUOTAPROC_GETQUOTA,
+ (xdrproc_t)xdr_ext_getquota_args, (char
*)&args.ext_arg,
+ (xdrproc_t)xdr_getquota_rslt, (char
*)&result,
+ timeout);
+
+ /* the result has been deserialized, let the client go */
+ auth_destroy(cl->cl_auth);
+ clnt_destroy(cl);
+ } else {
/* clnt_create() polls for a while to establish a connection */
cl = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp");
if (cl == NULL) {
@@ -328,8 +366,8 @@
cl->cl_auth = authunix_create_default();
/* make the rquota call on the remote host */
- args.gqa_pathp = path;
- args.gqa_uid = root->uid;
+ args.arg.gqa_pathp = path;
+ args.arg.gqa_uid = id;
timeout.tv_sec = RQUOTA_GETQUOTA_TIMEOUT_SECS;
timeout.tv_usec = 0;
@@ -341,7 +379,7 @@
/* the result has been deserialized, let the client go */
auth_destroy(cl->cl_auth);
clnt_destroy(cl);
-
+ }
if (call_status != RPC_SUCCESS) {
const char *rpc_error_msg = clnt_sperrno(call_status);
@@ -367,8 +405,9 @@
}
}
if (getenv("DEBUG") != NULL) {
- i_info("quota-fs: uid=%s, value=%llu, "
- "limit=%llu, active=%d", dec2str(root->uid),
+ i_info("quota-fs: %cid=%s, value=%llu, "
+ "limit=%llu, active=%d", group ? 'g' : 'u',
+ dec2str(id),
(unsigned long long)*value_r,
(unsigned long long)*limit_r, rq->rq_active);
}
@@ -376,8 +415,9 @@
}
case Q_NOQUOTA:
if (getenv("DEBUG") != NULL) {
- i_info("quota-fs: uid=%s, limit=unlimited",
- dec2str(root->uid));
+ i_info("quota-fs: %cid=%s, limit=unlimited",
+ group ? 'g' : 'u',
+ dec2str(id));
}
return 1;
case Q_EPERM:
@@ -614,7 +654,8 @@
#ifdef HAVE_RQUOTA
if (strcmp(root->mount->type, "nfs") == 0) {
T_BEGIN {
- ret = do_rquota(root, bytes, value_r, &limit);
+ ret = do_rquota(root, root->group_disabled ? FALSE : TRUE,
+ bytes, value_r, &limit);
} T_END;
} else
#endif