diff options
author | tjr <tjr@FreeBSD.org> | 2002-12-13 09:59:40 +0000 |
---|---|---|
committer | tjr <tjr@FreeBSD.org> | 2002-12-13 09:59:40 +0000 |
commit | bcd327d9a44f1ca6c358929cb93dd40acf3d7295 (patch) | |
tree | 48b504971d855aed854c98ac4ba5826748b47684 /sys | |
parent | 33cac8d3682293ff210e1d5f6d0006c02cc2d93f (diff) | |
download | FreeBSD-src-bcd327d9a44f1ca6c358929cb93dd40acf3d7295.zip FreeBSD-src-bcd327d9a44f1ca6c358929cb93dd40acf3d7295.tar.gz |
Drop filedesc lock and acquire Giant around calls to malloc() and free().
These call uma_large_malloc() and uma_large_free() which require Giant.
Fixes panic when descriptor table is larger than KMEM_ZMAX bytes
noticed by kkenn.
Reviewed by: jhb
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/kern_descrip.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 852cd39..27e0bcc 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -1056,7 +1056,13 @@ fdalloc(td, want, result) while (nfiles < want) nfiles <<= 1; FILEDESC_UNLOCK(fdp); + /* + * XXX malloc() calls uma_large_malloc() for sizes larger + * than KMEM_ZMAX bytes. uma_large_malloc() requires Giant. + */ + mtx_lock(&Giant); newofile = malloc(nfiles * OFILESIZE, M_FILEDESC, M_WAITOK); + mtx_unlock(&Giant); /* * Deal with file-table extend race that might have @@ -1064,7 +1070,12 @@ fdalloc(td, want, result) */ FILEDESC_LOCK(fdp); if (fdp->fd_nfiles >= nfiles) { + /* XXX uma_large_free() needs Giant. */ + FILEDESC_UNLOCK(fdp); + mtx_lock(&Giant); free(newofile, M_FILEDESC); + mtx_unlock(&Giant); + FILEDESC_LOCK(fdp); continue; } newofileflags = (char *) &newofile[nfiles]; @@ -1087,8 +1098,14 @@ fdalloc(td, want, result) fdp->fd_ofileflags = newofileflags; fdp->fd_nfiles = nfiles; fdexpand++; - if (oldofile != NULL) + if (oldofile != NULL) { + /* XXX uma_large_free() needs Giant. */ + FILEDESC_UNLOCK(fdp); + mtx_lock(&Giant); free(oldofile, M_FILEDESC); + mtx_unlock(&Giant); + FILEDESC_LOCK(fdp); + } } return (0); } |