diff options
Diffstat (limited to 'super-intel.c')
-rw-r--r-- | super-intel.c | 44 |
1 files changed, 37 insertions, 7 deletions
diff --git a/super-intel.c b/super-intel.c index f011a31f..d2035ccd 100644 --- a/super-intel.c +++ b/super-intel.c @@ -4523,6 +4523,11 @@ static int find_intel_hba_capability(int fd, struct intel_super *super, char *de struct sys_dev *hba_name; int rv = 0; + if (fd >= 0 && test_partition(fd)) { + pr_err("imsm: %s is a partition, cannot be used in IMSM\n", + devname); + return 1; + } if (fd < 0 || check_env("IMSM_NO_PLATFORM")) { super->orom = NULL; super->hba = NULL; @@ -5285,10 +5290,22 @@ static int check_name(struct intel_super *super, char *name, int quiet) { struct imsm_super *mpb = super->anchor; char *reason = NULL; + char *start = name; + size_t len = strlen(name); int i; - if (strlen(name) > MAX_RAID_SERIAL_LEN) + if (len > 0) { + while (isspace(start[len - 1])) + start[--len] = 0; + while (*start && isspace(*start)) + ++start, --len; + memmove(name, start, len + 1); + } + + if (len > MAX_RAID_SERIAL_LEN) reason = "must be 16 characters or less"; + else if (len == 0) + reason = "must be a non-empty string"; for (i = 0; i < mpb->num_raid_devs; i++) { struct imsm_dev *dev = get_imsm_dev(super, i); @@ -8119,7 +8136,8 @@ static int mark_failure(struct intel_super *super, set_imsm_ord_tbl_ent(map2, slot2, idx | IMSM_ORD_REBUILD); } - if (map->failed_disk_num == 0xff) + if (map->failed_disk_num == 0xff || + (!is_rebuilding(dev) && map->failed_disk_num > slot)) map->failed_disk_num = slot; clear_disk_badblocks(super->bbm_log, ord_to_idx(ord)); @@ -8541,13 +8559,25 @@ static void imsm_set_disk(struct active_array *a, int n, int state) break; } if (is_rebuilding(dev)) { - dprintf_cont("while rebuilding."); + dprintf_cont("while rebuilding "); if (map->map_state != map_state) { - dprintf_cont(" Map state change"); - end_migration(dev, super, map_state); + dprintf_cont("map state change "); + if (n == map->failed_disk_num) { + dprintf_cont("end migration"); + end_migration(dev, super, map_state); + } else { + dprintf_cont("raid10 double degradation, map state change"); + map->map_state = map_state; + } super->updates_pending++; - } else if (!rebuild_done) { + } else if (!rebuild_done) break; + else if (n == map->failed_disk_num) { + /* r10 double degraded to degraded transition */ + dprintf_cont("raid10 double degradation end migration"); + end_migration(dev, super, map_state); + a->last_checkpoint = 0; + super->updates_pending++; } /* check if recovery is really finished */ @@ -8558,7 +8588,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state) } if (recovery_not_finished) { dprintf_cont("\n"); - dprintf("Rebuild has not finished yet, state not changed"); + dprintf_cont("Rebuild has not finished yet, map state changes only if raid10 double degradation happens"); if (a->last_checkpoint < mdi->recovery_start) { a->last_checkpoint = mdi->recovery_start; |