diff --git a/sbin/geom/class/mirror/geom_mirror.c b/sbin/geom/class/mirror/geom_mirror.c index 0ace7337e578..7fc01cdd2f71 100644 --- a/sbin/geom/class/mirror/geom_mirror.c +++ b/sbin/geom/class/mirror/geom_mirror.c @@ -67,12 +67,14 @@ struct g_command class_commands[] = { { 'a', "autosync", NULL, G_TYPE_BOOL }, { 'b', "balance", configure_balance, G_TYPE_STRING }, { 'd', "dynamic", NULL, G_TYPE_BOOL }, + { 'f', "failsync", NULL, G_TYPE_BOOL }, + { 'F', "nofailsync", NULL, G_TYPE_BOOL }, { 'h', "hardcode", NULL, G_TYPE_BOOL }, { 'n', "noautosync", NULL, G_TYPE_BOOL }, { 's', "slice", &configure_slice, G_TYPE_NUMBER }, G_OPT_SENTINEL }, - "[-adhnv] [-b balance] [-s slice] name" + "[-adfFhnv] [-b balance] [-s slice] name" }, { "deactivate", G_FLAG_VERBOSE, NULL, G_NULL_OPTS, "[-v] name prov ..." @@ -86,12 +88,13 @@ struct g_command class_commands[] = { { "label", G_FLAG_VERBOSE, mirror_main, { { 'b', "balance", label_balance, G_TYPE_STRING }, + { 'F', "nofailsync", NULL, G_TYPE_BOOL }, { 'h', "hardcode", NULL, G_TYPE_BOOL }, { 'n', "noautosync", NULL, G_TYPE_BOOL }, { 's', "slice", &label_slice, G_TYPE_NUMBER }, G_OPT_SENTINEL }, - "[-hnv] [-b balance] [-s slice] name prov ..." + "[-Fhnv] [-b balance] [-s slice] name prov ..." }, { "insert", G_FLAG_VERBOSE, NULL, { @@ -154,7 +157,7 @@ mirror_label(struct gctl_req *req) unsigned sectorsize; off_t mediasize; intmax_t val; - int error, i, nargs, bal, hardcode, noautosync; + int error, i, nargs, bal, hardcode; nargs = gctl_get_int(req, "nargs"); if (nargs < 2) { @@ -182,9 +185,10 @@ mirror_label(struct gctl_req *req) return; } md.md_balance = bal; - noautosync = gctl_get_int(req, "noautosync"); - if (noautosync) + if (gctl_get_int(req, "noautosync")) md.md_mflags |= G_MIRROR_DEVICE_FLAG_NOAUTOSYNC; + if (gctl_get_int(req, "nofailsync")) + md.md_mflags |= G_MIRROR_DEVICE_FLAG_NOFAILSYNC; hardcode = gctl_get_int(req, "hardcode"); /* diff --git a/sbin/geom/class/mirror/gmirror.8 b/sbin/geom/class/mirror/gmirror.8 index a58212cae735..4d62f728a5e5 100644 --- a/sbin/geom/class/mirror/gmirror.8 +++ b/sbin/geom/class/mirror/gmirror.8 @@ -33,7 +33,7 @@ .Sh SYNOPSIS .Nm .Cm label -.Op Fl hnv +.Op Fl Fhnv .Op Fl b Ar balance .Op Fl s Ar slice .Ar name @@ -44,7 +44,7 @@ .Ar prov ... .Nm .Cm configure -.Op Fl adhnv +.Op Fl adfFhnv .Op Fl b Ar balance .Op Fl s Ar slice .Ar name @@ -142,6 +142,9 @@ Split read requests, which are bigger than or equal to slice size on N pieces, where N is the number of active components. This is the default balance algorithm. .El +.It Fl F +Do not synchronize after a power failure or system crash. +Assumes device is in consistent state. .It Fl h Hardcode providers' names in metadata. .It Fl n @@ -167,6 +170,11 @@ Turn on autosynchronization of stale components. Specifies balance algorithm to use. .It Fl d Do not hardcode providers' names in metadata. +.It Fl f +Synchronize device after a power failure or system crash. +.It Fl F +Do not synchronize after a power failure or system crash. +Assumes device is in consistent state. .It Fl h Hardcode providers' names in metadata. .It Fl n diff --git a/sbin/geom/class/raid3/geom_raid3.c b/sbin/geom/class/raid3/geom_raid3.c index 3f4df978ad8f..1bb41cbde593 100644 --- a/sbin/geom/class/raid3/geom_raid3.c +++ b/sbin/geom/class/raid3/geom_raid3.c @@ -58,6 +58,8 @@ struct g_command class_commands[] = { { { 'a', "autosync", NULL, G_TYPE_BOOL }, { 'd', "dynamic", NULL, G_TYPE_BOOL }, + { 'f', "failsync", NULL, G_TYPE_BOOL }, + { 'F', "nofailsync", NULL, G_TYPE_BOOL }, { 'h', "hardcode", NULL, G_TYPE_BOOL }, { 'n', "noautosync", NULL, G_TYPE_BOOL }, { 'r', "round_robin", NULL, G_TYPE_BOOL }, @@ -66,7 +68,7 @@ struct g_command class_commands[] = { { 'W', "noverify", NULL, G_TYPE_BOOL }, G_OPT_SENTINEL }, - "[-adhnrRvwW] name" + "[-adfFhnrRvwW] name" }, { "dump", 0, raid3_main, G_NULL_OPTS, "prov ..." @@ -82,12 +84,13 @@ struct g_command class_commands[] = { { "label", G_FLAG_VERBOSE, raid3_main, { { 'h', "hardcode", NULL, G_TYPE_BOOL }, + { 'F', "nofailsync", NULL, G_TYPE_BOOL }, { 'n', "noautosync", NULL, G_TYPE_BOOL }, { 'r', "round_robin", NULL, G_TYPE_BOOL }, { 'w', "verify", NULL, G_TYPE_BOOL }, G_OPT_SENTINEL }, - "[-hnrvw] name prov prov prov ..." + "[-hFnrvw] name prov prov prov ..." }, { "rebuild", G_FLAG_VERBOSE, NULL, G_NULL_OPTS, "[-v] name prov" @@ -142,7 +145,8 @@ raid3_label(struct gctl_req *req) const char *str; unsigned sectorsize, ssize; off_t mediasize, msize; - int error, i, nargs, hardcode, noautosync, round_robin, verify; + int hardcode, round_robin, verify; + int error, i, nargs; nargs = gctl_get_int(req, "nargs"); if (nargs < 4) { @@ -165,9 +169,10 @@ raid3_label(struct gctl_req *req) md.md_genid = 0; md.md_syncid = 1; md.md_sync_offset = 0; - noautosync = gctl_get_int(req, "noautosync"); - if (noautosync) + if (gctl_get_int(req, "noautosync")) md.md_mflags |= G_RAID3_DEVICE_FLAG_NOAUTOSYNC; + if (gctl_get_int(req, "nofailsync")) + md.md_mflags |= G_RAID3_DEVICE_FLAG_NOFAILSYNC; round_robin = gctl_get_int(req, "round_robin"); if (round_robin) md.md_mflags |= G_RAID3_DEVICE_FLAG_ROUND_ROBIN; diff --git a/sbin/geom/class/raid3/graid3.8 b/sbin/geom/class/raid3/graid3.8 index b2da0bf9e791..d9420b6d4aac 100644 --- a/sbin/geom/class/raid3/graid3.8 +++ b/sbin/geom/class/raid3/graid3.8 @@ -33,7 +33,7 @@ .Sh SYNOPSIS .Nm .Cm label -.Op Fl hnrvw +.Op Fl Fhnrvw .Ar name .Ar prov prov prov ... .Nm @@ -42,7 +42,7 @@ .Ar prov ... .Nm .Cm configure -.Op Fl adhnrRvwW +.Op Fl adfFhnrRvwW .Ar name .Nm .Cm rebuild @@ -97,6 +97,9 @@ The number of components must be equal to 3, 5, 9, 17, etc.\& (2^n + 1). .Pp Additional options include: .Bl -tag -width ".Fl h" +.It Fl F +Do not synchronize after a power failure or system crash. +Assumes device is in consistent state. .It Fl h Hardcode providers' names in metadata. .It Fl n @@ -134,6 +137,11 @@ Additional options include: Turn on autosynchronization of stale components. .It Fl d Do not hardcode providers' names in metadata. +.It Fl f +Synchronize device after a power failure or system crash. +.It Fl F +Do not synchronize after a power failure or system crash. +Assumes device is in consistent state. .It Fl h Hardcode providers' names in metadata. .It Fl n diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c index f03da3bceaa9..419611eb520c 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 a6ddc51b15b3..eb67b6e08ba7 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 957878209755..27e58ceb31c2 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 e08e33128db2..776b6bd3a0a7 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 1032142f8a56..a37599999359 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 67d1f4419b47..952ac2bf9f76 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) {