#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<NUM_LIMITS; res++) {
+ if ((id > 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 */
+/* interface version */
+
+#define VCI_VERSION 0x00020200
+#define VCI_LEGACY_VERSION 0x000100FF
+
+
enum {
+ VCI_KCBIT_NO_DYNAMIC = 0,
VCI_KCBIT_LEGACY = 1,
- VCI_KCBIT_LEGACYNET,
- VCI_KCBIT_NGNET,
+ VCI_KCBIT_LEGACYNET = 2,
+ VCI_KCBIT_NGNET = 3,
- VCI_KCBIT_PROC_SECURE,
- VCI_KCBIT_HARDCPU,
- VCI_KCBIT_HARDCPU_IDLE,
+ VCI_KCBIT_PROC_SECURE = 4,
+ VCI_KCBIT_HARDCPU = 5,
+ VCI_KCBIT_IDLELIMIT = 6,
+ VCI_KCBIT_IDLETIME = 7,
- VCI_KCBIT_LEGACY_VERSION = 15,
+ VCI_KCBIT_COWBL = 8,
+ VCI_KCBIT_FULLCOWBL = 9,
+ VCI_KCBIT_SPACES = 10,
+ VCI_KCBIT_LEGACY_VERSION = 15,
VCI_KCBIT_DEBUG = 16,
VCI_KCBIT_HISTORY = 20,
- VCI_KCBIT_TAGXID = 24,
+ VCI_KCBIT_TAGGED = 24,
};
{
return
/* various legacy options */
+#ifndef CONFIG_VSERVER_DYNAMIC_IDS
+ (1 << VCI_KCBIT_NO_DYNAMIC) |
+#endif
#ifdef CONFIG_VSERVER_LEGACY
(1 << VCI_KCBIT_LEGACY) |
#endif
#ifdef CONFIG_VSERVER_HARDCPU
(1 << VCI_KCBIT_HARDCPU) |
#endif
-#ifdef CONFIG_VSERVER_HARDCPU_IDLE
- (1 << VCI_KCBIT_HARDCPU_IDLE) |
+#ifdef CONFIG_VSERVER_IDLELIMIT
+ (1 << VCI_KCBIT_IDLELIMIT) |
+#endif
+#ifdef CONFIG_VSERVER_IDLETIME
+ (1 << VCI_KCBIT_IDLETIME) |
+#endif
+#ifdef CONFIG_VSERVER_COWBL
+ (1 << VCI_KCBIT_COWBL) |
+ (1 << VCI_KCBIT_FULLCOWBL) |
#endif
+ (1 << VCI_KCBIT_SPACES) |
/* debug options */
#ifdef CONFIG_VSERVER_DEBUG
(1 << VCI_KCBIT_HISTORY) |
#endif
- /* inode xid tagging */
-#if defined(CONFIG_INOXID_NONE)
- (0 << VCI_KCBIT_TAGXID) |
-#elif defined(CONFIG_INOXID_UID16)
- (1 << VCI_KCBIT_TAGXID) |
-#elif defined(CONFIG_INOXID_GID16)
- (2 << VCI_KCBIT_TAGXID) |
-#elif defined(CONFIG_INOXID_UGID24)
- (3 << VCI_KCBIT_TAGXID) |
-#elif defined(CONFIG_INOXID_INTERN)
- (4 << VCI_KCBIT_TAGXID) |
-#elif defined(CONFIG_INOXID_RUNTIME)
- (5 << VCI_KCBIT_TAGXID) |
+ /* inode context tagging */
+#if defined(CONFIG_TAGGING_NONE)
+ (0 << VCI_KCBIT_TAGGED) |
+#elif defined(CONFIG_TAGGING_UID16)
+ (1 << VCI_KCBIT_TAGGED) |
+#elif defined(CONFIG_TAGGING_GID16)
+ (2 << VCI_KCBIT_TAGGED) |
+#elif defined(CONFIG_TAGGING_ID24)
+ (3 << VCI_KCBIT_TAGGED) |
+#elif defined(CONFIG_TAGGING_INTERN)
+ (4 << VCI_KCBIT_TAGGED) |
+#elif defined(CONFIG_TAGGING_RUNTIME)
+ (5 << VCI_KCBIT_TAGGED) |
#else
- (7 << VCI_KCBIT_TAGXID) |
+ (7 << VCI_KCBIT_TAGGED) |
#endif
0;
}