[PATCH] Double-level file descriptor allocation

Skip Ford skip.ford at verizon.net
Wed Jan 21 14:22:23 PST 2004


Here's a DragonFly port of Tim Robbins' FreeBSD port of Niels
Provos' NetBSD file descriptor allocation code.

I've been running this code on DragonFly just over a month.  I
would've posted sooner had I known there was interest.  Tim's
initial post for FreeBSD didn't get many responses and I just
ported it for fun back then.

Niels' test program which I'm attaching opens, closes, and
times how long it takes to reopen some files.  The times just for
reopening the files on my UP system with and without this patch
are:
          fd    Unpatched      Patched
            1    0.765650     0.781279
         2001    1.148484     0.789092
         4001    1.546935     0.765657
         6001    2.062582     0.781276
         8001    2.515725     0.796906
        10001    3.086061     0.796904
        12001    3.632955     0.765654
        14001    4.086098     0.757841
        16001    4.515805     0.820343
        18001    4.976759     0.812530
        20001    5.429916     0.796905
        22001    5.898652     0.773467
        24001    6.336188     0.773455
        26001    6.750268     0.804718
        28001    7.179972     0.789091
        30001    7.633110     0.781281
        32001    8.070632     0.789091
        34001    8.523771     0.796906
        36001    8.953479     0.789092
        38001    9.375370     0.765656
        40001   10.117587     0.789090
        42001   10.758238     0.789091
        44001   11.367636     0.804718
        46001   11.820781     0.812531
        48001   12.453618     0.812530

I never did get the final FreeBSD single-level version to compile.
The double-level bitmap in this patch was reduced to one in the
FreeBSD version by des because it added complexity for not enough
gain in his opinion.

-- 
Skip
/*
 * Here is the benchmark that I used way back to measure performance of
 * file descriptor allocation.  Hope it helps.
 *
 * Niels.
 */
#include <stdio.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/resource.h>

#define NFILES  50000
#define TRIALS  10000L

int files[NFILES];

#define ssec ru_stime.tv_sec
#define usec ru_utime.tv_sec
#define susec ru_stime.tv_usec
#define uusec ru_utime.tv_usec

void
massage (int fd)
{
  u_long i;
  struct rusage t1, t2;

  getrusage(RUSAGE_SELF, &t1);

  for (i = 0; i < TRIALS; i++) {
    close (files[0]);
    close (files[fd]);
    files[0] = open("/etc/passwd", O_RDONLY, 0);
    if (files[0] == -1) {
      perror("massage: open(0)");
      exit (0);
    }
    files[fd] = open("/etc/passwd", O_RDONLY, 0);
    if (files[fd] == -1) {
      perror("massage: open");
      exit (0);
    }
  }

  getrusage(RUSAGE_SELF, &t2);

  printf ("%d %lf\n", fd, (double)(t2.ssec + t2.usec - t1.ssec - t1.usec) +
          (double)(t2.susec + t2.uusec - t1.susec - t1.uusec)/1000000);

}

int
main (void)
{
  int i;

  for (i = 0; i < NFILES; i++) {
    files[i] = open("/etc/passwd", O_RDONLY, 0);
        printf ("%d: %d\n", i, files[i]);
    if (files[i] == -1) {
      perror("open");
      exit (0);
    }
  }

  for (i = 1; i < NFILES; i += 2000)
    massage (i);

  return 1;
}
Index: sys/sys/filedesc.h
===================================================================
RCS file: /home/dcvs/src/sys/sys/filedesc.h,v
retrieving revision 1.7
diff -u -r1.7 filedesc.h
--- sys/sys/filedesc.h	13 Oct 2003 21:15:48 -0000	1.7
+++ sys/sys/filedesc.h	29 Nov 2003 03:25:53 -0000
@@ -56,6 +56,11 @@
  */
 #define NDFILE		20
 #define NDEXTENT	50		/* 250 bytes in 256-byte alloc. */
+#define	NDENTRIES	32		/* 32 fds per entry */
+#define	NDENTRYMASK	(NDENTRIES - 1)
+#define	NDENTRYSHIFT	5		/* bits per entry */
+#define	NDLOSLOTS(x)	(((x) + NDENTRIES - 1) >> NDENTRYSHIFT)
+#define	NDHISLOTS(x)	((NDLOSLOTS(x) + NDENTRIES - 1) >> NDENTRYSHIFT)
 
 struct klist;
 struct namecache;
@@ -70,6 +75,8 @@
 	struct  namecache *fd_nrdir;	/* root directory */
 	struct  namecache *fd_njdir;	/* jail directory */
 	int	fd_nfiles;		/* number of open files allocated */
+	uint32_t	*fd_himap;	/* each bit points to 32 fds */
+	uint32_t	*fd_lomap;	/* bitmap of free fds */
 	u_short	fd_lastfile;		/* high-water mark of fd_ofiles */
 	u_short	fd_freefile;		/* approx. next free file */
 	u_short	fd_cmask;		/* mask for file creation */
@@ -95,6 +102,12 @@
 	 */
 	struct	file *fd_dfiles[NDFILE];
 	char	fd_dfileflags[NDFILE];
+	/*
+	 * These arrays are used when the number of open files is
+	 * <= 1024, and are then pointed to by the pointers above.
+	 */
+	uint32_t	fd_dhimap[NDENTRIES >> NDENTRYSHIFT];
+	uint32_t	fd_dlomap[NDENTRIES];
 };
 
 
@@ -165,6 +178,7 @@
 int	fdalloc (struct proc *p, int want, int *result);
 int	fdavail (struct proc *p, int n);
 int	falloc (struct proc *p, struct file **resultfp, int *resultfd);
+int	fd_find_last_set(struct filedesc *, int);
 void	fsetcred(struct file *fp, struct ucred *cr);
 void	ffree (struct file *);
 struct	filedesc *fdinit (struct proc *p);
@@ -188,6 +202,36 @@
 filedesc_to_leader_alloc(struct filedesc_to_leader *old,
 			 struct proc *leader);
 
+static __inline void
+fd_used(struct filedesc *fdp, int fd)
+{
+	u_int off = fd >> NDENTRYSHIFT;
+ 
+	fdp->fd_lomap[off] |= 1 << (fd & NDENTRYMASK);
+	if (fdp->fd_lomap[off] == ~0)
+		fdp->fd_himap[off >> NDENTRYSHIFT] |= 1 << (off & NDENTRYMASK);
+ 
+	if (fd > fdp->fd_lastfile)
+		fdp->fd_lastfile = fd;
+}
+               
+static __inline void
+fd_unused(struct filedesc *fdp, int fd)               
+{  
+        u_int off = fd >> NDENTRYSHIFT;
+
+	if (fd < fdp->fd_freefile)
+		fdp->fd_freefile = fd;
+	if (fdp->fd_lomap[off] == ~0)
+		fdp->fd_himap[off >> NDENTRYSHIFT] &= ~(1 << (off & NDENTRYMASK));
+	fdp->fd_lomap[off] &= ~(1 << (fd & NDENTRYMASK));
+#ifdef KASSERT	/* XXX */
+        KASSERT(fd <= fdp->fd_lastfile,
+	    ("fd_unused: fd_lastfile inconsistent"));
+#endif
+	if (fd == fdp->fd_lastfile)
+		fdp->fd_lastfile = fd_find_last_set(fdp, fd);
+}
 #endif
 
 #endif
Index: sys/kern/init_main.c
===================================================================
RCS file: /home/dcvs/src/sys/kern/init_main.c,v
retrieving revision 1.26
diff -u -r1.26 init_main.c
--- sys/kern/init_main.c	10 Nov 2003 06:12:13 -0000	1.26
+++ sys/kern/init_main.c	29 Nov 2003 02:22:49 -0000
@@ -345,6 +345,8 @@
 	fdp->fd_fd.fd_ofiles = fdp->fd_dfiles;
 	fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags;
 	fdp->fd_fd.fd_nfiles = NDFILE;
+	fdp->fd_fd.fd_himap = fdp->fd_dhimap;
+	fdp->fd_fd.fd_lomap = fdp->fd_dlomap;
 
 	/* Create the limits structures. */
 	p->p_limit = &limit0;
Index: sys/kern/kern_descrip.c
===================================================================
RCS file: /home/dcvs/src/sys/kern/kern_descrip.c,v
retrieving revision 1.17
diff -u -r1.17 kern_descrip.c
--- sys/kern/kern_descrip.c	21 Oct 2003 01:05:09 -0000	1.17
+++ sys/kern/kern_descrip.c	9 Dec 2003 11:09:21 -0000
@@ -104,6 +104,63 @@
 static int badfo_kqfilter (struct file *fp, struct knote *kn);
 static int badfo_stat (struct file *fp, struct stat *sb, struct thread *td);
 static int badfo_close (struct file *fp, struct thread *td);
+static __inline int	find_next_zero(uint32_t *, int, u_int);
+
+static __inline int
+find_next_zero(uint32_t *bitmap, int want, u_int bits)
+{
+	int i, off, maxoff;
+	uint32_t sub;
+
+	if (want > bits)
+		return -1;
+
+	off = want >> NDENTRYSHIFT;
+	i = want & NDENTRYMASK;
+	if (i) {
+		sub = bitmap[off] | ((u_int)~0 >> (NDENTRIES - i));
+		if (sub != ~0)
+			goto found;
+		off++;
+	}
+
+	maxoff = NDLOSLOTS(bits);
+	while (off < maxoff) {
+		if ((sub = bitmap[off]) != ~0)
+			goto found;
+		off++;
+	}
+
+	return (-1);
+
+found:
+	return (off << NDENTRYSHIFT) + ffs(~sub) - 1;
+}
+
+int
+fd_find_last_set(struct filedesc *fd, int last)
+{
+	int off, i;
+	struct file **ofiles = fd->fd_ofiles;
+	uint32_t *bitmap = fd->fd_lomap;
+
+	off = (last - 1) >> NDENTRYSHIFT;
+
+	while (!bitmap[off] && off >= 0)
+		off--;
+
+	if (off < 0)
+		return (0);
+       
+	i = ((off + 1) << NDENTRYSHIFT) - 1;
+	if (i >= last)
+		i = last - 1;
+
+	while (i > 0 && ofiles[i] == NULL)
+		i--;
+
+	return (i);
+}
 
 /*
  * Descriptor management.
@@ -426,13 +483,8 @@
 	 * avoid this case.
 	 */
 	if (fdp->fd_ofiles[old] != fp) {
-		if (fdp->fd_ofiles[new] == NULL) {
-			if (new < fdp->fd_freefile)
-				fdp->fd_freefile = new;
-			while (fdp->fd_lastfile > 0 &&
-			    fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
-				fdp->fd_lastfile--;
-		}
+		if (fdp->fd_ofiles[new] == NULL)
+			fd_unused(fdp, new);
 		fdrop(fp, td);
 		return (EBADF);
 	}
@@ -465,8 +517,7 @@
 	 */
 	fdp->fd_ofiles[new] = fp;
 	fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
-	if (new > fdp->fd_lastfile)
-		fdp->fd_lastfile = new;
+	fd_used(fdp, new);
 	*res = new;
 
 	/*
@@ -638,6 +689,7 @@
 #endif
 	fdp->fd_ofiles[fd] = NULL;
 	fdp->fd_ofileflags[fd] = 0;
+	fd_unused(fdp, fd);
 	holdleaders = 0;
 	if (p->p_fdtol != NULL) {
 		/*
@@ -652,10 +704,6 @@
 	 * we now hold the fp reference that used to be owned by the descriptor
 	 * array.
 	 */
-	while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
-		fdp->fd_lastfile--;
-	if (fd < fdp->fd_freefile)
-		fdp->fd_freefile = fd;
 	if (fd < fdp->fd_knlistsize)
 		knote_fdclose(p, fd);
 	error = closef(fp, td);
@@ -784,9 +832,11 @@
 {
 	struct filedesc *fdp = p->p_fd;
 	int i;
-	int lim, last, nfiles;
+	int lim, last, nfiles, oldnfiles;
 	struct file **newofile;
 	char *newofileflags;
+	uint32_t *newhimap, *newlomap, *oldhimap, *oldlomap;
+	u_int off, new;
 
 	/*
 	 * Search for a free descriptor starting at the higher
@@ -796,13 +846,29 @@
 	lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfilesperproc);
 	for (;;) {
 		last = min(fdp->fd_nfiles, lim);
+again:
 		if ((i = want) < fdp->fd_freefile)
 			i = fdp->fd_freefile;
-		for (; i < last; i++) {
-			if (fdp->fd_ofiles[i] == NULL) {
-				fdp->fd_ofileflags[i] = 0;
-				if (i > fdp->fd_lastfile)
-					fdp->fd_lastfile = i;
+		off = i >> NDENTRYSHIFT;
+		new = find_next_zero(fdp->fd_himap, off,
+		    (last + NDENTRIES - 1) >> NDENTRYSHIFT);
+		if (new != -1) {
+			i = find_next_zero(&fdp->fd_lomap[new], 
+			    new > off ? 0 : i & NDENTRYMASK, NDENTRIES);
+			if (i == -1) {
+				/* 
+				 * free file descriptor in this block was
+				 * below want, try again with higher want.
+				 */
+				want = (new + 1) << NDENTRYSHIFT;
+				goto again;
+			}
+			i += (new << NDENTRYSHIFT);
+			if (i < last) {
+				KASSERT(fdp->fd_ofiles[i] == NULL,
+				    ("free descriptor isn't"));
+				fdp->fd_ofileflags[i] = 0; /* XXX needed? */
+				fd_used(fdp, i);
 				if (want <= fdp->fd_freefile)
 					fdp->fd_freefile = i;
 				*result = i;
@@ -819,15 +885,28 @@
 			nfiles = NDEXTENT;
 		else
 			nfiles = 2 * fdp->fd_nfiles;
+		oldnfiles = fdp->fd_nfiles;
 		MALLOC(newofile, struct file **, nfiles * OFILESIZE,
 		    M_FILEDESC, M_WAITOK);
 
+		if (NDHISLOTS(nfiles) > NDHISLOTS(oldnfiles)) {
+			newhimap = malloc(NDHISLOTS(nfiles) * sizeof(uint32_t),
+			    M_FILEDESC, M_WAITOK);
+			newlomap = malloc(NDLOSLOTS(nfiles) * sizeof(uint32_t),
+			    M_FILEDESC, M_WAITOK);
+		} else
+			newhimap = newlomap = NULL;
+
 		/*
 		 * deal with file-table extend race that might have occured
 		 * when malloc was blocked.
 		 */
 		if (fdp->fd_nfiles >= nfiles) {
 			FREE(newofile, M_FILEDESC);
+			if (newhimap != NULL)
+				free(newhimap, M_FILEDESC);
+			if (newlomap != NULL)
+				free(newlomap, M_FILEDESC);
 			continue;
 		}
 		newofileflags = (char *) &newofile[nfiles];
@@ -845,8 +924,31 @@
 			FREE(fdp->fd_ofiles, M_FILEDESC);
 		fdp->fd_ofiles = newofile;
 		fdp->fd_ofileflags = newofileflags;
+		oldlomap = oldhimap = NULL;
+		if (NDHISLOTS(nfiles) > NDHISLOTS(oldnfiles)) {
+			memcpy(newhimap, fdp->fd_himap,
+			    (i = NDHISLOTS(oldnfiles) * sizeof(uint32_t)));
+			memset((char *)newhimap + i, 0,
+			    NDHISLOTS(nfiles) * sizeof(uint32_t) - i);
+			memcpy(newlomap, fdp->fd_lomap,
+			    (i = NDLOSLOTS(oldnfiles) * sizeof(uint32_t)));
+			memset((char *)newlomap + i, 0,
+			    NDLOSLOTS(nfiles) * sizeof(uint32_t) - i);
+			if (NDHISLOTS(oldnfiles) > NDHISLOTS(NDFILE)) {
+				oldhimap = fdp->fd_himap;
+				oldlomap = fdp->fd_lomap;
+			}
+			fdp->fd_himap = newhimap;
+			fdp->fd_lomap = newlomap;
+		}
 		fdp->fd_nfiles = nfiles;
 		fdexpand++;
+		if (oldlomap != NULL || oldhimap != NULL) {
+			if (oldlomap != NULL)
+				free(oldlomap, M_FILEDESC);
+			if (oldhimap != NULL)
+				free(oldhimap, M_FILEDESC);
+  		}
 	}
 	return (0);
 }
@@ -990,6 +1092,8 @@
 	newfdp->fd_fd.fd_ofileflags = newfdp->fd_dfileflags;
 	newfdp->fd_fd.fd_nfiles = NDFILE;
 	newfdp->fd_fd.fd_knlistsize = -1;
+	newfdp->fd_fd.fd_himap = newfdp->fd_dhimap;
+	newfdp->fd_fd.fd_lomap = newfdp->fd_dlomap;
 
 	return (&newfdp->fd_fd);
 }
@@ -1041,6 +1145,10 @@
 		newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles;
 		newfdp->fd_ofileflags =
 		    ((struct filedesc0 *) newfdp)->fd_dfileflags;
+		newfdp->fd_himap =
+		    ((struct filedesc0 *) newfdp)->fd_dhimap;
+		newfdp->fd_lomap =
+		    ((struct filedesc0 *) newfdp)->fd_dlomap;
 		i = NDFILE;
 	} else {
 		/*
@@ -1053,11 +1161,26 @@
 			i /= 2;
 		MALLOC(newfdp->fd_ofiles, struct file **, i * OFILESIZE,
 		    M_FILEDESC, M_WAITOK);
+		if (NDHISLOTS(i) <= NDHISLOTS(NDFILE)) {
+			newfdp->fd_himap =
+			    ((struct filedesc0 *) newfdp)->fd_dhimap;
+			newfdp->fd_lomap =
+			    ((struct filedesc0 *) newfdp)->fd_dlomap;
+		} else {
+			newfdp->fd_himap = malloc(NDHISLOTS(i) * sizeof(uint32_t),
+			    M_FILEDESC, M_WAITOK);
+			newfdp->fd_lomap = malloc(NDLOSLOTS(i) * sizeof(uint32_t),
+			    M_FILEDESC, M_WAITOK);
+		}
 		newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
 	}
 	newfdp->fd_nfiles = i;
 	bcopy(fdp->fd_ofiles, newfdp->fd_ofiles, i * sizeof(struct file **));
 	bcopy(fdp->fd_ofileflags, newfdp->fd_ofileflags, i * sizeof(char));
+	if (i < NDENTRIES * NDENTRIES)
+		i = NDENTRIES * NDENTRIES; /* size of inlined bitmaps */
+	memcpy(newfdp->fd_himap, fdp->fd_himap, NDHISLOTS(i)*sizeof(uint32_t));
+	memcpy(newfdp->fd_lomap, fdp->fd_lomap, NDLOSLOTS(i)*sizeof(uint32_t));
 
 	/*
 	 * kq descriptors cannot be copied.
@@ -1066,12 +1189,9 @@
 		fpp = &newfdp->fd_ofiles[newfdp->fd_lastfile];
 		for (i = newfdp->fd_lastfile; i >= 0; i--, fpp--) {
 			if (*fpp != NULL && (*fpp)->f_type == DTYPE_KQUEUE) {
+				fd_unused(newfdp, i);
 				*fpp = NULL;
-				if (i < newfdp->fd_freefile)
-					newfdp->fd_freefile = i;
 			}
-			if (*fpp == NULL && i == newfdp->fd_lastfile && i > 0)
-				newfdp->fd_lastfile--;
 		}
 		newfdp->fd_knlist = NULL;
 		newfdp->fd_knlistsize = -1;
@@ -1185,6 +1305,10 @@
 	}
 	if (fdp->fd_nfiles > NDFILE)
 		FREE(fdp->fd_ofiles, M_FILEDESC);
+	if (NDHISLOTS(fdp->fd_nfiles) > NDHISLOTS(NDFILE)) {
+		free(fdp->fd_himap, M_FILEDESC);
+		free(fdp->fd_lomap, M_FILEDESC);
+	}
 	if (fdp->fd_cdir)
 		vrele(fdp->fd_cdir);
 	if (fdp->fd_rdir)
@@ -1256,13 +1380,10 @@
 			fp = fdp->fd_ofiles[i];
 			fdp->fd_ofiles[i] = NULL;
 			fdp->fd_ofileflags[i] = 0;
-			if (i < fdp->fd_freefile)
-				fdp->fd_freefile = i;
+			fd_unused(fdp, i);
 			(void) closef(fp, td);
 		}
 	}
-	while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
-		fdp->fd_lastfile--;
 }
 
 /*
@@ -1301,13 +1422,10 @@
 			fp = fdp->fd_ofiles[i];
 			fdp->fd_ofiles[i] = NULL;
 			fdp->fd_ofileflags[i] = 0;
-			if (i < fdp->fd_freefile)
-				fdp->fd_freefile = i;
+			fd_unused(fdp, i);
 			(void) closef(fp, td);
 		}
 	}
-	while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
-		fdp->fd_lastfile--;
 }
 
 /*
@@ -1345,6 +1463,7 @@
                        error = vn_open(&nd, flags, 0);
                        if (error != 0) {
                                fdp->fd_ofiles[i] = NULL;
+				fd_unused(fdp, i);
                                fdrop(fp, td);
                                break;
                        }
@@ -1579,9 +1698,9 @@
 #endif
 		fdp->fd_ofiles[indx] = wfp;
 		fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
+		fd_used(fdp, indx);
 		fhold(wfp);
-		if (indx > fdp->fd_lastfile)
-			fdp->fd_lastfile = indx;
+
 		/*
 		 * we now own the reference to fp that the ofiles[] array
 		 * used to own.  Release it.
@@ -1603,6 +1722,8 @@
 		fdp->fd_ofiles[dfd] = NULL;
 		fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
 		fdp->fd_ofileflags[dfd] = 0;
+		fd_unused(fdp, dfd);
+		fd_used(fdp, indx);
 
 		/*
 		 * we now own the reference to fp that the ofiles[] array
@@ -1610,20 +1731,7 @@
 		 */
 		if (fp)
 			fdrop(fp, curthread);
-		/*
-		 * Complete the clean up of the filedesc structure by
-		 * recomputing the various hints.
-		 */
-		if (indx > fdp->fd_lastfile) {
-			fdp->fd_lastfile = indx;
-		} else {
-			while (fdp->fd_lastfile > 0 &&
-			   fdp->fd_ofiles[fdp->fd_lastfile] == NULL) {
-				fdp->fd_lastfile--;
-			}
-			if (dfd < fdp->fd_freefile)
-				fdp->fd_freefile = dfd;
-		}
+
 		return (0);
 
 	default:
Index: sys/kern/sys_pipe.c
===================================================================
RCS file: /home/dcvs/src/sys/kern/sys_pipe.c,v
retrieving revision 1.13
diff -u -r1.13 sys_pipe.c
--- sys/kern/sys_pipe.c	3 Nov 2003 17:11:21 -0000	1.13
+++ sys/kern/sys_pipe.c	29 Nov 2003 03:25:53 -0000
@@ -220,6 +220,7 @@
 	if (error) {
 		if (fdp->fd_ofiles[fd1] == rf) {
 			fdp->fd_ofiles[fd1] = NULL;
+			fd_unused(fdp, fd1);
 			fdrop(rf, td);
 		}
 		fdrop(rf, td);
Index: sys/kern/uipc_syscalls.c
===================================================================
RCS file: /home/dcvs/src/sys/kern/uipc_syscalls.c,v
retrieving revision 1.20
diff -u -r1.20 uipc_syscalls.c
--- sys/kern/uipc_syscalls.c	15 Oct 2003 08:43:37 -0000	1.20
+++ sys/kern/uipc_syscalls.c	29 Nov 2003 03:25:53 -0000
@@ -109,6 +109,7 @@
 	if (error) {
 		if (fdp->fd_ofiles[fd] == fp) {
 			fdp->fd_ofiles[fd] = NULL;
+			fd_unused(fdp, fd);
 			fdrop(fp, td);
 		}
 	} else {
@@ -328,6 +329,7 @@
 		*res = -1;
 		if (fdp->fd_ofiles[fd] == nfp) {
 			fdp->fd_ofiles[fd] = NULL;
+			fd_unused(fdp, fd);
 			fdrop(nfp, td);
 		}
 	}
@@ -486,12 +488,14 @@
 free4:
 	if (fdp->fd_ofiles[sv[1]] == fp2) {
 		fdp->fd_ofiles[sv[1]] = NULL;
+		fd_unused(fdp, sv[1]);
 		fdrop(fp2, td);
 	}
 	fdrop(fp2, td);
 free3:
 	if (fdp->fd_ofiles[sv[0]] == fp1) {
 		fdp->fd_ofiles[sv[0]] = NULL;
+		fd_unused(fdp, sv[0]);
 		fdrop(fp1, td);
 	}
 	fdrop(fp1, td);
Index: sys/kern/vfs_syscalls.c
===================================================================
RCS file: /home/dcvs/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.28
diff -u -r1.28 vfs_syscalls.c
--- sys/kern/vfs_syscalls.c	14 Nov 2003 19:31:22 -0000	1.28
+++ sys/kern/vfs_syscalls.c	29 Nov 2003 03:28:00 -0000
@@ -975,6 +975,7 @@
 		 */
 		if (fdp->fd_ofiles[indx] == fp) {
 			fdp->fd_ofiles[indx] = NULL;
+			fd_unused(fdp, indx);
 			fdrop(fp, td);
 		}
 
@@ -1029,6 +1030,7 @@
 			 */
 			if (fdp->fd_ofiles[indx] == fp) {
 				fdp->fd_ofiles[indx] = NULL;
+				fd_unused(fdp, indx);
 				fdrop(fp, td);
 			}
 			fdrop(fp, td);
@@ -2907,6 +2909,7 @@
 			 */
 			if (fdp->fd_ofiles[indx] == fp) {
 				fdp->fd_ofiles[indx] = NULL;
+				fd_unused(fdp, indx);
 				fdrop(fp, td);
 			}
 




More information about the Kernel mailing list