In message <pine.bsf.4.10.9907151329040.9501-100...@merlin.th.physik.uni-bonn.d
e>, Jan Conrad writes:
>after wondering for two years why FreeBSD (2.2.x ... 3.2) might lock up
>when an NFS server is down, I think I have found one reason for that (see
>kern/12609 - I now know it doesn't belong to kern - sorry).
>
>It is the implementation of getcwd (src/lib/libc/gen/getcwd.c). When
>examining the parent dir of a mounted filesystem, getcwd lstats every
>directory entry prior to the mountpoint to find out the name of the
>mountpoint (but it would only need the inodes's device to do a rough 
>check....).

This should no longer be an issue with FreeBSD 3.x, as the system normally
uses the new _getcwd syscall. The old code is still in getcwd.c, but is
only used if the syscall isn't present (e.g. if running a 3.x executable
on a 2.2 system).

We use the following patch on all our 2.2-stable machines, which works
around the problem. This was submitted as PR bin/6658, but it wasn't
committed, as a backport of 3.x's _getcwd (which never occurred) was
considered to be a more appropriate change.

Ian

--- getcwd.c.orig       Tue Jun 30 15:38:44 1998
+++ getcwd.c    Tue Jun 30 15:39:08 1998
@@ -36,6 +36,7 @@
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/param.h>
+#include <sys/mount.h>
 #include <sys/stat.h>
 
 #include <errno.h>
@@ -169,7 +170,28 @@
                                if (dp->d_fileno == ino)
                                        break;
                        }
-               } else
+               } else {
+                       struct statfs sfs;
+                       char *dirname;
+
+                       /*
+                        * Try to get the directory name by using statfs on
+                        * the mount point. 
+                        */
+                       if (!statfs(up[3] ? up + 3 : ".", &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,7 +209,9 @@
                                if (s.st_dev == dev && s.st_ino == ino)
                                        break;
                        }
+               }
 
+found:
                /*
                 * Check for length of the current name, preceding slash,
                 * leading slash.


To Unsubscribe: send mail to majord...@freebsd.org
with "unsubscribe freebsd-hackers" in the body of the message

Reply via email to