Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 17 May 98 03:38:48 +0100 (BST)
From:      iedowse@maths.tcd.ie
To:        FreeBSD-gnats-submit@FreeBSD.ORG
Subject:   bin/6658: -stable getcwd(3) performs unnecessary lstats
Message-ID:  <9805170338.aa14317@walton.maths.tcd.ie>

next in thread | raw e-mail | index | archive | help

>Number:         6658
>Category:       bin
>Synopsis:       -stable getcwd(3) performs unnecessary lstats
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:
>Keywords:
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sat May 16 19:40:03 PDT 1998
>Last-Modified:
>Originator:     Ian Dowse
>Organization:
	School of Mathematics,
	Trinity College Dublin
>Release:        FreeBSD 2.2.6-STABLE i386
>Environment:

	FreeBSD 2.2.6-STABLE

>Description:
	
	getcwd(3) in -stable does a lot of lstat'ing every time it crosses
	a mount point. This can really slow down its operation if it has
	to lstat nfs disks or slow devices. The usual suggested workaround
	of putting all 'slow' filesystems in separate directories is not
	ideal.

	The path component that getcwd does all these lstats to find can
	virtually always be obtained using statfs(2) at a much lower cost.
	The patch below makes getcwd first try statfs, and then resort to
	the old method if this fails (I'm not convinced that statfs will
	get the correct answer in absolutely every situation).

	This PR can of course be ignored if a getcwd syscall is likely to
	appear soon in -stable.

>How-To-Repeat:

	Run sh with cwd in filesystem /f1 while nfs filesystem /f2 is not
	responding.

>Fix:
	
*** /usr/src/lib/libc/gen/getcwd.c	Thu Mar 26 09:22:48 1998
--- getcwd.c	Sun May 17 03:30:24 1998
***************
*** 36,41 ****
--- 36,42 ----
  #endif /* LIBC_SCCS and not lint */
  
  #include <sys/param.h>
+ #include <sys/mount.h>
  #include <sys/stat.h>
  
  #include <errno.h>
***************
*** 169,175 ****
  				if (dp->d_fileno == ino)
  					break;
  			}
! 		} else
  			for (;;) {
  				if (!(dp = readdir(dir)))
  					goto notfound;
--- 170,193 ----
  				if (dp->d_fileno == ino)
  					break;
  			}
! 		} else {
! 			struct statfs sfs;
! 			char *dirname;
! 
! 			if (!statfs(".", &sfs) &&
! 			    (dirname = rindex(sfs.f_mntonname, '/'))) 
! 				while((dp = readdir(dir))) {
! 					if (ISDOT(dp))
! 						continue;
! 					bcopy(dp->d_name, bup, dp->d_namlen+1);
! 					if (!strcmp(dirname + 1, dp->d_name) &&
! 					    !lstat(up, &s) &&
! 					    s.st_dev == dev &&
! 					    s.st_ino == ino)
! 						goto found;
! 				}
! 			rewinddir(dir);
! 
  			for (;;) {
  				if (!(dp = readdir(dir)))
  					goto notfound;
***************
*** 187,193 ****
--- 205,213 ----
  				if (s.st_dev == dev && s.st_ino == ino)
  					break;
  			}
+ 		}
  
+ found:
  		/*
  		 * Check for length of the current name, preceding slash,
  		 * leading slash.
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?9805170338.aa14317>