From 4e5528c6f7b66f40617dabb232bc6c016bb86204 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Tue, 27 May 2008 09:18:38 +1000 Subject: [PATCH] Implement mark_clean for ddf and remove mark_dirty and mark_sync mark_dirty is just a special case of mark_clean - with sync_pos == 0. mark_sync is not required. We don't modify the metadata when sync finishes. Only when the array becomes non-writeable at which point we use mark_clean to record how far the resync progressed. --- mdadm.h | 11 +++++++++-- monitor.c | 14 ++++++++------ super-ddf.c | 34 +++++++++++++++++++++------------- super-intel.c | 45 ++++----------------------------------------- 4 files changed, 42 insertions(+), 62 deletions(-) diff --git a/mdadm.h b/mdadm.h index 6bf0c625..9dacdc4d 100644 --- a/mdadm.h +++ b/mdadm.h @@ -411,9 +411,16 @@ extern struct superswitch { /* for mdmon */ int (*open_new)(struct supertype *c, struct active_array *a, int inst); + /* This tells the metadata handler that all data up to sync_pos is + * known to be insync, and will stay insync until told otherwise. + * All data beyond sync_pos may not be insync. + * If sync_pos == 0, this marks the array as 'dirty'. + * If sync_pos == ~0, this marks it as fully 'clean'. + * If other numbers cannot be stored, they should be treated as 0. + * mark_clean is always called with a sync_pos of 0 before any + * write to an array with redundancy is allowed. + */ void (*mark_clean)(struct active_array *a, unsigned long long sync_pos); - void (*mark_dirty)(struct active_array *a); - void (*mark_sync)(struct active_array *a, unsigned long long resync); void (*set_disk)(struct active_array *a, int n, int state); void (*sync_metadata)(struct active_array *a); diff --git a/monitor.c b/monitor.c index 5fbbc833..a630c937 100644 --- a/monitor.c +++ b/monitor.c @@ -250,12 +250,12 @@ static int read_and_act(struct active_array *a) deactivate = 1; } if (a->curr_state == write_pending) { - a->container->ss->mark_dirty(a); + a->container->ss->mark_clean(a, 0); a->next_state = active; } if (a->curr_state == active_idle) { /* Set array to 'clean' FIRST, then - * a->ss->mark_clean(a); + * a->ss->mark_clean(a, ~0ULL); * just ignore for now. */ } @@ -269,16 +269,18 @@ static int read_and_act(struct active_array *a) if (a->resync_start == ~0ULL) a->next_state = read_auto; /* array is clean */ else { - a->container->ss->mark_dirty(a); + a->container->ss->mark_clean(a, 0); a->next_state = active; } } if (a->curr_action == idle && a->prev_action == resync) { - /* check resync_start to see if it is 'max' */ - get_resync_start(a); - a->container->ss->mark_sync(a, a->resync_start); + /* A resync has finished. The endpoint is recorded in + * 'sync_start'. We don't update the metadata + * until the array goes inactive or readonly though. + * Just check if we need to fiddle spares. + */ check_degraded = 1; } diff --git a/super-ddf.c b/super-ddf.c index 91c53dae..9ca18eb1 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -2447,25 +2447,35 @@ static int compare_super_ddf(struct supertype *st, struct supertype *tst) return 0; } +/* + * A new array 'a' has been started which claims to be instance 'inst' + * within container 'c'. + * We need to confirm that the array matches the metadata in 'c' so + * that we don't corrupt any metadata. + */ static int ddf_open_new(struct supertype *c, struct active_array *a, int inst) { fprintf(stderr, "ddf: open_new %d\n", inst); return 0; } +/* + * The array 'a' is to be marked clean in the metadata. + * If 'sync_pos' is not ~(unsigned long long)0, then the array is only + * clean up to the point (in sectors). If that cannot be recorded in the + * metadata, then leave it as dirty. + * + * For DDF, we need to clear the DDF_state_inconsistent bit in the + * !global! virtual_disk.virtual_entry structure. + */ static void ddf_mark_clean(struct active_array *a, unsigned long long sync_pos) { - fprintf(stderr, "ddf: mark clean %llu\n", sync_pos); -} - -static void ddf_mark_dirty(struct active_array *a) -{ - fprintf(stderr, "ddf: mark dirty\n"); -} - -static void ddf_mark_sync(struct active_array *a, unsigned long long resync) -{ - fprintf(stderr, "ddf: mark sync\n"); + struct ddf_super *ddf = a->container->sb; + int inst = a->info.container_member; + if (sync_pos == ~0ULL) + ddf->virt->entries[inst].state |= DDF_state_inconsistent; + else + ddf->virt->entries[inst].state &= ~DDF_state_inconsistent; } static void ddf_set_disk(struct active_array *a, int n, int state) @@ -2512,8 +2522,6 @@ struct superswitch super_ddf = { .open_new = ddf_open_new, .load_super = load_super_ddf, .mark_clean = ddf_mark_clean, - .mark_dirty = ddf_mark_dirty, - .mark_sync = ddf_mark_sync, .set_disk = ddf_set_disk, .sync_metadata = ddf_sync_metadata, diff --git a/super-intel.c b/super-intel.c index a72d0de4..b57e9b1c 100644 --- a/super-intel.c +++ b/super-intel.c @@ -1129,23 +1129,12 @@ static void imsm_mark_clean(struct active_array *a, unsigned long long sync_pos) int inst = a->info.container_member; struct intel_super *super = a->container->sb; struct imsm_dev *dev = get_imsm_dev(super->mpb, inst); + int dirty = (sync_pos != ~0ULL); - if (dev->vol.dirty) { - fprintf(stderr, "imsm: mark clean %llu\n", sync_pos); - dev->vol.dirty = 0; - super->updates_pending++; - } -} + if (dev->vol.dirty != dirty) { + fprintf(stderr, "imsm: mark 'clean' %llu\n", sync_pos); -static void imsm_mark_dirty(struct active_array *a) -{ - int inst = a->info.container_member; - struct intel_super *super = a->container->sb; - struct imsm_dev *dev = get_imsm_dev(super->mpb, inst); - - if (!dev->vol.dirty) { - fprintf(stderr, "imsm: mark dirty\n"); - dev->vol.dirty = 1; + dev->vol.dirty = dirty; super->updates_pending++; } } @@ -1227,30 +1216,6 @@ static int imsm_count_failed(struct imsm_super *mpb, struct imsm_map *map) return failed; } -static void imsm_mark_sync(struct active_array *a, unsigned long long resync) -{ - int inst = a->info.container_member; - struct intel_super *super = a->container->sb; - struct imsm_dev *dev = get_imsm_dev(super->mpb, inst); - struct imsm_map *map = dev->vol.map; - int failed; - __u8 map_state; - - if (resync != ~0ULL) - return; - - fprintf(stderr, "imsm: mark sync\n"); - - failed = imsm_count_failed(super->mpb, map); - map_state = imsm_check_degraded(super->mpb, inst, failed); - if (!failed) - map_state = IMSM_T_STATE_NORMAL; - if (map->map_state != map_state) { - map->map_state = map_state; - super->updates_pending++; - } -} - static void imsm_set_disk(struct active_array *a, int n, int state) { int inst = a->info.container_member; @@ -1392,8 +1357,6 @@ struct superswitch super_imsm = { .open_new = imsm_open_new, .load_super = load_super_imsm, .mark_clean = imsm_mark_clean, - .mark_dirty = imsm_mark_dirty, - .mark_sync = imsm_mark_sync, .set_disk = imsm_set_disk, .sync_metadata = imsm_sync_metadata, }; -- 2.39.2