mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-18 10:35:55 +00:00
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.
This commit is contained in:
parent
09a3b0db35
commit
3398491b2f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=280702
@ -2562,19 +2562,43 @@ static struct g_class g_swap_class = {
|
|||||||
DECLARE_GEOM_CLASS(g_swap_class, g_class);
|
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
|
static void
|
||||||
swapgeom_done(struct bio *bp2)
|
swapgeom_done(struct bio *bp2)
|
||||||
{
|
{
|
||||||
|
struct swdevt *sp;
|
||||||
struct buf *bp;
|
struct buf *bp;
|
||||||
|
struct g_consumer *cp;
|
||||||
|
int destroy;
|
||||||
|
|
||||||
bp = bp2->bio_caller2;
|
bp = bp2->bio_caller2;
|
||||||
|
cp = bp2->bio_from;
|
||||||
bp->b_ioflags = bp2->bio_flags;
|
bp->b_ioflags = bp2->bio_flags;
|
||||||
if (bp2->bio_error)
|
if (bp2->bio_error)
|
||||||
bp->b_ioflags |= BIO_ERROR;
|
bp->b_ioflags |= BIO_ERROR;
|
||||||
bp->b_resid = bp->b_bcount - bp2->bio_completed;
|
bp->b_resid = bp->b_bcount - bp2->bio_completed;
|
||||||
bp->b_error = bp2->bio_error;
|
bp->b_error = bp2->bio_error;
|
||||||
bufdone(bp);
|
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);
|
g_destroy_bio(bp2);
|
||||||
|
if (destroy)
|
||||||
|
g_waitfor_event(swapgeom_close_ev, cp, M_WAITOK, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -2583,13 +2607,17 @@ swapgeom_strategy(struct buf *bp, struct swdevt *sp)
|
|||||||
struct bio *bio;
|
struct bio *bio;
|
||||||
struct g_consumer *cp;
|
struct g_consumer *cp;
|
||||||
|
|
||||||
|
mtx_lock(&sw_dev_mtx);
|
||||||
cp = sp->sw_id;
|
cp = sp->sw_id;
|
||||||
if (cp == NULL) {
|
if (cp == NULL) {
|
||||||
|
mtx_unlock(&sw_dev_mtx);
|
||||||
bp->b_error = ENXIO;
|
bp->b_error = ENXIO;
|
||||||
bp->b_ioflags |= BIO_ERROR;
|
bp->b_ioflags |= BIO_ERROR;
|
||||||
bufdone(bp);
|
bufdone(bp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
cp->index++;
|
||||||
|
mtx_unlock(&sw_dev_mtx);
|
||||||
if (bp->b_iocmd == BIO_WRITE)
|
if (bp->b_iocmd == BIO_WRITE)
|
||||||
bio = g_new_bio();
|
bio = g_new_bio();
|
||||||
else
|
else
|
||||||
@ -2601,6 +2629,7 @@ swapgeom_strategy(struct buf *bp, struct swdevt *sp)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bio->bio_caller1 = sp;
|
||||||
bio->bio_caller2 = bp;
|
bio->bio_caller2 = bp;
|
||||||
bio->bio_cmd = bp->b_iocmd;
|
bio->bio_cmd = bp->b_iocmd;
|
||||||
bio->bio_offset = (bp->b_blkno - sp->sw_first) * PAGE_SIZE;
|
bio->bio_offset = (bp->b_blkno - sp->sw_first) * PAGE_SIZE;
|
||||||
@ -2624,31 +2653,36 @@ static void
|
|||||||
swapgeom_orphan(struct g_consumer *cp)
|
swapgeom_orphan(struct g_consumer *cp)
|
||||||
{
|
{
|
||||||
struct swdevt *sp;
|
struct swdevt *sp;
|
||||||
|
int destroy;
|
||||||
|
|
||||||
mtx_lock(&sw_dev_mtx);
|
mtx_lock(&sw_dev_mtx);
|
||||||
TAILQ_FOREACH(sp, &swtailq, sw_list)
|
TAILQ_FOREACH(sp, &swtailq, sw_list) {
|
||||||
if (sp->sw_id == cp)
|
if (sp->sw_id == cp) {
|
||||||
sp->sw_flags |= SW_CLOSING;
|
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);
|
mtx_unlock(&sw_dev_mtx);
|
||||||
}
|
if (destroy)
|
||||||
|
swapgeom_close_ev(cp, 0);
|
||||||
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
|
static void
|
||||||
swapgeom_close(struct thread *td, struct swdevt *sw)
|
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 */
|
/* 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)
|
if (gp == NULL)
|
||||||
gp = g_new_geomf(&g_swap_class, "swap");
|
gp = g_new_geomf(&g_swap_class, "swap");
|
||||||
cp = g_new_consumer(gp);
|
cp = g_new_consumer(gp);
|
||||||
|
cp->index = 0; /* Number of active I/Os. */
|
||||||
|
cp->private = NULL; /* Orphanization flag */
|
||||||
g_attach(cp, pp);
|
g_attach(cp, pp);
|
||||||
/*
|
/*
|
||||||
* XXX: Everytime you think you can improve the margin for
|
* XXX: Everytime you think you can improve the margin for
|
||||||
|
Loading…
Reference in New Issue
Block a user