Skip Menu |

This queue is for tickets about the Quota CPAN distribution.

Report information
The Basics
Id: 52813
Status: resolved
Priority: 0/
Queue: Quota

People
Owner: Nobody in particular
Requestors: somewhere.or.other+bitcard [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 1.6.3
Fixed in: (no value)



Subject: quota block count truncation
There's a small bug in the Perl Quota module that truncates the number of blocks to 32-bits, meaning that really big quotas (eg. 15 TB), don't show up correctly. This is related to a patch in the rquotad server available in CVS (committed 14 Dec 2009) at http://sourceforge.net/projects/linuxquota/. My co-worker has been working with the developer there (jkar8572). Basically, we want to have 15 TB (15*2^40 byte) quotas, but using the standard 1kB (2^10 byte) block size, that overflows the 32-bit integer for the number of blocks. With the help of that developer, we made it start using a 1 MB block size (2^20 byte), which means we only have 15*2^20 blocks (was 15*2^30 blocks), which fits. I'm running on an x86_64 CentOS Linux 5.3 machine with Perl v5.8.8 (stock), quota-tools v3.13 (also stock), and the Perl Quota module v1.6.3 (not stock). In the Quota.xs file, we have things like this: dqp->QS_BHARD = gq_rslt.GQR_RQUOTA.rq_bhardlimit * qb_fac; The "dqp->QS_BHARD" is 64-bit on this system, but "gq_rslt.GQR_RQUOTA.rq_bhardlimit" and "qb_fac" are both 32-bit. The individual values both fit inside a 32-bit integer, but the product doesn't. Therefore, I'm simply casting them to qsize_t, before the multiplication, like this: dqp->QS_BHARD = (qsize_t)gq_rslt.GQR_RQUOTA.rq_bhardlimit * (qsize_t)qb_fac; I'm sure this is a very messy patch, and not very portable across architectures, OSs, etc. I'm honestly not certain of the implications in the wider scope. I can help test if need be. Just let me know. Lloyd Brown
Subject: Perl_Quota_overflow.patch
--- Quota-1.6.3/Quota.xs 2008-12-21 05:05:53.000000000 -0700 +++ Quota-1.6.3.patched/Quota.xs 2009-12-15 15:04:02.659000000 -0700 @@ -193,9 +193,9 @@ /* we rely on the fact that block sizes are always powers of 2 */ /* so the conversion factor will never be a fraction */ int qb_fac = gq_rslt.GQR_RQUOTA.rq_bsize / DEV_QBSIZE; - dqp->QS_BHARD = gq_rslt.GQR_RQUOTA.rq_bhardlimit * qb_fac; - dqp->QS_BSOFT = gq_rslt.GQR_RQUOTA.rq_bsoftlimit * qb_fac; - dqp->QS_BCUR = gq_rslt.GQR_RQUOTA.rq_curblocks * qb_fac; + dqp->QS_BHARD = (qsize_t)gq_rslt.GQR_RQUOTA.rq_bhardlimit * (qsize_t)qb_fac; + dqp->QS_BSOFT = (qsize_t)gq_rslt.GQR_RQUOTA.rq_bsoftlimit * (qsize_t)qb_fac; + dqp->QS_BCUR = (qsize_t)gq_rslt.GQR_RQUOTA.rq_curblocks * (qsize_t)qb_fac; } else { int qb_fac = DEV_QBSIZE / gq_rslt.GQR_RQUOTA.rq_bsize;
Just so this is clear, this only affects remote RPC quota type stuff, as reported by rpc.rquotad. As it happens, the remote server in this case is also running CentOS 5.3, x86_64, but I doubt that's relevant. The remote server is the one with the patched rquotad server, and the 15 TB quota.
This code should also do the trick without depending on a specific type: if (gq_rslt.GQR_RQUOTA.rq_bsize >= DEV_QBSIZE) { /* assign first, multiply later: ** so that mult works with the possibly larger type in dqp */ dqp->QS_BHARD = gq_rslt.GQR_RQUOTA.rq_bhardlimit; dqp->QS_BSOFT = gq_rslt.GQR_RQUOTA.rq_bsoftlimit; dqp->QS_BCUR = gq_rslt.GQR_RQUOTA.rq_curblocks; /* we rely on the fact that block sizes are always powers of 2 */ /* so the conversion factor will never be a fraction */ int qb_fac = gq_rslt.GQR_RQUOTA.rq_bsize / DEV_QBSIZE; dqp->QS_BHARD *= qb_fac; dqp->QS_BSOFT *= qb_fac; dqp->QS_BCUR *= qb_fac; } Can you confirm if this works in your setup? TIA Note 64-bit quotas aren't officially supported by the Perl Quota module yet, as they will be reported correctly only if using a 64-bit Perl. Supporting them in a 32-bit Perl would be messy. But since your patch won't harm 32-bit users I'll certainly include it in some form. Thanks for the bug report. -tom
Confirmed. That seems to also work for us. So, basically you just assign it first (upgrading 32->64bit), then you *=, which will automatically upgrade to 64bit. Very clever. I like it. Lloyd
From: somewhere.or.other+bitcard [...] gmail.com
Just curious. Is there any intention to integrate this patch into a release soon?
The fix is included in release Quota-1.6.4 Thanks again