From owner-svn-src-head@FreeBSD.ORG Tue Nov 1 20:56:19 2011 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 84848106564A; Tue, 1 Nov 2011 20:56:19 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 73DE08FC16; Tue, 1 Nov 2011 20:56:19 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id pA1KuJfM083267; Tue, 1 Nov 2011 20:56:19 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id pA1KuJrt083264; Tue, 1 Nov 2011 20:56:19 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <201111012056.pA1KuJrt083264@svn.freebsd.org> From: Alexander Motin Date: Tue, 1 Nov 2011 20:56:19 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r227004 - head/sys/geom/concat X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 01 Nov 2011 20:56:19 -0000 Author: mav Date: Tue Nov 1 20:56:19 2011 New Revision: 227004 URL: http://svn.freebsd.org/changeset/base/227004 Log: Refactor disk disconnection and geom destruction handling sequences. Do not close/destroy opened consumer directly in case of disconnect. Instead keep it existing until it will be closed in regular way in response to upstream provider destruction. Delay geom destruction in the same way. Previous implementation could destroy consumers still having active requests and worked only because of global workaround made on GEOM level. Modified: head/sys/geom/concat/g_concat.c head/sys/geom/concat/g_concat.h Modified: head/sys/geom/concat/g_concat.c ============================================================================== --- head/sys/geom/concat/g_concat.c Tue Nov 1 19:29:03 2011 (r227003) +++ head/sys/geom/concat/g_concat.c Tue Nov 1 20:56:19 2011 (r227004) @@ -117,25 +117,33 @@ g_concat_remove_disk(struct g_concat_dis struct g_consumer *cp; struct g_concat_softc *sc; + g_topology_assert(); KASSERT(disk->d_consumer != NULL, ("Non-valid disk in %s.", __func__)); sc = disk->d_softc; cp = disk->d_consumer; - G_CONCAT_DEBUG(0, "Disk %s removed from %s.", cp->provider->name, - sc->sc_name); + if (!disk->d_removed) { + G_CONCAT_DEBUG(0, "Disk %s removed from %s.", + cp->provider->name, sc->sc_name); + disk->d_removed = 1; + } - disk->d_consumer = NULL; if (sc->sc_provider != NULL) { sc->sc_provider->flags |= G_PF_WITHER; + G_CONCAT_DEBUG(0, "Device %s deactivated.", + sc->sc_provider->name); g_orphan_provider(sc->sc_provider, ENXIO); sc->sc_provider = NULL; - G_CONCAT_DEBUG(0, "Device %s removed.", sc->sc_name); } if (cp->acr > 0 || cp->acw > 0 || cp->ace > 0) - g_access(cp, -cp->acr, -cp->acw, -cp->ace); + return; + disk->d_consumer = NULL; g_detach(cp); g_destroy_consumer(cp); + /* If there are no valid disks anymore, remove device. */ + if (LIST_EMPTY(&sc->sc_geom->consumer)) + g_concat_destroy(sc, 1); } static void @@ -155,37 +163,18 @@ g_concat_orphan(struct g_consumer *cp) if (disk == NULL) /* Possible? */ return; g_concat_remove_disk(disk); - - /* If there are no valid disks anymore, remove device. */ - if (g_concat_nvalid(sc) == 0) - g_concat_destroy(sc, 1); } static int g_concat_access(struct g_provider *pp, int dr, int dw, int de) { - struct g_consumer *cp1, *cp2; - struct g_concat_softc *sc; + struct g_consumer *cp1, *cp2, *tmp; + struct g_concat_disk *disk; struct g_geom *gp; int error; + g_topology_assert(); gp = pp->geom; - sc = gp->softc; - - if (sc == NULL) { - /* - * It looks like geom is being withered. - * In that case we allow only negative requests. - */ - KASSERT(dr <= 0 && dw <= 0 && de <= 0, - ("Positive access request (device=%s).", pp->name)); - if ((pp->acr + dr) == 0 && (pp->acw + dw) == 0 && - (pp->ace + de) == 0) { - G_CONCAT_DEBUG(0, "Device %s definitely destroyed.", - gp->name); - } - return (0); - } /* On first open, grab an extra "exclusive" bit */ if (pp->acr == 0 && pp->acw == 0 && pp->ace == 0) @@ -194,22 +183,24 @@ g_concat_access(struct g_provider *pp, i if ((pp->acr + dr) == 0 && (pp->acw + dw) == 0 && (pp->ace + de) == 0) de--; - error = ENXIO; - LIST_FOREACH(cp1, &gp->consumer, consumer) { + LIST_FOREACH_SAFE(cp1, &gp->consumer, consumer, tmp) { error = g_access(cp1, dr, dw, de); - if (error == 0) - continue; - /* - * If we fail here, backout all previous changes. - */ - LIST_FOREACH(cp2, &gp->consumer, consumer) { - if (cp1 == cp2) - return (error); - g_access(cp2, -dr, -dw, -de); + if (error != 0) + goto fail; + disk = cp1->private; + if (cp1->acr == 0 && cp1->acw == 0 && cp1->ace == 0 && + disk->d_removed) { + g_concat_remove_disk(disk); /* May destroy geom. */ } - /* NOTREACHED */ } + return (0); +fail: + LIST_FOREACH(cp2, &gp->consumer, consumer) { + if (cp1 == cp2) + break; + g_access(cp2, -dr, -dw, -de); + } return (error); } @@ -391,6 +382,7 @@ g_concat_check_and_run(struct g_concat_s u_int no, sectorsize = 0; off_t start; + g_topology_assert(); if (g_concat_nvalid(sc) != sc->sc_ndisks) return; @@ -419,7 +411,7 @@ g_concat_check_and_run(struct g_concat_s sc->sc_provider = pp; g_error_provider(pp, 0); - G_CONCAT_DEBUG(0, "Device %s activated.", sc->sc_name); + G_CONCAT_DEBUG(0, "Device %s activated.", sc->sc_provider->name); } static int @@ -461,6 +453,7 @@ g_concat_add_disk(struct g_concat_softc struct g_geom *gp; int error; + g_topology_assert(); /* Metadata corrupted? */ if (no >= sc->sc_ndisks) return (EINVAL); @@ -509,6 +502,7 @@ g_concat_add_disk(struct g_concat_softc disk->d_softc = sc; disk->d_start = 0; /* not yet */ disk->d_end = 0; /* not yet */ + disk->d_removed = 0; G_CONCAT_DEBUG(0, "Disk %s attached to %s.", pp->name, sc->sc_name); @@ -576,8 +570,8 @@ static int g_concat_destroy(struct g_concat_softc *sc, boolean_t force) { struct g_provider *pp; + struct g_consumer *cp, *cp1; struct g_geom *gp; - u_int no; g_topology_assert(); @@ -597,24 +591,23 @@ g_concat_destroy(struct g_concat_softc * } } - for (no = 0; no < sc->sc_ndisks; no++) { - if (sc->sc_disks[no].d_consumer != NULL) - g_concat_remove_disk(&sc->sc_disks[no]); + gp = sc->sc_geom; + LIST_FOREACH_SAFE(cp, &gp->consumer, consumer, cp1) { + g_concat_remove_disk(cp->private); + if (cp1 == NULL) + return (0); /* Recursion happened. */ } + if (!LIST_EMPTY(&gp->consumer)) + return (EINPROGRESS); - gp = sc->sc_geom; gp->softc = NULL; KASSERT(sc->sc_provider == NULL, ("Provider still exists? (device=%s)", gp->name)); free(sc->sc_disks, M_CONCAT); free(sc, M_CONCAT); - pp = LIST_FIRST(&gp->provider); - if (pp == NULL || (pp->acr == 0 && pp->acw == 0 && pp->ace == 0)) - G_CONCAT_DEBUG(0, "Device %s destroyed.", gp->name); - + G_CONCAT_DEBUG(0, "Device %s destroyed.", gp->name); g_wither_geom(gp, ENXIO); - return (0); } Modified: head/sys/geom/concat/g_concat.h ============================================================================== --- head/sys/geom/concat/g_concat.h Tue Nov 1 19:29:03 2011 (r227003) +++ head/sys/geom/concat/g_concat.h Tue Nov 1 20:56:19 2011 (r227004) @@ -72,6 +72,7 @@ struct g_concat_disk { struct g_concat_softc *d_softc; off_t d_start; off_t d_end; + int d_removed; }; struct g_concat_softc {