Timo Sirainen wrote:
On Tue, 2009-02-17 at 11:14 +0300, fandorin@rol.ru 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