diff options
author | dyson <dyson@FreeBSD.org> | 1998-01-11 21:35:38 +0000 |
---|---|---|
committer | dyson <dyson@FreeBSD.org> | 1998-01-11 21:35:38 +0000 |
commit | 2aff55e25fd0e9baef0fea9e9feb2ebbe6628fbe (patch) | |
tree | ae70643abb712e7d5261e18b848f062720a79f8f /sys/kern/kern_exec.c | |
parent | dfbd942cf7e4827c057bbcd9b65a0f3e39023d75 (diff) | |
download | FreeBSD-src-2aff55e25fd0e9baef0fea9e9feb2ebbe6628fbe.zip FreeBSD-src-2aff55e25fd0e9baef0fea9e9feb2ebbe6628fbe.tar.gz |
Implement the first page access for object type determination more
VM clean. Also, use vm_map_insert instead of vm_mmap.
Reviewed by: dg@freebsd.org
Diffstat (limited to 'sys/kern/kern_exec.c')
-rw-r--r-- | sys/kern/kern_exec.c | 156 |
1 files changed, 94 insertions, 62 deletions
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index eb40b91..76cbb93 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: kern_exec.c,v 1.72 1997/12/27 02:56:21 bde Exp $ + * $Id: kern_exec.c,v 1.73 1998/01/06 05:15:34 dyson Exp $ */ #include <sys/param.h> @@ -54,17 +54,22 @@ #include <vm/vm_prot.h> #include <sys/lock.h> #include <vm/pmap.h> +#include <vm/vm_page.h> #include <vm/vm_map.h> #include <vm/vm_kern.h> #include <vm/vm_extern.h> #include <vm/vm_object.h> #include <vm/vm_zone.h> +#include <vm/vm_pager.h> +#include <vm/vm_pageout.h> #include <machine/reg.h> static int *exec_copyout_strings __P((struct image_params *)); -static int exec_check_permissions(struct image_params *); +static int exec_check_permissions __P((struct image_params *)); +static int exec_map_first_page __P((struct image_params *)); +static void exec_unmap_first_page __P((struct image_params *)); /* * XXX trouble here if sizeof(caddr_t) != sizeof(int), other parts @@ -114,7 +119,6 @@ execve(p, uap) imgp->proc = p; imgp->uap = uap; imgp->attr = &attr; - imgp->image_header = NULL; imgp->argc = imgp->envc = 0; imgp->argv0 = NULL; imgp->entry_addr = 0; @@ -122,18 +126,21 @@ execve(p, uap) imgp->interpreted = 0; imgp->interpreter_name[0] = '\0'; imgp->auxargs = NULL; + imgp->vp = NULL; + imgp->firstpage = NULL; /* * Allocate temporary demand zeroed space for argument and * environment strings */ - imgp->stringbase = (char *)kmem_alloc_wait(exec_map, ARG_MAX); + imgp->stringbase = (char *)kmem_alloc_wait(exec_map, ARG_MAX + PAGE_SIZE); if (imgp->stringbase == NULL) { error = ENOMEM; goto exec_fail; } imgp->stringp = imgp->stringbase; imgp->stringspace = ARG_MAX; + imgp->image_header = imgp->stringbase + ARG_MAX; /* * Translate the file name. namei() returns a vnode pointer @@ -147,7 +154,8 @@ interpret: error = namei(ndp); if (error) { - kmem_free_wakeup(exec_map, (vm_offset_t)imgp->stringbase, ARG_MAX); + kmem_free_wakeup(exec_map, (vm_offset_t)imgp->stringbase, + ARG_MAX + PAGE_SIZE); goto exec_fail; } @@ -162,38 +170,7 @@ interpret: goto exec_fail_dealloc; } - /* - * Get the image header, which we define here as meaning the first - * page of the executable. - */ - if (imgp->vp->v_object && imgp->vp->v_mount && - imgp->vp->v_mount->mnt_stat.f_iosize >= PAGE_SIZE && - imgp->vp->v_object->un_pager.vnp.vnp_size >= - imgp->vp->v_mount->mnt_stat.f_iosize) { - /* - * Get a buffer with (at least) the first page. - */ - error = bread(imgp->vp, 0, imgp->vp->v_mount->mnt_stat.f_iosize, - p->p_ucred, &bp); - imgp->image_header = bp->b_data; - } else { - int resid; - - /* - * The filesystem block size is too small, so do this the hard - * way. Malloc some space and read PAGE_SIZE worth of the image - * header into it. - */ - imgp->image_header = malloc(PAGE_SIZE, M_TEMP, M_WAITOK); - error = vn_rdwr(UIO_READ, imgp->vp, - (void *)imgp->image_header, PAGE_SIZE, 0, - UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p); - /* - * Clear out any remaining junk. - */ - if (!error && resid) - bzero((char *)imgp->image_header + PAGE_SIZE - resid, resid); - } + error = exec_map_first_page(imgp); VOP_UNLOCK(imgp->vp, 0, p); if (error) goto exec_fail_dealloc; @@ -216,13 +193,7 @@ interpret: if (error) goto exec_fail_dealloc; if (imgp->interpreted) { - /* free old bp/image_header */ - if (bp != NULL) { - brelse(bp); - bp = NULL; - } else - free((void *)imgp->image_header, M_TEMP); - imgp->image_header = NULL; + exec_unmap_first_page(imgp); /* free old vnode and name buffer */ vrele(ndp->ni_vp); zfree(namei_zone, ndp->ni_cnd.cn_pnbuf); @@ -351,31 +322,26 @@ interpret: /* Set entry address */ setregs(p, imgp->entry_addr, (u_long)stack_base); +exec_fail_dealloc: + /* * free various allocated resources */ - kmem_free_wakeup(exec_map, (vm_offset_t)imgp->stringbase, ARG_MAX); - if (bp != NULL) - brelse(bp); - else if (imgp->image_header != NULL) - free((void *)imgp->image_header, M_TEMP); - vrele(ndp->ni_vp); - zfree(namei_zone, ndp->ni_cnd.cn_pnbuf); - - return (0); + if (imgp->firstpage) + exec_unmap_first_page(imgp); -exec_fail_dealloc: if (imgp->stringbase != NULL) - kmem_free_wakeup(exec_map, (vm_offset_t)imgp->stringbase, ARG_MAX); - if (bp != NULL) - brelse(bp); - else if (imgp->image_header != NULL) - free((void *)imgp->image_header, M_TEMP); + kmem_free_wakeup(exec_map, (vm_offset_t)imgp->stringbase, + ARG_MAX + PAGE_SIZE); + if (ndp->ni_vp) { vrele(ndp->ni_vp); zfree(namei_zone, ndp->ni_cnd.cn_pnbuf); } + if (error == 0) + return (0); + exec_fail: if (imgp->vmspace_destroyed) { /* sorry, no more process anymore. exit gracefully */ @@ -387,6 +353,71 @@ exec_fail: } } +int +exec_map_first_page(imgp) + struct image_params *imgp; +{ + int s; + vm_page_t m; + vm_object_t object; + + + if (imgp->firstpage) { + exec_unmap_first_page(imgp); + } + + object = imgp->vp->v_object; + s = splvm(); + +retry: + m = vm_page_lookup(object, 0); + if (m == NULL) { + m = vm_page_alloc(object, 0, VM_ALLOC_NORMAL); + if (m == NULL) { + VM_WAIT; + goto retry; + } + } else if ((m->flags & PG_BUSY) || m->busy) { + m->flags |= PG_WANTED; + tsleep(m, PVM, "execpw", 0); + goto retry; + } + + m->flags |= PG_BUSY; + + if ((m->valid & VM_PAGE_BITS_ALL) != VM_PAGE_BITS_ALL) { + int rv; + rv = vm_pager_get_pages(object, &m, 1, 0); + if (rv != VM_PAGER_OK) { + vm_page_protect(m, VM_PROT_NONE); + vm_page_deactivate(m); + PAGE_WAKEUP(m); + splx(s); + return EIO; + } + } + + vm_page_wire(m); + PAGE_WAKEUP(m); + splx(s); + + pmap_kenter((vm_offset_t) imgp->image_header, VM_PAGE_TO_PHYS(m)); + imgp->firstpage = m; + + return 0; +} + +void +exec_unmap_first_page(imgp) + struct image_params *imgp; +{ + if (imgp->firstpage) { + pmap_kremove((vm_offset_t) imgp->image_header); + vm_page_unwire(imgp->firstpage); + imgp->firstpage = NULL; + } +} + /* * Destroy old address space, and allocate a new stack * The new stack is only SGROWSIZ large because it is grown @@ -420,10 +451,11 @@ exec_new_vmspace(imgp) } /* Allocate a new stack */ - error = vm_map_find(map, NULL, 0, (vm_offset_t *)&stack_addr, - SGROWSIZ, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); + error = vm_map_insert(&vmspace->vm_map, NULL, 0, + (vm_offset_t) stack_addr, (vm_offset_t) USRSTACK, + VM_PROT_ALL, VM_PROT_ALL, 0); if (error) - return(error); + return (error); vmspace->vm_ssize = SGROWSIZ >> PAGE_SHIFT; |