]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super-intel.c
imsm: Clear migration record when no migration in progress
[thirdparty/mdadm.git] / super-intel.c
index ca97bcc173a996cd30d0b5037ca30d8a8f651d96..69cab38c8f47f24ae2640aef2809428bda7b4609 100644 (file)
@@ -4248,6 +4248,8 @@ static int write_super_imsm_spares(struct intel_super *super, int doclose)
        return 0;
 }
 
+static int is_gen_migration(struct imsm_dev *dev);
+
 static int write_super_imsm(struct supertype *st, int doclose)
 {
        struct intel_super *super = st->sb;
@@ -4259,6 +4261,7 @@ static int write_super_imsm(struct supertype *st, int doclose)
        int i;
        __u32 mpb_size = sizeof(struct imsm_super) - sizeof(struct imsm_disk);
        int num_disks = 0;
+       int clear_migration_record = 1;
 
        /* 'generation' is incremented everytime the metadata is written */
        generation = __le32_to_cpu(mpb->generation_num);
@@ -4293,6 +4296,8 @@ static int write_super_imsm(struct supertype *st, int doclose)
                        imsm_copy_dev(dev, dev2);
                        mpb_size += sizeof_imsm_dev(dev, 0);
                }
+               if (is_gen_migration(dev2))
+                       clear_migration_record = 0;
        }
        mpb_size += __le32_to_cpu(mpb->bbm_log_size);
        mpb->mpb_size = __cpu_to_le32(mpb_size);
@@ -4301,6 +4306,9 @@ static int write_super_imsm(struct supertype *st, int doclose)
        sum = __gen_imsm_checksum(mpb);
        mpb->check_sum = __cpu_to_le32(sum);
 
+       if (clear_migration_record)
+               memset(super->migr_rec_buf, 0, 512);
+
        /* write the mpb for disks that compose raid devices */
        for (d = super->disks; d ; d = d->next) {
                if (d->index < 0)
@@ -4308,6 +4316,14 @@ static int write_super_imsm(struct supertype *st, int doclose)
                if (store_imsm_mpb(d->fd, mpb))
                        fprintf(stderr, "%s: failed for device %d:%d %s\n",
                                __func__, d->major, d->minor, strerror(errno));
+               if (clear_migration_record) {
+                       unsigned long long dsize;
+
+                       get_dev_size(d->fd, NULL, &dsize);
+                       if (lseek64(d->fd, dsize - 512, SEEK_SET) >= 0) {
+                               write(d->fd, super->migr_rec_buf, 512);
+                       }
+               }
                if (doclose) {
                        close(d->fd);
                        d->fd = -1;
@@ -8304,6 +8320,53 @@ int wait_for_reshape_imsm(struct mdinfo *sra, unsigned long long to_complete,
 
 }
 
+/*******************************************************************************
+ * Function:   check_degradation_change
+ * Description:        Check that array hasn't become failed.
+ * Parameters:
+ *     info    : for sysfs access
+ *     sources : source disks descriptors
+ *     degraded: previous degradation level
+ * Returns:
+ *     degradation level
+ ******************************************************************************/
+int check_degradation_change(struct mdinfo *info,
+                            int *sources,
+                            int degraded)
+{
+       unsigned long long new_degraded;
+       sysfs_get_ll(info, NULL, "degraded", &new_degraded);
+       if (new_degraded != (unsigned long long)degraded) {
+               /* check each device to ensure it is still working */
+               struct mdinfo *sd;
+               new_degraded = 0;
+               for (sd = info->devs ; sd ; sd = sd->next) {
+                       if (sd->disk.state & (1<<MD_DISK_FAULTY))
+                               continue;
+                       if (sd->disk.state & (1<<MD_DISK_SYNC)) {
+                               char sbuf[20];
+                               if (sysfs_get_str(info,
+                                       sd, "state", sbuf, 20) < 0 ||
+                                       strstr(sbuf, "faulty") ||
+                                       strstr(sbuf, "in_sync") == NULL) {
+                                       /* this device is dead */
+                                       sd->disk.state = (1<<MD_DISK_FAULTY);
+                                       if (sd->disk.raid_disk >= 0 &&
+                                           sources[sd->disk.raid_disk] >= 0) {
+                                               close(sources[
+                                                       sd->disk.raid_disk]);
+                                               sources[sd->disk.raid_disk] =
+                                                       -1;
+                                       }
+                                       new_degraded++;
+                               }
+                       }
+               }
+       }
+
+       return new_degraded;
+}
+
 /*******************************************************************************
  * Function:   imsm_manage_reshape
  * Description:        Function finds array under reshape and it manages reshape
@@ -8348,6 +8411,7 @@ static int imsm_manage_reshape(
        unsigned long long start_src; /* [bytes] */
        unsigned long long start; /* [bytes] */
        unsigned long long start_buf_shift; /* [bytes] */
+       int degraded = 0;
 
        if (!fds || !offsets || !destfd || !destoffsets || !sra)
                goto abort;
@@ -8414,6 +8478,15 @@ static int imsm_manage_reshape(
                        * __le32_to_cpu(migr_rec->curr_migr_unit);
                unsigned long long border;
 
+               /* Check that array hasn't become failed.
+                */
+               degraded = check_degradation_change(sra, fds, degraded);
+               if (degraded > 1) {
+                       dprintf("imsm: Abort reshape due to degradation"
+                               " level (%i)\n", degraded);
+                       goto abort;
+               }
+
                next_step = __le32_to_cpu(migr_rec->blocks_per_unit);
 
                if ((current_position + next_step) > max_position)