changeset 19250:6e954fd9b63c

12009 Memory leaks in blkdev when blkdev device is detached Reviewed by: Robert Mustacchi <rm@fingolfin.org> Reviewed by: Igor Kozhukhov <igor@dilos.org> Reviewed by: Randy Fishel <randyf@sibernet.com> Reviewed by: Matthias Scheler <matthias.scheler@wdc.com> Approved by: Dan McDonald <danmcd@joyent.com>
author Paul Winder <paul@winders.demon.co.uk>
date Thu, 21 Nov 2019 14:08:31 +0000
parents 7e17c5e0d17a
children e432880e1e13
files usr/src/uts/common/io/blkdev/blkdev.c
diffstat 1 files changed, 38 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/io/blkdev/blkdev.c	Fri Nov 22 13:16:49 2019 +0000
+++ b/usr/src/uts/common/io/blkdev/blkdev.c	Thu Nov 21 14:08:31 2019 +0000
@@ -495,20 +495,35 @@
 bd_errstats_setstr(kstat_named_t *k, char *str, size_t len, char *alt)
 {
 	char	*tmp;
+	size_t	km_len;
 
 	if (KSTAT_NAMED_STR_PTR(k) == NULL) {
-		if (len > 0) {
-			tmp = kmem_alloc(len + 1, KM_SLEEP);
-			(void) strlcpy(tmp, str, len + 1);
-		} else {
-			tmp = alt;
-		}
+		if (len > 0)
+			km_len = strnlen(str, len);
+		else if (alt != NULL)
+			km_len = strlen(alt);
+		else
+			return;
+
+		tmp = kmem_alloc(km_len + 1, KM_SLEEP);
+		bcopy(len > 0 ? str : alt, tmp, km_len);
+		tmp[km_len] = '\0';
 
 		kstat_named_setstr(k, tmp);
 	}
 }
 
 static void
+bd_errstats_clrstr(kstat_named_t *k)
+{
+	if (KSTAT_NAMED_STR_PTR(k) == NULL)
+		return;
+
+	kmem_free(KSTAT_NAMED_STR_PTR(k), KSTAT_NAMED_STR_BUFLEN(k));
+	kstat_named_setstr(k, NULL);
+}
+
+static void
 bd_init_errstats(bd_t *bd, bd_drive_t *drive)
 {
 	struct bd_errstats	*est = bd->d_kerr;
@@ -535,6 +550,22 @@
 }
 
 static void
+bd_fini_errstats(bd_t *bd)
+{
+	struct bd_errstats	*est = bd->d_kerr;
+
+	mutex_enter(&bd->d_errmutex);
+
+	bd_errstats_clrstr(&est->bd_model);
+	bd_errstats_clrstr(&est->bd_vid);
+	bd_errstats_clrstr(&est->bd_pid);
+	bd_errstats_clrstr(&est->bd_revision);
+	bd_errstats_clrstr(&est->bd_serial);
+
+	mutex_exit(&bd->d_errmutex);
+}
+
+static void
 bd_queues_free(bd_t *bd)
 {
 	uint32_t i;
@@ -773,6 +804,7 @@
 	}
 
 	if (bd->d_errstats != NULL) {
+		bd_fini_errstats(bd);
 		kstat_delete(bd->d_errstats);
 		bd->d_errstats = NULL;
 	} else {