diff options
author | alc <alc@FreeBSD.org> | 2005-12-24 04:57:50 +0000 |
---|---|---|
committer | alc <alc@FreeBSD.org> | 2005-12-24 04:57:50 +0000 |
commit | 8d1c855285d26806b49deffc0f5d95750477a96e (patch) | |
tree | 58a83bc5bd4286833347363325ea92026b4fbf33 /sys/kern/imgact_aout.c | |
parent | 4b072f53d2c7434569874d9474c75cff868b4209 (diff) | |
download | FreeBSD-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.c | 15 |
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); |