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>