diff options
author | jhb <jhb@FreeBSD.org> | 2002-09-11 20:56:05 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2002-09-11 20:56:05 +0000 |
commit | ae7eea133f7d1d4b931097c6b84d401ce3c3474d (patch) | |
tree | 099a879657da9c8bc4dd2872c938c477b28766df /sys/kern/kern_ktrace.c | |
parent | 603b838523988e5e25b694b8bbb20c716cb47cd6 (diff) | |
download | FreeBSD-src-ae7eea133f7d1d4b931097c6b84d401ce3c3474d.zip FreeBSD-src-ae7eea133f7d1d4b931097c6b84d401ce3c3474d.tar.gz |
- Change ktrace genio events to only copy up to ktr_geniosize bytes of a
transfer to a malloc'd buffer and use that bufer for the ktrace event.
This means that genio ktrace events no longer need to be synchronous.
- Now that ktr_buffer isn't overloaded to sometimes point to a cached uio
pointer for genio requests and always points to a malloc'd buffer if not
NULL, free the buffer in ktr_freerequest() instead of in
ktr_writerequest(). This closes a memory leak for ktrace events that
used a malloc'd buffer that had their vnode ripped out from under them
while they were on the todo list.
Suggested by: bde (1, in principle)
Diffstat (limited to 'sys/kern/kern_ktrace.c')
-rw-r--r-- | sys/kern/kern_ktrace.c | 36 |
1 files changed, 18 insertions, 18 deletions
diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index f6ceb61..c6d85e1 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -283,6 +283,8 @@ ktr_freerequest(struct ktr_request *req) vrele(req->ktr_vp); mtx_unlock(&Giant); } + if (req->ktr_header.ktr_buffer != NULL) + free(req->ktr_header.ktr_buffer, M_KTRACE); mtx_lock(&ktrace_mtx); STAILQ_INSERT_HEAD(&ktr_free, req, ktr_list); mtx_unlock(&ktrace_mtx); @@ -419,19 +421,29 @@ ktrgenio(fd, rw, uio, error) { struct ktr_request *req; struct ktr_genio *ktg; + int datalen; + char *buf; if (error) return; + uio->uio_offset = 0; + uio->uio_rw = UIO_WRITE; + datalen = imin(uio->uio_resid, ktr_geniosize); + buf = malloc(datalen, M_KTRACE, M_WAITOK); + if (uiomove(buf, datalen, uio)) { + free(buf, M_KTRACE); + return; + } req = ktr_getrequest(KTR_GENIO); - if (req == NULL) + if (req == NULL) { + free(buf, M_KTRACE); return; + } ktg = &req->ktr_data.ktr_genio; ktg->ktr_fd = fd; ktg->ktr_rw = rw; - req->ktr_header.ktr_buffer = uio; - uio->uio_offset = 0; - uio->uio_rw = UIO_WRITE; - req->ktr_synchronous = 1; + req->ktr_header.ktr_len = datalen; + req->ktr_header.ktr_buffer = buf; ktr_submitrequest(req); } @@ -730,7 +742,6 @@ ktr_writerequest(struct ktr_request *req) { struct ktr_header *kth; struct vnode *vp; - struct uio *uio = NULL; struct proc *p; struct thread *td; struct ucred *cred; @@ -774,12 +785,7 @@ ktr_writerequest(struct ktr_request *req) aiov[auio.uio_iovcnt].iov_len = buflen; auio.uio_resid += buflen; auio.uio_iovcnt++; - } else - uio = kth->ktr_buffer; - KASSERT((uio == NULL) ^ (kth->ktr_type == KTR_GENIO), - ("ktrace: uio and genio mismatch")); - if (uio != NULL) - kth->ktr_len += uio->uio_resid; + } mtx_lock(&Giant); vn_start_write(vp, &mp, V_WAIT); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); @@ -789,15 +795,9 @@ ktr_writerequest(struct ktr_request *req) if (error == 0) #endif error = VOP_WRITE(vp, &auio, IO_UNIT | IO_APPEND, cred); - if (error == 0 && uio != NULL) { - (void)VOP_LEASE(vp, td, cred, LEASE_WRITE); - error = VOP_WRITE(vp, uio, IO_UNIT | IO_APPEND, cred); - } VOP_UNLOCK(vp, 0, td); vn_finished_write(mp); mtx_unlock(&Giant); - if (buflen != 0) - free(kth->ktr_buffer, M_KTRACE); if (!error) return; /* |