Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 22 Jul 2010 10:24:28 +0000 (UTC)
From:      Jaakko Heinonen <jh@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r210371 - head/sys/dev/md
Message-ID:  <201007221024.o6MAOSsr016472@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jh
Date: Thu Jul 22 10:24:28 2010
New Revision: 210371
URL: http://svn.freebsd.org/changeset/base/210371

Log:
  Convert md(4) to use alloc_unr(9) and alloc_unr_specific(9) for unit
  number allocation. The old approach had some problems such as it allowed
  an overflow to occur in the unit number calculation.
  
  PR:		kern/122288

Modified:
  head/sys/dev/md/md.c

Modified: head/sys/dev/md/md.c
==============================================================================
--- head/sys/dev/md/md.c	Thu Jul 22 09:14:18 2010	(r210370)
+++ head/sys/dev/md/md.c	Thu Jul 22 10:24:28 2010	(r210371)
@@ -130,6 +130,7 @@ static void g_md_dumpconf(struct sbuf *s
 static int	mdunits;
 static struct cdev *status_dev = 0;
 static struct sx md_sx;
+static struct unrhdr *md_uh;
 
 static d_ioctl_t mdctlioctl;
 
@@ -748,20 +749,20 @@ mdfind(int unit)
 static struct md_s *
 mdnew(int unit, int *errp, enum md_types type)
 {
-	struct md_s *sc, *sc2;
-	int error, max = -1;
+	struct md_s *sc;
+	int error;
 
 	*errp = 0;
-	LIST_FOREACH(sc2, &md_softc_list, list) {
-		if (unit == sc2->unit) {
-			*errp = EBUSY;
-			return (NULL);
-		}
-		if (unit == -1 && sc2->unit > max) 
-			max = sc2->unit;
-	}
 	if (unit == -1)
-		unit = max + 1;
+		unit = alloc_unr(md_uh);
+	else
+		unit = alloc_unr_specific(md_uh, unit);
+
+	if (unit == -1) {
+		*errp = EBUSY;
+		return (NULL);
+	}
+
 	sc = (struct md_s *)malloc(sizeof *sc, M_MD, M_WAITOK | M_ZERO);
 	sc->type = type;
 	bioq_init(&sc->bio_queue);
@@ -774,6 +775,7 @@ mdnew(int unit, int *errp, enum md_types
 		return (sc);
 	LIST_REMOVE(sc, list);
 	mtx_destroy(&sc->queue_mtx);
+	free_unr(md_uh, sc->unit);
 	free(sc, M_MD);
 	*errp = error;
 	return (NULL);
@@ -1012,6 +1014,7 @@ mddestroy(struct md_s *sc, struct thread
 		uma_zdestroy(sc->uma);
 
 	LIST_REMOVE(sc, list);
+	free_unr(md_uh, sc->unit);
 	free(sc, M_MD);
 	return (0);
 }
@@ -1097,8 +1100,11 @@ xmdctlioctl(struct cdev *dev, u_long cmd
 		}
 		if (mdio->md_options & MD_AUTOUNIT)
 			sc = mdnew(-1, &error, mdio->md_type);
-		else
+		else {
+			if (mdio->md_unit > INT_MAX)
+				return (EINVAL);
 			sc = mdnew(mdio->md_unit, &error, mdio->md_type);
+		}
 		if (sc == NULL)
 			return (error);
 		if (mdio->md_options & MD_AUTOUNIT)
@@ -1226,6 +1232,7 @@ g_md_init(struct g_class *mp __unused)
 	mod = NULL;
 	sx_init(&md_sx, "MD config lock");
 	g_topology_unlock();
+	md_uh = new_unrhdr(0, INT_MAX, NULL);
 #ifdef MD_ROOT_SIZE
 	sx_xlock(&md_sx);
 	md_preloaded(mfs_root.start, sizeof(mfs_root.start));
@@ -1322,4 +1329,5 @@ g_md_fini(struct g_class *mp __unused)
 	sx_destroy(&md_sx);
 	if (status_dev != NULL)
 		destroy_dev(status_dev);
+	delete_unrhdr(md_uh);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201007221024.o6MAOSsr016472>