summaryrefslogtreecommitdiffstats
path: root/sys/geom
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2004-12-19 23:12:00 +0000
committerpjd <pjd@FreeBSD.org>2004-12-19 23:12:00 +0000
commit8c72a601a3bfebd36875647941a8cc673aa6e62d (patch)
tree4b33d8e0ebbb1cb22d588c56f78149b01a56f731 /sys/geom
parentfccc23ca68e7836b885fced15aa1e228112d9e20 (diff)
downloadFreeBSD-src-8c72a601a3bfebd36875647941a8cc673aa6e62d.zip
FreeBSD-src-8c72a601a3bfebd36875647941a8cc673aa6e62d.tar.gz
Some major cleanups.
Keeping consumers open when device is closed is very hard. We need to open consumers sometimes to update metadata, etc. Many hacks was introduced in the past to made it possible. You cannot be sure that you can open consumer for writing always, even if you think it should be allowed. If one of the mirror components is for example da0 and you try to open it, you can get EPERM when da0s1 is opened for reading (because BSD class opens consumers (da0) with an extra 'e' bit set). Waiting for the events queue to be empty may do the trick, but it makes code much uglier (as you cannot always call g_waitidle()), it doesn't solve all edge cases and it can introduce deadlocks if there are events in the queue that wait for gmirror. I removed those hacks. Now all consumers are open r1w1e1 always, even if device is closed. Maybe it is less clean from GEOM perspective, but simpify code a lot and make it much more reliable. The only issue was retaste event which is sent when we close consumers opened for writing. I ignore retaste event by not detaching consumer immediately (so retaste event is not send to my class) and sending event right after it to detach and destroy consumer.
Diffstat (limited to 'sys/geom')
-rw-r--r--sys/geom/mirror/g_mirror.c282
1 files changed, 107 insertions, 175 deletions
diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c
index 77eedba..afbbdf7 100644
--- a/sys/geom/mirror/g_mirror.c
+++ b/sys/geom/mirror/g_mirror.c
@@ -96,10 +96,8 @@ 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,
- int waitidle);
-static void g_mirror_update_device(struct g_mirror_softc *sc, boolean_t force,
- int waitidle);
+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 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);
@@ -317,15 +315,50 @@ g_mirror_is_busy(struct g_mirror_softc *sc, struct g_consumer *cp)
}
static void
+g_mirror_destroy_consumer(void *arg, int flags)
+{
+ struct g_consumer *cp;
+
+ cp = arg;
+ G_MIRROR_DEBUG(1, "Consumer %s destroyed.", cp->provider->name);
+ g_detach(cp);
+ g_destroy_consumer(cp);
+}
+
+static void
g_mirror_kill_consumer(struct g_mirror_softc *sc, struct g_consumer *cp)
{
+ struct g_provider *pp;
+ int retaste_wait;
g_topology_assert();
cp->private = NULL;
if (g_mirror_is_busy(sc, cp))
return;
- G_MIRROR_DEBUG(2, "Consumer %s destroyed.", cp->provider->name);
+ pp = cp->provider;
+ retaste_wait = 0;
+ if (cp->acw == 1) {
+ if ((pp->geom->flags & G_GEOM_WITHER) == 0)
+ retaste_wait = 1;
+ }
+ G_MIRROR_DEBUG(2, "Access %s r%dw%de%d = %d", pp->name, -cp->acr,
+ -cp->acw, -cp->ace, 0);
+ g_access(cp, -cp->acr, -cp->acw, -cp->ace);
+ if (retaste_wait) {
+ /*
+ * After retaste event was send (inside g_access()), we can send
+ * event to detach and destroy consumer.
+ * A class, which has consumer to the given provider connected
+ * will not receive retaste event for the provider.
+ * This is the way how I ignore retaste events when I close
+ * consumers opened for write: I detach and destroy consumer
+ * after retaste event is sent.
+ */
+ g_post_event(g_mirror_destroy_consumer, cp, M_WAITOK, NULL);
+ return;
+ }
+ G_MIRROR_DEBUG(1, "Consumer %s destroyed.", pp->name);
g_detach(cp);
g_destroy_consumer(cp);
}
@@ -345,6 +378,13 @@ g_mirror_connect_disk(struct g_mirror_disk *disk, struct g_provider *pp)
error = g_attach(disk->d_consumer, pp);
if (error != 0)
return (error);
+ error = g_access(disk->d_consumer, 1, 1, 1);
+ if (error != 0) {
+ G_MIRROR_DEBUG(0, "Cannot open consumer %s (error=%d).",
+ pp->name, error);
+ return (error);
+ }
+
G_MIRROR_DEBUG(2, "Disk %s connected.", g_mirror_get_diskname(disk));
return (0);
}
@@ -357,18 +397,10 @@ g_mirror_disconnect_consumer(struct g_mirror_softc *sc, struct g_consumer *cp)
if (cp == NULL)
return;
- if (cp->provider != NULL) {
- G_MIRROR_DEBUG(2, "Disk %s disconnected.", cp->provider->name);
- if (cp->acr > 0 || cp->acw > 0 || cp->ace > 0) {
- G_MIRROR_DEBUG(2, "Access %s r%dw%de%d = %d",
- cp->provider->name, -cp->acr, -cp->acw, -cp->ace,
- 0);
- g_access(cp, -cp->acr, -cp->acw, -cp->ace);
- }
+ if (cp->provider != NULL)
g_mirror_kill_consumer(sc, cp);
- } else {
+ else
g_destroy_consumer(cp);
- }
}
/*
@@ -572,7 +604,7 @@ g_mirror_write_metadata(struct g_mirror_disk *disk,
struct g_consumer *cp;
off_t offset, length;
u_char *sector;
- int close = 0, error = 0;
+ int error = 0;
g_topology_assert();
@@ -580,38 +612,18 @@ g_mirror_write_metadata(struct g_mirror_disk *disk,
cp = disk->d_consumer;
KASSERT(cp != NULL, ("NULL consumer (%s).", sc->sc_name));
KASSERT(cp->provider != NULL, ("NULL provider (%s).", sc->sc_name));
+ KASSERT(cp->acr == 1 && cp->acw == 1 && cp->ace == 1,
+ ("Consumer %s closed? (r%dw%de%d).", cp->provider->name, cp->acr,
+ cp->acw, cp->ace));
length = cp->provider->sectorsize;
offset = cp->provider->mediasize - length;
sector = malloc((size_t)length, M_MIRROR, M_WAITOK | M_ZERO);
- /*
- * Open consumer if it wasn't opened and remember to close it.
- */
- if (cp->acw == 0) {
- error = g_access(cp, 0, 1, 1);
- G_MIRROR_DEBUG(2, "Access %s r%dw%de%d = %d",
- cp->provider->name, 0, 1, 1, error);
- if (error == 0)
- close = 1;
-#ifdef INVARIANTS
- } else {
- KASSERT(cp->acw > 0 && cp->ace > 0,
- ("Consumer %s not opened (r%dw%de%d).", cp->provider->name,
- cp->acr, cp->acw, cp->ace));
-#endif
- }
- if (error == 0) {
- if (md != NULL)
- mirror_metadata_encode(md, sector);
- g_topology_unlock();
- error = g_write_data(cp, offset, sector, length);
- g_topology_lock();
- }
+ if (md != NULL)
+ mirror_metadata_encode(md, sector);
+ g_topology_unlock();
+ error = g_write_data(cp, offset, sector, length);
+ g_topology_lock();
free(sector, M_MIRROR);
- if (close) {
- g_access(cp, 0, -1, -1);
- G_MIRROR_DEBUG(2, "Access %s r%dw%de%d = %d",
- cp->provider->name, 0, -1, -1, 0);
- }
if (error != 0) {
disk->d_softc->sc_bump_syncid = G_MIRROR_BUMP_IMMEDIATELY;
g_mirror_event_send(disk, G_MIRROR_DISK_STATE_DISCONNECTED,
@@ -697,7 +709,7 @@ g_mirror_update_metadata(struct g_mirror_disk *disk)
}
static void
-g_mirror_bump_syncid(struct g_mirror_softc *sc, int waitidle)
+g_mirror_bump_syncid(struct g_mirror_softc *sc)
{
struct g_mirror_disk *disk;
@@ -713,8 +725,6 @@ g_mirror_bump_syncid(struct g_mirror_softc *sc, int waitidle)
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);
}
}
@@ -1026,7 +1036,7 @@ g_mirror_sync_request(struct bio *bp)
bp->bio_cmd = BIO_WRITE;
bp->bio_cflags = 0;
cp = disk->d_consumer;
- KASSERT(cp->acr == 0 && cp->acw == 1 && cp->ace == 1,
+ KASSERT(cp->acr == 1 && cp->acw == 1 && cp->ace == 1,
("Consumer %s not opened (r%dw%de%d).", cp->provider->name,
cp->acr, cp->acw, cp->ace));
cp->index++;
@@ -1067,7 +1077,6 @@ 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();
}
@@ -1111,7 +1120,7 @@ g_mirror_request_prefer(struct g_mirror_softc *sc, struct bio *bp)
cbp->bio_done = g_mirror_done;
cbp->bio_to = cp->provider;
G_MIRROR_LOGREQ(3, cbp, "Sending request.");
- KASSERT(cp->acr > 0 && cp->ace > 0,
+ KASSERT(cp->acr == 1 && cp->acw == 1 && cp->ace == 1,
("Consumer %s not opened (r%dw%de%d).", cp->provider->name, cp->acr,
cp->acw, cp->ace));
cp->index++;
@@ -1146,7 +1155,7 @@ g_mirror_request_round_robin(struct g_mirror_softc *sc, struct bio *bp)
cbp->bio_done = g_mirror_done;
cbp->bio_to = cp->provider;
G_MIRROR_LOGREQ(3, cbp, "Sending request.");
- KASSERT(cp->acr > 0 && cp->ace > 0,
+ KASSERT(cp->acr == 1 && cp->acw == 1 && cp->ace == 1,
("Consumer %s not opened (r%dw%de%d).", cp->provider->name, cp->acr,
cp->acw, cp->ace));
cp->index++;
@@ -1194,7 +1203,7 @@ g_mirror_request_load(struct g_mirror_softc *sc, struct bio *bp)
cbp->bio_to = cp->provider;
binuptime(&disk->d_last_used);
G_MIRROR_LOGREQ(3, cbp, "Sending request.");
- KASSERT(cp->acr > 0 && cp->ace > 0,
+ KASSERT(cp->acr == 1 && cp->acw == 1 && cp->ace == 1,
("Consumer %s not opened (r%dw%de%d).", cp->provider->name, cp->acr,
cp->acw, cp->ace));
cp->index++;
@@ -1263,7 +1272,7 @@ g_mirror_request_split(struct g_mirror_softc *sc, struct bio *bp)
disk = cbp->bio_caller1;
cbp->bio_caller1 = NULL;
cp = disk->d_consumer;
- KASSERT(cp->acr > 0 && cp->ace > 0,
+ KASSERT(cp->acr == 1 && cp->acw == 1 && cp->ace == 1,
("Consumer %s not opened (r%dw%de%d).", cp->provider->name,
cp->acr, cp->acw, cp->ace));
disk->d_consumer->index++;
@@ -1346,7 +1355,7 @@ g_mirror_register_request(struct bio *bp)
cp = disk->d_consumer;
cbp->bio_caller1 = cp;
cbp->bio_to = cp->provider;
- KASSERT(cp->acw > 0 && cp->ace > 0,
+ KASSERT(cp->acr == 1 && cp->acw == 1 && cp->ace == 1,
("Consumer %s not opened (r%dw%de%d).",
cp->provider->name, cp->acr, cp->acw, cp->ace));
}
@@ -1365,7 +1374,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, 1);
+ g_mirror_bump_syncid(sc);
g_topology_unlock();
}
return;
@@ -1452,26 +1461,22 @@ 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, waitidle);
+ g_mirror_update_device(sc, 1);
} 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, waitidle);
+ ep->e_state);
if (ep->e_error == 0)
- g_mirror_update_device(sc, 0, waitidle);
+ g_mirror_update_device(sc, 0);
}
g_topology_unlock();
if ((ep->e_flags & G_MIRROR_EVENT_DONTWAIT) != 0) {
@@ -1605,45 +1610,28 @@ static void
g_mirror_update_access(struct g_mirror_disk *disk)
{
struct g_provider *pp;
- struct g_consumer *cp;
- int acr, acw, ace, cpw, error;
g_topology_assert();
- cp = disk->d_consumer;
pp = disk->d_softc->sc_provider;
- if (pp == NULL) {
- acr = -cp->acr;
- acw = -cp->acw;
- ace = -cp->ace;
- } else {
- acr = pp->acr - cp->acr;
- acw = pp->acw - cp->acw;
- ace = pp->ace - cp->ace;
- /* Grab an extra "exclusive" bit. */
- if (pp->acr > 0 || pp->acw > 0 || pp->ace > 0)
- ace++;
- }
- if (acr == 0 && acw == 0 && ace == 0)
- return;
- cpw = cp->acw;
- error = g_access(cp, acr, acw, ace);
- G_MIRROR_DEBUG(2, "Access %s r%dw%de%d = %d", cp->provider->name, acr,
- acw, ace, error);
- if (error != 0) {
- disk->d_softc->sc_bump_syncid = G_MIRROR_BUMP_ON_FIRST_WRITE;
- g_mirror_event_send(disk, G_MIRROR_DISK_STATE_DISCONNECTED,
- G_MIRROR_EVENT_DONTWAIT);
+ if (pp == NULL)
return;
- }
- if (cpw == 0 && cp->acw > 0) {
- G_MIRROR_DEBUG(1, "Disk %s (device %s) marked as dirty.",
- g_mirror_get_diskname(disk), disk->d_softc->sc_name);
- disk->d_flags |= G_MIRROR_DISK_FLAG_DIRTY;
- } else if (cpw > 0 && cp->acw == 0) {
- G_MIRROR_DEBUG(1, "Disk %s (device %s) marked as clean.",
- g_mirror_get_diskname(disk), disk->d_softc->sc_name);
- disk->d_flags &= ~G_MIRROR_DISK_FLAG_DIRTY;
+ if (pp->acw > 0) {
+ if ((disk->d_flags & G_MIRROR_DISK_FLAG_DIRTY) == 0) {
+ G_MIRROR_DEBUG(1,
+ "Disk %s (device %s) marked as dirty.",
+ g_mirror_get_diskname(disk),
+ disk->d_softc->sc_name);
+ disk->d_flags |= G_MIRROR_DISK_FLAG_DIRTY;
+ }
+ } else if (pp->acw == 0) {
+ if ((disk->d_flags & G_MIRROR_DISK_FLAG_DIRTY) != 0) {
+ G_MIRROR_DEBUG(1,
+ "Disk %s (device %s) marked as clean.",
+ g_mirror_get_diskname(disk),
+ disk->d_softc->sc_name);
+ disk->d_flags &= ~G_MIRROR_DISK_FLAG_DIRTY;
+ }
}
}
@@ -1661,19 +1649,9 @@ g_mirror_sync_start(struct g_mirror_disk *disk)
("Device not in RUNNING state (%s, %u).", sc->sc_name,
sc->sc_state));
cp = disk->d_consumer;
- KASSERT(cp->acr == 0 && cp->acw == 0 && cp->ace == 0,
- ("Consumer %s already opened.", cp->provider->name));
G_MIRROR_DEBUG(0, "Device %s: rebuilding provider %s.", sc->sc_name,
g_mirror_get_diskname(disk));
- error = g_access(cp, 0, 1, 1);
- G_MIRROR_DEBUG(2, "Access %s r%dw%de%d = %d", cp->provider->name, 0, 1,
- 1, error);
- if (error != 0) {
- g_mirror_event_send(disk, G_MIRROR_DISK_STATE_DISCONNECTED,
- G_MIRROR_EVENT_DONTWAIT);
- return;
- }
disk->d_flags |= G_MIRROR_DISK_FLAG_DIRTY;
KASSERT(disk->d_sync.ds_consumer == NULL,
("Sync consumer already exists (device=%s, disk=%s).",
@@ -1716,17 +1694,11 @@ g_mirror_sync_stop(struct g_mirror_disk *disk, int type)
disk->d_softc->sc_name, g_mirror_get_diskname(disk));
}
cp = disk->d_sync.ds_consumer;
- g_access(cp, -1, 0, 0);
g_mirror_kill_consumer(disk->d_softc, cp);
free(disk->d_sync.ds_data, M_MIRROR);
disk->d_sync.ds_consumer = NULL;
disk->d_softc->sc_sync.ds_ndisks--;
cp = disk->d_consumer;
- KASSERT(cp->acr == 0 && cp->acw == 1 && cp->ace == 1,
- ("Consumer %s not opened.", cp->provider->name));
- g_access(cp, 0, -1, -1);
- G_MIRROR_DEBUG(2, "Access %s r%dw%de%d = %d", cp->provider->name, 0, -1,
- -1, 0);
disk->d_flags &= ~G_MIRROR_DISK_FLAG_DIRTY;
}
@@ -1859,7 +1831,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, int waitidle)
+g_mirror_update_device(struct g_mirror_softc *sc, boolean_t force)
{
struct g_mirror_disk *disk;
u_int state;
@@ -2052,7 +2024,7 @@ g_mirror_update_device(struct g_mirror_softc *sc, boolean_t force, int waitidle)
*/
if (sc->sc_bump_syncid == G_MIRROR_BUMP_IMMEDIATELY) {
sc->sc_bump_syncid = 0;
- g_mirror_bump_syncid(sc, waitidle);
+ g_mirror_bump_syncid(sc);
}
break;
default:
@@ -2071,7 +2043,7 @@ g_mirror_update_device(struct g_mirror_softc *sc, boolean_t force, int waitidle)
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, int waitidle)
+g_mirror_update_disk(struct g_mirror_disk *disk, u_int state)
{
struct g_mirror_softc *sc;
@@ -2153,8 +2125,6 @@ again:
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.",
@@ -2187,8 +2157,6 @@ again:
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));
@@ -2213,8 +2181,6 @@ again:
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);
}
@@ -2278,8 +2244,6 @@ again:
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;
@@ -2310,17 +2274,12 @@ g_mirror_read_metadata(struct g_consumer *cp, struct g_mirror_metadata *md)
buf = g_read_data(cp, pp->mediasize - pp->sectorsize, pp->sectorsize,
&error);
g_topology_lock();
- if (buf == NULL) {
- g_access(cp, -1, 0, 0);
- return (error);
- }
+ g_access(cp, -1, 0, 0);
if (error != 0) {
- g_access(cp, -1, 0, 0);
- g_free(buf);
+ if (buf != NULL)
+ g_free(buf);
return (error);
}
- error = g_access(cp, -1, 0, 0);
- KASSERT(error == 0, ("Cannot decrease access count for %s.", pp->name));
/* Decode metadata. */
error = mirror_metadata_decode(buf, md);
@@ -2429,7 +2388,7 @@ g_mirror_access(struct g_provider *pp, int acr, int acw, int ace)
{
struct g_mirror_softc *sc;
struct g_mirror_disk *disk;
- int dcr, dcw, dce, err, error;
+ int dcr, dcw, dce;
g_topology_assert();
G_MIRROR_DEBUG(2, "Access request for %s: r%dw%de%d.", pp->name, acr,
@@ -2439,13 +2398,6 @@ g_mirror_access(struct g_provider *pp, int acr, int acw, int ace)
dcw = pp->acw + acw;
dce = pp->ace + ace;
- /* On first open, grab an extra "exclusive" bit */
- if (pp->acr == 0 && pp->acw == 0 && pp->ace == 0)
- ace++;
- /* ... and let go of it on last close */
- if (dcr == 0 && dcw == 0 && dce == 0)
- ace--;
-
sc = pp->geom->softc;
if (sc == NULL || LIST_EMPTY(&sc->sc_disks) ||
(sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROY) != 0) {
@@ -2454,47 +2406,27 @@ g_mirror_access(struct g_provider *pp, int acr, int acw, int ace)
else
return (ENXIO);
}
- error = ENXIO;
LIST_FOREACH(disk, &sc->sc_disks, d_next) {
if (disk->d_state != G_MIRROR_DISK_STATE_ACTIVE)
continue;
- err = g_access(disk->d_consumer, acr, acw, ace);
- G_MIRROR_DEBUG(2, "Access %s r%dw%de%d = %d",
- g_mirror_get_diskname(disk), acr, acw, ace, err);
- if (err == 0) {
- /*
- * Mark disk as dirty on open and unmark on close.
- */
- if (pp->acw == 0 && dcw > 0) {
- G_MIRROR_DEBUG(1,
- "Disk %s (device %s) marked as dirty.",
- g_mirror_get_diskname(disk), sc->sc_name);
- disk->d_flags |= G_MIRROR_DISK_FLAG_DIRTY;
- g_mirror_update_metadata(disk);
- } else if (pp->acw > 0 && dcw == 0) {
- G_MIRROR_DEBUG(1,
- "Disk %s (device %s) marked as clean.",
- g_mirror_get_diskname(disk), sc->sc_name);
- disk->d_flags &= ~G_MIRROR_DISK_FLAG_DIRTY;
- g_mirror_update_metadata(disk);
- }
- error = 0;
- } else {
- sc->sc_bump_syncid = G_MIRROR_BUMP_ON_FIRST_WRITE;
- g_mirror_event_send(disk,
- G_MIRROR_DISK_STATE_DISCONNECTED,
- G_MIRROR_EVENT_DONTWAIT);
+ /*
+ * Mark disk as dirty on open and unmark on close.
+ */
+ if (pp->acw == 0 && dcw > 0) {
+ G_MIRROR_DEBUG(1,
+ "Disk %s (device %s) marked as dirty.",
+ g_mirror_get_diskname(disk), sc->sc_name);
+ disk->d_flags |= G_MIRROR_DISK_FLAG_DIRTY;
+ g_mirror_update_metadata(disk);
+ } else if (pp->acw > 0 && dcw == 0) {
+ G_MIRROR_DEBUG(1,
+ "Disk %s (device %s) marked as clean.",
+ g_mirror_get_diskname(disk), sc->sc_name);
+ disk->d_flags &= ~G_MIRROR_DISK_FLAG_DIRTY;
+ g_mirror_update_metadata(disk);
}
}
- /*
- * Be sure to return 0 for negativate access requests.
- * In case of some HW problems, it is possible that we don't have
- * any active disk here, so loop above will be no-op and error will
- * be ENXIO.
- */
- if (error != 0 && acr <= 0 && acw <= 0 && ace <= 0)
- error = 0;
- return (error);
+ return (0);
}
static struct g_geom *
OpenPOWER on IntegriCloud