]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Grow: support consistency policy change
authorArtur Paszkiewicz <artur.paszkiewicz@intel.com>
Wed, 29 Mar 2017 09:54:20 +0000 (11:54 +0200)
committerJes Sorensen <Jes.Sorensen@gmail.com>
Wed, 29 Mar 2017 15:35:16 +0000 (11:35 -0400)
Extend the --consistency-policy parameter to work also in Grow mode.
Using it changes the currently active consistency policy in the kernel
driver and updates the metadata to make this change permanent. Currently
this supports only changing between "ppl" and "resync" policies, that is
enabling or disabling PPL at runtime.

Signed-off-by: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
Signed-off-by: Jes Sorensen <Jes.Sorensen@gmail.com>
Grow.c
ReadMe.c
mdadm.8.in
mdadm.c
mdadm.h

diff --git a/Grow.c b/Grow.c
index a849012b3c0fb1ade6f0b17360e774619e43fcba..b86b53ec96ce41882a5dc9be63d5740f88847cd1 100755 (executable)
--- a/Grow.c
+++ b/Grow.c
@@ -528,6 +528,178 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s)
        return 0;
 }
 
        return 0;
 }
 
+int Grow_consistency_policy(char *devname, int fd, struct context *c, struct shape *s)
+{
+       struct supertype *st;
+       struct mdinfo *sra;
+       struct mdinfo *sd;
+       char *subarray = NULL;
+       int ret = 0;
+       char container_dev[PATH_MAX];
+
+       if (s->consistency_policy != CONSISTENCY_POLICY_RESYNC &&
+           s->consistency_policy != CONSISTENCY_POLICY_PPL) {
+               pr_err("Operation not supported for consistency policy %s\n",
+                      map_num(consistency_policies, s->consistency_policy));
+               return 1;
+       }
+
+       st = super_by_fd(fd, &subarray);
+       if (!st)
+               return 1;
+
+       sra = sysfs_read(fd, NULL, GET_CONSISTENCY_POLICY|GET_LEVEL|
+                                  GET_DEVS|GET_STATE);
+       if (!sra) {
+               ret = 1;
+               goto free_st;
+       }
+
+       if (s->consistency_policy == CONSISTENCY_POLICY_PPL &&
+           !st->ss->write_init_ppl) {
+               pr_err("%s metadata does not support PPL\n", st->ss->name);
+               ret = 1;
+               goto free_info;
+       }
+
+       if (sra->array.level != 5) {
+               pr_err("Operation not supported for array level %d\n",
+                               sra->array.level);
+               ret = 1;
+               goto free_info;
+       }
+
+       if (sra->consistency_policy == (unsigned)s->consistency_policy) {
+               pr_err("Consistency policy is already %s\n",
+                      map_num(consistency_policies, s->consistency_policy));
+               ret = 1;
+               goto free_info;
+       } else if (sra->consistency_policy != CONSISTENCY_POLICY_RESYNC &&
+                  sra->consistency_policy != CONSISTENCY_POLICY_PPL) {
+               pr_err("Current consistency policy is %s, cannot change to %s\n",
+                      map_num(consistency_policies, sra->consistency_policy),
+                      map_num(consistency_policies, s->consistency_policy));
+               ret = 1;
+               goto free_info;
+       }
+
+       if (subarray) {
+               char *update;
+
+               if (s->consistency_policy == CONSISTENCY_POLICY_PPL)
+                       update = "ppl";
+               else
+                       update = "no-ppl";
+
+               sprintf(container_dev, "/dev/%s", st->container_devnm);
+
+               ret = Update_subarray(container_dev, subarray, update, NULL,
+                                     c->verbose);
+               if (ret)
+                       goto free_info;
+       }
+
+       if (s->consistency_policy == CONSISTENCY_POLICY_PPL) {
+               struct mdinfo info;
+
+               if (subarray) {
+                       struct mdinfo *mdi;
+                       int cfd;
+
+                       cfd = open(container_dev, O_RDWR|O_EXCL);
+                       if (cfd < 0) {
+                               pr_err("Failed to open %s\n", container_dev);
+                               ret = 1;
+                               goto free_info;
+                       }
+
+                       ret = st->ss->load_container(st, cfd, st->container_devnm);
+                       close(cfd);
+
+                       if (ret) {
+                               pr_err("Cannot read superblock for %s\n",
+                                      container_dev);
+                               goto free_info;
+                       }
+
+                       mdi = st->ss->container_content(st, subarray);
+                       info = *mdi;
+                       free(mdi);
+               }
+
+               for (sd = sra->devs; sd; sd = sd->next) {
+                       int dfd;
+                       char *devpath;
+
+                       if ((sd->disk.state & (1 << MD_DISK_SYNC)) == 0)
+                               continue;
+
+                       devpath = map_dev(sd->disk.major, sd->disk.minor, 0);
+                       dfd = dev_open(devpath, O_RDWR);
+                       if (dfd < 0) {
+                               pr_err("Failed to open %s\n", devpath);
+                               ret = 1;
+                               goto free_info;
+                       }
+
+                       if (!subarray) {
+                               ret = st->ss->load_super(st, dfd, NULL);
+                               if (ret) {
+                                       pr_err("Failed to load super-block.\n");
+                                       close(dfd);
+                                       goto free_info;
+                               }
+
+                               ret = st->ss->update_super(st, sra, "ppl", devname,
+                                                          c->verbose, 0, NULL);
+                               if (ret) {
+                                       close(dfd);
+                                       st->ss->free_super(st);
+                                       goto free_info;
+                               }
+                               st->ss->getinfo_super(st, &info, NULL);
+                       }
+
+                       ret |= sysfs_set_num(sra, sd, "ppl_sector", info.ppl_sector);
+                       ret |= sysfs_set_num(sra, sd, "ppl_size", info.ppl_size);
+
+                       if (ret) {
+                               pr_err("Failed to set PPL attributes for %s\n",
+                                      sd->sys_name);
+                               close(dfd);
+                               st->ss->free_super(st);
+                               goto free_info;
+                       }
+
+                       ret = st->ss->write_init_ppl(st, &info, dfd);
+                       if (ret)
+                               pr_err("Failed to write PPL\n");
+
+                       close(dfd);
+
+                       if (!subarray)
+                               st->ss->free_super(st);
+
+                       if (ret)
+                               goto free_info;
+               }
+       }
+
+       ret = sysfs_set_str(sra, NULL, "consistency_policy",
+                           map_num(consistency_policies,
+                                   s->consistency_policy));
+       if (ret)
+               pr_err("Failed to change array consistency policy\n");
+
+free_info:
+       sysfs_free(sra);
+free_st:
+       free(st);
+       free(subarray);
+
+       return ret;
+}
+
 /*
  * When reshaping an array we might need to backup some data.
  * This is written to all spares with a 'super_block' describing it.
 /*
  * When reshaping an array we might need to backup some data.
  * This is written to all spares with a 'super_block' describing it.
index fc04c2c3a00d8d908ed8cc4a899fe3e1c373ff4d..eb8fb4b746bd1b9d255c005f6fa9883e11f68812 100644 (file)
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -559,28 +559,30 @@ char Help_grow[] =
 "reconfiguration.\n"
 "\n"
 "Options that are valid with the grow (-G --grow) mode are:\n"
 "reconfiguration.\n"
 "\n"
 "Options that are valid with the grow (-G --grow) mode are:\n"
-"  --level=       -l   : Tell mdadm what level to convert the array to.\n"
-"  --layout=      -p   : For a FAULTY array, set/change the error mode.\n"
-"                      : for other arrays, update the layout\n"
-"  --size=        -z   : Change the active size of devices in an array.\n"
-"                      : This is useful if all devices have been replaced\n"
-"                      : with larger devices.   Value is in Kilobytes, or\n"
-"                      : the special word 'max' meaning 'as large as possible'.\n"
-"  --assume-clean      : When increasing the --size, this flag will avoid\n"
-"                      : a resync of the new space\n"
-"  --chunk=       -c   : Change the chunksize of the array\n"
-"  --raid-devices= -n  : Change the number of active devices in an array.\n"
-"  --add=         -a   : Add listed devices as part of reshape.  This is\n"
-"                      : needed for resizing a RAID0 which cannot have\n"
-"                      : spares already present.\n"
-"  --bitmap=      -b   : Add or remove a write-intent bitmap.\n"
-"  --backup-file= file : A file on a different device to store data for a\n"
-"                      : short time while increasing raid-devices on a\n"
-"                      : RAID4/5/6 array. Also needed throughout a reshape\n"
-"                      : when changing parameters other than raid-devices\n"
-"  --array-size=  -Z   : Change visible size of array.  This does not change\n"
-"                      : any data on the device, and is not stable across restarts.\n"
-"  --data-offset=      : Location on device to move start of data to.\n"
+"  --level=           -l : Tell mdadm what level to convert the array to.\n"
+"  --layout=          -p : For a FAULTY array, set/change the error mode.\n"
+"                        : for other arrays, update the layout\n"
+"  --size=            -z : Change the active size of devices in an array.\n"
+"                        : This is useful if all devices have been replaced\n"
+"                        : with larger devices.   Value is in Kilobytes, or\n"
+"                        : the special word 'max' meaning 'as large as possible'.\n"
+"  --assume-clean        : When increasing the --size, this flag will avoid\n"
+"                        : a resync of the new space\n"
+"  --chunk=           -c : Change the chunksize of the array\n"
+"  --raid-devices=    -n : Change the number of active devices in an array.\n"
+"  --add=             -a : Add listed devices as part of reshape.  This is\n"
+"                        : needed for resizing a RAID0 which cannot have\n"
+"                        : spares already present.\n"
+"  --bitmap=          -b : Add or remove a write-intent bitmap.\n"
+"  --backup-file= file   : A file on a different device to store data for a\n"
+"                        : short time while increasing raid-devices on a\n"
+"                        : RAID4/5/6 array. Also needed throughout a reshape\n"
+"                        : when changing parameters other than raid-devices\n"
+"  --array-size=      -Z : Change visible size of array. This does not change any\n"
+"                        : data on the device, and is not stable across restarts.\n"
+"  --data-offset=        : Location on device to move start of data to.\n"
+"  --consistency-policy= : Change the consistency policy of an active array.\n"
+"                     -k : Currently works only for PPL with RAID5.\n"
 ;
 
 char Help_incr[] =
 ;
 
 char Help_incr[] =
index 1178ed9ba320cb037a4e537054f26c4f0effbe0a..744c12b534bfe43b34fb4bd673a50613723b060a 100644 (file)
@@ -126,7 +126,7 @@ of component devices and changing the number of active devices in
 Linear and RAID levels 0/1/4/5/6,
 changing the RAID level between 0, 1, 5, and 6, and between 0 and 10,
 changing the chunk size and layout for RAID 0,4,5,6,10 as well as adding or
 Linear and RAID levels 0/1/4/5/6,
 changing the RAID level between 0, 1, 5, and 6, and between 0 and 10,
 changing the chunk size and layout for RAID 0,4,5,6,10 as well as adding or
-removing a write-intent bitmap.
+removing a write-intent bitmap and changing the array's consistency policy.
 
 .TP
 .B "Incremental Assembly"
 
 .TP
 .B "Incremental Assembly"
@@ -1050,6 +1050,10 @@ after unclean shutdown. Implicitly selected when using
 For RAID5 only, Partial Parity Log is used to close the write hole and
 eliminate resync. PPL is stored in the metadata region of RAID member drives,
 no additional journal drive is needed.
 For RAID5 only, Partial Parity Log is used to close the write hole and
 eliminate resync. PPL is stored in the metadata region of RAID member drives,
 no additional journal drive is needed.
+
+.PP
+Can be used with \-\-grow to change the consistency policy of an active array
+in some cases. See CONSISTENCY POLICY CHANGES below.
 .RE
 
 
 .RE
 
 
@@ -2694,6 +2698,8 @@ RAID0, RAID4, and RAID5, and between RAID0 and RAID10 (in the near-2 mode).
 .IP \(bu 4
 add a write-intent bitmap to any array which supports these bitmaps, or
 remove a write-intent bitmap from such an array.
 .IP \(bu 4
 add a write-intent bitmap to any array which supports these bitmaps, or
 remove a write-intent bitmap from such an array.
+.IP \(bu 4
+change the array's consistency policy.
 .PP
 
 Using GROW on containers is currently supported only for Intel's IMSM
 .PP
 
 Using GROW on containers is currently supported only for Intel's IMSM
@@ -2850,6 +2856,16 @@ can be added.  Note that if you add a bitmap stored in a file which is
 in a filesystem that is on the RAID array being affected, the system
 will deadlock.  The bitmap must be on a separate filesystem.
 
 in a filesystem that is on the RAID array being affected, the system
 will deadlock.  The bitmap must be on a separate filesystem.
 
+.SS CONSISTENCY POLICY CHANGES
+
+The consistency policy of an active array can be changed by using the
+.B \-\-consistency\-policy
+option in Grow mode. Currently this works only for the
+.B ppl
+and
+.B resync
+policies and allows to enable or disable the RAID5 Partial Parity Log (PPL).
+
 .SH INCREMENTAL MODE
 
 .HP 12
 .SH INCREMENTAL MODE
 
 .HP 12
diff --git a/mdadm.c b/mdadm.c
index 6edf3abb14df55577db83568b161966b3410eaa3..5ebf1175b5781871b17a14ea5ad73f09462e049e 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
@@ -1221,6 +1221,7 @@ int main(int argc, char *argv[])
                        s.journaldisks = 1;
                        continue;
                case O(CREATE, 'k'):
                        s.journaldisks = 1;
                        continue;
                case O(CREATE, 'k'):
+               case O(GROW, 'k'):
                        s.consistency_policy = map_name(consistency_policies,
                                                        optarg);
                        if (s.consistency_policy == UnSet ||
                        s.consistency_policy = map_name(consistency_policies,
                                                        optarg);
                        if (s.consistency_policy == UnSet ||
@@ -1679,6 +1680,8 @@ int main(int argc, char *argv[])
                        rv = Grow_reshape(devlist->devname, mdfd,
                                          devlist->next,
                                          data_offset, &c, &s);
                        rv = Grow_reshape(devlist->devname, mdfd,
                                          devlist->next,
                                          data_offset, &c, &s);
+               } else if (s.consistency_policy != UnSet) {
+                       rv = Grow_consistency_policy(devlist->devname, mdfd, &c, &s);
                } else if (array_size == 0)
                        pr_err("no changes to --grow\n");
                break;
                } else if (array_size == 0)
                        pr_err("no changes to --grow\n");
                break;
diff --git a/mdadm.h b/mdadm.h
index 2c7066dcaecea8b86035827edfa063d53bd63542..4891acf5d15a67af9d047a8123db47b5d44a1cfc 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -1331,6 +1331,8 @@ extern int Grow_restart(struct supertype *st, struct mdinfo *info,
 extern int Grow_continue(int mdfd, struct supertype *st,
                         struct mdinfo *info, char *backup_file,
                         int forked, int freeze_reshape);
 extern int Grow_continue(int mdfd, struct supertype *st,
                         struct mdinfo *info, char *backup_file,
                         int forked, int freeze_reshape);
+extern int Grow_consistency_policy(char *devname, int fd,
+                                  struct context *c, struct shape *s);
 
 extern int restore_backup(struct supertype *st,
                          struct mdinfo *content,
 
 extern int restore_backup(struct supertype *st,
                          struct mdinfo *content,