From 47ad4f2d45e406c6316909bc12bc760b2fdd6afb Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Mon, 4 Mar 2024 22:14:07 -0600 Subject: [PATCH] ktrace: log genio events on failed write Visibility into the contents of the buffer when a write(2) has failed can be immensely useful in debugging IPC issues -- pushing this to discuss the idea, or maybe an alternative where we can set a flag like KTRFAC_ERRIO to enable it. When a genio event is potentially raised after an error, currently we'll just free the uio and return. However, such data can be useful when debugging communication between processes to, e.g., understand what the remote side should have grabbed before closing a pipe. Tap out the entire buffer on failure rather than simply discarding it. Reviewed by: kib, markj Differential Revision: https://reviews.freebsd.org/D43799 --- sys/kern/kern_ktrace.c | 2 +- sys/kern/sys_generic.c | 3 ++- sys/kern/uipc_syscalls.c | 3 ++- sys/netinet/sctp_syscalls.c | 6 ++++-- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index 877a25ffa4c..6ace3ea52c6 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -767,7 +767,7 @@ ktrgenio(int fd, enum uio_rw rw, struct uio *uio, int error) int datalen; char *buf; - if (error) { + if (error != 0 && (rw == UIO_READ || error == EFAULT)) { freeuio(uio); return; } diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index f6190c3fb05..b926f98892a 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -577,7 +577,8 @@ dofilewrite(struct thread *td, int fd, struct file *fp, struct uio *auio, cnt -= auio->uio_resid; #ifdef KTRACE if (ktruio != NULL) { - ktruio->uio_resid = cnt; + if (error == 0) + ktruio->uio_resid = cnt; ktrgenio(fd, UIO_WRITE, ktruio, error); } #endif diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index dce0ab9b53d..b2d03d932b9 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -772,7 +772,8 @@ kern_sendit(struct thread *td, int s, struct msghdr *mp, int flags, td->td_retval[0] = len - auio.uio_resid; #ifdef KTRACE if (ktruio != NULL) { - ktruio->uio_resid = td->td_retval[0]; + if (error == 0) + ktruio->uio_resid = td->td_retval[0]; ktrgenio(s, UIO_WRITE, ktruio, error); } #endif diff --git a/sys/netinet/sctp_syscalls.c b/sys/netinet/sctp_syscalls.c index a5e4fa8f960..d67e260b6f9 100644 --- a/sys/netinet/sctp_syscalls.c +++ b/sys/netinet/sctp_syscalls.c @@ -290,7 +290,8 @@ sys_sctp_generic_sendmsg(struct thread *td, struct sctp_generic_sendmsg_args *ua td->td_retval[0] = len - auio.uio_resid; #ifdef KTRACE if (ktruio != NULL) { - ktruio->uio_resid = td->td_retval[0]; + if (error == 0) + ktruio->uio_resid = td->td_retval[0]; ktrgenio(uap->sd, UIO_WRITE, ktruio, error); } #endif /* KTRACE */ @@ -404,7 +405,8 @@ sys_sctp_generic_sendmsg_iov(struct thread *td, struct sctp_generic_sendmsg_iov_ td->td_retval[0] = len - auio.uio_resid; #ifdef KTRACE if (ktruio != NULL) { - ktruio->uio_resid = td->td_retval[0]; + if (error == 0) + ktruio->uio_resid = td->td_retval[0]; ktrgenio(uap->sd, UIO_WRITE, ktruio, error); } #endif /* KTRACE */