svn commit: r355895 - stable/12/sys/geom
Alexander Motin
mav at FreeBSD.org
Thu Dec 19 01:34:35 UTC 2019
Author: mav
Date: Thu Dec 19 01:34:34 2019
New Revision: 355895
URL: https://svnweb.freebsd.org/changeset/base/355895
Log:
MFC r355451: Remove some branching from GEOM_DISK hot path.
pp->private just can not be NULL in those places.
In g_disk_start() and g_disk_ioctl() both dp != NULL and !dp->d_destroyed
should always be true if disk_gone() and disk_destroy() are used properly,
since GEOM does not send requests to errored providers. If the protocol is
not followed, then no amount of additional checks here give real safety.
In g_disk_access() though the checks are useful, since GEOM blocks only
new opens for errored providers, but allows closes. It should not happen
if disk_gone() and disk_destroy() are used properly, but may otherwise.
To improve cases when disk_gone() is not used, call it from disk_destroy().
It does not give full guaranties, but it errors the provider and makes
GEOM block unwanted requests at least after some race.
Modified:
stable/12/sys/geom/geom_disk.c
Directory Properties:
stable/12/ (props changed)
Modified: stable/12/sys/geom/geom_disk.c
==============================================================================
--- stable/12/sys/geom/geom_disk.c Thu Dec 19 01:32:15 2019 (r355894)
+++ stable/12/sys/geom/geom_disk.c Thu Dec 19 01:34:34 2019 (r355895)
@@ -108,7 +108,7 @@ g_disk_access(struct g_provider *pp, int r, int w, int
pp->name, r, w, e);
g_topology_assert();
sc = pp->private;
- if (sc == NULL || (dp = sc->dp) == NULL || dp->d_destroyed) {
+ if ((dp = sc->dp) == NULL || dp->d_destroyed) {
/*
* Allow decreasing access count even if disk is not
* available anymore.
@@ -274,6 +274,8 @@ g_disk_ioctl(struct g_provider *pp, u_long cmd, void *
sc = pp->private;
dp = sc->dp;
+ KASSERT(dp != NULL && !dp->d_destroyed,
+ ("g_disk_ioctl(%lx) on destroyed disk %s", cmd, pp->name));
if (dp->d_ioctl == NULL)
return (ENOIOCTL);
@@ -432,10 +434,9 @@ g_disk_start(struct bio *bp)
biotrack(bp, __func__);
sc = bp->bio_to->private;
- if (sc == NULL || (dp = sc->dp) == NULL || dp->d_destroyed) {
- g_io_deliver(bp, ENXIO);
- return;
- }
+ dp = sc->dp;
+ KASSERT(dp != NULL && !dp->d_destroyed,
+ ("g_disk_start(%p) on destroyed disk %s", bp, bp->bio_to->name));
error = EJUSTRETURN;
switch(bp->bio_cmd) {
case BIO_DELETE:
@@ -893,8 +894,9 @@ void
disk_destroy(struct disk *dp)
{
- g_cancel_event(dp);
+ disk_gone(dp);
dp->d_destroyed = 1;
+ g_cancel_event(dp);
if (dp->d_devstat != NULL)
devstat_remove_entry(dp->d_devstat);
g_post_event(g_disk_destroy, dp, M_WAITOK, NULL);
@@ -919,6 +921,16 @@ disk_gone(struct disk *dp)
struct g_provider *pp;
mtx_pool_lock(mtxpool_sleep, dp);
+
+ /*
+ * Second wither call makes no sense, plus we can not access the list
+ * of providers without topology lock after calling wither once.
+ */
+ if (dp->d_goneflag != 0) {
+ mtx_pool_unlock(mtxpool_sleep, dp);
+ return;
+ }
+
dp->d_goneflag = 1;
/*
@@ -943,13 +955,11 @@ disk_gone(struct disk *dp)
mtx_pool_unlock(mtxpool_sleep, dp);
gp = dp->d_geom;
- if (gp != NULL) {
- pp = LIST_FIRST(&gp->provider);
- if (pp != NULL) {
- KASSERT(LIST_NEXT(pp, provider) == NULL,
- ("geom %p has more than one provider", gp));
- g_wither_provider(pp, ENXIO);
- }
+ pp = LIST_FIRST(&gp->provider);
+ if (pp != NULL) {
+ KASSERT(LIST_NEXT(pp, provider) == NULL,
+ ("geom %p has more than one provider", gp));
+ g_wither_provider(pp, ENXIO);
}
}
More information about the svn-src-stable
mailing list