| /* |
| * Copyright (C) 2000-2009, Parallels, Inc. All rights reserved. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| |
| #include <stdio.h> |
| #include <limits.h> |
| #include <stdlib.h> |
| #include <ctype.h> |
| #include <string.h> |
| #include <errno.h> |
| |
| #include "ub.h" |
| #include "res.h" |
| #include "validate.h" |
| #include "vzctl_param.h" |
| #include "vzerror.h" |
| #include "logger.h" |
| #include "util.h" |
| |
| int page_size = -1; |
| |
| static int read_yn() |
| { |
| char buf[1024]; |
| |
| fprintf(stderr, " (y/n) [y] "); |
| while (fgets(buf, sizeof(buf), stdin) != NULL) { |
| if (buf[0] == 'y' || buf[0] == '\n') { |
| return 1; |
| } |
| else if (buf[0] == 'n') |
| return 0; |
| fprintf(stderr, " (y/n) [y] "); |
| } |
| return 0; |
| } |
| |
| static int check_param(struct ub_struct *param, int log) |
| { |
| int ret = 0; |
| #define CHECKPARAM(name) \ |
| if (param->name == NULL) { \ |
| if (log) \ |
| logger(-1, 0, "Error: parameter " #name \ |
| " not found"); \ |
| ret = 1; \ |
| } \ |
| |
| CHECKPARAM(numproc); |
| CHECKPARAM(numtcpsock); |
| CHECKPARAM(numothersock); |
| CHECKPARAM(oomguarpages) |
| CHECKPARAM(vmguarpages); |
| CHECKPARAM(kmemsize); |
| CHECKPARAM(tcpsndbuf); |
| CHECKPARAM(tcprcvbuf); |
| CHECKPARAM(othersockbuf); |
| CHECKPARAM(dgramrcvbuf); |
| CHECKPARAM(privvmpages); |
| CHECKPARAM(numfile); |
| CHECKPARAM(dcachesize); |
| CHECKPARAM(physpages) |
| CHECKPARAM(numpty) |
| |
| return ret; |
| } |
| |
| #define SET_MES(val) logger(0, 0, "set to %lu", (val)); |
| #define SET2_MES(val1, val2) logger(0, 0, "set to %lu:%lu", (val1), (val2)); |
| |
| /** Validate vswap config |
| * Current ideas are: |
| * 1. only check physpages and swappages |
| * 2. barrier should be zero for both |
| * 3. physpages.limit should not exceed host RAM |
| * 4. swappages.limit should not exceed host swap |
| */ |
| static int validate_vswap(vps_res *param, int recover, int ask) |
| { |
| struct ub_struct *ub = ¶m->ub; |
| int changed = 0; |
| int ret = 0; |
| unsigned long long tmp; |
| unsigned long ram, swap; |
| |
| #define CHECK_VSWAP(name, limit) \ |
| if (ub->name != NULL) { \ |
| if (ub->name[0] != 0) { \ |
| logger(-1, 0, "Error: " #name ".bar should be " \ |
| "= 0 (currently, %lu)", \ |
| ub->name[0]); \ |
| if (ask || recover) { \ |
| SET_MES((unsigned long) 0); \ |
| if (ask) \ |
| recover = read_yn(); \ |
| if (recover) { \ |
| ub->name[0] = 0; \ |
| changed++; \ |
| } \ |
| } \ |
| if (!recover) ret = 1; \ |
| } \ |
| if (ub->name[1] > (limit)) { \ |
| logger(-1, 0, "Warning: " #name ".lim should " \ |
| "be <= %lu (currently, %lu)", \ |
| (limit), ub->name[1]); \ |
| if (ask || recover) { \ |
| SET_MES((unsigned long int)(limit)); \ |
| if (ask) recover = read_yn(); \ |
| if (recover) { \ |
| ub->name[1] = (limit); \ |
| changed++; \ |
| } \ |
| } \ |
| if (!recover) ret = 1; \ |
| } \ |
| } else { \ |
| logger(-1, 0, "Error: parameter " #name " not found"); \ |
| ret = 1; \ |
| } |
| |
| if (get_mem(&tmp) < 0) |
| return -1; |
| ram = tmp / page_size; |
| |
| if (get_swap(&tmp) < 0) |
| return -1; |
| swap = tmp / page_size; |
| |
| CHECK_VSWAP(physpages, ram); |
| CHECK_VSWAP(swappages, swap); |
| |
| return ret; |
| } |
| |
| int validate(vps_res *param, int recover, int ask, int vswap) |
| { |
| unsigned long avnumproc; |
| int ret = 0; |
| unsigned long val, val1; |
| unsigned long tmp_val0, tmp_val1; |
| int changed = 0; |
| struct ub_struct *ub; |
| |
| if (vswap) |
| return validate_vswap(param, recover, ask); |
| |
| #define CHECK_BL(x, name) \ |
| if (x) { \ |
| if ((x)[0] > (x)[1]) { \ |
| logger(-1, 0, "Error: barrier should be <= limit for " \ |
| #name " (currently, %lu:%lu)", \ |
| (x)[0], (x)[1]); \ |
| if (ask || recover) { \ |
| tmp_val1 = (x)[0]; \ |
| tmp_val0 = (x)[0]; \ |
| SET2_MES(tmp_val0, tmp_val1) \ |
| if (ask) recover = read_yn(); \ |
| if (recover) { \ |
| (x)[1] = tmp_val1; \ |
| changed++; \ |
| } \ |
| } \ |
| if (!recover) ret = 1; \ |
| } \ |
| } else { \ |
| logger(-1, 0, "Error: parameter " #name " not found"); \ |
| ret = 1; \ |
| } |
| |
| #define CHECK_B(name) \ |
| if (ub->name != NULL) { \ |
| if ((ub->name[0] != ub->name[1])) { \ |
| logger(-1, 0, "Error: barrier should be equal to limit" \ |
| " for " #name " (currently, %lu:%lu)", \ |
| ub->name[0], ub->name[1]); \ |
| if (ask || recover) { \ |
| tmp_val0 = max_ul(ub->name[0], ub->name[1]); \ |
| tmp_val1 = tmp_val0; \ |
| SET2_MES(tmp_val0, tmp_val1) \ |
| if (ask) recover = read_yn(); \ |
| if (recover) { \ |
| ub->name[0] = tmp_val0; \ |
| ub->name[1] = tmp_val1; \ |
| changed++; \ |
| } \ |
| } \ |
| if (!recover) ret = 1; \ |
| } \ |
| } else { \ |
| logger(-1, 0, "Error: parameter " #name " not found"); \ |
| ret = 1; \ |
| } |
| |
| if (param == NULL) |
| return 1; |
| ub = ¶m->ub; |
| if (check_param(ub, 1)) |
| return 1; |
| if (ub->avnumproc != NULL) |
| avnumproc = ub->avnumproc[0]; |
| else |
| avnumproc = ub->numproc[0] / 2; |
| /* 1 Check barrier & limit */ |
| /* Primary */ |
| CHECK_B(numproc) |
| CHECK_B(numtcpsock) |
| CHECK_B(numothersock) |
| if (ub->vmguarpages != NULL) { |
| if (ub->vmguarpages[1] != LONG_MAX) { |
| logger(-1, 0, "Error: limit should be = %lu for" |
| " vmguarpages (currently, %lu)", LONG_MAX, |
| ub->vmguarpages[1]); |
| if (ask || recover) { |
| SET_MES((unsigned long) LONG_MAX); |
| if (ask) |
| recover = read_yn(); |
| if (recover) { |
| ub->vmguarpages[1] = LONG_MAX; |
| changed++; |
| } |
| } |
| if (!recover) ret = 1; |
| // if (!ask) fprintf(stderr, "\n"); |
| } |
| } else { |
| logger(-1, 0, "Error: parameter vmguarpages not found"); |
| ret = 1; |
| } |
| /* Secondary */ |
| CHECK_BL(ub->kmemsize, kmemsize) |
| CHECK_BL(ub->tcpsndbuf, tcpsndbuf) |
| CHECK_BL(ub->tcprcvbuf, tcprcvbuf) |
| CHECK_BL(ub->othersockbuf, othersockbuf) |
| CHECK_BL(ub->dgramrcvbuf, dgramrcvbuf) |
| if (ub->oomguarpages != NULL) { |
| if (ub->oomguarpages[1] != LONG_MAX) { |
| logger(-1, 0, "Error: limit should be = %lu for" |
| " oomguarpages (currently, %lu)", LONG_MAX, |
| ub->oomguarpages[1]); |
| if (ask || recover) { |
| SET_MES((unsigned long) LONG_MAX); |
| if (ask) |
| recover = read_yn(); |
| if (recover) { |
| ub->oomguarpages[1] = LONG_MAX; |
| changed++; |
| } |
| } |
| if (!recover) ret = 1; |
| // if (!ask) fprintf(stderr, "\n"); |
| } |
| } else { |
| logger(-1, 0, "Error: parameter oomguarpages not found"); |
| ret = 1; |
| } |
| CHECK_BL(ub->privvmpages, privvmpages) |
| /* Auxiliary */ |
| CHECK_BL(ub->lockedpages, lockedpages) |
| CHECK_B(shmpages) |
| if (ub->physpages != NULL) { |
| if (ub->physpages[0] != 0) { |
| logger(-1, 0, "Error: barrier should be = 0 for" |
| " physpages (currently, %lu)", |
| ub->physpages[0]); |
| if (ask || recover) { |
| SET_MES((unsigned long) 0); |
| if (ask) |
| recover = read_yn(); |
| if (recover) { |
| ub->physpages[0] = 0; |
| changed++; |
| } |
| } |
| if (!recover) ret = 1; |
| // if (!ask) fprintf(stderr, "\n"); |
| } |
| if (ub->physpages[1] != LONG_MAX) { |
| logger(-1, 0, "Error: limit should be = %lu for" |
| " physpages (currently, %lu)", LONG_MAX, |
| ub->physpages[1]); |
| if (ask || recover) { |
| SET_MES((unsigned long) LONG_MAX); |
| if (ask) |
| recover = read_yn(); |
| if (recover) { |
| ub->physpages[1] = LONG_MAX; |
| changed++; |
| } |
| } |
| if (!recover) ret = 1; |
| // if (!ask) fprintf(stderr, "\n"); |
| } |
| } else { |
| logger(-1, 0, "Error: parameter physpages not found"); |
| ret = 1; |
| } |
| CHECK_B(numfile) |
| CHECK_BL(ub->numflock, numflock) |
| CHECK_B(numpty) |
| CHECK_B(numsiginfo) |
| CHECK_BL(ub->dcachesize, dcachesize) |
| CHECK_B(numiptent) |
| if (param->dq.enable == YES) { |
| CHECK_BL(param->dq.diskspace, diskspace) |
| CHECK_BL(param->dq.diskinodes, diskinodes) |
| } |
| |
| /* 2 Check formulas */ |
| val = ub->numfile[0] * 384; |
| val &= LONG_MAX; |
| if (ub->dcachesize[1] < val) { |
| logger(-1, 0, "Warning: dcachesize.lim should be > %lu" |
| " (currently, %lu)", val, |
| ub->dcachesize[1]); |
| if (ask || recover) { |
| SET_MES(val); |
| if (ask) |
| recover = read_yn(); |
| if (recover) { |
| ub->dcachesize[1] = val; |
| changed++; |
| } |
| } |
| if (!recover) ret = 1; |
| // if (!ask) fprintf(stderr, "\n"); |
| } |
| |
| val = (40 * 1024 * avnumproc) + ub->dcachesize[1]; |
| val &= LONG_MAX; |
| if (ub->kmemsize[0] < val) { |
| logger(-1, 0, "Error: kmemsize.bar should be > %lu" |
| " (currently, %lu)", val, ub->kmemsize[0]); |
| if (ask || recover) { |
| tmp_val1 = ub->kmemsize[1] + val - ub->kmemsize[0]; |
| tmp_val0 = val; |
| SET2_MES(tmp_val0, tmp_val1); |
| if (ask) |
| recover = read_yn(); |
| if (recover) { |
| ub->kmemsize[1] = tmp_val1; |
| ub->kmemsize[0] = tmp_val0; |
| changed++; |
| } |
| } |
| if (!recover) ret = 1; |
| // if (!ask) fprintf(stderr, "\n"); |
| } |
| if (ub->privvmpages[0] < ub->vmguarpages[0]) { |
| logger(-1, 0, "Warning: privvmpages.bar should be > %lu" |
| " (currently, %lu)", ub->vmguarpages[0], |
| ub->privvmpages[0]); |
| if (ask || recover) { |
| tmp_val0 = ub->vmguarpages[0]; |
| tmp_val1 = ub->privvmpages[1] < tmp_val0 ? |
| tmp_val0 : ub->vmguarpages[1]; |
| SET_MES(tmp_val0); |
| if (ask) |
| recover = read_yn(); |
| if (recover) { |
| ub->privvmpages[0] = tmp_val0; |
| ub->privvmpages[1] = tmp_val1; |
| changed++; |
| } |
| } |
| if (!recover) ret = 1; |
| // if (!ask) fprintf(stderr, "\n"); |
| } |
| val = 2.5 * 1024 * ub->numtcpsock[0]; |
| val &= LONG_MAX; |
| if (ub->tcpsndbuf[1] - ub->tcpsndbuf[0] < val) { |
| logger(-1, 0, "Error: tcpsndbuf.lim-tcpsndbuf.bar" |
| " should be > %lu (currently, %lu-%lu=%lu)", |
| val, ub->tcpsndbuf[1], ub->tcpsndbuf[0], |
| ub->tcpsndbuf[1]-ub->tcpsndbuf[0]); |
| if (ask || recover) { |
| tmp_val1 = ub->tcpsndbuf[0] + val; |
| tmp_val0 = ub->tcpsndbuf[0]; |
| SET2_MES(tmp_val0, tmp_val1); |
| if (ask) |
| recover = read_yn(); |
| if (recover) { |
| ub->tcpsndbuf[1] = tmp_val1; |
| changed++; |
| } |
| } |
| if (!recover) ret = 1; |
| // if (!ask) fprintf(stderr, "\n"); |
| } |
| val = 2.5 * 1024 * ub->numothersock[0]; |
| val &= LONG_MAX; |
| if (ub->othersockbuf[1] - ub->othersockbuf[0] < val) { |
| logger(-1, 0, "Error: othersockbuf.lim-othersockbuf.bar" |
| " should be > %lu (currently, %lu-%lu=%lu)", |
| val, ub->othersockbuf[1], ub->othersockbuf[0], |
| ub->othersockbuf[1]-ub->othersockbuf[0]); |
| if (ask || recover) { |
| tmp_val1 = ub->othersockbuf[0] + val; |
| tmp_val0 = ub->othersockbuf[0]; |
| SET2_MES(tmp_val0, tmp_val1) |
| if (ask) |
| recover = read_yn(); |
| if (recover) { |
| ub->othersockbuf[1] = tmp_val1; |
| changed++; |
| } |
| } |
| if (!recover) ret = 1; |
| // if (!ask) fprintf(stderr, "\n"); |
| } |
| val = 2.5 * 1024 * ub->numtcpsock[0]; |
| val &= LONG_MAX; |
| if (ub->tcprcvbuf[1] - ub->tcprcvbuf[0] < val) { |
| logger(-1, 0, "Warning: tcprcvbuf.lim-tcprcvbuf.bar" |
| " should be > %lu (currently, %lu-%lu=%lu)", |
| val, ub->tcprcvbuf[1], ub->tcprcvbuf[0], |
| ub->tcprcvbuf[1] - ub->tcprcvbuf[0]); |
| if (ask || recover) { |
| tmp_val1 = ub->tcprcvbuf[0] + val; |
| tmp_val0 = ub->tcprcvbuf[0]; |
| SET2_MES(tmp_val0, tmp_val1) |
| if (ask) |
| recover = read_yn(); |
| if (recover) { |
| ub->tcprcvbuf[1] = tmp_val1; |
| changed++; |
| } |
| } |
| if (!recover) ret = 1; |
| // if (!ask) fprintf(stderr, "\n"); |
| } |
| val = 64 * 1024; |
| if (ub->tcprcvbuf[0] < val) { |
| logger(-1, 0, "Warning: tcprcvbuf.bar should be > %lu" |
| " (currently, %lu)", val, |
| ub->tcprcvbuf[0]); |
| if (ask || recover) { |
| tmp_val1 = ub->tcprcvbuf[1]+val-ub->tcprcvbuf[0]; |
| tmp_val0 = val; |
| SET2_MES(tmp_val0, tmp_val1) |
| if (ask) |
| recover = read_yn(); |
| if (recover) { |
| ub->tcprcvbuf[1] = tmp_val1; |
| ub->tcprcvbuf[0] = tmp_val0; |
| changed++; |
| } |
| } |
| if (!recover) ret = 1; |
| // if (!ask) fprintf(stderr, "\n"); |
| } |
| val = 64 * 1024; |
| if (ub->tcpsndbuf[0] < val) { |
| logger(-1, 0, "Warning: tcpsndbuf.bar should be > %lu" |
| " (currently, %lu)", val, |
| ub->tcpsndbuf[0]); |
| if (ask || recover) { |
| tmp_val1 = ub->tcpsndbuf[1]+val-ub->tcpsndbuf[0]; |
| tmp_val0 = val; |
| SET2_MES(tmp_val0, tmp_val1) |
| if (ask) |
| recover = read_yn(); |
| if (recover) { |
| ub->tcpsndbuf[1] = tmp_val1; |
| ub->tcpsndbuf[0] = tmp_val0; |
| changed++; |
| } |
| } |
| if (!recover) ret = 1; |
| // if (!ask) fprintf(stderr, "\n"); |
| } |
| val = 32 * 1024; |
| val1 = 129 * 1024; |
| if (ub->dgramrcvbuf[0] < val) { |
| logger(-1, 0, "Warning: dgramrcvbuf.bar should be >" |
| " %lu (currently, %lu)", val, |
| ub->dgramrcvbuf[0]); |
| if (ask || recover) { |
| tmp_val1 = ub->dgramrcvbuf[1] + val - |
| ub->dgramrcvbuf[0]; |
| tmp_val0 = val; |
| SET2_MES(tmp_val0, tmp_val1) |
| if (ask) |
| recover = read_yn(); |
| if (recover) { |
| ub->dgramrcvbuf[1] = tmp_val1; |
| ub->dgramrcvbuf[0] = tmp_val0; |
| changed++; |
| } |
| } |
| if (!recover) ret = 1; |
| // if (!ask) fprintf(stderr, "\n"); |
| } else if (ub->dgramrcvbuf[0] < val1) { |
| logger(-1, 0, "Recommendation: dgramrcvbuf.bar should be >" |
| " %lu (currently, %lu)", val1, |
| ub->dgramrcvbuf[0]); |
| if (ask || recover) { |
| tmp_val1 = ub->dgramrcvbuf[1] + val1 - |
| ub->dgramrcvbuf[0]; |
| tmp_val0 = val1; |
| SET2_MES(tmp_val0, tmp_val1) |
| if (ask) |
| recover = read_yn(); |
| if (recover) { |
| ub->dgramrcvbuf[1] = tmp_val1; |
| ub->dgramrcvbuf[0] = tmp_val0; |
| changed++; |
| } |
| } |
| // if (!ask) fprintf(stderr, "\n"); |
| } |
| val = 32 * 1024; |
| val1 = 129 * 1024; |
| if (ub->othersockbuf[0] < val) { |
| logger(-1, 0, "Warning: othersockbuf.bar should be >" |
| " %lu (currently, %lu)", val, |
| ub->othersockbuf[0]); |
| if (ask || recover) { |
| tmp_val1 = ub->othersockbuf[1] + val - |
| ub->othersockbuf[0]; |
| tmp_val0 = val; |
| SET2_MES(tmp_val0, tmp_val1) |
| if (ask) |
| recover = read_yn(); |
| if (recover) { |
| ub->othersockbuf[1] = tmp_val1; |
| ub->othersockbuf[0] = tmp_val0; |
| changed++; |
| } |
| } |
| if (!recover) ret = 1; |
| // if (!ask) fprintf(stderr, "\n"); |
| } else if (ub->othersockbuf[0] < val1) { |
| logger(-1, 0, "Recommendation: othersockbuf.bar should be >" |
| " %lu (currently, %lu)", val1, |
| ub->othersockbuf[0]); |
| if (ask || recover) { |
| tmp_val1 = ub->othersockbuf[1] + val1 - |
| ub->othersockbuf[0]; |
| tmp_val0 = val1; |
| SET2_MES(tmp_val0, tmp_val1) |
| if (ask) |
| recover = read_yn(); |
| if (recover) { |
| ub->othersockbuf[1] = tmp_val1; |
| ub->othersockbuf[0] = tmp_val0; |
| changed++; |
| } |
| } |
| // if (!ask) fprintf(stderr, "\n"); |
| } |
| val = avnumproc * 32; |
| val1 = ub->numtcpsock[0] + ub->numothersock[0] + ub->numpty[0]; |
| if (val1 > val) |
| val = val1; |
| val &= LONG_MAX; |
| if (ub->numfile[0] < val) { |
| logger(-1, 0, "Warning: numfile should be > %lu" |
| " (currently, %lu)", val, ub->numfile[0]); |
| if (ask || recover) { |
| tmp_val1 = ub->numfile[1] + val - ub->numfile[0]; |
| tmp_val0 = val; |
| SET2_MES(tmp_val0, tmp_val1) |
| if (ask) |
| recover = read_yn(); |
| if (recover) { |
| ub->numfile[1] = tmp_val1; |
| ub->numfile[0] = tmp_val0; |
| changed++; |
| } |
| } |
| if (!recover) ret = 1; |
| // if (!ask) fprintf(stderr, "\n"); |
| } |
| |
| return ret; |
| } |
| |
| int calc_ve_utilization(struct ub_struct *param, struct CRusage *rusage, |
| struct mem_struct *mem, int numerator) |
| { |
| double kmem_net; |
| |
| memset(rusage, 0, sizeof(struct CRusage)); |
| if (param == NULL) |
| return -1; |
| if (check_param(param, 1)) |
| return -1; |
| kmem_net = (double)param->kmemsize[0] + |
| (double)param->tcprcvbuf[0] + |
| (double)param->tcpsndbuf[0] + |
| (double)param->dgramrcvbuf[0] + |
| (double)param->othersockbuf[0]; |
| /* Low memory */ |
| rusage->low_mem = kmem_net; |
| if (!numerator) |
| rusage->low_mem /= mem->lowmem; |
| /* Total RAM */ |
| rusage->total_ram = ((double)param->physpages[0] * page_size + |
| kmem_net); |
| if (!numerator) |
| rusage->total_ram /= mem->ram; |
| /* Mem + Swap */ |
| rusage->mem_swap = ((double)param->oomguarpages[0] * page_size + |
| kmem_net); |
| if (!numerator) |
| rusage->mem_swap /= (mem->ram + mem->swap); |
| /* Allocated memory */ |
| rusage->alloc_mem = ((double)param->privvmpages[0] * page_size + |
| kmem_net); |
| if (!numerator) |
| rusage->alloc_mem /= (mem->ram + mem->swap); |
| |
| return 0; |
| } |
| |
| int calc_ve_commitment(struct ub_struct *param, struct CRusage *rusage, |
| struct mem_struct *mem, int numerator) |
| { |
| double kmem_net; |
| |
| memset(rusage, 0, sizeof(struct CRusage)); |
| if (param == NULL) |
| return -1; |
| if (check_param(param, 1)) |
| return -1; |
| kmem_net = (double)param->kmemsize[1] + |
| (double)param->tcprcvbuf[1] + |
| (double)param->tcpsndbuf[1] + |
| (double)param->dgramrcvbuf[1] + |
| (double)param->othersockbuf[1]; |
| /* Low memory */ |
| rusage->low_mem = kmem_net; |
| if (!numerator) |
| rusage->low_mem /= mem->lowmem; |
| /* Total RAM */ |
| rusage->total_ram = ((double)param->physpages[0] * page_size + |
| kmem_net); |
| if (!numerator) |
| rusage->total_ram /= mem->ram; |
| /* Mem + Swap */ |
| rusage->mem_swap = ((double)param->oomguarpages[0] * page_size + |
| kmem_net); |
| if (!numerator) |
| rusage->mem_swap /= (mem->ram + mem->swap); |
| /* Allocated memory */ |
| rusage->alloc_mem = ((double)param->vmguarpages[0] * page_size + |
| kmem_net); |
| if (!numerator) |
| rusage->alloc_mem /= (mem->ram + mem->swap); |
| /* Allocated memory limit */ |
| rusage->alloc_mem_lim = ((double)param->privvmpages[1] * page_size + |
| kmem_net); |
| if (!numerator) |
| rusage->alloc_mem_lim /= (mem->ram + mem->swap); |
| /* Max Allocated memory limit */ |
| rusage->alloc_mem_max_lim = ((double)param->privvmpages[1] * page_size + |
| kmem_net); |
| if (!numerator) |
| rusage->alloc_mem_max_lim /= mem->ram; |
| return 0; |
| } |