X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=include%2Flinux%2Fvserver%2Flimit_int.h;h=aadf5a5388d843a3e23299c01f55525f4854bc8c;hb=refs%2Fheads%2Fvserver;hp=a48d242b3a81706a0061cac1c15d743dd738f95a;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/include/linux/vserver/limit_int.h b/include/linux/vserver/limit_int.h index a48d242b3..aadf5a538 100644 --- a/include/linux/vserver/limit_int.h +++ b/include/linux/vserver/limit_int.h @@ -1,76 +1,198 @@ #ifndef _VX_LIMIT_INT_H #define _VX_LIMIT_INT_H +#include "context.h" #ifdef __KERNEL__ -#define VXD_RCRES(r) VXD_CBIT(cres, (r)) -#define VXD_RLIMIT(r) VXD_CBIT(limit, (r)) +#define VXD_RCRES_COND(r) VXD_CBIT(cres, (r)) +#define VXD_RLIMIT_COND(r) VXD_CBIT(limit, (r)) extern const char *vlimit_name[NUM_LIMITS]; static inline void __vx_acc_cres(struct vx_info *vxi, int res, int dir, void *_data, char *_file, int _line) { - if (VXD_RCRES(res)) - vxlprintk(1, "vx_acc_cres[%5d,%s,%2d]: %5d%s (%p)", + if (VXD_RCRES_COND(res)) + vxlprintk(1, "vx_acc_cres[%5d,%s,%2d]: %5ld%s (%p)", (vxi ? vxi->vx_id : -1), vlimit_name[res], res, - (vxi ? atomic_read(&vxi->limit.rcur[res]) : 0), + (vxi ? (long)__rlim_get(&vxi->limit, res) : 0), (dir > 0) ? "++" : "--", _data, _file, _line); if (!vxi) return; if (dir > 0) - atomic_inc(&vxi->limit.rcur[res]); + __rlim_inc(&vxi->limit, res); else - atomic_dec(&vxi->limit.rcur[res]); + __rlim_dec(&vxi->limit, res); } static inline void __vx_add_cres(struct vx_info *vxi, int res, int amount, void *_data, char *_file, int _line) { - if (VXD_RCRES(res)) - vxlprintk(1, "vx_add_cres[%5d,%s,%2d]: %5d += %5d (%p)", + if (VXD_RCRES_COND(res)) + vxlprintk(1, "vx_add_cres[%5d,%s,%2d]: %5ld += %5d (%p)", (vxi ? vxi->vx_id : -1), vlimit_name[res], res, - (vxi ? atomic_read(&vxi->limit.rcur[res]) : 0), + (vxi ? (long)__rlim_get(&vxi->limit, res) : 0), amount, _data, _file, _line); if (amount == 0) return; if (!vxi) return; - atomic_add(amount, &vxi->limit.rcur[res]); + __rlim_add(&vxi->limit, res, amount); } +static inline +int __vx_cres_adjust_max(struct _vx_limit *limit, int res, rlim_t value) +{ + int cond = (value > __rlim_rmax(limit, res)); + + if (cond) + __rlim_rmax(limit, res) = value; + return cond; +} + +static inline +int __vx_cres_adjust_min(struct _vx_limit *limit, int res, rlim_t value) +{ + int cond = (value < __rlim_rmin(limit, res)); + + if (cond) + __rlim_rmin(limit, res) = value; + return cond; +} + +static inline +void __vx_cres_fixup(struct _vx_limit *limit, int res, rlim_t value) +{ + if (!__vx_cres_adjust_max(limit, res, value)) + __vx_cres_adjust_min(limit, res, value); +} + + +/* return values: + +1 ... no limit hit + -1 ... over soft limit + 0 ... over hard limit */ + static inline int __vx_cres_avail(struct vx_info *vxi, - int res, int num, char *_file, int _line) + int res, int num, char *_file, int _line) { - unsigned long value; + struct _vx_limit *limit; + rlim_t value; - if (VXD_RLIMIT(res)) - vxlprintk(1, "vx_cres_avail[%5d,%s,%2d]: %5ld > %5d + %5d", + if (VXD_RLIMIT_COND(res)) + vxlprintk(1, "vx_cres_avail[%5d,%s,%2d]: %5ld/%5ld > %5ld + %5d", (vxi ? vxi->vx_id : -1), vlimit_name[res], res, - (vxi ? vxi->limit.rlim[res] : 1), - (vxi ? atomic_read(&vxi->limit.rcur[res]) : 0), + (vxi ? (long)__rlim_soft(&vxi->limit, res) : -1), + (vxi ? (long)__rlim_hard(&vxi->limit, res) : -1), + (vxi ? (long)__rlim_get(&vxi->limit, res) : 0), num, _file, _line); - if (num == 0) - return 1; if (!vxi) return 1; - value = atomic_read(&vxi->limit.rcur[res]); + limit = &vxi->limit; + value = __rlim_get(limit, res); - if (value > vxi->limit.rmax[res]) - vxi->limit.rmax[res] = value; + if (!__vx_cres_adjust_max(limit, res, value)) + __vx_cres_adjust_min(limit, res, value); - if (vxi->limit.rlim[res] == RLIM_INFINITY) + if (num == 0) return 1; - if (value + num <= vxi->limit.rlim[res]) + if (__rlim_soft(limit, res) == RLIM_INFINITY) + return -1; + if (value + num <= __rlim_soft(limit, res)) + return -1; + + if (__rlim_hard(limit, res) == RLIM_INFINITY) + return 1; + if (value + num <= __rlim_hard(limit, res)) return 1; - atomic_inc(&vxi->limit.lhit[res]); + __rlim_hit(limit, res); return 0; } + +static const int VLA_RSS[] = { RLIMIT_RSS, VLIMIT_ANON, VLIMIT_MAPPED, 0 }; + +static inline +rlim_t __vx_cres_array_sum(struct _vx_limit *limit, const int *array) +{ + rlim_t value, sum = 0; + int res; + + while ((res = *array++)) { + value = __rlim_get(limit, res); + __vx_cres_fixup(limit, res, value); + sum += value; + } + return sum; +} + +static inline +rlim_t __vx_cres_array_fixup(struct _vx_limit *limit, const int *array) +{ + rlim_t value = __vx_cres_array_sum(limit, array + 1); + int res = *array; + + if (value == __rlim_get(limit, res)) + return value; + + __rlim_set(limit, res, value); + /* now adjust min/max */ + if (!__vx_cres_adjust_max(limit, res, value)) + __vx_cres_adjust_min(limit, res, value); + + return value; +} + +static inline int __vx_cres_array_avail(struct vx_info *vxi, + const int *array, int num, char *_file, int _line) +{ + struct _vx_limit *limit; + rlim_t value = 0; + int res; + + if (num == 0) + return 1; + if (!vxi) + return 1; + + limit = &vxi->limit; + res = *array; + value = __vx_cres_array_sum(limit, array+1); + + __rlim_set(limit, res, value); + __vx_cres_fixup(limit, res, value); + + return __vx_cres_avail(vxi, res, num, _file, _line); +} + + +static inline void vx_limit_fixup(struct _vx_limit *limit, int id) +{ + rlim_t value; + int res; + + /* complex resources first */ + if ((id < 0) || (id == RLIMIT_RSS)) + __vx_cres_array_fixup(limit, VLA_RSS); + + for (res=0; res 0) && (res != id)) + continue; + + value = __rlim_get(limit, res); + __vx_cres_fixup(limit, res, value); + + /* not supposed to happen, maybe warn? */ + if (__rlim_rmax(limit, res) > __rlim_hard(limit, res)) + __rlim_rmax(limit, res) = __rlim_hard(limit, res); + } +} + + #endif /* __KERNEL__ */ -#endif /* _VX_LIMIT_H */ +#endif /* _VX_LIMIT_INT_H */