From 62d615d50844083e4b9cc1406ee92afa4e84aef3 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Tue, 20 Jun 2006 21:31:38 +0000 Subject: [PATCH] Conditionally acquire Giant around VFS operations. --- sys/compat/ndis/subr_ndis.c | 29 ++++++++++++++++------------- sys/kern/kern_linker.c | 13 ++++++++++--- sys/kern/link_elf.c | 6 +++++- sys/kern/link_elf_obj.c | 6 +++++- 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c index 40ff5435d944..3ed857b5371d 100644 --- a/sys/compat/ndis/subr_ndis.c +++ b/sys/compat/ndis/subr_ndis.c @@ -2925,7 +2925,7 @@ NdisOpenFile(status, filehandle, filelength, filename, highestaddr) char *afilename = NULL; struct thread *td = curthread; struct nameidata nd; - int flags, error; + int flags, error, vfslocked; struct vattr vat; struct vattr *vap = &vat; ndis_fh *fh; @@ -2998,8 +2998,6 @@ NdisOpenFile(status, filehandle, filelength, filename, highestaddr) snprintf(path, MAXPATHLEN, "%s/%s", ndis_filepath, afilename); - mtx_lock(&Giant); - /* Some threads don't have a current working directory. */ if (td->td_proc->p_fd->fd_rdir == NULL) @@ -3007,12 +3005,11 @@ NdisOpenFile(status, filehandle, filelength, filename, highestaddr) if (td->td_proc->p_fd->fd_cdir == NULL) td->td_proc->p_fd->fd_cdir = rootvnode; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td); + NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, path, td); flags = FREAD; error = vn_open(&nd, &flags, 0, -1); if (error) { - mtx_unlock(&Giant); *status = NDIS_STATUS_FILE_NOT_FOUND; ExFreePool(fh); printf("NDIS: open file %s failed: %d\n", path, error); @@ -3020,6 +3017,7 @@ NdisOpenFile(status, filehandle, filelength, filename, highestaddr) free(afilename, M_DEVBUF); return; } + vfslocked = NDHASGIANT(&nd); ExFreePool(path); @@ -3028,7 +3026,7 @@ NdisOpenFile(status, filehandle, filelength, filename, highestaddr) /* Get the file size. */ VOP_GETATTR(nd.ni_vp, vap, td->td_ucred, td); VOP_UNLOCK(nd.ni_vp, 0, td); - mtx_unlock(&Giant); + VFS_UNLOCK_GIANT(vfslocked); fh->nf_vp = nd.ni_vp; fh->nf_map = NULL; @@ -3050,7 +3048,8 @@ NdisMapFile(status, mappedbuffer, filehandle) struct thread *td = curthread; linker_file_t lf; caddr_t kldstart; - int error, resid; + int error, resid, vfslocked; + struct vnode *vp; if (filehandle == NULL) { *status = NDIS_STATUS_FAILURE; @@ -3088,10 +3087,11 @@ NdisMapFile(status, mappedbuffer, filehandle) return; } - mtx_lock(&Giant); - error = vn_rdwr(UIO_READ, fh->nf_vp, fh->nf_map, fh->nf_maplen, 0, + vp = fh->nf_vp; + vfslocked = VFS_LOCK_GIANT(vp->v_mount); + error = vn_rdwr(UIO_READ, vp, fh->nf_map, fh->nf_maplen, 0, UIO_SYSSPACE, 0, td->td_ucred, NOCRED, &resid, td); - mtx_unlock(&Giant); + VFS_UNLOCK_GIANT(vfslocked); if (error) *status = NDIS_STATUS_FAILURE; @@ -3126,6 +3126,8 @@ NdisCloseFile(filehandle) { struct thread *td = curthread; ndis_fh *fh; + int vfslocked; + struct vnode *vp; if (filehandle == NULL) return; @@ -3141,9 +3143,10 @@ NdisCloseFile(filehandle) return; if (fh->nf_type == NDIS_FH_TYPE_VFS) { - mtx_lock(&Giant); - vn_close(fh->nf_vp, FREAD, td->td_ucred, td); - mtx_unlock(&Giant); + vp = fh->nf_vp; + vfslocked = VFS_LOCK_GIANT(vp->v_mount); + vn_close(vp, FREAD, td->td_ucred, td); + VFS_UNLOCK_GIANT(vfslocked); } fh->nf_vp = NULL; diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c index 6eb62b6cfda5..986f34a0413d 100644 --- a/sys/kern/kern_linker.c +++ b/sys/kern/kern_linker.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -1483,7 +1484,7 @@ linker_lookup_file(const char *path, int pathlen, const char *name, struct nameidata nd; struct thread *td = curthread; /* XXX */ char *result, **cpp, *sep; - int error, len, extlen, reclen, flags; + int error, len, extlen, reclen, flags, vfslocked; enum vtype type; extlen = 0; @@ -1504,16 +1505,18 @@ linker_lookup_file(const char *path, int pathlen, const char *name, * Attempt to open the file, and return the path if * we succeed and it's a regular file. */ - NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, result, td); + NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, result, td); flags = FREAD; error = vn_open(&nd, &flags, 0, -1); if (error == 0) { + vfslocked = NDHASGIANT(&nd); NDFREE(&nd, NDF_ONLY_PNBUF); type = nd.ni_vp->v_type; if (vap) VOP_GETATTR(nd.ni_vp, vap, td->td_ucred, td); VOP_UNLOCK(nd.ni_vp, 0, td); vn_close(nd.ni_vp, FREAD, td->td_ucred, td); + VFS_UNLOCK_GIANT(vfslocked); if (type == VREG) return (result); } @@ -1541,6 +1544,7 @@ linker_hints_lookup(const char *path, int pathlen, const char *modname, u_char *hints = NULL; u_char *cp, *recptr, *bufend, *result, *best, *pathbuf, *sep; int error, ival, bestver, *intp, reclen, found, flags, clen, blen; + int vfslocked = 0; result = NULL; bestver = found = 0; @@ -1552,11 +1556,12 @@ linker_hints_lookup(const char *path, int pathlen, const char *modname, snprintf(pathbuf, reclen, "%.*s%s%s", pathlen, path, sep, linker_hintfile); - NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, pathbuf, td); + NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE, UIO_SYSSPACE, pathbuf, td); flags = FREAD; error = vn_open(&nd, &flags, 0, -1); if (error) goto bad; + vfslocked = NDHASGIANT(&nd); NDFREE(&nd, NDF_ONLY_PNBUF); if (nd.ni_vp->v_type != VREG) goto bad; @@ -1580,6 +1585,7 @@ linker_hints_lookup(const char *path, int pathlen, const char *modname, goto bad; VOP_UNLOCK(nd.ni_vp, 0, td); vn_close(nd.ni_vp, FREAD, cred, td); + VFS_UNLOCK_GIANT(vfslocked); nd.ni_vp = NULL; if (reclen != 0) { printf("can't read %d\n", reclen); @@ -1648,6 +1654,7 @@ linker_hints_lookup(const char *path, int pathlen, const char *modname, if (nd.ni_vp != NULL) { VOP_UNLOCK(nd.ni_vp, 0, td); vn_close(nd.ni_vp, FREAD, cred, td); + VFS_UNLOCK_GIANT(vfslocked); } /* * If nothing found or hints is absent - fallback to the old diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c index 7b3f1abc1b08..14b9c2e7ffab 100644 --- a/sys/kern/link_elf.c +++ b/sys/kern/link_elf.c @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -556,17 +557,19 @@ link_elf_load_file(linker_class_t cls, const char* filename, int symstrindex; int symcnt; int strcnt; + int vfslocked; GIANT_REQUIRED; shdr = NULL; lf = NULL; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, td); + NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, filename, td); flags = FREAD; error = vn_open(&nd, &flags, 0, -1); if (error) return error; + vfslocked = NDHASGIANT(&nd); NDFREE(&nd, NDF_ONLY_PNBUF); #ifdef MAC error = mac_check_kld_load(curthread->td_ucred, nd.ni_vp); @@ -859,6 +862,7 @@ link_elf_load_file(linker_class_t cls, const char* filename, free(firstpage, M_LINKER); VOP_UNLOCK(nd.ni_vp, 0, td); vn_close(nd.ni_vp, FREAD, td->td_ucred, td); + VFS_UNLOCK_GIANT(vfslocked); return error; } diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c index de43b7a43068..5a102983634e 100644 --- a/sys/kern/link_elf_obj.c +++ b/sys/kern/link_elf_obj.c @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -393,6 +394,7 @@ link_elf_load_file(linker_class_t cls, const char *filename, int nsym; int pb, rl, ra; int alignmask; + int vfslocked; GIANT_REQUIRED; @@ -401,11 +403,12 @@ link_elf_load_file(linker_class_t cls, const char *filename, mapsize = 0; hdr = NULL; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, td); + NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, filename, td); flags = FREAD; error = vn_open(&nd, &flags, 0, -1); if (error) return error; + vfslocked = NDHASGIANT(&nd); NDFREE(&nd, NDF_ONLY_PNBUF); #ifdef MAC error = mac_check_kld_load(td->td_ucred, nd.ni_vp); @@ -788,6 +791,7 @@ link_elf_load_file(linker_class_t cls, const char *filename, free(hdr, M_LINKER); VOP_UNLOCK(nd.ni_vp, 0, td); vn_close(nd.ni_vp, FREAD, td->td_ucred, td); + VFS_UNLOCK_GIANT(vfslocked); return error; }