Coda File System

coda-src/dir/dirbody.c patch for *BSD

From: Matthew Fredette <mfredett_at_bbnplanet.com>
Date: Thu, 18 Feb 1999 12:15:17 -0500 (EST)
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
fredette_at_bbnplanet.com, fredette_at_mit.edu, fredette_at_theory.lcs.mit.edu
"[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]
Received on 1999-02-18 12:17:24