git: d87f1e2e3646 - stable/13 - Make msgbuf_peekbytes() not return leading zeroes.

From: Alexander Motin <mav_at_FreeBSD.org>
Date: Sat, 18 Dec 2021 01:36:28 UTC
The branch stable/13 has been updated by mav:

URL: https://cgit.FreeBSD.org/src/commit/?id=d87f1e2e36461a2ab028fb25b2312903efe5b10a

commit d87f1e2e36461a2ab028fb25b2312903efe5b10a
Author:     Alexander Motin <mav@FreeBSD.org>
AuthorDate: 2021-12-11 04:18:52 +0000
Commit:     Alexander Motin <mav@FreeBSD.org>
CommitDate: 2021-12-18 01:36:23 +0000

    Make msgbuf_peekbytes() not return leading zeroes.
    
    Introduce new MSGBUF_WRAP flag, indicating that buffer has wrapped
    at least once and does not keep zeroes from the last msgbuf_clear().
    It allows msgbuf_peekbytes() to return only real data, not requiring
    every consumer to trim the leading zeroes after doing pointless copy.
    The most visible effect is that kern.msgbuf sysctl now always returns
    proper zero-terminated string, not only after the first buffer wrap.
    
    MFC after:      1 week
    Sponsored by:   iXsystems, Inc.
    
    (cherry picked from commit 81dc00331d148fab19af24833521334e39f3692d)
---
 sys/kern/subr_msgbuf.c | 55 +++++++++++++++++++++++---------------------------
 sys/sys/msgbuf.h       |  7 +++++--
 2 files changed, 30 insertions(+), 32 deletions(-)

diff --git a/sys/kern/subr_msgbuf.c b/sys/kern/subr_msgbuf.c
index 8af013d52a2d..b41e78dd886e 100644
--- a/sys/kern/subr_msgbuf.c
+++ b/sys/kern/subr_msgbuf.c
@@ -69,10 +69,10 @@ msgbuf_init(struct msgbuf *mbp, void *ptr, int size)
 	mbp->msg_ptr = ptr;
 	mbp->msg_size = size;
 	mbp->msg_seqmod = SEQMOD(size);
-	msgbuf_clear(mbp);
-	mbp->msg_magic = MSG_MAGIC;
 	mbp->msg_lastpri = -1;
 	mbp->msg_flags = 0;
+	msgbuf_clear(mbp);
+	mbp->msg_magic = MSG_MAGIC;
 	bzero(&mbp->msg_lock, sizeof(mbp->msg_lock));
 	mtx_init(&mbp->msg_lock, "msgbuf", NULL, MTX_SPIN);
 }
@@ -123,6 +123,7 @@ msgbuf_clear(struct msgbuf *mbp)
 	mbp->msg_wseq = 0;
 	mbp->msg_rseq = 0;
 	mbp->msg_cksum = 0;
+	mbp->msg_flags &= ~MSGBUF_WRAP;
 }
 
 /*
@@ -145,18 +146,17 @@ msgbuf_getcount(struct msgbuf *mbp)
  *
  * The caller should hold the message buffer spinlock.
  */
-
 static void
-msgbuf_do_addchar(struct msgbuf * const mbp, u_int * const seq, const int c)
+msgbuf_do_addchar(struct msgbuf * const mbp, const int c)
 {
 	u_int pos;
 
 	/* Make sure we properly wrap the sequence number. */
-	pos = MSGBUF_SEQ_TO_POS(mbp, *seq);
+	pos = MSGBUF_SEQ_TO_POS(mbp, mbp->msg_wseq);
 	mbp->msg_cksum += (u_int)(u_char)c -
 	    (u_int)(u_char)mbp->msg_ptr[pos];
 	mbp->msg_ptr[pos] = c;
-	*seq = MSGBUF_SEQNORM(mbp, *seq + 1);
+	mbp->msg_wseq = MSGBUF_SEQADD(mbp, mbp->msg_wseq, 1);
 }
 
 /*
@@ -167,7 +167,9 @@ msgbuf_addchar(struct msgbuf *mbp, int c)
 {
 	mtx_lock_spin(&mbp->msg_lock);
 
-	msgbuf_do_addchar(mbp, &mbp->msg_wseq, c);
+	msgbuf_do_addchar(mbp, c);
+	if (mbp->msg_wseq >= mbp->msg_size)
+		mbp->msg_flags |= MSGBUF_WRAP;
 
 	mtx_unlock_spin(&mbp->msg_lock);
 }
@@ -183,7 +185,6 @@ msgbuf_addchar(struct msgbuf *mbp, int c)
 void
 msgbuf_addstr(struct msgbuf *mbp, int pri, const char *str, int filter_cr)
 {
-	u_int seq;
 	size_t len, prefix_len;
 	char prefix[MAXPRIBUF];
 	char buf[32];
@@ -205,11 +206,6 @@ msgbuf_addstr(struct msgbuf *mbp, int pri, const char *str, int filter_cr)
 	if (pri != -1)
 		prefix_len = sprintf(prefix, "<%d>", pri);
 
-	/*
-	 * Starting write sequence number.
-	 */
-	seq = mbp->msg_wseq;
-
 	/*
 	 * Whenever there is a change in priority, we have to insert a
 	 * newline, and a priority prefix if the priority is not -1.  Here
@@ -218,7 +214,7 @@ msgbuf_addstr(struct msgbuf *mbp, int pri, const char *str, int filter_cr)
 	 * insert a newline before this string.
 	 */
 	if (mbp->msg_lastpri != pri && (mbp->msg_flags & MSGBUF_NEEDNL) != 0) {
-		msgbuf_do_addchar(mbp, &seq, '\n');
+		msgbuf_do_addchar(mbp, '\n');
 		mbp->msg_flags &= ~MSGBUF_NEEDNL;
 	}
 
@@ -233,7 +229,7 @@ msgbuf_addstr(struct msgbuf *mbp, int pri, const char *str, int filter_cr)
 			int j;
 
 			for (j = 0; j < prefix_len; j++)
-				msgbuf_do_addchar(mbp, &seq, prefix[j]);
+				msgbuf_do_addchar(mbp, prefix[j]);
 		}
 
 		if (msgbuf_show_timestamp && needtime == 1 &&
@@ -241,7 +237,7 @@ msgbuf_addstr(struct msgbuf *mbp, int pri, const char *str, int filter_cr)
 			snprintf(buf, sizeof(buf), "[%jd] ",
 			    (intmax_t)time_uptime);
 			for (j = 0; buf[j] != '\0'; j++)
-				msgbuf_do_addchar(mbp, &seq, buf[j]);
+				msgbuf_do_addchar(mbp, buf[j]);
 			needtime = 0;
 		}
 
@@ -265,14 +261,10 @@ msgbuf_addstr(struct msgbuf *mbp, int pri, const char *str, int filter_cr)
 		else
 			mbp->msg_flags |= MSGBUF_NEEDNL;
 
-		msgbuf_do_addchar(mbp, &seq, str[i]);
+		msgbuf_do_addchar(mbp, str[i]);
 	}
-	/*
-	 * Update the write sequence number for the actual number of
-	 * characters we put in the message buffer.  (Depends on whether
-	 * carriage returns are filtered.)
-	 */
-	mbp->msg_wseq = seq;
+	if (mbp->msg_wseq >= mbp->msg_size)
+		mbp->msg_flags |= MSGBUF_WRAP;
 
 	/*
 	 * Set the last priority.
@@ -302,9 +294,9 @@ msgbuf_getchar(struct msgbuf *mbp)
 		return (-1);
 	}
 	if (len > mbp->msg_size)
-		mbp->msg_rseq = MSGBUF_SEQNORM(mbp, wseq - mbp->msg_size);
+		mbp->msg_rseq = MSGBUF_SEQSUB(mbp, wseq, mbp->msg_size);
 	c = (u_char)mbp->msg_ptr[MSGBUF_SEQ_TO_POS(mbp, mbp->msg_rseq)];
-	mbp->msg_rseq = MSGBUF_SEQNORM(mbp, mbp->msg_rseq + 1);
+	mbp->msg_rseq = MSGBUF_SEQADD(mbp, mbp->msg_rseq, 1);
 
 	mtx_unlock_spin(&mbp->msg_lock);
 
@@ -329,7 +321,7 @@ msgbuf_getbytes(struct msgbuf *mbp, char *buf, int buflen)
 		return (0);
 	}
 	if (len > mbp->msg_size) {
-		mbp->msg_rseq = MSGBUF_SEQNORM(mbp, wseq - mbp->msg_size);
+		mbp->msg_rseq = MSGBUF_SEQSUB(mbp, wseq, mbp->msg_size);
 		len = mbp->msg_size;
 	}
 	pos = MSGBUF_SEQ_TO_POS(mbp, mbp->msg_rseq);
@@ -337,7 +329,7 @@ msgbuf_getbytes(struct msgbuf *mbp, char *buf, int buflen)
 	len = min(len, (u_int)buflen);
 
 	bcopy(&mbp->msg_ptr[pos], buf, len);
-	mbp->msg_rseq = MSGBUF_SEQNORM(mbp, mbp->msg_rseq + len);
+	mbp->msg_rseq = MSGBUF_SEQADD(mbp, mbp->msg_rseq, len);
 
 	mtx_unlock_spin(&mbp->msg_lock);
 
@@ -363,7 +355,10 @@ msgbuf_peekbytes(struct msgbuf *mbp, char *buf, int buflen, u_int *seqp)
 
 	if (buf == NULL) {
 		/* Just initialise *seqp. */
-		*seqp = MSGBUF_SEQNORM(mbp, mbp->msg_wseq - mbp->msg_size);
+		if (mbp->msg_flags & MSGBUF_WRAP)
+			*seqp = MSGBUF_SEQSUB(mbp, mbp->msg_wseq, mbp->msg_size);
+		else
+			*seqp = 0;
 		mtx_unlock_spin(&mbp->msg_lock);
 		return (0);
 	}
@@ -375,14 +370,14 @@ msgbuf_peekbytes(struct msgbuf *mbp, char *buf, int buflen, u_int *seqp)
 		return (0);
 	}
 	if (len > mbp->msg_size) {
-		*seqp = MSGBUF_SEQNORM(mbp, wseq - mbp->msg_size);
+		*seqp = MSGBUF_SEQSUB(mbp, wseq, mbp->msg_size);
 		len = mbp->msg_size;
 	}
 	pos = MSGBUF_SEQ_TO_POS(mbp, *seqp);
 	len = min(len, mbp->msg_size - pos);
 	len = min(len, (u_int)buflen);
 	bcopy(&mbp->msg_ptr[MSGBUF_SEQ_TO_POS(mbp, *seqp)], buf, len);
-	*seqp = MSGBUF_SEQNORM(mbp, *seqp + len);
+	*seqp = MSGBUF_SEQADD(mbp, *seqp, len);
 
 	mtx_unlock_spin(&mbp->msg_lock);
 
diff --git a/sys/sys/msgbuf.h b/sys/sys/msgbuf.h
index 27aba1a8e0ed..6768b862faf7 100644
--- a/sys/sys/msgbuf.h
+++ b/sys/sys/msgbuf.h
@@ -50,6 +50,7 @@ struct msgbuf {
 	int	   msg_lastpri;		/* saved priority value */
 	u_int      msg_flags;
 #define MSGBUF_NEEDNL	0x01	/* set when newline needed */
+#define MSGBUF_WRAP	0x02	/* buffer has wrapped around */
 	struct mtx msg_lock;		/* mutex to protect the buffer */
 };
 
@@ -57,8 +58,10 @@ struct msgbuf {
 #define	MSGBUF_SEQNORM(mbp, seq)	(((seq) + (mbp)->msg_seqmod) % \
     (mbp)->msg_seqmod)
 #define	MSGBUF_SEQ_TO_POS(mbp, seq)	((seq) % (mbp)->msg_size)
-/* Subtract sequence numbers.  Note that only positive values result. */
-#define	MSGBUF_SEQSUB(mbp, seq1, seq2)	(MSGBUF_SEQNORM((mbp), (seq1) - (seq2)))
+/* Add/subtract normalized sequence numbers.  Normalized values result. */
+#define	MSGBUF_SEQADD(mbp, seq1, seq2)	(((seq1) + (seq2)) % (mbp)->msg_seqmod)
+#define	MSGBUF_SEQSUB(mbp, seq1, seq2)	((seq1) >= (seq2) ? (seq1) - (seq2) : \
+    (seq1) + (mbp)->msg_seqmod - (seq2))
 
 #ifdef _KERNEL
 extern int	msgbufsize;