Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/dkwedge dk(4): Avoid holding dkwedges_lock while all...
details: https://anonhg.NetBSD.org/src/rev/544bbe555d57
branches: trunk
changeset: 374372:544bbe555d57
user: riastradh <riastradh%NetBSD.org@localhost>
date: Fri Apr 21 18:24:19 2023 +0000
description:
dk(4): Avoid holding dkwedges_lock while allocating array.
This is not great -- we shouldn't be choosing the unit number here
anyway; we should just let autoconf do it for us -- but it's better
than potentially blocking any dk_openlock or dk_rawlock (which are
sometimes held when waiting for dkwedges_lock) for memory allocation.
diffstat:
sys/dev/dkwedge/dk.c | 48 +++++++++++++++++++++++++++++++++++++++---------
1 files changed, 39 insertions(+), 9 deletions(-)
diffs (87 lines):
diff -r 1617c1360537 -r 544bbe555d57 sys/dev/dkwedge/dk.c
--- a/sys/dev/dkwedge/dk.c Fri Apr 21 18:09:38 2023 +0000
+++ b/sys/dev/dkwedge/dk.c Fri Apr 21 18:24:19 2023 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dk.c,v 1.126 2023/04/21 18:09:38 riastradh Exp $ */
+/* $NetBSD: dk.c,v 1.127 2023/04/21 18:24:19 riastradh Exp $ */
/*-
* Copyright (c) 2004, 2005, 2006, 2007 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dk.c,v 1.126 2023/04/21 18:09:38 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dk.c,v 1.127 2023/04/21 18:24:19 riastradh Exp $");
#ifdef _KERNEL_OPT
#include "opt_dkwedge.h"
@@ -242,21 +242,49 @@ dkwedge_compute_pdev(const char *pname,
* dkwedge_array_expand:
*
* Expand the dkwedges array.
+ *
+ * Releases and reacquires dkwedges_lock as a writer.
*/
-static void
+static int
dkwedge_array_expand(void)
{
- int newcnt = ndkwedges + 16;
- struct dkwedge_softc **newarray, **oldarray;
+
+ const unsigned incr = 16;
+ unsigned newcnt, oldcnt;
+ struct dkwedge_softc **newarray = NULL, **oldarray = NULL;
+
+ KASSERT(rw_write_held(&dkwedges_lock));
+ oldcnt = ndkwedges;
+ oldarray = dkwedges;
+
+ if (oldcnt >= INT_MAX - incr)
+ return ENFILE; /* XXX */
+ newcnt = oldcnt + incr;
+
+ rw_exit(&dkwedges_lock);
newarray = malloc(newcnt * sizeof(*newarray), M_DKWEDGE,
M_WAITOK|M_ZERO);
- if ((oldarray = dkwedges) != NULL)
+ rw_enter(&dkwedges_lock, RW_WRITER);
+
+ if (ndkwedges != oldcnt || dkwedges != oldarray) {
+ oldarray = NULL; /* already recycled */
+ goto out;
+ }
+
+ if (oldarray != NULL)
memcpy(newarray, dkwedges, ndkwedges * sizeof(*newarray));
dkwedges = newarray;
+ newarray = NULL; /* transferred to dkwedges */
ndkwedges = newcnt;
+
+out: rw_exit(&dkwedges_lock);
if (oldarray != NULL)
free(oldarray, M_DKWEDGE);
+ if (newarray != NULL)
+ free(newarray, M_DKWEDGE);
+ rw_enter(&dkwedges_lock, RW_WRITER);
+ return 0;
}
static void
@@ -434,9 +462,11 @@ dkwedge_add(struct dkwedge_info *dkw)
if (error)
break;
KASSERT(unit == ndkwedges);
- if (scpp == NULL)
- dkwedge_array_expand();
- else {
+ if (scpp == NULL) {
+ error = dkwedge_array_expand();
+ if (error)
+ break;
+ } else {
KASSERT(scpp == &dkwedges[sc->sc_cfdata.cf_unit]);
*scpp = sc;
break;
Home |
Main Index |
Thread Index |
Old Index