Skip site navigation (1)Skip section navigation (2)
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>