*** kvm_read.c.orig Fri Jun 4 15:45:13 1999 --- kvm_read.c Fri Jun 4 15:49:13 1999 *************** *** 0 **** --- 1,194 ---- + /* + * This file obtains memory usage via FreeBSD's kvm library. + * It is a modified version of read_mem.c which is + * Copyright (c) 1999 Albert Dorofeev + * use this in place of that file for FreeBSD systems. + * + * This software is distributed under GPL. For details see LICENSE file. + */ + + + #include + #include + #include + #include + #include + + #include "state.h" + + #include + #include + #include + #include + #include + #include + #include + #include + #include + + extern struct asmem_state state; + + kvm_t *kd; + + #define SVAR(var) __STRING(var) /* to force expansion */ + #define KGET(idx, var) \ + KGET1(idx, &var, sizeof(var), SVAR(var)) + #define KGET1(idx, p, s, msg) \ + KGET2(nl[idx].n_value, p, s, msg) + #define KGET2(addr, p, s, msg) \ + if (kvm_read(kd, (u_long)(addr), p, s) != s) \ + warnx("cannot read %s: %s", msg, kvm_geterr(kd)) + + struct nlist nl[] = { + #define VM_SWAPLIST 0 + { "_swaplist" },/* list of free swap areas */ + #define VM_SWDEVT 1 + { "_swdevt" }, /* list of swap devices and sizes */ + #define VM_NSWAP 2 + { "_nswap" }, /* size of largest swap device */ + #define VM_NSWDEV 3 + { "_nswdev" }, /* number of swap devices */ + #define VM_DMMAX 4 + { "_dmmax" }, /* maximum size of a swap block */ + #define X_CNT 5 + { "_cnt" }, + #define X_BUFSPACE 6 + { "_bufspace" }, /* K in buffer cache */ + { "" } + }; + + int close_meminfo() + { + kvm_close(kd); + return 0; + } + + int read_meminfo() + { + + int nswap, nswdev, dmmax; + int i, avail, nfree, used, bufspace = 0; + struct swdevt *sw; + struct vmmeter sum; + long *perdev; + struct rlist head; + struct rlisthdr swaplist; + struct rlist *swapptr; + u_long ptr; + + KGET(VM_NSWAP, nswap); + KGET(VM_NSWDEV, nswdev); + KGET(VM_DMMAX, dmmax); + KGET1(VM_SWAPLIST, &swaplist, sizeof swaplist, "swaplist"); + if ((sw = (struct swdevt*)malloc(nswdev * sizeof(*sw))) == NULL || + (perdev = (long *)malloc(nswdev * sizeof(*perdev))) == NULL) + errx(1, "malloc"); + KGET1(VM_SWDEVT, &ptr, sizeof ptr, "swdevt"); + KGET2(ptr, sw, nswdev * sizeof(*sw), "*swdevt"); + + /* Count up swap space. */ + nfree = 0; + memset(perdev, 0, nswdev * sizeof(*perdev)); + swapptr = swaplist.rlh_list; + while (swapptr) { + int top, bottom, next_block; + + KGET2(swapptr, &head, sizeof(struct rlist), "swapptr"); + + top = head.rl_end; + bottom = head.rl_start; + + nfree += top - bottom + 1; + + /* + * Swap space is split up among the configured disks. + * + * For interleaved swap devices, the first dmmax blocks + * of swap space some from the first disk, the next dmmax + * blocks from the next, and so on up to nswap blocks. + * + * The list of free space joins adjacent free blocks, + * ignoring device boundries. If we want to keep track + * of this information per device, we'll just have to + * extract it ourselves. + */ + while (top / dmmax != bottom / dmmax) { + next_block = ((bottom + dmmax) / dmmax); + perdev[(bottom / dmmax) % nswdev] += + next_block * dmmax - bottom; + bottom = next_block * dmmax; + } + perdev[(bottom / dmmax) % nswdev] += + top - bottom + 1; + + swapptr = head.rl_next; + } + + avail = 0; + for (i = 0; i < nswdev; i++) { + int xsize, xfree; + + /* + * Don't report statistics for partitions which have not + * yet been activated via swapon(8). + */ + if (!(sw[i].sw_flags & SW_FREED)) + continue; + + /* The first dmmax is never allocated to avoid trashing of + * disklabels + */ + xsize = sw[i].sw_nblks - dmmax; + xfree = perdev[i]; + used = xsize - xfree; + avail += xsize; + } + + /* + * If only one partition has been set up via swapon(8), we don't + * need to bother with totals. + */ + used = avail - nfree; + free(sw); + free(perdev); + + state.fresh.swap_total = avail * 512; + state.fresh.swap_used = used * 512; + state.fresh.swap_free = (avail - used) * 512; + + KGET(X_CNT, sum); + KGET(X_BUFSPACE, bufspace); + + state.fresh.total = sum.v_page_size * sum.v_page_count; + state.fresh.used = sum.v_page_size * (sum.v_page_count - sum.v_free_count); + state.fresh.free = sum.v_page_size * sum.v_free_count; + state.fresh.shared = 0; + state.fresh.cached = sum.v_page_size * sum.v_cache_count; + + state.fresh.buffers = bufspace; + return(0); + + } + + int open_meminfo() + { + + if (kd == 0) { + kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, 0); + if (kd != NULL) { + if (kvm_nlist(kd, nl) < 0) { + errx(1, "kvm_nlist: %s", kvm_geterr(kd)); + } + + if (nl[0].n_type == 0) { + errx(1, "no namelist"); + } + } else { + warnx("kvm not available"); + return(-1); + } + } + return(0); + } + +