From owner-svn-src-all@freebsd.org Mon May 11 22:39:53 2020 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id B815B2D8D51; Mon, 11 May 2020 22:39:53 +0000 (UTC) (envelope-from cem@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 49LbV14QdYz4K8C; Mon, 11 May 2020 22:39:53 +0000 (UTC) (envelope-from cem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 9327A25C07; Mon, 11 May 2020 22:39:53 +0000 (UTC) (envelope-from cem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 04BMdrAc084553; Mon, 11 May 2020 22:39:53 GMT (envelope-from cem@FreeBSD.org) Received: (from cem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 04BMdrq9084552; Mon, 11 May 2020 22:39:53 GMT (envelope-from cem@FreeBSD.org) Message-Id: <202005112239.04BMdrq9084552@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: cem set sender to cem@FreeBSD.org using -f From: Conrad Meyer Date: Mon, 11 May 2020 22:39:53 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r360941 - head/sys/geom/mirror X-SVN-Group: head X-SVN-Commit-Author: cem X-SVN-Commit-Paths: head/sys/geom/mirror X-SVN-Commit-Revision: 360941 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 11 May 2020 22:39:53 -0000 Author: cem Date: Mon May 11 22:39:53 2020 New Revision: 360941 URL: https://svnweb.freebsd.org/changeset/base/360941 Log: geom(4) mirror: Do not panic on gmirror(8) insert, resize Geom_mirror initialization occurs in spurts and the present of a non-destroyed g_mirror softc does not always indicate that the geom has launched (i.e., has an sc_provider). Some gmirror(8) commands (via g_mirror_ctl) depend on a g_mirror's sc_provider (insert and resize). For those commands, g_mirror_ctl is modified to sleep-poll in an interruptible way until the target geom is either launched or destroyed. Reviewed by: markj Tested by: markj Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D24780 Modified: head/sys/geom/mirror/g_mirror_ctl.c Modified: head/sys/geom/mirror/g_mirror_ctl.c ============================================================================== --- head/sys/geom/mirror/g_mirror_ctl.c Mon May 11 22:38:32 2020 (r360940) +++ head/sys/geom/mirror/g_mirror_ctl.c Mon May 11 22:39:53 2020 (r360941) @@ -44,6 +44,10 @@ __FBSDID("$FreeBSD$"); #include #include +/* + * Configure, Rebuild, Remove, Deactivate, Forget, and Stop operations do not + * seem to depend on any particular g_mirror initialization state. + */ static struct g_mirror_softc * g_mirror_find_device(struct g_class *mp, const char *name) { @@ -61,6 +65,10 @@ g_mirror_find_device(struct g_class *mp, const char *n strcmp(sc->sc_name, name) == 0) { g_topology_unlock(); sx_xlock(&sc->sc_lock); + if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROY) != 0) { + sx_xunlock(&sc->sc_lock); + return (NULL); + } return (sc); } } @@ -68,6 +76,55 @@ g_mirror_find_device(struct g_class *mp, const char *n return (NULL); } +/* Insert and Resize operations depend on a launched GEOM (sc_provider). */ +#define GMFL_VALID_FLAGS (M_WAITOK | M_NOWAIT) +static struct g_mirror_softc * +g_mirror_find_launched_device(struct g_class *mp, const char *name, int flags) +{ + struct g_mirror_softc *sc; + int error; + + KASSERT((flags & ~GMFL_VALID_FLAGS) == 0 && + flags != GMFL_VALID_FLAGS && flags != 0, + ("%s: Invalid flags %x\n", __func__, (unsigned)flags)); +#undef GMFL_VALID_FLAGS + + while (true) { + sc = g_mirror_find_device(mp, name); + if (sc == NULL) + return (NULL); + if (sc->sc_provider != NULL) + return (sc); + if (flags & M_NOWAIT) { + sx_xunlock(&sc->sc_lock); + return (NULL); + } + + /* + * This is a dumb hack. G_mirror does not expose any real + * wakeup API for observing state changes, and even if it did, + * its "RUNNING" state does not actually reflect all softc + * elements being initialized. + * + * Revamping g_mirror to have a 3rd, ACTUALLY_RUNNING state and + * updating all assertions and sc_state checks is a large work + * and would be easy to introduce regressions. + * + * Revamping g_mirror to have a wakeup for state changes would + * be difficult if one wanted to capture more than just + * sc_state and sc_provider. + * + * For now, just dummy sleep-poll until sc_provider shows up, + * the user cancels, or the g_mirror is destroyed. + */ + error = sx_sleep(&sc, &sc->sc_lock, PRIBIO | PCATCH | PDROP, + "GM:launched", 1); + if (error != 0 && error != EWOULDBLOCK) + return (NULL); + } + __unreachable(); +} + static struct g_mirror_disk * g_mirror_find_disk(struct g_mirror_softc *sc, const char *name) { @@ -605,7 +662,7 @@ g_mirror_ctl_insert(struct gctl_req *req, struct g_cla gctl_error(req, "No 'arg%u' argument.", 0); return; } - sc = g_mirror_find_device(mp, name); + sc = g_mirror_find_launched_device(mp, name, M_WAITOK); if (sc == NULL) { gctl_error(req, "No such device: %s.", name); return; @@ -847,7 +904,7 @@ g_mirror_ctl_resize(struct gctl_req *req, struct g_cla gctl_error(req, "Invalid '%s' argument.", "size"); return; } - sc = g_mirror_find_device(mp, name); + sc = g_mirror_find_launched_device(mp, name, M_WAITOK); if (sc == NULL) { gctl_error(req, "No such device: %s.", name); return;