From owner-svn-src-head@FreeBSD.ORG Thu Mar 26 17:21:13 2015 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 9D662DB9; Thu, 26 Mar 2015 17:21:13 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 89554A7A; Thu, 26 Mar 2015 17:21:13 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t2QHLD7b083020; Thu, 26 Mar 2015 17:21:13 GMT (envelope-from mav@FreeBSD.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t2QHLDCB083019; Thu, 26 Mar 2015 17:21:13 GMT (envelope-from mav@FreeBSD.org) Message-Id: <201503261721.t2QHLDCB083019@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: mav set sender to mav@FreeBSD.org using -f From: Alexander Motin Date: Thu, 26 Mar 2015 17:21:13 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r280702 - head/sys/vm X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.18-1 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: Thu, 26 Mar 2015 17:21:13 -0000 Author: mav Date: Thu Mar 26 17:21:12 2015 New Revision: 280702 URL: https://svnweb.freebsd.org/changeset/base/280702 Log: 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. MFC after: 2 weeks Sponsored by: iXsystems, Inc. Modified: head/sys/vm/swap_pager.c Modified: head/sys/vm/swap_pager.c ============================================================================== --- head/sys/vm/swap_pager.c Thu Mar 26 17:13:11 2015 (r280701) +++ head/sys/vm/swap_pager.c Thu Mar 26 17:21:12 2015 (r280702) @@ -2563,18 +2563,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 @@ -2583,13 +2607,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 @@ -2601,6 +2629,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; @@ -2624,31 +2653,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); } @@ -2689,6 +2723,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