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

Reply via email to