|
|
619d785 |
From 7e1c5c8074e5d83cfda5b66140c177954b836118 Mon Sep 17 00:00:00 2001
|
|
|
619d785 |
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
|
|
|
619d785 |
Date: Thu, 6 Jan 2011 17:59:27 +0100
|
|
|
619d785 |
Subject: [PATCH] Make RPC block factor dynamic
|
|
|
619d785 |
|
|
|
619d785 |
Former static factor (RPC_DQBLK_SIZE_BITS) had problem to carry values
|
|
|
619d785 |
bigger than hard-coded limit (2^(32 + RPC_DQBLK_SIZE_BITS) - 1).
|
|
|
619d785 |
|
|
|
619d785 |
This patch makes the factor dynamic. It selects best value to prevent
|
|
|
619d785 |
overflow (XDR has 32b variables, some file system support 64b quotas)
|
|
|
619d785 |
and to achieve highest possible precision.
|
|
|
619d785 |
|
|
|
619d785 |
The client site uses the factor carried via RPC correctly.
|
|
|
619d785 |
|
|
|
619d785 |
There is similar problem with setquota. This patch does not address it,
|
|
|
619d785 |
however it can be easily resused and fixed.
|
|
|
619d785 |
---
|
|
|
619d785 |
rquota_server.c | 34 +++++++++++++++++++++++++++++-----
|
|
|
619d785 |
1 files changed, 29 insertions(+), 5 deletions(-)
|
|
|
619d785 |
|
|
|
619d785 |
diff --git a/rquota_server.c b/rquota_server.c
|
|
|
619d785 |
index 0e83689..cff6191 100644
|
|
|
619d785 |
--- a/rquota_server.c
|
|
|
619d785 |
+++ b/rquota_server.c
|
|
|
619d785 |
@@ -91,17 +91,42 @@ static inline void servnet2utildqblk(struct util_dqblk *u, sq_dqblk * n)
|
|
|
619d785 |
u->dqb_itime = 0;
|
|
|
619d785 |
}
|
|
|
619d785 |
|
|
|
619d785 |
+/* XDR transports 32b variables exactly. Find smallest needed shift to fit
|
|
|
619d785 |
+ * 64b variable into into 32 bits and to preserve precision as high as
|
|
|
619d785 |
+ * possible. */
|
|
|
619d785 |
+static int find_block_shift(qsize_t hard, qsize_t soft, qsize_t cur)
|
|
|
619d785 |
+{
|
|
|
619d785 |
+ int shift;
|
|
|
619d785 |
+ qsize_t value;
|
|
|
619d785 |
+
|
|
|
619d785 |
+ value = (hard > soft) ? hard : soft;
|
|
|
619d785 |
+ for (shift = QUOTABLOCK_BITS; value; shift++) value >>= 1;
|
|
|
619d785 |
+
|
|
|
619d785 |
+ cur >>= shift;
|
|
|
619d785 |
+ for (; cur; shift++) cur >>= 1;
|
|
|
619d785 |
+
|
|
|
619d785 |
+ shift -= 32;
|
|
|
619d785 |
+ if (shift < 0) shift = 0;
|
|
|
619d785 |
+
|
|
|
619d785 |
+ return shift;
|
|
|
619d785 |
+}
|
|
|
619d785 |
+
|
|
|
619d785 |
static inline void servutil2netdqblk(struct rquota *n, struct util_dqblk *u)
|
|
|
619d785 |
{
|
|
|
619d785 |
time_t now;
|
|
|
619d785 |
+ int shift;
|
|
|
619d785 |
|
|
|
619d785 |
- time(&now;;
|
|
|
619d785 |
- n->rq_bhardlimit = (u->dqb_bhardlimit << QUOTABLOCK_BITS) >> RPC_DQBLK_SIZE_BITS;
|
|
|
619d785 |
- n->rq_bsoftlimit = (u->dqb_bsoftlimit << QUOTABLOCK_BITS) >> RPC_DQBLK_SIZE_BITS;
|
|
|
619d785 |
+ shift = find_block_shift(u->dqb_bhardlimit, u->dqb_bsoftlimit,
|
|
|
619d785 |
+ u->dqb_curspace);
|
|
|
619d785 |
+ n->rq_bsize = 1 << shift;
|
|
|
619d785 |
+ n->rq_bhardlimit = (u->dqb_bhardlimit << QUOTABLOCK_BITS) >> shift;
|
|
|
619d785 |
+ n->rq_bsoftlimit = (u->dqb_bsoftlimit << QUOTABLOCK_BITS) >> shift;
|
|
|
619d785 |
n->rq_fhardlimit = u->dqb_ihardlimit;
|
|
|
619d785 |
n->rq_fsoftlimit = u->dqb_isoftlimit;
|
|
|
619d785 |
- n->rq_curblocks = (u->dqb_curspace + RPC_DQBLK_SIZE - 1) >> RPC_DQBLK_SIZE_BITS;
|
|
|
619d785 |
+ n->rq_curblocks = (u->dqb_curspace + n->rq_bsize - 1) >> shift;
|
|
|
619d785 |
n->rq_curfiles = u->dqb_curinodes;
|
|
|
619d785 |
+
|
|
|
619d785 |
+ time(&now;;
|
|
|
619d785 |
if (u->dqb_btime)
|
|
|
619d785 |
n->rq_btimeleft = u->dqb_btime - now;
|
|
|
619d785 |
else
|
|
|
619d785 |
@@ -258,7 +283,6 @@ getquota_rslt *getquotainfo(int lflags, caddr_t * argp, struct svc_req * rqstp)
|
|
|
619d785 |
}
|
|
|
619d785 |
|
|
|
619d785 |
result.status = Q_NOQUOTA;
|
|
|
619d785 |
- result.getquota_rslt_u.gqr_rquota.rq_bsize = RPC_DQBLK_SIZE;
|
|
|
619d785 |
|
|
|
619d785 |
if (init_mounts_scan(1, &pathp, MS_QUIET | MS_NO_MNTPOINT | MS_NFS_ALL | ((flags & FL_AUTOFS) ? 0 : MS_NO_AUTOFS)) < 0)
|
|
|
619d785 |
goto out;
|
|
|
619d785 |
--
|
|
|
619d785 |
1.7.3.4
|
|
|
619d785 |
|