diff options
author | kib <kib@FreeBSD.org> | 2006-08-08 12:29:26 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2006-08-08 12:29:26 +0000 |
commit | ecc9acd26891da5892fc77bf0ed0df59cf810c1e (patch) | |
tree | 15d2fbed2dbc5571937620818025af1a243af9d6 /sys/compat/linprocfs | |
parent | 7c6c98a7255276df19be3353b070d8677f165cb6 (diff) | |
download | FreeBSD-src-ecc9acd26891da5892fc77bf0ed0df59cf810c1e.zip FreeBSD-src-ecc9acd26891da5892fc77bf0ed0df59cf810c1e.tar.gz |
Lock the vnode around the call to VOP_GETATTR. Move the locked code
and vn_fullpath (that call malloc(..., M_WAITOK)) from under the
vm object lock, since sleep is not allowed while holding the mutex.
Being there, wrap VOP_GETATTR call with conditional Giant aquire.
Currently this is (almost) noop because pseudofs is Giant-locked.
Tested by: kris
Approved by: pjd (mentor)
MFC after: 2 weeks
Diffstat (limited to 'sys/compat/linprocfs')
-rw-r--r-- | sys/compat/linprocfs/linprocfs.c | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c index 2508023..6f32aaf 100644 --- a/sys/compat/linprocfs/linprocfs.c +++ b/sys/compat/linprocfs/linprocfs.c @@ -803,6 +803,7 @@ linprocfs_doprocmaps(PFS_FILL_ARGS) int error; struct vnode *vp; struct vattr vat; + int locked; PROC_LOCK(p); error = p_candebug(td, p); @@ -831,18 +832,28 @@ linprocfs_doprocmaps(PFS_FILL_ARGS) lobj = tobj; ino = 0; if (lobj) { - vp = lobj->handle; VM_OBJECT_LOCK(lobj); off = IDX_TO_OFF(lobj->size); - if (lobj->type == OBJT_VNODE && lobj->handle) { - vn_fullpath(td, vp, &name, &freename); - VOP_GETATTR(vp, &vat, td->td_ucred, td); - ino = vat.va_fileid; + if (lobj->type == OBJT_VNODE) { + vp = lobj->handle; + if (vp) + vref(vp); } + else + vp = NULL; flags = obj->flags; ref_count = obj->ref_count; shadow_count = obj->shadow_count; VM_OBJECT_UNLOCK(lobj); + if (vp) { + vn_fullpath(td, vp, &name, &freename); + locked = VFS_LOCK_GIANT(vp->v_mount); + vn_lock(vp, LK_SHARED | LK_RETRY, td); + VOP_GETATTR(vp, &vat, td->td_ucred, td); + ino = vat.va_fileid; + vput(vp); + VFS_UNLOCK_GIANT(locked); + } } else { flags = 0; ref_count = 0; |