Before trying to update metadata (so open consumer for writing), be sure

that the events queue is empty. In other case we're able to hit the race
where for example da0s1 is tasted by some other class, which means that
da0 is open with exclusive bit set, which means that we can't open da0
for writing if it is our component.

Reported by:	Attila Nagy <bra@fsn.hu> (and somebody else sometime ago,
		                          but I cannot find who it was)
This commit is contained in:
Pawel Jakub Dawidek 2004-11-09 23:27:21 +00:00
parent b8005b9b24
commit 085f43afae
2 changed files with 53 additions and 21 deletions

View File

@ -96,8 +96,10 @@ struct g_class g_mirror_class = {
static void g_mirror_destroy_provider(struct g_mirror_softc *sc);
static int g_mirror_update_disk(struct g_mirror_disk *disk, u_int state);
static void g_mirror_update_device(struct g_mirror_softc *sc, boolean_t force);
static int g_mirror_update_disk(struct g_mirror_disk *disk, u_int state,
int waitidle);
static void g_mirror_update_device(struct g_mirror_softc *sc, boolean_t force,
int waitidle);
static void g_mirror_dumpconf(struct sbuf *sb, const char *indent,
struct g_geom *gp, struct g_consumer *cp, struct g_provider *pp);
static void g_mirror_sync_stop(struct g_mirror_disk *disk, int type);
@ -695,7 +697,7 @@ g_mirror_update_metadata(struct g_mirror_disk *disk)
}
static void
g_mirror_bump_syncid(struct g_mirror_softc *sc)
g_mirror_bump_syncid(struct g_mirror_softc *sc, int waitidle)
{
struct g_mirror_disk *disk;
@ -711,6 +713,8 @@ g_mirror_bump_syncid(struct g_mirror_softc *sc)
if (disk->d_state == G_MIRROR_DISK_STATE_ACTIVE ||
disk->d_state == G_MIRROR_DISK_STATE_SYNCHRONIZING) {
disk->d_sync.ds_syncid = sc->sc_syncid;
if (waitidle)
g_waitidlelock();
g_mirror_update_metadata(disk);
}
}
@ -1063,6 +1067,7 @@ g_mirror_sync_request(struct bio *bp)
* XXX: This should be configurable.
*/
g_topology_lock();
g_waitidlelock();
g_mirror_update_metadata(disk);
g_topology_unlock();
}
@ -1360,7 +1365,7 @@ g_mirror_register_request(struct bio *bp)
if (sc->sc_bump_syncid == G_MIRROR_BUMP_ON_FIRST_WRITE) {
sc->sc_bump_syncid = 0;
g_topology_lock();
g_mirror_bump_syncid(sc);
g_mirror_bump_syncid(sc, 1);
g_topology_unlock();
}
return;
@ -1447,22 +1452,26 @@ g_mirror_worker(void *arg)
*/
ep = g_mirror_event_get(sc);
if (ep != NULL) {
int waitidle = 0;
g_topology_lock();
if ((ep->e_flags & G_MIRROR_EVENT_DONTWAIT) != 0)
waitidle = 1;
if ((ep->e_flags & G_MIRROR_EVENT_DEVICE) != 0) {
/* Update only device status. */
G_MIRROR_DEBUG(3,
"Running event for device %s.",
sc->sc_name);
ep->e_error = 0;
g_mirror_update_device(sc, 1);
g_mirror_update_device(sc, 1, waitidle);
} else {
/* Update disk status. */
G_MIRROR_DEBUG(3, "Running event for disk %s.",
g_mirror_get_diskname(ep->e_disk));
ep->e_error = g_mirror_update_disk(ep->e_disk,
ep->e_state);
ep->e_state, waitidle);
if (ep->e_error == 0)
g_mirror_update_device(sc, 0);
g_mirror_update_device(sc, 0, waitidle);
}
g_topology_unlock();
if ((ep->e_flags & G_MIRROR_EVENT_DONTWAIT) != 0) {
@ -1850,7 +1859,7 @@ g_mirror_determine_state(struct g_mirror_disk *disk)
* Update device state.
*/
static void
g_mirror_update_device(struct g_mirror_softc *sc, boolean_t force)
g_mirror_update_device(struct g_mirror_softc *sc, boolean_t force, int waitidle)
{
struct g_mirror_disk *disk;
u_int state;
@ -2043,7 +2052,7 @@ g_mirror_update_device(struct g_mirror_softc *sc, boolean_t force)
*/
if (sc->sc_bump_syncid == G_MIRROR_BUMP_IMMEDIATELY) {
sc->sc_bump_syncid = 0;
g_mirror_bump_syncid(sc);
g_mirror_bump_syncid(sc, waitidle);
}
break;
default:
@ -2062,7 +2071,7 @@ g_mirror_update_device(struct g_mirror_softc *sc, boolean_t force)
g_mirror_disk_state2str(disk->d_state), \
g_mirror_disk_state2str(state), sc->sc_name)
static int
g_mirror_update_disk(struct g_mirror_disk *disk, u_int state)
g_mirror_update_disk(struct g_mirror_disk *disk, u_int state, int waitidle)
{
struct g_mirror_softc *sc;
@ -2144,6 +2153,8 @@ g_mirror_update_disk(struct g_mirror_disk *disk, u_int state)
disk->d_state = state;
disk->d_sync.ds_offset = 0;
disk->d_sync.ds_offset_done = 0;
if (waitidle)
g_waitidlelock();
g_mirror_update_access(disk);
g_mirror_update_metadata(disk);
G_MIRROR_DEBUG(0, "Device %s: provider %s activated.",
@ -2176,6 +2187,8 @@ g_mirror_update_disk(struct g_mirror_disk *disk, u_int state)
disk->d_flags &= ~G_MIRROR_DISK_FLAG_DIRTY;
disk->d_state = state;
if (waitidle)
g_waitidlelock();
g_mirror_update_metadata(disk);
G_MIRROR_DEBUG(0, "Device %s: provider %s is stale.",
sc->sc_name, g_mirror_get_diskname(disk));
@ -2200,6 +2213,8 @@ g_mirror_update_disk(struct g_mirror_disk *disk, u_int state)
disk->d_flags &= ~G_MIRROR_DISK_FLAG_DIRTY;
disk->d_state = state;
if (sc->sc_provider != NULL) {
if (waitidle)
g_waitidlelock();
g_mirror_sync_start(disk);
g_mirror_update_metadata(disk);
}
@ -2263,6 +2278,8 @@ g_mirror_update_disk(struct g_mirror_disk *disk, u_int state)
g_mirror_destroy_disk(disk);
sc->sc_ndisks--;
LIST_FOREACH(disk, &sc->sc_disks, d_next) {
if (waitidle)
g_waitidlelock();
g_mirror_update_metadata(disk);
}
break;

View File

@ -134,8 +134,10 @@ struct g_class g_raid3_class = {
static void g_raid3_destroy_provider(struct g_raid3_softc *sc);
static int g_raid3_update_disk(struct g_raid3_disk *disk, u_int state);
static void g_raid3_update_device(struct g_raid3_softc *sc, boolean_t force);
static int g_raid3_update_disk(struct g_raid3_disk *disk, u_int state,
int waitidle);
static void g_raid3_update_device(struct g_raid3_softc *sc, boolean_t force,
int waitidle);
static void g_raid3_dumpconf(struct sbuf *sb, const char *indent,
struct g_geom *gp, struct g_consumer *cp, struct g_provider *pp);
static void g_raid3_sync_stop(struct g_raid3_softc *sc, int type);
@ -720,7 +722,7 @@ g_raid3_update_metadata(struct g_raid3_disk *disk)
}
static void
g_raid3_bump_syncid(struct g_raid3_softc *sc)
g_raid3_bump_syncid(struct g_raid3_softc *sc, int waitidle)
{
struct g_raid3_disk *disk;
u_int n;
@ -736,6 +738,8 @@ g_raid3_bump_syncid(struct g_raid3_softc *sc)
if (disk->d_state == G_RAID3_DISK_STATE_ACTIVE ||
disk->d_state == G_RAID3_DISK_STATE_SYNCHRONIZING) {
disk->d_sync.ds_syncid = sc->sc_syncid;
if (waitidle)
g_waitidlelock();
g_raid3_update_metadata(disk);
}
}
@ -1450,6 +1454,7 @@ g_raid3_sync_request(struct bio *bp)
* XXX: This should be configurable.
*/
g_topology_lock();
g_waitidlelock();
g_raid3_update_metadata(disk);
g_topology_unlock();
}
@ -1627,7 +1632,7 @@ g_raid3_register_request(struct bio *pbp)
if (sc->sc_bump_syncid == G_RAID3_BUMP_ON_FIRST_WRITE) {
sc->sc_bump_syncid = 0;
g_topology_lock();
g_raid3_bump_syncid(sc);
g_raid3_bump_syncid(sc, 1);
g_topology_unlock();
}
g_raid3_scatter(pbp);
@ -1712,22 +1717,26 @@ g_raid3_worker(void *arg)
*/
ep = g_raid3_event_get(sc);
if (ep != NULL) {
int waitidle = 0;
g_topology_lock();
if ((ep->e_flags & G_RAID3_EVENT_DONTWAIT) != 0)
waitidle = 1;
if ((ep->e_flags & G_RAID3_EVENT_DEVICE) != 0) {
/* Update only device status. */
G_RAID3_DEBUG(3,
"Running event for device %s.",
sc->sc_name);
ep->e_error = 0;
g_raid3_update_device(sc, 1);
g_raid3_update_device(sc, 1, waitidle);
} else {
/* Update disk status. */
G_RAID3_DEBUG(3, "Running event for disk %s.",
g_raid3_get_diskname(ep->e_disk));
ep->e_error = g_raid3_update_disk(ep->e_disk,
ep->e_state);
ep->e_state, waitidle);
if (ep->e_error == 0)
g_raid3_update_device(sc, 0);
g_raid3_update_device(sc, 0, waitidle);
}
g_topology_unlock();
if ((ep->e_flags & G_RAID3_EVENT_DONTWAIT) != 0) {
@ -2124,7 +2133,7 @@ g_raid3_determine_state(struct g_raid3_disk *disk)
* Update device state.
*/
static void
g_raid3_update_device(struct g_raid3_softc *sc, boolean_t force)
g_raid3_update_device(struct g_raid3_softc *sc, boolean_t force, int waitidle)
{
struct g_raid3_disk *disk;
u_int state;
@ -2245,7 +2254,7 @@ g_raid3_update_device(struct g_raid3_softc *sc, boolean_t force)
*/
if (sc->sc_bump_syncid == G_RAID3_BUMP_IMMEDIATELY) {
sc->sc_bump_syncid = 0;
g_raid3_bump_syncid(sc);
g_raid3_bump_syncid(sc, waitidle);
}
if (g_raid3_ndisks(sc, G_RAID3_DISK_STATE_NEW) > 0)
return;
@ -2274,7 +2283,7 @@ g_raid3_update_device(struct g_raid3_softc *sc, boolean_t force)
*/
if (sc->sc_bump_syncid == G_RAID3_BUMP_IMMEDIATELY) {
sc->sc_bump_syncid = 0;
g_raid3_bump_syncid(sc);
g_raid3_bump_syncid(sc, waitidle);
}
if (g_raid3_ndisks(sc, G_RAID3_DISK_STATE_NEW) > 0)
return;
@ -2310,7 +2319,7 @@ g_raid3_update_device(struct g_raid3_softc *sc, boolean_t force)
g_raid3_disk_state2str(disk->d_state), \
g_raid3_disk_state2str(state), sc->sc_name)
static int
g_raid3_update_disk(struct g_raid3_disk *disk, u_int state)
g_raid3_update_disk(struct g_raid3_disk *disk, u_int state, int waitidle)
{
struct g_raid3_softc *sc;
@ -2377,6 +2386,8 @@ g_raid3_update_disk(struct g_raid3_disk *disk, u_int state)
disk->d_state = state;
disk->d_sync.ds_offset = 0;
disk->d_sync.ds_offset_done = 0;
if (waitidle)
g_waitidlelock();
g_raid3_update_access(disk);
g_raid3_update_metadata(disk);
G_RAID3_DEBUG(0, "Device %s: provider %s activated.",
@ -2410,6 +2421,8 @@ g_raid3_update_disk(struct g_raid3_disk *disk, u_int state)
disk->d_flags &= ~G_RAID3_DISK_FLAG_DIRTY;
disk->d_state = state;
if (waitidle)
g_waitidlelock();
g_raid3_update_metadata(disk);
G_RAID3_DEBUG(0, "Device %s: provider %s is stale.",
sc->sc_name, g_raid3_get_diskname(disk));
@ -2435,6 +2448,8 @@ g_raid3_update_disk(struct g_raid3_disk *disk, u_int state)
disk->d_flags &= ~G_RAID3_DISK_FLAG_DIRTY;
disk->d_state = state;
if (sc->sc_provider != NULL) {
if (waitidle)
g_waitidlelock();
g_raid3_sync_start(sc);
g_raid3_update_metadata(disk);
}