diff -NurpP --minimal linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/dlimit_cmd.h linux-2.6.31.6-vs2.3.0.36.24.2/include/linux/vserver/dlimit_cmd.h --- linux-2.6.31.6-vs2.3.0.36.24/include/linux/vserver/dlimit_cmd.h 2009-09-10 16:11:43.000000000 +0200 +++ linux-2.6.31.6-vs2.3.0.36.24.2/include/linux/vserver/dlimit_cmd.h 2009-11-21 20:30:12.000000000 +0100 @@ -29,6 +29,41 @@ struct vcmd_ctx_dlimit_v0 { #define CDLIM_INFINITY ((uint32_t)~0UL) #define CDLIM_KEEP ((uint32_t)~1UL) +#define DLIME_UNIT 0 +#define DLIME_KILO 1 +#define DLIME_MEGA 2 +#define DLIME_GIGA 3 + +#define DLIMF_SHIFT 0x10 + +#define DLIMS_USED 0 +#define DLIMS_TOTAL 2 + +static inline +uint64_t dlimit_space_32to64(uint32_t val, uint32_t flags, int shift) +{ + int exp = (flags & DLIMF_SHIFT) ? + (flags >> shift) & DLIME_GIGA : DLIME_KILO; + return val << (10LL * exp); +} + +static inline +uint32_t dlimit_space_64to32(uint64_t val, uint32_t *flags, int shift) +{ + int exp = 0; + + if (*flags & DLIMF_SHIFT) { + while (val > (1LL << 32) && (exp < 3)) { + val >>= 10LL; + exp++; + } + *flags &= ~(DLIME_GIGA << shift); + *flags |= exp << shift; + } else + val >>= 10LL; + return val; +} + #ifdef __KERNEL__ #ifdef CONFIG_COMPAT diff -NurpP --minimal linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/dlimit.c linux-2.6.31.6-vs2.3.0.36.24.2/kernel/vserver/dlimit.c --- linux-2.6.31.6-vs2.3.0.36.24/kernel/vserver/dlimit.c 2009-09-10 16:11:43.000000000 +0200 +++ linux-2.6.31.6-vs2.3.0.36.24.2/kernel/vserver/dlimit.c 2009-11-21 20:30:53.000000000 +0100 @@ -3,10 +3,11 @@ * * Virtual Server: Context Disk Limits * - * Copyright (C) 2004-2007 Herbert Pötzl + * Copyright (C) 2004-2009 Herbert Pötzl * * V0.01 initial version * V0.02 compat32 splitup + * V0.03 extended interface * */ @@ -287,6 +288,8 @@ int do_set_dlimit(uint32_t id, const cha goto out_release; if (!(sb = path.dentry->d_inode->i_sb)) goto out_release; + + /* sanity checks */ if ((reserved != CDLIM_KEEP && reserved > 100) || (inodes_used != CDLIM_KEEP && @@ -306,16 +309,16 @@ int do_set_dlimit(uint32_t id, const cha dli->dl_inodes_used = inodes_used; if (inodes_total != CDLIM_KEEP) dli->dl_inodes_total = inodes_total; - if (space_used != CDLIM_KEEP) { - dli->dl_space_used = space_used; - dli->dl_space_used <<= 10; - } + if (space_used != CDLIM_KEEP) + dli->dl_space_used = dlimit_space_32to64( + space_used, flags, DLIMS_USED); + if (space_total == CDLIM_INFINITY) dli->dl_space_total = DLIM_INFINITY; - else if (space_total != CDLIM_KEEP) { - dli->dl_space_total = space_total; - dli->dl_space_total <<= 10; - } + else if (space_total != CDLIM_KEEP) + dli->dl_space_total = dlimit_space_32to64( + space_total, flags, DLIMS_TOTAL); + if (reserved != CDLIM_KEEP) dli->dl_nrlmult = (1 << 10) * (100 - reserved) / 100; @@ -389,11 +392,15 @@ int do_get_dlimit(uint32_t id, const cha spin_lock(&dli->dl_lock); *inodes_used = dli->dl_inodes_used; *inodes_total = dli->dl_inodes_total; - *space_used = dli->dl_space_used >> 10; + + *space_used = dlimit_space_64to32( + dli->dl_space_used, flags, DLIMS_USED); + if (dli->dl_space_total == DLIM_INFINITY) *space_total = CDLIM_INFINITY; - else - *space_total = dli->dl_space_total >> 10; + else + *space_total = dlimit_space_64to32( + dli->dl_space_total, flags, DLIMS_TOTAL); *reserved = 100 - ((dli->dl_nrlmult * 100 + 512) >> 10); spin_unlock(&dli->dl_lock);