svn commit: r206810 - in stable/8: etc/defaults etc/rc.d sbin sbin/ggate/ggatec sbin/ggate/ggatel sbin/hastctl sbin/hastd share/examples share/examples/hast share/man/man5 sys/geom/gate

Pawel Jakub Dawidek pjd at FreeBSD.org
Sun Apr 18 21:14:50 UTC 2010


Author: pjd
Date: Sun Apr 18 21:14:49 2010
New Revision: 206810
URL: http://svn.freebsd.org/changeset/base/206810

Log:
  MFC r204076,r204077,r204083,r205279:
  
  r204076:
  
  Please welcome HAST - Highly Avalable Storage.
  
  HAST allows to transparently store data on two physically separated machines
  connected over the TCP/IP network. HAST works in Primary-Secondary
  (Master-Backup, Master-Slave) configuration, which means that only one of the
  cluster nodes can be active at any given time. Only Primary node is able to
  handle I/O requests to HAST-managed devices. Currently HAST is limited to two
  cluster nodes in total.
  
  HAST operates on block level - it provides disk-like devices in /dev/hast/
  directory for use by file systems and/or applications. Working on block level
  makes it transparent for file systems and applications. There in no difference
  between using HAST-provided device and raw disk, partition, etc. All of them
  are just regular GEOM providers in FreeBSD.
  
  For more information please consult hastd(8), hastctl(8) and hast.conf(5)
  manual pages, as well as http://wiki.FreeBSD.org/HAST.
  
  Sponsored by:	FreeBSD Foundation
  Sponsored by:	OMCnet Internet Service GmbH
  Sponsored by:	TransIP BV
  
  r204077:
  
  Remove some lines left over by accident.
  
  r204083:
  
  Add missing KEYWORD line.
  
  Pointed out by:	dougb
  
  r205279 sys:
  
  Simplify loops.

Added:
  stable/8/etc/rc.d/hastd
     - copied, changed from r204076, head/etc/rc.d/hastd
  stable/8/sbin/hastctl/
     - copied from r204076, head/sbin/hastctl/
  stable/8/sbin/hastd/
     - copied from r204076, head/sbin/hastd/
  stable/8/share/examples/hast/
     - copied from r204076, head/share/examples/hast/
Modified:
  stable/8/etc/defaults/rc.conf
  stable/8/etc/rc.d/Makefile
  stable/8/sbin/Makefile
  stable/8/sbin/ggate/ggatec/ggatec.c
  stable/8/sbin/ggate/ggatel/ggatel.c
  stable/8/share/examples/Makefile
  stable/8/share/man/man5/rc.conf.5
  stable/8/sys/geom/gate/g_gate.c
  stable/8/sys/geom/gate/g_gate.h
Directory Properties:
  stable/8/etc/   (props changed)
  stable/8/sbin/   (props changed)
  stable/8/sbin/atacontrol/   (props changed)
  stable/8/sbin/bsdlabel/   (props changed)
  stable/8/sbin/camcontrol/   (props changed)
  stable/8/sbin/ddb/   (props changed)
  stable/8/sbin/devfs/   (props changed)
  stable/8/sbin/dhclient/   (props changed)
  stable/8/sbin/dump/   (props changed)
  stable/8/sbin/dumpfs/   (props changed)
  stable/8/sbin/fsck/   (props changed)
  stable/8/sbin/fsck_ffs/   (props changed)
  stable/8/sbin/geom/   (props changed)
  stable/8/sbin/geom/class/stripe/   (props changed)
  stable/8/sbin/ggate/   (props changed)
  stable/8/sbin/growfs/   (props changed)
  stable/8/sbin/ifconfig/   (props changed)
  stable/8/sbin/iscontrol/   (props changed)
  stable/8/sbin/mdconfig/   (props changed)
  stable/8/sbin/mksnap_ffs/   (props changed)
  stable/8/sbin/mount/   (props changed)
  stable/8/sbin/mount_cd9660/   (props changed)
  stable/8/sbin/mount_msdosfs/   (props changed)
  stable/8/sbin/mount_nfs/   (props changed)
  stable/8/sbin/natd/   (props changed)
  stable/8/sbin/newfs/   (props changed)
  stable/8/sbin/restore/   (props changed)
  stable/8/sbin/routed/   (props changed)
  stable/8/sbin/sysctl/   (props changed)
  stable/8/sbin/tunefs/   (props changed)
  stable/8/sbin/umount/   (props changed)
  stable/8/share/examples/   (props changed)
  stable/8/share/man/man5/   (props changed)
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/dev/uath/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)

Modified: stable/8/etc/defaults/rc.conf
==============================================================================
--- stable/8/etc/defaults/rc.conf	Sun Apr 18 20:34:46 2010	(r206809)
+++ stable/8/etc/defaults/rc.conf	Sun Apr 18 21:14:49 2010	(r206810)
@@ -258,6 +258,9 @@ syslogd_flags="-s"		# Flags to syslogd (
 inetd_enable="NO"		# Run the network daemon dispatcher (YES/NO).
 inetd_program="/usr/sbin/inetd"	# path to inetd, if you want a different one.
 inetd_flags="-wW -C 60"		# Optional flags to inetd
+hastd_enable="NO"		# Run the HAST daemon (YES/NO).
+hastd_program="/sbin/hastd"	# path to hastd, if you want a different one.
+hastd_flags=""			# Optional flags to hastd.
 #
 # named.  It may be possible to run named in a sandbox, man security for
 # details.

Modified: stable/8/etc/rc.d/Makefile
==============================================================================
--- stable/8/etc/rc.d/Makefile	Sun Apr 18 20:34:46 2010	(r206809)
+++ stable/8/etc/rc.d/Makefile	Sun Apr 18 21:14:49 2010	(r206810)
@@ -12,7 +12,7 @@ FILES=	DAEMON FILESYSTEMS LOGIN NETWORKI
 	encswap \
 	fsck ftp-proxy ftpd \
 	gbde geli geli2 gssd \
-	hcsecd \
+	hastd hcsecd \
 	hostapd hostid hostid_save hostname \
 	inetd initrandom \
 	ip6addrctl ipfilter ipfs ipfw ipmon \

Copied and modified: stable/8/etc/rc.d/hastd (from r204076, head/etc/rc.d/hastd)
==============================================================================
--- head/etc/rc.d/hastd	Thu Feb 18 23:16:19 2010	(r204076, copy source)
+++ stable/8/etc/rc.d/hastd	Sun Apr 18 21:14:49 2010	(r206810)
@@ -6,6 +6,7 @@
 # PROVIDE: hastd
 # REQUIRE: NETWORKING syslogd
 # BEFORE:  DAEMON
+# KEYWORD: nojail shutdown
 
 . /etc/rc.subr
 
@@ -18,10 +19,6 @@ required_files="/etc/hast.conf"
 stop_precmd="hastd_stop_precmd"
 required_modules="geom_gate:g_gate"
 
-sockfile="/var/run/syslogd.sockets"
-evalargs="rc_flags=\"\`set_socketlist\` \$rc_flags\""
-altlog_proglist="named"
-
 hastd_stop_precmd()
 {
 	${hastctl} role init all

Modified: stable/8/sbin/Makefile
==============================================================================
--- stable/8/sbin/Makefile	Sun Apr 18 20:34:46 2010	(r206809)
+++ stable/8/sbin/Makefile	Sun Apr 18 21:14:49 2010	(r206810)
@@ -36,6 +36,8 @@ SUBDIR=	adjkerntz \
 	ggate \
 	growfs \
 	gvinum \
+	hastctl \
+	hastd \
 	ifconfig \
 	init \
 	${_ipf} \

Modified: stable/8/sbin/ggate/ggatec/ggatec.c
==============================================================================
--- stable/8/sbin/ggate/ggatec/ggatec.c	Sun Apr 18 20:34:46 2010	(r206809)
+++ stable/8/sbin/ggate/ggatec/ggatec.c	Sun Apr 18 21:14:49 2010	(r206810)
@@ -59,7 +59,7 @@ enum { UNSET, CREATE, DESTROY, LIST, RES
 
 static const char *path = NULL;
 static const char *host = NULL;
-static int unit = -1;
+static int unit = G_GATE_UNIT_AUTO;
 static unsigned flags = 0;
 static int force = 0;
 static unsigned queue_size = G_GATE_QUEUE_SIZE;

Modified: stable/8/sbin/ggate/ggatel/ggatel.c
==============================================================================
--- stable/8/sbin/ggate/ggatel/ggatel.c	Sun Apr 18 20:34:46 2010	(r206809)
+++ stable/8/sbin/ggate/ggatel/ggatel.c	Sun Apr 18 21:14:49 2010	(r206810)
@@ -50,7 +50,7 @@
 enum { UNSET, CREATE, DESTROY, LIST, RESCUE } action = UNSET;
 
 static const char *path = NULL;
-static int unit = -1;
+static int unit = G_GATE_UNIT_AUTO;
 static unsigned flags = 0;
 static int force = 0;
 static unsigned queue_size = G_GATE_QUEUE_SIZE;

Modified: stable/8/share/examples/Makefile
==============================================================================
--- stable/8/share/examples/Makefile	Sun Apr 18 20:34:46 2010	(r206809)
+++ stable/8/share/examples/Makefile	Sun Apr 18 21:14:49 2010	(r206810)
@@ -13,6 +13,7 @@ LDIRS=	BSD_daemon \
 	drivers \
 	etc \
 	find_interface \
+	hast \
 	ibcs2 \
 	ipfw \
 	kld \
@@ -69,6 +70,11 @@ XFILES=	BSD_daemon/FreeBSD.pfa \
 	find_interface/Makefile \
 	find_interface/README \
 	find_interface/find_interface.c \
+	hast/ucarp.sh \
+	hast/ucarp_down.sh \
+	hast/ucarp_up.sh \
+	hast/vip-down.sh \
+	hast/vip-up.sh \
 	ibcs2/README \
 	ibcs2/hello.uu \
 	ipfw/change_rules.sh \

Modified: stable/8/share/man/man5/rc.conf.5
==============================================================================
--- stable/8/share/man/man5/rc.conf.5	Sun Apr 18 20:34:46 2010	(r206809)
+++ stable/8/share/man/man5/rc.conf.5	Sun Apr 18 21:14:49 2010	(r206810)
@@ -1645,6 +1645,27 @@ is set to
 .Dq Li YES ,
 these are the flags to pass to
 .Xr inetd 8 .
+.It Va hastd_enable
+.Pq Vt bool
+If set to
+.Dq Li YES ,
+run the
+.Xr hastd 8
+daemon.
+.It Va hastd_program
+.Pq Vt str
+Path to
+.Xr hastd 8
+(default
+.Pa /sbin/hastd ) .
+.It Va hastd_flags
+.Pq Vt str
+If
+.Va hastd_enable
+is set to
+.Dq Li YES ,
+these are the flags to pass to
+.Xr hastd 8 .
 .It Va named_enable
 .Pq Vt bool
 If set to

Modified: stable/8/sys/geom/gate/g_gate.c
==============================================================================
--- stable/8/sys/geom/gate/g_gate.c	Sun Apr 18 20:34:46 2010	(r206809)
+++ stable/8/sys/geom/gate/g_gate.c	Sun Apr 18 21:14:49 2010	(r206810)
@@ -1,7 +1,11 @@
 /*-
  * Copyright (c) 2004-2006 Pawel Jakub Dawidek <pjd at FreeBSD.org>
+ * Copyright (c) 2009-2010 The FreeBSD Foundation
  * All rights reserved.
  *
+ * Portions of this software were developed by Pawel Jakub Dawidek
+ * under sponsorship from the FreeBSD Foundation.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -53,9 +57,14 @@ static MALLOC_DEFINE(M_GATE, "gg_data", 
 
 SYSCTL_DECL(_kern_geom);
 SYSCTL_NODE(_kern_geom, OID_AUTO, gate, CTLFLAG_RW, 0, "GEOM_GATE stuff");
-static u_int g_gate_debug = 0;
-SYSCTL_UINT(_kern_geom_gate, OID_AUTO, debug, CTLFLAG_RW, &g_gate_debug, 0,
+static int g_gate_debug = 0;
+TUNABLE_INT("kern.geom.gate.debug", &g_gate_debug);
+SYSCTL_INT(_kern_geom_gate, OID_AUTO, debug, CTLFLAG_RW, &g_gate_debug, 0,
     "Debug level");
+static u_int g_gate_maxunits = 256;
+TUNABLE_INT("kern.geom.gate.maxunits", &g_gate_maxunits);
+SYSCTL_UINT(_kern_geom_gate, OID_AUTO, maxunits, CTLFLAG_RDTUN,
+    &g_gate_maxunits, 0, "Maximum number of ggate devices");
 
 struct g_class g_gate_class = {
 	.name = G_GATE_CLASS_NAME,
@@ -71,10 +80,9 @@ static struct cdevsw g_gate_cdevsw = {
 };
 
 
-static LIST_HEAD(, g_gate_softc) g_gate_list =
-    LIST_HEAD_INITIALIZER(g_gate_list);
-static struct mtx g_gate_list_mtx;
-
+static struct g_gate_softc **g_gate_units;
+static u_int g_gate_nunits;
+static struct mtx g_gate_units_lock;
 
 static int
 g_gate_destroy(struct g_gate_softc *sc, boolean_t force)
@@ -84,13 +92,13 @@ g_gate_destroy(struct g_gate_softc *sc, 
 	struct bio *bp;
 
 	g_topology_assert();
-	mtx_assert(&g_gate_list_mtx, MA_OWNED);
+	mtx_assert(&g_gate_units_lock, MA_OWNED);
 	pp = sc->sc_provider;
 	if (!force && (pp->acr != 0 || pp->acw != 0 || pp->ace != 0)) {
-		mtx_unlock(&g_gate_list_mtx);
+		mtx_unlock(&g_gate_units_lock);
 		return (EBUSY);
 	}
-	mtx_unlock(&g_gate_list_mtx);
+	mtx_unlock(&g_gate_units_lock);
 	mtx_lock(&sc->sc_queue_mtx);
 	if ((sc->sc_flags & G_GATE_FLAG_DESTROY) == 0)
 		sc->sc_flags |= G_GATE_FLAG_DESTROY;
@@ -101,38 +109,29 @@ g_gate_destroy(struct g_gate_softc *sc, 
 	g_orphan_provider(pp, ENXIO);
 	callout_drain(&sc->sc_callout);
 	mtx_lock(&sc->sc_queue_mtx);
-	for (;;) {
-		bp = bioq_first(&sc->sc_inqueue);
-		if (bp != NULL) {
-			bioq_remove(&sc->sc_inqueue, bp);
-			sc->sc_queue_count--;
-			G_GATE_LOGREQ(1, bp, "Request canceled.");
-			g_io_deliver(bp, ENXIO);
-		} else {
-			break;
-		}
+	while ((bp = bioq_first(&sc->sc_inqueue)) != NULL) {
+		bioq_remove(&sc->sc_inqueue, bp);
+		sc->sc_queue_count--;
+		G_GATE_LOGREQ(1, bp, "Request canceled.");
+		g_io_deliver(bp, ENXIO);
 	}
-	for (;;) {
-		bp = bioq_first(&sc->sc_outqueue);
-		if (bp != NULL) {
-			bioq_remove(&sc->sc_outqueue, bp);
-			sc->sc_queue_count--;
-			G_GATE_LOGREQ(1, bp, "Request canceled.");
-			g_io_deliver(bp, ENXIO);
-		} else {
-			break;
-		}
+	while ((bp = bioq_first(&sc->sc_outqueue)) != NULL) {
+		bioq_remove(&sc->sc_outqueue, bp);
+		sc->sc_queue_count--;
+		G_GATE_LOGREQ(1, bp, "Request canceled.");
+		g_io_deliver(bp, ENXIO);
 	}
 	mtx_unlock(&sc->sc_queue_mtx);
 	g_topology_unlock();
-	mtx_lock(&g_gate_list_mtx);
+	mtx_lock(&g_gate_units_lock);
 	/* One reference is ours. */
 	sc->sc_ref--;
-	while (sc->sc_ref > 0) {
-		msleep(&sc->sc_ref, &g_gate_list_mtx, 0, "gg:destroy", 0);
-	}
-	LIST_REMOVE(sc, sc_next);
-	mtx_unlock(&g_gate_list_mtx);
+	while (sc->sc_ref > 0)
+		msleep(&sc->sc_ref, &g_gate_units_lock, 0, "gg:destroy", 0);
+	g_gate_units[sc->sc_unit] = NULL;
+	KASSERT(g_gate_nunits > 0, ("negative g_gate_nunits?"));
+	g_gate_nunits--;
+	mtx_unlock(&g_gate_units_lock);
 	mtx_destroy(&sc->sc_queue_mtx);
 	g_topology_lock();
 	G_GATE_DEBUG(0, "Device %s destroyed.", gp->name);
@@ -196,7 +195,7 @@ g_gate_start(struct bio *bp)
 	if (sc->sc_queue_count > sc->sc_queue_size) {
 		mtx_unlock(&sc->sc_queue_mtx);
 		G_GATE_LOGREQ(1, bp, "Queue full, request canceled.");
-		g_io_deliver(bp, EIO);
+		g_io_deliver(bp, ENOMEM);
 		return;
 	}
 
@@ -211,18 +210,29 @@ g_gate_start(struct bio *bp)
 }
 
 static struct g_gate_softc *
-g_gate_hold(u_int unit)
+g_gate_hold(u_int unit, const char *name)
 {
-	struct g_gate_softc *sc;
+	struct g_gate_softc *sc = NULL;
 
-	mtx_lock(&g_gate_list_mtx);
-	LIST_FOREACH(sc, &g_gate_list, sc_next) {
-		if (sc->sc_unit == unit)
+	mtx_lock(&g_gate_units_lock);
+	if (unit >= 0 && unit < g_gate_maxunits)
+		sc = g_gate_units[unit];
+	else if (unit == G_GATE_NAME_GIVEN) {
+		KASSERT(name != NULL, ("name is NULL"));
+		for (unit = 0; unit < g_gate_maxunits; unit++) {
+			if (g_gate_units[unit] == NULL)
+				continue;
+			if (strcmp(name,
+			    g_gate_units[unit]->sc_provider->name) != 0) {
+				continue;
+			}
+			sc = g_gate_units[unit];
 			break;
+		}
 	}
 	if (sc != NULL)
 		sc->sc_ref++;
-	mtx_unlock(&g_gate_list_mtx);
+	mtx_unlock(&g_gate_units_lock);
 	return (sc);
 }
 
@@ -231,40 +241,34 @@ g_gate_release(struct g_gate_softc *sc)
 {
 
 	g_topology_assert_not();
-	mtx_lock(&g_gate_list_mtx);
+	mtx_lock(&g_gate_units_lock);
 	sc->sc_ref--;
 	KASSERT(sc->sc_ref >= 0, ("Negative sc_ref for %s.", sc->sc_name));
-	if (sc->sc_ref == 0 && (sc->sc_flags & G_GATE_FLAG_DESTROY) != 0) {
+	if (sc->sc_ref == 0 && (sc->sc_flags & G_GATE_FLAG_DESTROY) != 0)
 		wakeup(&sc->sc_ref);
-		mtx_unlock(&g_gate_list_mtx);
-	} else {
-		mtx_unlock(&g_gate_list_mtx);
-	}
+	mtx_unlock(&g_gate_units_lock);
 }
 
 static int
-g_gate_getunit(int unit)
+g_gate_getunit(int unit, int *errorp)
 {
-	struct g_gate_softc *sc;
 
-	mtx_assert(&g_gate_list_mtx, MA_OWNED);
+	mtx_assert(&g_gate_units_lock, MA_OWNED);
 	if (unit >= 0) {
-		LIST_FOREACH(sc, &g_gate_list, sc_next) {
-			if (sc->sc_unit == unit)
-				return (-1);
-		}
+		if (unit >= g_gate_maxunits)
+			*errorp = EINVAL;
+		else if (g_gate_units[unit] == NULL)
+			return (unit);
+		else
+			*errorp = EEXIST;
 	} else {
-		unit = 0;
-once_again:
-		LIST_FOREACH(sc, &g_gate_list, sc_next) {
-			if (sc->sc_unit == unit) {
-				if (++unit > 666)
-					return (-1);
-				goto once_again;
-			}
+		for (unit = 0; unit < g_gate_maxunits; unit++) {
+			if (g_gate_units[unit] == NULL)
+				return (unit);
 		}
+		*errorp = ENFILE;
 	}
-	return (unit);
+	return (-1);
 }
 
 static void
@@ -276,7 +280,7 @@ g_gate_guard(void *arg)
 
 	sc = arg;
 	binuptime(&curtime);
-	g_gate_hold(sc->sc_unit);
+	g_gate_hold(sc->sc_unit, NULL);
 	mtx_lock(&sc->sc_queue_mtx);
 	TAILQ_FOREACH_SAFE(bp, &sc->sc_inqueue.queue, bio_queue, bp2) {
 		if (curtime.sec - bp->bio_t0.sec < 5)
@@ -311,7 +315,7 @@ g_gate_dumpconf(struct sbuf *sb, const c
 	sc = gp->softc;
 	if (sc == NULL || pp != NULL || cp != NULL)
 		return;
-	g_gate_hold(sc->sc_unit);
+	g_gate_hold(sc->sc_unit, NULL);
 	if ((sc->sc_flags & G_GATE_FLAG_READONLY) != 0) {
 		sbuf_printf(sb, "%s<access>%s</access>\n", indent, "read-only");
 	} else if ((sc->sc_flags & G_GATE_FLAG_WRITEONLY) != 0) {
@@ -328,6 +332,7 @@ g_gate_dumpconf(struct sbuf *sb, const c
 	sbuf_printf(sb, "%s<queue_size>%u</queue_size>\n", indent,
 	    sc->sc_queue_size);
 	sbuf_printf(sb, "%s<ref>%u</ref>\n", indent, sc->sc_ref);
+	sbuf_printf(sb, "%s<unit>%d</unit>\n", indent, sc->sc_unit);
 	g_topology_unlock();
 	g_gate_release(sc);
 	g_topology_lock();
@@ -339,6 +344,8 @@ g_gate_create(struct g_gate_ctl_create *
 	struct g_gate_softc *sc;
 	struct g_geom *gp;
 	struct g_provider *pp;
+	char name[NAME_MAX];
+	int error = 0, unit;
 
 	if (ggio->gctl_mediasize == 0) {
 		G_GATE_DEBUG(1, "Invalid media size.");
@@ -357,15 +364,22 @@ g_gate_create(struct g_gate_ctl_create *
 		G_GATE_DEBUG(1, "Invalid flags.");
 		return (EINVAL);
 	}
-	if (ggio->gctl_unit < -1) {
+	if (ggio->gctl_unit != G_GATE_UNIT_AUTO &&
+	    ggio->gctl_unit != G_GATE_NAME_GIVEN &&
+	    ggio->gctl_unit < 0) {
 		G_GATE_DEBUG(1, "Invalid unit number.");
 		return (EINVAL);
 	}
+	if (ggio->gctl_unit == G_GATE_NAME_GIVEN &&
+	    ggio->gctl_name[0] == '\0') {
+		G_GATE_DEBUG(1, "No device name.");
+		return (EINVAL);
+	}
 
 	sc = malloc(sizeof(*sc), M_GATE, M_WAITOK | M_ZERO);
 	sc->sc_flags = (ggio->gctl_flags & G_GATE_USERFLAGS);
 	strlcpy(sc->sc_info, ggio->gctl_info, sizeof(sc->sc_info));
-	sc->sc_seq = 0;
+	sc->sc_seq = 1;
 	bioq_init(&sc->sc_inqueue);
 	bioq_init(&sc->sc_outqueue);
 	mtx_init(&sc->sc_queue_mtx, "gg:queue", NULL, MTX_DEF);
@@ -375,26 +389,44 @@ g_gate_create(struct g_gate_ctl_create *
 		sc->sc_queue_size = G_GATE_MAX_QUEUE_SIZE;
 	sc->sc_timeout = ggio->gctl_timeout;
 	callout_init(&sc->sc_callout, CALLOUT_MPSAFE);
-	mtx_lock(&g_gate_list_mtx);
-	ggio->gctl_unit = g_gate_getunit(ggio->gctl_unit);
-	if (ggio->gctl_unit == -1) {
-		mtx_unlock(&g_gate_list_mtx);
+	mtx_lock(&g_gate_units_lock);
+	sc->sc_unit = g_gate_getunit(ggio->gctl_unit, &error);
+	if (sc->sc_unit < 0) {
+		mtx_unlock(&g_gate_units_lock);
 		mtx_destroy(&sc->sc_queue_mtx);
 		free(sc, M_GATE);
-		return (EBUSY);
+		return (error);
 	}
-	sc->sc_unit = ggio->gctl_unit;
-	LIST_INSERT_HEAD(&g_gate_list, sc, sc_next);
-	mtx_unlock(&g_gate_list_mtx);
+	if (ggio->gctl_unit == G_GATE_NAME_GIVEN)
+		snprintf(name, sizeof(name), "%s", ggio->gctl_name);
+	else {
+		snprintf(name, sizeof(name), "%s%d", G_GATE_PROVIDER_NAME,
+		    sc->sc_unit);
+	}
+	/* Check for name collision. */
+	for (unit = 0; unit < g_gate_maxunits; unit++) {
+		if (g_gate_units[unit] == NULL)
+			continue;
+		if (strcmp(name, g_gate_units[unit]->sc_provider->name) != 0)
+			continue;
+		mtx_unlock(&g_gate_units_lock);
+		mtx_destroy(&sc->sc_queue_mtx);
+		free(sc, M_GATE);
+		return (EEXIST);
+	}
+	g_gate_units[sc->sc_unit] = sc;
+	g_gate_nunits++;
+	mtx_unlock(&g_gate_units_lock);
+
+	ggio->gctl_unit = sc->sc_unit;
 
 	g_topology_lock();
-	gp = g_new_geomf(&g_gate_class, "%s%d", G_GATE_PROVIDER_NAME,
-	    sc->sc_unit);
+	gp = g_new_geomf(&g_gate_class, "%s", name);
 	gp->start = g_gate_start;
 	gp->access = g_gate_access;
 	gp->dumpconf = g_gate_dumpconf;
 	gp->softc = sc;
-	pp = g_new_providerf(gp, "%s%d", G_GATE_PROVIDER_NAME, sc->sc_unit);
+	pp = g_new_providerf(gp, "%s", name);
 	pp->mediasize = ggio->gctl_mediasize;
 	pp->sectorsize = ggio->gctl_sectorsize;
 	sc->sc_provider = pp;
@@ -446,11 +478,11 @@ g_gate_ioctl(struct cdev *dev, u_long cm
 		struct g_gate_ctl_destroy *ggio = (void *)addr;
 
 		G_GATE_CHECK_VERSION(ggio);
-		sc = g_gate_hold(ggio->gctl_unit);
+		sc = g_gate_hold(ggio->gctl_unit, ggio->gctl_name);
 		if (sc == NULL)
 			return (ENXIO);
 		g_topology_lock();
-		mtx_lock(&g_gate_list_mtx);
+		mtx_lock(&g_gate_units_lock);
 		error = g_gate_destroy(sc, ggio->gctl_force);
 		g_topology_unlock();
 		if (error != 0)
@@ -463,7 +495,7 @@ g_gate_ioctl(struct cdev *dev, u_long cm
 		struct bio *tbp, *lbp;
 
 		G_GATE_CHECK_VERSION(ggio);
-		sc = g_gate_hold(ggio->gctl_unit);
+		sc = g_gate_hold(ggio->gctl_unit, ggio->gctl_name);
 		if (sc == NULL)
 			return (ENXIO);
 		lbp = NULL;
@@ -491,6 +523,8 @@ g_gate_ioctl(struct cdev *dev, u_long cm
 					break;
 			}
 		}
+		if (ggio->gctl_unit == G_GATE_NAME_GIVEN)
+			ggio->gctl_unit = sc->sc_unit;
 		mtx_unlock(&sc->sc_queue_mtx);
 		g_gate_release(sc);
 		return (error);
@@ -500,7 +534,7 @@ g_gate_ioctl(struct cdev *dev, u_long cm
 		struct g_gate_ctl_io *ggio = (void *)addr;
 
 		G_GATE_CHECK_VERSION(ggio);
-		sc = g_gate_hold(ggio->gctl_unit);
+		sc = g_gate_hold(ggio->gctl_unit, NULL);
 		if (sc == NULL)
 			return (ENXIO);
 		error = 0;
@@ -561,7 +595,7 @@ start_end:
 		struct g_gate_ctl_io *ggio = (void *)addr;
 
 		G_GATE_CHECK_VERSION(ggio);
-		sc = g_gate_hold(ggio->gctl_unit);
+		sc = g_gate_hold(ggio->gctl_unit, NULL);
 		if (sc == NULL)
 			return (ENOENT);
 		error = 0;
@@ -631,20 +665,24 @@ g_gate_modevent(module_t mod, int type, 
 
 	switch (type) {
 	case MOD_LOAD:
-		mtx_init(&g_gate_list_mtx, "gg_list_lock", NULL, MTX_DEF);
+		mtx_init(&g_gate_units_lock, "gg_units_lock", NULL, MTX_DEF);
+		g_gate_units = malloc(g_gate_maxunits * sizeof(g_gate_units[0]),
+		    M_GATE, M_WAITOK | M_ZERO);
+		g_gate_nunits = 0;
 		g_gate_device();
 		break;
 	case MOD_UNLOAD:
-		mtx_lock(&g_gate_list_mtx);
-		if (!LIST_EMPTY(&g_gate_list)) {
-			mtx_unlock(&g_gate_list_mtx);
+		mtx_lock(&g_gate_units_lock);
+		if (g_gate_nunits > 0) {
+			mtx_unlock(&g_gate_units_lock);
 			error = EBUSY;
 			break;
 		}
-		mtx_unlock(&g_gate_list_mtx);
-		mtx_destroy(&g_gate_list_mtx);
+		mtx_unlock(&g_gate_units_lock);
+		mtx_destroy(&g_gate_units_lock);
 		if (status_dev != 0)
 			destroy_dev(status_dev);
+		free(g_gate_units, M_GATE);
 		break;
 	default:
 		return (EOPNOTSUPP);

Modified: stable/8/sys/geom/gate/g_gate.h
==============================================================================
--- stable/8/sys/geom/gate/g_gate.h	Sun Apr 18 20:34:46 2010	(r206809)
+++ stable/8/sys/geom/gate/g_gate.h	Sun Apr 18 21:14:49 2010	(r206810)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2004-2006 Pawel Jakub Dawidek <pjd at FreeBSD.org>
+ * Copyright (c) 2004-2009 Pawel Jakub Dawidek <pjd at FreeBSD.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -41,7 +41,7 @@
 #define	G_GATE_MOD_NAME		"ggate"
 #define	G_GATE_CTL_NAME		"ggctl"
 
-#define G_GATE_VERSION		1
+#define G_GATE_VERSION		2
 
 /*
  * Maximum number of request that can be stored in
@@ -54,6 +54,15 @@
 #define	G_GATE_FLAG_DESTROY	0x1000
 #define	G_GATE_USERFLAGS	(G_GATE_FLAG_READONLY | G_GATE_FLAG_WRITEONLY)
 
+/*
+ * Pick unit number automatically in /dev/ggate<unit>.
+ */
+#define	G_GATE_UNIT_AUTO	(-1)
+/*
+ * Full provider name is given, so don't use ggate<unit>.
+ */
+#define	G_GATE_NAME_GIVEN	(-2)
+
 #define G_GATE_CMD_CREATE	_IOWR('m', 0, struct g_gate_ctl_create)
 #define G_GATE_CMD_DESTROY	_IOWR('m', 1, struct g_gate_ctl_destroy)
 #define G_GATE_CMD_CANCEL	_IOWR('m', 2, struct g_gate_ctl_cancel)
@@ -120,20 +129,23 @@ struct g_gate_ctl_create {
 	u_int	gctl_flags;
 	u_int	gctl_maxcount;
 	u_int	gctl_timeout;
+	char	gctl_name[NAME_MAX];
 	char	gctl_info[G_GATE_INFOSIZE];
-	int	gctl_unit;	/* out */
+	int	gctl_unit;	/* in/out */
 };
 
 struct g_gate_ctl_destroy {
 	u_int	gctl_version;
 	int	gctl_unit;
 	int	gctl_force;
+	char	gctl_name[NAME_MAX];
 };
 
 struct g_gate_ctl_cancel {
 	u_int		gctl_version;
 	int		gctl_unit;
 	uintptr_t	gctl_seq;
+	char		gctl_name[NAME_MAX];
 };
 
 struct g_gate_ctl_io {


More information about the svn-src-stable-8 mailing list