Index: sys/vm/swap_pager.c =================================================================== --- sys/vm/swap_pager.c +++ sys/vm/swap_pager.c @@ -2520,7 +2520,6 @@ DECLARE_GEOM_CLASS(g_swap_class, g_class); - static void swapgeom_close_ev(void *arg, int flags) { @@ -2532,6 +2531,20 @@ g_destroy_consumer(cp); } +static int +swapgeom_check_close(struct g_consumer *cp, struct swdevt *sp) +{ + + mtx_assert(&sw_dev_mtx, MA_OWNED); + if (cp->index == 0) { + if (g_post_event(swapgeom_close_ev, cp, M_NOWAIT, NULL) == 0) { + sp->sw_id = NULL; + return 1; + } + } + return 0; +} + static void swapgeom_done(struct bio *bp2) { @@ -2547,13 +2560,10 @@ bp->b_resid = bp->b_bcount - bp2->bio_completed; bp->b_error = bp2->bio_error; bufdone(bp); + sp = bp2->bio_caller1; mtx_lock(&sw_dev_mtx); - if ((--cp->index) == 0 && cp->private) { - if (g_post_event(swapgeom_close_ev, cp, M_NOWAIT, NULL) == 0) { - sp = bp2->bio_caller1; - sp->sw_id = NULL; - } - } + --cp->index; + swapgeom_check_close(cp, sp); mtx_unlock(&sw_dev_mtx); g_destroy_bio(bp2); } @@ -2566,13 +2576,14 @@ mtx_lock(&sw_dev_mtx); cp = sp->sw_id; - if (cp == NULL) { + if (cp == NULL || swapgeom_check_close(cp, sp)) { mtx_unlock(&sw_dev_mtx); bp->b_error = ENXIO; bp->b_ioflags |= BIO_ERROR; bufdone(bp); return; } + cp->index++; mtx_unlock(&sw_dev_mtx); if (bp->b_iocmd == BIO_WRITE) @@ -2580,6 +2591,9 @@ else bio = g_alloc_bio(); if (bio == NULL) { + mtx_lock(&sw_dev_mtx); + --cp->index; + mtx_unlock(&sw_dev_mtx); bp->b_error = ENOMEM; bp->b_ioflags |= BIO_ERROR; bufdone(bp); @@ -2619,7 +2633,7 @@ break; } } - cp->private = (void *)(uintptr_t)1; + --cp->index; /* Drop reference we were created with */ destroy = ((sp != NULL) && (cp->index == 0)); if (destroy) sp->sw_id = NULL; @@ -2680,8 +2694,8 @@ if (gp == NULL) gp = g_new_geomf(&g_swap_class, "swap"); cp = g_new_consumer(gp); - cp->index = 0; /* Number of active I/Os. */ - cp->private = NULL; /* Orphanization flag */ + cp->index = 1; /* Number of active I/Os, plus one for being active. */ + cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE; g_attach(cp, pp); /* * XXX: Everytime you think you can improve the margin for