summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/io/blkdev
diff options
context:
space:
mode:
authorPaul Winder <paul@winders.demon.co.uk>2019-11-21 14:08:31 +0000
committerDan McDonald <danmcd@joyent.com>2019-11-25 11:10:02 -0500
commit247e9a8ed695b16d62e2a0cb581e5c07d949d5ae (patch)
tree6fc7618006187f5a1a048a8349b2c859488db6c2 /usr/src/uts/common/io/blkdev
parenteb44bcc7bc940d7cc1f4c10afa5a1cb7ec0dd198 (diff)
downloadillumos-joyent-247e9a8ed695b16d62e2a0cb581e5c07d949d5ae.tar.gz
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>
Diffstat (limited to 'usr/src/uts/common/io/blkdev')
-rw-r--r--usr/src/uts/common/io/blkdev/blkdev.c44
1 files changed, 38 insertions, 6 deletions
diff --git a/usr/src/uts/common/io/blkdev/blkdev.c b/usr/src/uts/common/io/blkdev/blkdev.c
index 3405187f60..2b185dff2b 100644
--- a/usr/src/uts/common/io/blkdev/blkdev.c
+++ b/usr/src/uts/common/io/blkdev/blkdev.c
@@ -495,20 +495,35 @@ static void
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 @@ bd_init_errstats(bd_t *bd, bd_drive_t *drive)
}
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 @@ bd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
}
if (bd->d_errstats != NULL) {
+ bd_fini_errstats(bd);
kstat_delete(bd->d_errstats);
bd->d_errstats = NULL;
} else {