nmh-workers
[Top] [All Lists]

yet another st_nlink optimization for folder(1)

1996-05-03 17:35:13
Occasionally somebody sends in a patch which gives folder the
optimization of assuming that the number of subdirectories in each
directory is exactly st_nlink - 2.  I've finally installed 6.8.4 and
while I was at it I've put together this patch which I believes provides
the st_nlink optimization in a way which is more complete than usual
(basically, it's documented and configurable).

I've heard that under AFS the st_nlink of a directory isn't always 2
more than the number of subdirectories.  Does anybody know what it
actually is?  (Is it always constant, or is it the number of
subdirectories - some other number?)  Does anybody know how some common
NFS implementations for non-Unix operating systems handle st_nlink for
directories?  I'd like to make the docs a little more clear on these
points, but I'm out of my experience.

-Roderick

Index: conf/doc/folder.rf
Prereq:  1.15
*** conf/doc/folder.rf  Tue Nov 30 23:00:16 1993
--- ../mh/conf/doc/folder.rf    Fri May  3 19:05:26 1996
***************
*** 207,210 ****
--- 207,224 ----
  There is no way to restore the default behavior
  (to ask the user whether to create a non-existant folder)
  after `\-create' or `\-nocreate' is given.
+ @BEGIN: NLINK_HACK
+ .sp
+ \fIMH\fR assumes that directories to which there are at least 2 links
+ have exactly st_nlink\-2 subdirectories.  This greatly speeds up the
+ normal case, but it causes \fIfolder\fR to become confused by folders
+ whose only subfolders are symbolic links to directories rather than
+ directories themselves (it won't see the subfolders).  If you have a
+ folder like that you can get more correct behavior from \fIfolder\fR by
+ creating a dummy folder inside it (`folder @.dummy', eg), though this
+ is distasteful in that you'll see the .dummy subfolder listed along with
+ your normal folders.  If this bothers you too much you'll have to
+ recompile \fIMH\fR without the NLINK_HACK option set and take the speed
+ penalty.
+ @END: NLINK_HACK
  .En
Index: conf/mh-gen.8
Prereq:  2.119
*** conf/mh-gen.8       Wed May  1 12:17:31 1996
--- ../mh/conf/mh-gen.8 Fri May  3 18:52:39 1996
***************
*** 749,754 ****
--- 762,788 ----
  option and get an undefined symbol \*(lq\(ru\^\(ruruserpass\*(rq
  when compiling, then you should omit this option.
  (See also `NORUSERPASS'.)
+
+ .ti -.5i
+ NLINK_HACK
+ .br
+ This is a (rather dramatic under certain circumstances) speed hack.  If
+ this is set then an optimization is used when scanning for folders
+ recursively:  For any directory which has at least 2 links it's assumed
+ that the number of subdirectories is st_nlink - 2.  This is true for
+ most Unix file systems, but isn't true for AFS file systems and might not
+ be true for file systems remotely mounted from non-Unix systems.  If the
+ st_nlink value returned by these systems is 0 or 1 all will be well (I
+ don't know if this is the case or not), but if it's at least 2 but not
+ always n_subdirs + 2 then \fIMH\fR will miss some subfolders.  Another
+ way that this can be broken is if you have a folder whose subfolders are
+ all symbolic links to other directories (if there's at least one real
+ subdirectory then the code will handle it).
+
+ Note that the code which implements this option assumes that you've got
+ symbolic links (or more precisely, lstat(2)).  If you don't have
+ lstat(2) the algorithm can be made both more correct and more efficient,
+ but I haven't bothered to code this up in a selectable manner.

  .ti -.5i
  NOIOCTLH
Index: conf/mhconfig.c
Prereq:  2.73
*** conf/mhconfig.c     Wed May  1 12:17:32 1996
--- ../mh/conf/mhconfig.c       Fri May  3 18:31:28 1996
***************
*** 138,144 ****
      "MIME", 0,        /* multi-media extensions */
      "MPOP", 0,        /* mobile pop */
      "MSGID", 0, /* slocal dup surpression */
!     "NORUSERPASS", 0, /* no ruserpass(3) */
      "TMA", 0, /* trusted mail */
      "TTYD", 0,
      "UCI", 0,
--- 139,146 ----
      "MIME", 0,        /* multi-media extensions */
      "MPOP", 0,        /* mobile pop */
      "MSGID", 0, /* slocal dup surpression */
!     "NLINK_HACK", 0,  /* assume st_nlink-2 subdirs */
!     "NORUSERPASS", 0, /* no ruserpass(3) */
      "TMA", 0, /* trusted mail */
      "TTYD", 0,
      "UCI", 0,
Index: uip/folder.c
Prereq:  2.11
*** uip/folder.c        Tue Nov 30 23:01:36 1993
--- ../mh/uip/folder.c  Fri May  3 18:29:54 1996
***************
*** 544,550 ****
--- 544,563 ----
      register struct direct *dp;
  #endif /* SYS5DIR */
      register    DIR * dd;
+ #ifdef NLINK_HACK
+     register int dirs_left;
+ #endif

+ #ifdef NLINK_HACK
+     if (stat (name, &st) != NOTOK && st.st_nlink > 1) {
+       dirs_left = st.st_nlink - 2;
+       if (dirs_left == 0)
+           return;
+     }
+     else
+       dirs_left = -1;
+ #endif
+
      cp = name + strlen (name);
      *cp++ = '/';
      *cp = '\0';
***************
*** 564,571 ****
  #endif /* SYS5DIR */
                continue;
            (void) strcpy (cp, dp -> d_name);
!           if (stat (name, &st) != NOTOK && (st.st_mode & S_IFMT) == S_IFDIR)
                addfold (base);
        }
      closedir (dd);

--- 577,594 ----
  #endif /* SYS5DIR */
                continue;
            (void) strcpy (cp, dp -> d_name);
!           if (stat (name, &st) != NOTOK && (st.st_mode & S_IFMT) == S_IFDIR) {
                addfold (base);
+ #ifdef NLINK_HACK
+               /* This might really be a symlink to a directory, don't
+                  decrement dirs_left unless it's an actual directory. */
+               if (lstat (name, &st) != NOTOK
+                       && (st.st_mode & S_IFMT) == S_IFDIR) {
+                   if (dirs_left > 0 && --dirs_left == 0)
+                       break;
+               }
+ #endif
+           }
        }
      closedir (dd);


--
Roderick Schertler
roderick(_at_)gate(_dot_)net


<Prev in Thread] Current Thread [Next in Thread>
  • yet another st_nlink optimization for folder(1), Roderick Schertler <=