home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Bug_Fixes / Net.v7bugs / 0051 < prev    next >
Encoding:
Text File  |  1981-12-14  |  2.3 KB  |  60 lines

  1. Apur-ee.177
  2. net.bugs.v7,net.bugs.2bsd,net.bugs.4bsd
  3. utzoo!decvax!pur-ee!bruner
  4. Fri Dec 11 21:19:01 1981
  5. "holes" in directories
  6. We discovered a particularly nasty problem with the way that UNIX
  7. handles directories when cleaning up a bad system crash.  A "hole"
  8. (region where no blocks are allocated) was created in /usr/tmp.
  9. "fsck" reported no unusual errors, but when we attempted to touch
  10. the inside of this directory (e.g. with "ls") we had all sorts of
  11. errors from our disc driver.
  12.  
  13. The problem is that UNIX assumes there will never be holes in
  14. directories (since normal operation does not create them).  The
  15. routine "namei" which searches directories contains the line:
  16.  
  17.     bp = bread(dp->i_dev,
  18.         bmap(dp, (daddr_t)(u.u_offset>>BSHIFT), B_READ));
  19.  
  20. If "bmap" is called with B_READ it will not allocate blocks to fill
  21. in "holes"; rather, it returns -1 if a hole exists.  This is then
  22. passed directly to "bread".  If your disc driver doesn't check for
  23. negative block numbers (ours didn't), you'll get invalid
  24. cylinder/surface/sector errors from your disc.  Even if the disc
  25. driver does catch the error, you still have problems.  In 2.8bsd
  26. and 4.1bsd the blocks following the "hole" are never reached, so
  27. you could lose a lot of files if the hole occurred near the
  28. beginning of the directory.  If there is no check for an error
  29. from "bread" then all sorts of inconsistent things can happen.
  30.  
  31. This problem exists in V7, 2.8bsd, and 4.1bsd.  It is difficult for
  32. "fsck" to fill in the hole, but certainly it should complain about
  33. the problem.  I implemented a kernel fix -- just have "namei" check
  34. the result of "bmap"; if negative (and the filesystem is read-write)
  35. it then fills in the hole, otherwise, the "hole" is skipped so that
  36. it can't cause any harm.  The fix varies slightly from system to
  37. system, but is approximately:
  38.  
  39. #include "../h/filsys.h"
  40.     ....
  41.     daddr_t bn;
  42.     struct filsys *getfs();
  43.     ....
  44.         if ((bn=bmap(dp, (daddr_t)(u.u_offset>>BSHIFT), B_READ) < 0) {
  45.             printf("hole in dir: %d/%d i=%d\n",
  46.                 major(dp->i_dev), minor(dp->i_dev),
  47.                 dp->i_number);
  48.             if (getfs(dp->i_dev)->s_ronly ||
  49.                 (bn=bmap(dp, (daddr_t)(u.u_offset>>BSHIFT),
  50.                 B_WRITE)) < 0) {
  51.                 u.u_offset += BSIZE;    /* skip block */
  52.                 goto eloop;
  53.             }
  54.         bp = bread(dp->i_dev, bn);
  55.  
  56. V6 does not have this problem, since it always fills in "holes" when
  57. the file is read (no 3rd argument to "bmap").
  58.  
  59. --John Bruner
  60.