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>
