[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