imgact_elf: do not relock the text vnode if possible.

We unlock the vnode around malloc(M_WAITOK), to make it possible for
pagedaemon to flush vnode pages for us.  Instead of doing it
unconditionally, first try M_NOWAIT allocation, which typically
succeed.  Only on failure, unlock the vnode and retry with M_WAITOK.

Reviewed by:	markj, trasz
Tested by:	mjg, pho
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D19923
This commit is contained in:
kib 2019-05-05 11:04:01 +00:00
parent 0d62ce2428
commit e3b87f7a32

View File

@ -957,9 +957,12 @@ __elfN(get_interp)(struct image_params *imgp, const Elf_Phdr *phdr,
interp_name_len = phdr->p_filesz;
if (phdr->p_offset > PAGE_SIZE ||
interp_name_len > PAGE_SIZE - phdr->p_offset) {
VOP_UNLOCK(imgp->vp, 0);
interp = malloc(interp_name_len + 1, M_TEMP, M_WAITOK);
vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
interp = malloc(interp_name_len + 1, M_TEMP, M_NOWAIT);
if (interp == NULL) {
VOP_UNLOCK(imgp->vp, 0);
interp = malloc(interp_name_len + 1, M_TEMP, M_WAITOK);
vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
}
error = vn_rdwr(UIO_READ, imgp->vp, interp,
interp_name_len, phdr->p_offset,
UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred,
@ -1278,7 +1281,12 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
/*
* Construct auxargs table (used by the fixup routine)
*/
elf_auxargs = malloc(sizeof(Elf_Auxargs), M_TEMP, M_WAITOK);
elf_auxargs = malloc(sizeof(Elf_Auxargs), M_TEMP, M_NOWAIT);
if (elf_auxargs == NULL) {
VOP_UNLOCK(imgp->vp, 0);
elf_auxargs = malloc(sizeof(Elf_Auxargs), M_TEMP, M_WAITOK);
vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
}
elf_auxargs->execfd = -1;
elf_auxargs->phdr = proghdr + et_dyn_addr;
elf_auxargs->phent = hdr->e_phentsize;
@ -2558,9 +2566,12 @@ __elfN(parse_notes)(struct image_params *imgp, Elf_Note *checknote,
ASSERT_VOP_LOCKED(imgp->vp, "parse_notes");
if (pnote->p_offset > PAGE_SIZE ||
pnote->p_filesz > PAGE_SIZE - pnote->p_offset) {
VOP_UNLOCK(imgp->vp, 0);
buf = malloc(pnote->p_filesz, M_TEMP, M_WAITOK);
vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
buf = malloc(pnote->p_filesz, M_TEMP, M_NOWAIT);
if (buf == NULL) {
VOP_UNLOCK(imgp->vp, 0);
buf = malloc(pnote->p_filesz, M_TEMP, M_WAITOK);
vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
}
error = vn_rdwr(UIO_READ, imgp->vp, buf, pnote->p_filesz,
pnote->p_offset, UIO_SYSSPACE, IO_NODELOCKED,
curthread->td_ucred, NOCRED, NULL, curthread);