+
+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);
+ }
+}
+
+