From b34fb80d8364fbc4f1737da5f2916fe5b39a9325 Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 1 Nov 2006 22:51:49 +0000 Subject: Now, that we have gjournal in the tree add possibility to configure gmirror and graid3 in a way that it is not resynchronized after a power failure or system crash. It is safe when gjournal is running on top of gmirror/graid3. --- sys/geom/mirror/g_mirror.c | 10 +++++++++- sys/geom/mirror/g_mirror.h | 14 ++++++++++---- sys/geom/mirror/g_mirror_ctl.c | 32 ++++++++++++++++++++++++++++++-- sys/geom/raid3/g_raid3.c | 10 +++++++++- sys/geom/raid3/g_raid3.h | 14 ++++++++++---- sys/geom/raid3/g_raid3_ctl.c | 33 ++++++++++++++++++++++++++++++--- 6 files changed, 98 insertions(+), 15 deletions(-) (limited to 'sys/geom') diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c index f03da3b..419611e 100644 --- a/sys/geom/mirror/g_mirror.c +++ b/sys/geom/mirror/g_mirror.c @@ -802,6 +802,8 @@ g_mirror_idle(struct g_mirror_softc *sc, int acw) if (sc->sc_provider == NULL) return (0); + if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_NOFAILSYNC) != 0) + return (0); if (sc->sc_idle) return (0); if (sc->sc_writes > 0) @@ -831,6 +833,8 @@ g_mirror_unidle(struct g_mirror_softc *sc) g_topology_assert_not(); sx_assert(&sc->sc_lock, SX_XLOCKED); + if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_NOFAILSYNC) != 0) + return; sc->sc_idle = 0; sc->sc_last_write = time_uptime; LIST_FOREACH(disk, &sc->sc_disks, d_next) { @@ -1884,6 +1888,8 @@ g_mirror_update_idle(struct g_mirror_softc *sc, struct g_mirror_disk *disk) sx_assert(&sc->sc_lock, SX_LOCKED); + if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_NOFAILSYNC) != 0) + return; if (!sc->sc_idle && (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), sc->sc_name); @@ -1928,7 +1934,8 @@ g_mirror_sync_start(struct g_mirror_disk *disk) G_MIRROR_DEBUG(0, "Device %s: rebuilding provider %s.", sc->sc_name, g_mirror_get_diskname(disk)); - disk->d_flags |= G_MIRROR_DISK_FLAG_DIRTY; + if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_NOFAILSYNC) == 0) + disk->d_flags |= G_MIRROR_DISK_FLAG_DIRTY; KASSERT(disk->d_sync.ds_consumer == NULL, ("Sync consumer already exists (device=%s, disk=%s).", sc->sc_name, g_mirror_get_diskname(disk))); @@ -3180,6 +3187,7 @@ g_mirror_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, sbuf_printf(sb, name); \ } \ } while (0) + ADD_FLAG(G_MIRROR_DEVICE_FLAG_NOFAILSYNC, "NOFAILSYNC"); ADD_FLAG(G_MIRROR_DEVICE_FLAG_NOAUTOSYNC, "NOAUTOSYNC"); #undef ADD_FLAG } diff --git a/sys/geom/mirror/g_mirror.h b/sys/geom/mirror/g_mirror.h index a6ddc51..eb67b6e0 100644 --- a/sys/geom/mirror/g_mirror.h +++ b/sys/geom/mirror/g_mirror.h @@ -41,8 +41,9 @@ * 1 - Added 'prefer' balance algorithm. * 2 - Added md_genid field to metadata. * 3 - Added md_provsize field to metadata. + * 4 - Added 'no failure synchronization' flag. */ -#define G_MIRROR_VERSION 3 +#define G_MIRROR_VERSION 4 #define G_MIRROR_BALANCE_NONE 0 #define G_MIRROR_BALANCE_ROUND_ROBIN 1 @@ -64,7 +65,9 @@ G_MIRROR_DISK_FLAG_INACTIVE) #define G_MIRROR_DEVICE_FLAG_NOAUTOSYNC 0x0000000000000001ULL -#define G_MIRROR_DEVICE_FLAG_MASK (G_MIRROR_DEVICE_FLAG_NOAUTOSYNC) +#define G_MIRROR_DEVICE_FLAG_NOFAILSYNC 0x0000000000000002ULL +#define G_MIRROR_DEVICE_FLAG_MASK (G_MIRROR_DEVICE_FLAG_NOAUTOSYNC | \ + G_MIRROR_DEVICE_FLAG_NOFAILSYNC) #ifdef _KERNEL extern u_int g_mirror_debug; @@ -341,7 +344,7 @@ mirror_metadata_decode_v2(const u_char *data, struct g_mirror_metadata *md) return (0); } static __inline int -mirror_metadata_decode_v3(const u_char *data, struct g_mirror_metadata *md) +mirror_metadata_decode_v3v4(const u_char *data, struct g_mirror_metadata *md) { MD5_CTX ctx; @@ -385,7 +388,8 @@ mirror_metadata_decode(const u_char *data, struct g_mirror_metadata *md) error = mirror_metadata_decode_v2(data, md); break; case 3: - error = mirror_metadata_decode_v3(data, md); + case 4: + error = mirror_metadata_decode_v3v4(data, md); break; default: error = EINVAL; @@ -456,6 +460,8 @@ mirror_metadata_dump(const struct g_mirror_metadata *md) if (md->md_mflags == 0) printf(" NONE"); else { + if ((md->md_mflags & G_MIRROR_DEVICE_FLAG_NOFAILSYNC) != 0) + printf(" NOFAILSYNC"); if ((md->md_mflags & G_MIRROR_DEVICE_FLAG_NOAUTOSYNC) != 0) printf(" NOAUTOSYNC"); } diff --git a/sys/geom/mirror/g_mirror_ctl.c b/sys/geom/mirror/g_mirror_ctl.c index 9578782..27e58ce 100644 --- a/sys/geom/mirror/g_mirror_ctl.c +++ b/sys/geom/mirror/g_mirror_ctl.c @@ -97,7 +97,8 @@ g_mirror_ctl_configure(struct gctl_req *req, struct g_class *mp) intmax_t *slicep; uint32_t slice; uint8_t balance; - int *nargs, *autosync, *noautosync, *hardcode, *dynamic, do_sync = 0; + int *autosync, *noautosync, *failsync, *nofailsync, *hardcode, *dynamic; + int *nargs, do_sync = 0, dirty = 1; nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); if (nargs == NULL) { @@ -128,6 +129,16 @@ g_mirror_ctl_configure(struct gctl_req *req, struct g_class *mp) gctl_error(req, "No '%s' argument.", "noautosync"); return; } + failsync = gctl_get_paraml(req, "failsync", sizeof(*failsync)); + if (failsync == NULL) { + gctl_error(req, "No '%s' argument.", "failsync"); + return; + } + nofailsync = gctl_get_paraml(req, "nofailsync", sizeof(*nofailsync)); + if (nofailsync == NULL) { + gctl_error(req, "No '%s' argument.", "nofailsync"); + return; + } hardcode = gctl_get_paraml(req, "hardcode", sizeof(*hardcode)); if (hardcode == NULL) { gctl_error(req, "No '%s' argument.", "hardcode"); @@ -143,6 +154,11 @@ g_mirror_ctl_configure(struct gctl_req *req, struct g_class *mp) "noautosync"); return; } + if (*failsync && *nofailsync) { + gctl_error(req, "'%s' and '%s' specified.", "failsync", + "nofailsync"); + return; + } if (*hardcode && *dynamic) { gctl_error(req, "'%s' and '%s' specified.", "hardcode", "dynamic"); @@ -180,7 +196,8 @@ g_mirror_ctl_configure(struct gctl_req *req, struct g_class *mp) return; } if (sc->sc_balance == balance && sc->sc_slice == slice && !*autosync && - !*noautosync && !*hardcode && !*dynamic) { + !*noautosync && !*failsync && !*nofailsync && !*hardcode && + !*dynamic) { sx_xunlock(&sc->sc_lock); gctl_error(req, "Nothing has changed."); return; @@ -196,6 +213,15 @@ g_mirror_ctl_configure(struct gctl_req *req, struct g_class *mp) if (*noautosync) sc->sc_flags |= G_MIRROR_DEVICE_FLAG_NOAUTOSYNC; } + if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_NOFAILSYNC) != 0) { + if (*failsync) + sc->sc_flags &= ~G_MIRROR_DEVICE_FLAG_NOFAILSYNC; + } else { + if (*nofailsync) { + sc->sc_flags |= G_MIRROR_DEVICE_FLAG_NOFAILSYNC; + dirty = 0; + } + } LIST_FOREACH(disk, &sc->sc_disks, d_next) { if (do_sync) { if (disk->d_state == G_MIRROR_DISK_STATE_SYNCHRONIZING) @@ -205,6 +231,8 @@ g_mirror_ctl_configure(struct gctl_req *req, struct g_class *mp) disk->d_flags |= G_MIRROR_DISK_FLAG_HARDCODED; else if (*dynamic) disk->d_flags &= ~G_MIRROR_DISK_FLAG_HARDCODED; + if (!dirty) + disk->d_flags &= ~G_MIRROR_DISK_FLAG_DIRTY; g_mirror_update_metadata(disk); if (do_sync) { if (disk->d_state == G_MIRROR_DISK_STATE_STALE) { diff --git a/sys/geom/raid3/g_raid3.c b/sys/geom/raid3/g_raid3.c index e08e331..776b6bd 100644 --- a/sys/geom/raid3/g_raid3.c +++ b/sys/geom/raid3/g_raid3.c @@ -861,6 +861,8 @@ g_raid3_idle(struct g_raid3_softc *sc, int acw) if (sc->sc_provider == NULL) return (0); + if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_NOFAILSYNC) != 0) + return (0); if (sc->sc_idle) return (0); if (sc->sc_writes > 0) @@ -892,6 +894,8 @@ g_raid3_unidle(struct g_raid3_softc *sc) g_topology_assert_not(); sx_assert(&sc->sc_lock, SX_XLOCKED); + if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_NOFAILSYNC) != 0) + return; sc->sc_idle = 0; sc->sc_last_write = time_uptime; for (i = 0; i < sc->sc_ndisks; i++) { @@ -2154,6 +2158,8 @@ g_raid3_update_idle(struct g_raid3_softc *sc, struct g_raid3_disk *disk) { sx_assert(&sc->sc_lock, SX_LOCKED); + if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_NOFAILSYNC) != 0) + return; if (!sc->sc_idle && (disk->d_flags & G_RAID3_DISK_FLAG_DIRTY) == 0) { G_RAID3_DEBUG(1, "Disk %s (device %s) marked as dirty.", g_raid3_get_diskname(disk), sc->sc_name); @@ -2206,7 +2212,8 @@ g_raid3_sync_start(struct g_raid3_softc *sc) G_RAID3_DEBUG(0, "Device %s: rebuilding provider %s.", sc->sc_name, g_raid3_get_diskname(disk)); - disk->d_flags |= G_RAID3_DISK_FLAG_DIRTY; + if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_NOFAILSYNC) == 0) + disk->d_flags |= G_RAID3_DISK_FLAG_DIRTY; KASSERT(disk->d_sync.ds_consumer == NULL, ("Sync consumer already exists (device=%s, disk=%s).", sc->sc_name, g_raid3_get_diskname(disk))); @@ -3481,6 +3488,7 @@ g_raid3_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, sbuf_printf(sb, name); \ } \ } while (0) + ADD_FLAG(G_RAID3_DEVICE_FLAG_NOFAILSYNC, "NOFAILSYNC"); ADD_FLAG(G_RAID3_DEVICE_FLAG_NOAUTOSYNC, "NOAUTOSYNC"); ADD_FLAG(G_RAID3_DEVICE_FLAG_ROUND_ROBIN, "ROUND-ROBIN"); diff --git a/sys/geom/raid3/g_raid3.h b/sys/geom/raid3/g_raid3.h index 1032142..a375999 100644 --- a/sys/geom/raid3/g_raid3.h +++ b/sys/geom/raid3/g_raid3.h @@ -42,8 +42,9 @@ * 2 - Added 'verify reading' algorithm. * 3 - Added md_genid field to metadata. * 4 - Added md_provsize field to metadata. + * 5 - Added 'no failure synchronization' flag. */ -#define G_RAID3_VERSION 4 +#define G_RAID3_VERSION 5 #define G_RAID3_DISK_FLAG_DIRTY 0x0000000000000001ULL #define G_RAID3_DISK_FLAG_SYNCHRONIZING 0x0000000000000002ULL @@ -57,9 +58,11 @@ #define G_RAID3_DEVICE_FLAG_NOAUTOSYNC 0x0000000000000001ULL #define G_RAID3_DEVICE_FLAG_ROUND_ROBIN 0x0000000000000002ULL #define G_RAID3_DEVICE_FLAG_VERIFY 0x0000000000000004ULL +#define G_RAID3_DEVICE_FLAG_NOFAILSYNC 0x0000000000000008ULL #define G_RAID3_DEVICE_FLAG_MASK (G_RAID3_DEVICE_FLAG_NOAUTOSYNC | \ G_RAID3_DEVICE_FLAG_ROUND_ROBIN | \ - G_RAID3_DEVICE_FLAG_VERIFY) + G_RAID3_DEVICE_FLAG_VERIFY | \ + G_RAID3_DEVICE_FLAG_NOFAILSYNC) #ifdef _KERNEL extern u_int g_raid3_debug; @@ -363,7 +366,7 @@ raid3_metadata_decode_v3(const u_char *data, struct g_raid3_metadata *md) return (0); } static __inline int -raid3_metadata_decode_v4(const u_char *data, struct g_raid3_metadata *md) +raid3_metadata_decode_v4v5(const u_char *data, struct g_raid3_metadata *md) { MD5_CTX ctx; @@ -405,7 +408,8 @@ raid3_metadata_decode(const u_char *data, struct g_raid3_metadata *md) error = raid3_metadata_decode_v3(data, md); break; case 4: - error = raid3_metadata_decode_v4(data, md); + case 5: + error = raid3_metadata_decode_v4v5(data, md); break; default: error = EINVAL; @@ -442,6 +446,8 @@ raid3_metadata_dump(const struct g_raid3_metadata *md) printf(" ROUND-ROBIN"); if ((md->md_mflags & G_RAID3_DEVICE_FLAG_VERIFY) != 0) printf(" VERIFY"); + if ((md->md_mflags & G_RAID3_DEVICE_FLAG_NOFAILSYNC) != 0) + printf(" NOFAILSYNC"); } printf("\n"); printf(" dflags:"); diff --git a/sys/geom/raid3/g_raid3_ctl.c b/sys/geom/raid3/g_raid3_ctl.c index 67d1f44..952ac2b 100644 --- a/sys/geom/raid3/g_raid3_ctl.c +++ b/sys/geom/raid3/g_raid3_ctl.c @@ -98,8 +98,9 @@ g_raid3_ctl_configure(struct gctl_req *req, struct g_class *mp) struct g_raid3_softc *sc; struct g_raid3_disk *disk; const char *name; - int *nargs, do_sync = 0; + int *nargs, do_sync = 0, dirty = 1; int *autosync, *noautosync; + int *failsync, *nofailsync; int *round_robin, *noround_robin; int *verify, *noverify; u_int n; @@ -128,6 +129,21 @@ g_raid3_ctl_configure(struct gctl_req *req, struct g_class *mp) "noautosync"); return; } + failsync = gctl_get_paraml(req, "failsync", sizeof(*failsync)); + if (failsync == NULL) { + gctl_error(req, "No '%s' argument.", "failsync"); + return; + } + nofailsync = gctl_get_paraml(req, "nofailsync", sizeof(*nofailsync)); + if (nofailsync == NULL) { + gctl_error(req, "No '%s' argument.", "nofailsync"); + return; + } + if (*failsync && *nofailsync) { + gctl_error(req, "'%s' and '%s' specified.", "failsync", + "nofailsync"); + return; + } round_robin = gctl_get_paraml(req, "round_robin", sizeof(*round_robin)); if (round_robin == NULL) { gctl_error(req, "No '%s' argument.", "round_robin"); @@ -159,8 +175,8 @@ g_raid3_ctl_configure(struct gctl_req *req, struct g_class *mp) "noverify"); return; } - if (!*autosync && !*noautosync && !*round_robin && !*noround_robin && - !*verify && !*noverify) { + if (!*autosync && !*noautosync && !*failsync && !*nofailsync && + !*round_robin && !*noround_robin && !*verify && !*noverify) { gctl_error(req, "Nothing has changed."); return; } @@ -188,6 +204,15 @@ g_raid3_ctl_configure(struct gctl_req *req, struct g_class *mp) if (*noautosync) sc->sc_flags |= G_RAID3_DEVICE_FLAG_NOAUTOSYNC; } + if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_NOFAILSYNC) != 0) { + if (*failsync) + sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_NOFAILSYNC; + } else { + if (*nofailsync) { + sc->sc_flags |= G_RAID3_DEVICE_FLAG_NOFAILSYNC; + dirty = 0; + } + } if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_VERIFY) != 0) { if (*noverify) sc->sc_flags &= ~G_RAID3_DEVICE_FLAG_VERIFY; @@ -215,6 +240,8 @@ g_raid3_ctl_configure(struct gctl_req *req, struct g_class *mp) if (disk->d_state == G_RAID3_DISK_STATE_SYNCHRONIZING) disk->d_flags &= ~G_RAID3_DISK_FLAG_FORCE_SYNC; } + if (!dirty) + disk->d_flags &= ~G_RAID3_DISK_FLAG_DIRTY; g_raid3_update_metadata(disk); if (do_sync) { if (disk->d_state == G_RAID3_DISK_STATE_STALE) { -- cgit v1.1