Date: Tue, 2 Dec 1997 16:49:37 -0800 (PST) From: dillon@best.net To: FreeBSD-gnats-submit@FreeBSD.ORG Subject: bin/5196: ps forces procs out of W state (w/patch) + quick & dirty /proc kernel crash workaround Message-ID: <199712030049.QAA14609@flea.best.net> Resent-Message-ID: <199712030100.RAA21458@hub.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 5196 >Category: bin >Synopsis: ps forces all IW'd processes into Is due to u-area read >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue Dec 2 17:00:01 PST 1997 >Last-Modified: >Originator: Matt Dillon >Organization: Best Internet Communications >Release: FreeBSD 2.2.5-STABLE i386 >Environment: FreeBSD 2.2.5-STABLE >Description: In large systems, processes never stay swapped out because some dummy runs ps every minute or two. ps reads the process u-area for argv and environment. This results in a small, but significant overhead (page directory, page tables, u-area pages) that can eat upwards of 20MBytes. The fix I include below does not attempt to access the u-area for processes that are not P_INMEM. I also add the -f flag (root only) to override the default behavior and read the u-area anyway. The patch below also contains a quick and dirty fix to serialize ps and thus avoid kernel crash conditions that can occur when /proc is accessed from multiple processes simultaniously. If you do not want to include this patch, please remove it... but at least include the u-area fix!! it saves 20MB on our more heavily loaded shell machines. >How-To-Repeat: set vm.v_free_target high to force swapping, then run ps axl. You should see bunches of 'IW' processes. Run it again... they've all reverted to 'Is'. >Fix: *** LINK/ps.c Fri Jun 6 09:09:12 1997 --- ps.c Tue Dec 2 16:37:18 1997 *************** *** 83,88 **** --- 83,89 ---- int totwidth; /* calculated width of requested variables */ static int needuser, needcomm, needenv; + static int forceuread; enum sort { DEFAULT, SORTMEM, SORTCPU } sortby = DEFAULT; *************** *** 103,108 **** --- 104,112 ---- char vfmt[] = "pid state time sl re pagein vsz rss lim tsiz %cpu %mem command"; kvm_t *kd; + int ps_kmem_lock_fd = -1; + void ps_kmem_lock(void); + void ps_kmem_unlock(void); int main(argc, argv) *************** *** 191,196 **** --- 195,204 ---- parsefmt(optarg); fmt = 1; break; + case 'f': + if (getuid() == 0) + forceuread = 1; + break; case 'p': pid = atol(optarg); xflg = 1; *************** *** 320,330 **** --- 328,340 ---- errx(1, "%s", kvm_geterr(kd)); if ((kinfo = malloc(nentries * sizeof(*kinfo))) == NULL) err(1, NULL); + ps_kmem_lock(); for (i = nentries; --i >= 0; ++kp) { kinfo[i].ki_p = kp; if (needuser) saveuser(&kinfo[i]); } + ps_kmem_unlock(); /* * print header */ *************** *** 393,398 **** --- 403,410 ---- return (s); } + #define UREADOK(ki) (forceuread || (KI_PROC(ki)->p_flag & P_INMEM)) + static void saveuser(ki) KINFO *ki; *************** *** 402,408 **** struct user *u_addr = (struct user *)USRSTACK; usp = &ki->ki_u; ! if (kvm_uread(kd, KI_PROC(ki), (unsigned long)&u_addr->u_stats, (char *)&pstats, sizeof(pstats)) == sizeof(pstats)) { /* * The u-area might be swapped out, and we can't get --- 414,420 ---- struct user *u_addr = (struct user *)USRSTACK; usp = &ki->ki_u; ! if (UREADOK(ki) && kvm_uread(kd, KI_PROC(ki), (unsigned long)&u_addr->u_stats, (char *)&pstats, sizeof(pstats)) == sizeof(pstats)) { /* * The u-area might be swapped out, and we can't get *************** *** 419,433 **** /* * save arguments if needed */ ! if (needcomm) ! ki->ki_args = fmt(kvm_getargv, ki, KI_PROC(ki)->p_comm, ! MAXCOMLEN); ! else ! ki->ki_args = NULL; ! if (needenv) ! ki->ki_env = fmt(kvm_getenvv, ki, (char *)NULL, 0); ! else ! ki->ki_env = NULL; } static int --- 431,458 ---- /* * save arguments if needed */ ! if (ps_kmem_lock_fd >= 0) { ! if (needcomm && UREADOK(ki)) { ! ki->ki_args = fmt(kvm_getargv, ki, KI_PROC(ki)->p_comm, ! MAXCOMLEN); ! } else if (needcomm) { ! ki->ki_args = malloc(strlen(KI_PROC(ki)->p_comm) + 3); ! sprintf(ki->ki_args, "(%s)", KI_PROC(ki)->p_comm); ! } else { ! ki->ki_args = NULL; ! } ! if (needenv && UREADOK(ki)) { ! ki->ki_env = fmt(kvm_getenvv, ki, (char *)NULL, 0); ! } else if (needenv) { ! ki->ki_env = malloc(3); ! strcpy(ki->ki_env, "()"); ! } else { ! ki->ki_env = NULL; ! } ! } else { ! ki->ki_args = KI_PROC(ki)->p_comm; ! ki->ki_env = NULL; ! } } static int *************** *** 523,525 **** --- 548,569 ---- " ps [-L]"); exit(1); } + + void + ps_kmem_lock(void) + { + if ((ps_kmem_lock_fd = open("/etc/ps_kmem_lock", O_RDWR)) >= 0) + flock(ps_kmem_lock_fd, LOCK_EX); + } + + void + ps_kmem_unlock(void) + { + if (ps_kmem_lock_fd >= 0) { + flock(ps_kmem_lock_fd, LOCK_UN); + close(ps_kmem_lock_fd); + ps_kmem_lock_fd = -1; + } + } + + >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199712030049.QAA14609>