Date: Thu, 9 Apr 2015 10:12:58 +0000 (UTC) From: Alexander Motin <mav@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r281306 - stable/9/sys/vm Message-ID: <201504091012.t39ACw2C015767@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mav Date: Thu Apr 9 10:12:58 2015 New Revision: 281306 URL: https://svnweb.freebsd.org/changeset/base/281306 Log: MFC r280702: Make swapper release orphaned (lost) GEOM provider. Swap device is still reported as enabled, and system still may crash later if some swapped-out kernel pages were lost with the device, but at least GEOM and CAM can now release the lost disk, allowing it to be reconnected. Modified: stable/9/sys/vm/swap_pager.c Directory Properties: stable/9/ (props changed) stable/9/sys/ (props changed) Modified: stable/9/sys/vm/swap_pager.c ============================================================================== --- stable/9/sys/vm/swap_pager.c Thu Apr 9 10:11:47 2015 (r281305) +++ stable/9/sys/vm/swap_pager.c Thu Apr 9 10:12:58 2015 (r281306) @@ -2508,18 +2508,42 @@ DECLARE_GEOM_CLASS(g_swap_class, g_class static void +swapgeom_close_ev(void *arg, int flags) +{ + struct g_consumer *cp; + + cp = arg; + g_access(cp, -1, -1, 0); + g_detach(cp); + g_destroy_consumer(cp); +} + +static void swapgeom_done(struct bio *bp2) { + struct swdevt *sp; struct buf *bp; + struct g_consumer *cp; + int destroy; bp = bp2->bio_caller2; + cp = bp2->bio_from; bp->b_ioflags = bp2->bio_flags; if (bp2->bio_error) bp->b_ioflags |= BIO_ERROR; bp->b_resid = bp->b_bcount - bp2->bio_completed; bp->b_error = bp2->bio_error; bufdone(bp); + mtx_lock(&sw_dev_mtx); + destroy = ((--cp->index) == 0 && cp->private); + if (destroy) { + sp = bp2->bio_caller1; + sp->sw_id = NULL; + } + mtx_unlock(&sw_dev_mtx); g_destroy_bio(bp2); + if (destroy) + g_waitfor_event(swapgeom_close_ev, cp, M_WAITOK, NULL); } static void @@ -2528,13 +2552,17 @@ swapgeom_strategy(struct buf *bp, struct struct bio *bio; struct g_consumer *cp; + mtx_lock(&sw_dev_mtx); cp = sp->sw_id; if (cp == NULL) { + 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) bio = g_new_bio(); else @@ -2546,6 +2574,7 @@ swapgeom_strategy(struct buf *bp, struct return; } + bio->bio_caller1 = sp; bio->bio_caller2 = bp; bio->bio_cmd = bp->b_iocmd; bio->bio_offset = (bp->b_blkno - sp->sw_first) * PAGE_SIZE; @@ -2569,31 +2598,36 @@ static void swapgeom_orphan(struct g_consumer *cp) { struct swdevt *sp; + int destroy; mtx_lock(&sw_dev_mtx); - TAILQ_FOREACH(sp, &swtailq, sw_list) - if (sp->sw_id == cp) + TAILQ_FOREACH(sp, &swtailq, sw_list) { + if (sp->sw_id == cp) { sp->sw_flags |= SW_CLOSING; + break; + } + } + cp->private = (void *)(uintptr_t)1; + destroy = ((sp != NULL) && (cp->index == 0)); + if (destroy) + sp->sw_id = NULL; mtx_unlock(&sw_dev_mtx); -} - -static void -swapgeom_close_ev(void *arg, int flags) -{ - struct g_consumer *cp; - - cp = arg; - g_access(cp, -1, -1, 0); - g_detach(cp); - g_destroy_consumer(cp); + if (destroy) + swapgeom_close_ev(cp, 0); } static void swapgeom_close(struct thread *td, struct swdevt *sw) { + struct g_consumer *cp; + mtx_lock(&sw_dev_mtx); + cp = sw->sw_id; + sw->sw_id = NULL; + mtx_unlock(&sw_dev_mtx); /* XXX: direct call when Giant untangled */ - g_waitfor_event(swapgeom_close_ev, sw->sw_id, M_WAITOK, NULL); + if (cp != NULL) + g_waitfor_event(swapgeom_close_ev, cp, M_WAITOK, NULL); } @@ -2634,6 +2668,8 @@ swapongeom_ev(void *arg, int flags) 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 */ g_attach(cp, pp); /* * XXX: Everytime you think you can improve the margin for
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201504091012.t39ACw2C015767>