summaryrefslogtreecommitdiffstats
path: root/sys/kern/imgact_aout.c
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2005-12-24 04:57:50 +0000
committeralc <alc@FreeBSD.org>2005-12-24 04:57:50 +0000
commit8d1c855285d26806b49deffc0f5d95750477a96e (patch)
tree58a83bc5bd4286833347363325ea92026b4fbf33 /sys/kern/imgact_aout.c
parent4b072f53d2c7434569874d9474c75cff868b4209 (diff)
downloadFreeBSD-src-8d1c855285d26806b49deffc0f5d95750477a96e.zip
FreeBSD-src-8d1c855285d26806b49deffc0f5d95750477a96e.tar.gz
Maintain the lock on the vnode for most of exec_elfN_imgact().
Specifically, it is required for the I/O that may be performed by elfN_load_section(). Avoid an obscure deadlock in the a.out, elf, and gzip image activators. Add a comment describing why the deadlock does not occur in the common case and how it might occur in less usual circumstances. Eliminate an unused variable from exec_aout_imgact(). In collaboration with: tegge
Diffstat (limited to 'sys/kern/imgact_aout.c')
-rw-r--r--sys/kern/imgact_aout.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c
index 572bc47..423a54d 100644
--- a/sys/kern/imgact_aout.c
+++ b/sys/kern/imgact_aout.c
@@ -98,8 +98,8 @@ exec_aout_imgact(imgp)
struct image_params *imgp;
{
const struct exec *a_out = (const struct exec *) imgp->image_header;
+ struct thread *td = curthread;
struct vmspace *vmspace;
- struct vnode *vp;
vm_map_t map;
vm_object_t object;
vm_offset_t text_end, data_end;
@@ -186,16 +186,27 @@ exec_aout_imgact(imgp)
PROC_UNLOCK(imgp->proc);
/*
+ * Avoid a possible deadlock if the current address space is destroyed
+ * and that address space maps the locked vnode. In the common case,
+ * the locked vnode's v_usecount is decremented but remains greater
+ * than zero. Consequently, the vnode lock is not needed by vrele().
+ * However, in cases where the vnode lock is external, such as nullfs,
+ * v_usecount may become zero.
+ */
+ VOP_UNLOCK(imgp->vp, 0, td);
+
+ /*
* Destroy old process VM and create a new one (with a new stack)
*/
exec_new_vmspace(imgp, &aout_sysvec);
+ vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY, td);
+
/*
* The vm space can be changed by exec_new_vmspace
*/
vmspace = imgp->proc->p_vmspace;
- vp = imgp->vp;
object = imgp->object;
map = &vmspace->vm_map;
vm_map_lock(map);
OpenPOWER on IntegriCloud