Here's a patch for coda-src/dir/dirbody.c that fixes a problem we 
were seeing with large directories under NetBSD 1.3.3 and FreeBSD
2.2.6.  readdir(3) on these machines treats directory entries that 
straddle a 4k boundary (readdir(3)'s buffer size) as end-of-directory
markers.  This patch to DIR_Convert() prevents the straddling from
happening when __BSD44__ is defined.

Matt

-- 
Matt Fredette                         http://mit.edu/fredette/www
[EMAIL PROTECTED], [EMAIL PROTECTED], [EMAIL PROTECTED]
"[Peter] Banks' career waned after joining `Flash' in 1972 and
 recording three albums all called `Two Sides Of Peter Banks.'"

[snip]
Index: dirbody.c
===================================================================
RCS file: /cvs/coda/coda-src/dir/dirbody.c,v
retrieving revision 1.1.1.2
retrieving revision 1.4
diff -c -r1.1.1.2 -r1.4
*** dirbody.c   1999/01/28 23:20:57     1.1.1.2
--- dirbody.c   1999/02/17 22:39:37     1.4
***************
*** 791,796 ****
--- 791,799 ----
        int num;
        char *buf;
        int offset = 0;
+ #ifdef __BSD44__
+       int direntlen;
+ #endif /* __BSD44__ */
  #ifdef DJGPP
        int rc;
  #endif
***************
*** 802,807 ****
--- 805,822 ----
        CODA_ASSERT( fd >= 0 );
  
        len = DIR_Length(dir);
+ #ifdef __BSD44__
+       /* because of a poor libc readdir(), directory entries
+          cannot span a 4k boundary.  because we can't know until
+          we write out the directory how much we will have to pad
+          things, just assume that we will have to pad one 
+          maximum-sized directory entry for each 4k chunk of
+          directory we write.  this leads to larger directories
+          on disk than we strictly need, but hey: */
+ #define BSD44_READDIR_BOUNDARY_LOG2 12
+ #define BSD44_READDIR_BOUNDARY (1 << BSD44_READDIR_BOUNDARY_LOG2)
+       len += (len >> BSD44_READDIR_BOUNDARY_LOG2) * ((sizeof(struct venus_dirent) + 
+3) & ~3);
+ #endif /* __BSD44__ */
  
  #ifndef DJGPP
        CODA_ASSERT( ftruncate(fd, len) == 0 );
***************
*** 820,825 ****
--- 835,863 ----
                        ep = dir_GetBlob(dir, num);
                        if (!ep) 
                                break;
+ #ifdef __BSD44__
+                       /* optimistically write the directory entry: */
+                       direntlen = dir_DirEntry2VDirent(ep, (struct venus_dirent *) 
+(buf + offset), vol);
+                       /* if what we just wrote crosses a 4k boundary: */
+                       if (((offset + direntlen) ^ offset) & ~(BSD44_READDIR_BOUNDARY 
+- 1)) {
+                               /* note that vd still points to the *previous* 
+directory 
+                                  entry.  calculate how much we have to add to its 
+d_reclen 
+                                  and offset for the padding: */
+                               direntlen = ((offset + (BSD44_READDIR_BOUNDARY - 1)) & 
+                                               ~(BSD44_READDIR_BOUNDARY - 1)) - 
+offset;
+                               vd->d_reclen += direntlen;
+                               offset += direntlen;
+                               /* fall through to let the original code rewrite the 
+entry */
+                       } 
+                       /* otherwise, we were successful the first time: */
+                       else {
+                               vd = (struct venus_dirent *)(buf + offset);
+                               offset += direntlen;
+                               num = ntohs(ep->next);
+                               continue;
+                       }
+ #endif /* __BSD44__ */
+ 
                        vd = (struct venus_dirent *)(buf + offset);
                        offset += dir_DirEntry2VDirent(ep, vd, vol);
                        num = ntohs(ep->next);
[snip]

Reply via email to