geom_disk: use a preallocated geom_event for disk destruction.

Preallocate a geom_event (using the new geom_alloc_event) when we create
a disk. When we create the disk, we're going to be in a sleepable
context, so we can always allocate this extra bit of memory. Then use
this preallocated memory to free the disk. CAM can try to free the disk
from an unsleepable context if there was I/O outstanding when the disk
was destroyted (say because the SIM said it had gone away). The I/O
context isn't sleepable. Rather than trying to invent a retry mechanism
and making sure all the other geom_disk consumers did it properly,
preallocating the event ensure that the geom_disk will be properly torn
down, even when there's memory pressure when the disk departs.

Reviewd by:		jhb
Sponsored by:		Netflix
Differential Revision:	https://reviews.freebsd.org/D30544
This commit is contained in:
Warner Losh 2021-07-23 15:21:02 -06:00
parent 380710a5c8
commit 47aeda7b70
2 changed files with 5 additions and 1 deletions

View File

@ -885,6 +885,7 @@ disk_create(struct disk *dp, int version)
dp->d_sectorsize, DEVSTAT_ALL_SUPPORTED,
DEVSTAT_TYPE_DIRECT, DEVSTAT_PRIORITY_MAX);
dp->d_geom = NULL;
dp->d_event = g_alloc_event(M_WAITOK);
dp->d_init_level = DISK_INIT_NONE;
@ -896,12 +897,14 @@ void
disk_destroy(struct disk *dp)
{
KASSERT(dp->d_event != NULL,
("Disk destroy for %p with event NULL", 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);
g_post_event_ep(g_disk_destroy, dp, dp->d_event, NULL);
}
void

View File

@ -125,6 +125,7 @@ struct disk {
/* Fields private to geom_disk, to be moved on next version bump */
LIST_HEAD(,disk_alias) d_aliases;
void *d_event;
};
#define DISKFLAG_RESERVED 0x0001 /* Was NEEDSGIANT */