From owner-svn-src-stable-8@FreeBSD.ORG Sun Apr 18 21:14:50 2010 Return-Path: Delivered-To: svn-src-stable-8@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1E0C4106566B; Sun, 18 Apr 2010 21:14:50 +0000 (UTC) (envelope-from pjd@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 08D2A8FC1A; Sun, 18 Apr 2010 21:14:50 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o3ILEoJb095444; Sun, 18 Apr 2010 21:14:50 GMT (envelope-from pjd@svn.freebsd.org) Received: (from pjd@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o3ILEnUo095433; Sun, 18 Apr 2010 21:14:49 GMT (envelope-from pjd@svn.freebsd.org) Message-Id: <201004182114.o3ILEnUo095433@svn.freebsd.org> From: Pawel Jakub Dawidek Date: Sun, 18 Apr 2010 21:14:49 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: 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 X-BeenThere: svn-src-stable-8@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 8-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 18 Apr 2010 21:14:50 -0000 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 + * 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%s\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%u\n", indent, sc->sc_queue_size); sbuf_printf(sb, "%s%u\n", indent, sc->sc_ref); + sbuf_printf(sb, "%s%d\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 + * Copyright (c) 2004-2009 Pawel Jakub Dawidek * 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. + */ +#define G_GATE_UNIT_AUTO (-1) +/* + * Full provider name is given, so don't use ggate. + */ +#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 {