From dd3a91c6ce0c4cdd4197bc73098933e19bcd919b Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Aug 01 2017 03:37:30 +0000 Subject: import mdadm-4.0-5.el7 --- diff --git a/.gitignore b/.gitignore index 094b437..69823cc 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/mdadm-3.4.tar.xz +SOURCES/mdadm-4.0.tar.xz diff --git a/.mdadm.metadata b/.mdadm.metadata index 01a9c90..986b723 100644 --- a/.mdadm.metadata +++ b/.mdadm.metadata @@ -1 +1 @@ -0b6c284970567bfa30dbc14ea5c0e2320582b80c SOURCES/mdadm-3.4.tar.xz +0886a47e8109f86160e45896ca6dc445fdeee710 SOURCES/mdadm-4.0.tar.xz diff --git a/SOURCES/Add-sector-size-as-spare-selection-criterion.patch b/SOURCES/Add-sector-size-as-spare-selection-criterion.patch new file mode 100644 index 0000000..c0eab20 --- /dev/null +++ b/SOURCES/Add-sector-size-as-spare-selection-criterion.patch @@ -0,0 +1,172 @@ +commit 4b57ecf6cea134edff75a2f3a87ee48d52715c70 +Author: Alexey Obitotskiy +Date: Tue May 9 12:25:47 2017 +0200 + + Add sector size as spare selection criterion + + Add sector size as new spare selection criterion. Assume that 0 means + there is no requirement for the sector size in the array. Skip disks + with unsuitable sector size when looking for a spare to move across + containers. + + Signed-off-by: Alexey Obitotskiy + Signed-off-by: Tomasz Majchrzak + Signed-off-by: Jes Sorensen + +diff --git a/Incremental.c b/Incremental.c +index fe9d644..30dc7a2 100644 +--- a/Incremental.c ++++ b/Incremental.c +@@ -867,7 +867,7 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol, + struct domainlist *dl = NULL; + struct mdinfo *sra; + unsigned long long devsize; +- struct spare_criteria sc = {0}; ++ struct spare_criteria sc = {0, 0}; + + if (is_subarray(mp->metadata)) + continue; +@@ -1627,7 +1627,7 @@ static int Incremental_container(struct supertype *st, char *devname, + struct mdinfo *sinfo; + + if (!sst->ss->load_container(sst, sfd, NULL)) { +- struct spare_criteria sc = {0}; ++ struct spare_criteria sc = {0, 0}; + + if (st->ss->get_spare_criteria) + st->ss->get_spare_criteria(st, &sc); +diff --git a/Monitor.c b/Monitor.c +index 9a2baad..c96f8e8 100644 +--- a/Monitor.c ++++ b/Monitor.c +@@ -731,6 +731,7 @@ static int get_required_spare_criteria(struct state *st, + if (!st->metadata || + !st->metadata->ss->get_spare_criteria) { + sc->min_size = 0; ++ sc->sector_size = 0; + return 0; + } + +@@ -787,6 +788,7 @@ static dev_t choose_spare(struct state *from, struct state *to, + from->devstate[d] == 0) { + struct dev_policy *pol; + unsigned long long dev_size; ++ unsigned int dev_sector_size; + + if (to->metadata->ss->external && + test_partition_from_id(from->devid[d])) +@@ -797,6 +799,12 @@ static dev_t choose_spare(struct state *from, struct state *to, + dev_size < sc->min_size) + continue; + ++ if (sc->sector_size && ++ dev_sector_size_from_id(from->devid[d], ++ &dev_sector_size) && ++ sc->sector_size != dev_sector_size) ++ continue; ++ + pol = devid_policy(from->devid[d]); + if (from->spare_group) + pol_add(&pol, pol_domain, +diff --git a/mdadm.h b/mdadm.h +index 8da7fd3..ec0a39e 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -363,6 +363,7 @@ struct createinfo { + + struct spare_criteria { + unsigned long long min_size; ++ unsigned int sector_size; + }; + + enum mode { +@@ -947,6 +948,7 @@ extern struct superswitch { + /* + * Return spare criteria for array: + * - minimum disk size can be used in array; ++ * - sector size can be used in array. + * Return values: 0 - for success and -EINVAL on error. + */ + int (*get_spare_criteria)(struct supertype *st, +@@ -1189,6 +1191,7 @@ extern int get_dev_size(int fd, char *dname, unsigned long long *sizep); + extern int get_dev_sector_size(int fd, char *dname, unsigned int *sectsizep); + extern int must_be_container(int fd); + extern int dev_size_from_id(dev_t id, unsigned long long *size); ++extern int dev_sector_size_from_id(dev_t id, unsigned int *size); + void wait_for(char *dev, int fd); + + /* +diff --git a/super-intel.c b/super-intel.c +index be973f8..ba6f810 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -1396,6 +1396,7 @@ int get_spare_criteria_imsm(struct supertype *st, struct spare_criteria *c) + unsigned long long size = 0; + + c->min_size = 0; ++ c->sector_size = 0; + + if (!super) + return -EINVAL; +@@ -1419,6 +1420,7 @@ int get_spare_criteria_imsm(struct supertype *st, struct spare_criteria *c) + size += imsm_min_reserved_sectors(super); + + c->min_size = size * 512; ++ c->sector_size = super->sector_size; + + return 0; + } +diff --git a/util.c b/util.c +index 8b3c67d..fc9cd3f 100644 +--- a/util.c ++++ b/util.c +@@ -1265,6 +1265,23 @@ int dev_size_from_id(dev_t id, unsigned long long *size) + return 0; + } + ++int dev_sector_size_from_id(dev_t id, unsigned int *size) ++{ ++ char buf[20]; ++ int fd; ++ ++ sprintf(buf, "%d:%d", major(id), minor(id)); ++ fd = dev_open(buf, O_RDONLY); ++ if (fd < 0) ++ return 0; ++ if (get_dev_sector_size(fd, NULL, size)) { ++ close(fd); ++ return 1; ++ } ++ close(fd); ++ return 0; ++} ++ + struct supertype *dup_super(struct supertype *orig) + { + struct supertype *st; +@@ -2129,12 +2146,24 @@ struct mdinfo *container_choose_spares(struct supertype *st, + if (d->disk.state == 0) { + /* check if size is acceptable */ + unsigned long long dev_size; ++ unsigned int dev_sector_size; ++ int size_valid = 0; ++ int sector_size_valid = 0; ++ + dev_t dev = makedev(d->disk.major,d->disk.minor); + + if (!criteria->min_size || + (dev_size_from_id(dev, &dev_size) && + dev_size >= criteria->min_size)) +- found = 1; ++ size_valid = 1; ++ ++ if (!criteria->sector_size || ++ (dev_sector_size_from_id(dev, &dev_sector_size) && ++ criteria->sector_size == dev_sector_size)) ++ sector_size_valid = 1; ++ ++ found = size_valid && sector_size_valid; ++ + /* check if domain matches */ + if (found && domlist) { + struct dev_policy *pol = devid_policy(dev); diff --git a/SOURCES/Allow-more-spare-selection-criteria.patch b/SOURCES/Allow-more-spare-selection-criteria.patch new file mode 100644 index 0000000..eba8997 --- /dev/null +++ b/SOURCES/Allow-more-spare-selection-criteria.patch @@ -0,0 +1,334 @@ +commit fbfdcb06dc5b1dcb227b0394f174faa2df734700 +Author: Alexey Obitotskiy +Date: Tue May 9 12:25:46 2017 +0200 + + Allow more spare selection criteria + + Disks can be moved across containers in order to be used as a spare + drive for reubild. At the moment the only requirement checked for such + disk is its size (if it matches donor expectations). In order to + introduce more criteria rename corresponding superswitch method to more + generic name and move function parameter to a structure. This change is + a big edit but it doesn't introduce any changes in code logic, it just + updates function naming and parameters. + + Signed-off-by: Alexey Obitotskiy + Signed-off-by: Tomasz Majchrzak + Signed-off-by: Jes Sorensen + +diff --git a/Incremental.c b/Incremental.c +index 680d318..fe9d644 100644 +--- a/Incremental.c ++++ b/Incremental.c +@@ -867,7 +867,7 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol, + struct domainlist *dl = NULL; + struct mdinfo *sra; + unsigned long long devsize; +- unsigned long long component_size = 0; ++ struct spare_criteria sc = {0}; + + if (is_subarray(mp->metadata)) + continue; +@@ -936,7 +936,8 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol, + } + if (st3->ss->load_container && + !st3->ss->load_container(st3, mdfd, mp->path)) { +- component_size = st3->ss->min_acceptable_spare_size(st3); ++ if (st3->ss->get_spare_criteria) ++ st3->ss->get_spare_criteria(st3, &sc); + st3->ss->free_super(st3); + } + free(st3); +@@ -947,7 +948,7 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol, + : INVALID_SECTORS) + < sra->component_size) + || +- (sra->component_size == 0 && devsize < component_size)) { ++ (sra->component_size == 0 && devsize < sc.min_size)) { + if (verbose > 1) + pr_err("not adding %s to %s as it is too small\n", + devname, mp->path); +@@ -1624,12 +1625,15 @@ static int Incremental_container(struct supertype *st, char *devname, + struct supertype *sst = + super_imsm.match_metadata_desc("imsm"); + struct mdinfo *sinfo; +- unsigned long long min_size = 0; +- if (st->ss->min_acceptable_spare_size) +- min_size = st->ss->min_acceptable_spare_size(st); ++ + if (!sst->ss->load_container(sst, sfd, NULL)) { ++ struct spare_criteria sc = {0}; ++ ++ if (st->ss->get_spare_criteria) ++ st->ss->get_spare_criteria(st, &sc); ++ + close(sfd); +- sinfo = container_choose_spares(sst, min_size, ++ sinfo = container_choose_spares(sst, &sc, + domains, NULL, + st->ss->name, 0); + sst->ss->free_super(sst); +diff --git a/Monitor.c b/Monitor.c +index ec643d4..9a2baad 100644 +--- a/Monitor.c ++++ b/Monitor.c +@@ -723,13 +723,14 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist, + return new_found; + } + +-static int get_min_spare_size_required(struct state *st, unsigned long long *sizep) ++static int get_required_spare_criteria(struct state *st, ++ struct spare_criteria *sc) + { + int fd; + + if (!st->metadata || +- !st->metadata->ss->min_acceptable_spare_size) { +- *sizep = 0; ++ !st->metadata->ss->get_spare_criteria) { ++ sc->min_size = 0; + return 0; + } + +@@ -743,7 +744,8 @@ static int get_min_spare_size_required(struct state *st, unsigned long long *siz + close(fd); + if (!st->metadata->sb) + return 1; +- *sizep = st->metadata->ss->min_acceptable_spare_size(st->metadata); ++ ++ st->metadata->ss->get_spare_criteria(st->metadata, sc); + st->metadata->ss->free_super(st->metadata); + + return 0; +@@ -775,7 +777,7 @@ static int check_donor(struct state *from, struct state *to) + } + + static dev_t choose_spare(struct state *from, struct state *to, +- struct domainlist *domlist, unsigned long long min_size) ++ struct domainlist *domlist, struct spare_criteria *sc) + { + int d; + dev_t dev = 0; +@@ -790,9 +792,9 @@ static dev_t choose_spare(struct state *from, struct state *to, + test_partition_from_id(from->devid[d])) + continue; + +- if (min_size && ++ if (sc->min_size && + dev_size_from_id(from->devid[d], &dev_size) && +- dev_size < min_size) ++ dev_size < sc->min_size) + continue; + + pol = devid_policy(from->devid[d]); +@@ -809,7 +811,7 @@ static dev_t choose_spare(struct state *from, struct state *to, + + static dev_t container_choose_spare(struct state *from, struct state *to, + struct domainlist *domlist, +- unsigned long long min_size, int active) ++ struct spare_criteria *sc, int active) + { + /* This is similar to choose_spare, but we cannot trust devstate, + * so we need to read the metadata instead +@@ -860,7 +862,7 @@ static dev_t container_choose_spare(struct state *from, struct state *to, + } + + /* We only need one spare so full list not needed */ +- list = container_choose_spares(st, min_size, domlist, from->spare_group, ++ list = container_choose_spares(st, sc, domlist, from->spare_group, + to->metadata->ss->name, 1); + if (list) { + struct mdinfo *disks = list->devs; +@@ -876,6 +878,7 @@ static void try_spare_migration(struct state *statelist, struct alert_info *info + { + struct state *from; + struct state *st; ++ struct spare_criteria sc; + + link_containers_with_subarrays(statelist); + for (st = statelist; st; st = st->next) +@@ -884,7 +887,6 @@ static void try_spare_migration(struct state *statelist, struct alert_info *info + struct domainlist *domlist = NULL; + int d; + struct state *to = st; +- unsigned long long min_size; + + if (to->parent_devnm[0] && !to->parent) + /* subarray monitored without parent container +@@ -895,14 +897,14 @@ static void try_spare_migration(struct state *statelist, struct alert_info *info + /* member of a container */ + to = to->parent; + +- if (get_min_spare_size_required(to, &min_size)) ++ if (get_required_spare_criteria(to, &sc)) + continue; + if (to->metadata->ss->external) { + /* We must make sure there is + * no suitable spare in container already. + * If there is we don't add more */ + dev_t devid = container_choose_spare( +- to, to, NULL, min_size, st->active); ++ to, to, NULL, &sc, st->active); + if (devid > 0) + continue; + } +@@ -925,10 +927,10 @@ static void try_spare_migration(struct state *statelist, struct alert_info *info + continue; + if (from->metadata->ss->external) + devid = container_choose_spare( +- from, to, domlist, min_size, 0); ++ from, to, domlist, &sc, 0); + else + devid = choose_spare(from, to, domlist, +- min_size); ++ &sc); + if (devid > 0 + && move_spare(from->devname, to->devname, devid)) { + alert("MoveSpare", to->devname, from->devname, info); +diff --git a/mdadm.h b/mdadm.h +index a92feb2..8da7fd3 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -361,6 +361,10 @@ struct createinfo { + struct supertype *supertype; + }; + ++struct spare_criteria { ++ unsigned long long min_size; ++}; ++ + enum mode { + ASSEMBLE=1, + BUILD, +@@ -940,11 +944,13 @@ extern struct superswitch { + */ + __u64 (*avail_size)(struct supertype *st, __u64 size, + unsigned long long data_offset); +- /* This is similar to 'avail_size' in purpose, but is used for +- * containers for which there is no 'component size' to compare. +- * This reports that whole-device size which is a minimum ++ /* ++ * Return spare criteria for array: ++ * - minimum disk size can be used in array; ++ * Return values: 0 - for success and -EINVAL on error. + */ +- unsigned long long (*min_acceptable_spare_size)(struct supertype *st); ++ int (*get_spare_criteria)(struct supertype *st, ++ struct spare_criteria *sc); + /* Find somewhere to put a bitmap - possibly auto-size it - and + * update the metadata to record this. The array may be newly + * created, in which case data_size may be updated, or it might +@@ -1507,7 +1513,7 @@ extern int assemble_container_content(struct supertype *st, int mdfd, + #define INCR_ALREADY 4 + #define INCR_YES 8 + extern struct mdinfo *container_choose_spares(struct supertype *st, +- unsigned long long min_size, ++ struct spare_criteria *criteria, + struct domainlist *domlist, + char *spare_group, + const char *metadata, int get_one); +diff --git a/super-intel.c b/super-intel.c +index e88fe82..be973f8 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -1383,37 +1383,44 @@ static __u32 imsm_min_reserved_sectors(struct intel_super *super) + return (remainder < rv) ? remainder : rv; + } + +-/* Return minimum size of a spare that can be used in this array*/ +-static unsigned long long min_acceptable_spare_size_imsm(struct supertype *st) ++/* ++ * Return minimum size of a spare and sector size ++ * that can be used in this array ++ */ ++int get_spare_criteria_imsm(struct supertype *st, struct spare_criteria *c) + { + struct intel_super *super = st->sb; + struct dl *dl; + struct extent *e; + int i; +- unsigned long long rv = 0; ++ unsigned long long size = 0; ++ ++ c->min_size = 0; + + if (!super) +- return rv; ++ return -EINVAL; + /* find first active disk in array */ + dl = super->disks; + while (dl && (is_failed(&dl->disk) || dl->index == -1)) + dl = dl->next; + if (!dl) +- return rv; ++ return -EINVAL; + /* find last lba used by subarrays */ + e = get_extents(super, dl); + if (!e) +- return rv; ++ return -EINVAL; + for (i = 0; e[i].size; i++) + continue; + if (i > 0) +- rv = e[i-1].start + e[i-1].size; ++ size = e[i-1].start + e[i-1].size; + free(e); + + /* add the amount of space needed for metadata */ +- rv = rv + imsm_min_reserved_sectors(super); ++ size += imsm_min_reserved_sectors(super); ++ ++ c->min_size = size * 512; + +- return rv * 512; ++ return 0; + } + + static int is_gen_migration(struct imsm_dev *dev); +@@ -10817,8 +10824,10 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st, + */ + static struct mdinfo *get_spares_for_grow(struct supertype *st) + { +- unsigned long long min_size = min_acceptable_spare_size_imsm(st); +- return container_choose_spares(st, min_size, NULL, NULL, NULL, 0); ++ struct spare_criteria sc; ++ ++ get_spare_criteria_imsm(st, &sc); ++ return container_choose_spares(st, &sc, NULL, NULL, NULL, 0); + } + + /****************************************************************************** +@@ -11853,7 +11862,7 @@ struct superswitch super_imsm = { + .update_super = update_super_imsm, + + .avail_size = avail_size_imsm, +- .min_acceptable_spare_size = min_acceptable_spare_size_imsm, ++ .get_spare_criteria = get_spare_criteria_imsm, + + .compare_super = compare_super_imsm, + +diff --git a/util.c b/util.c +index 11ff2cc..8b3c67d 100644 +--- a/util.c ++++ b/util.c +@@ -2107,7 +2107,7 @@ int experimental(void) + * if spare_group given add it to domains of each spare + * metadata allows to test domains using metadata of destination array */ + struct mdinfo *container_choose_spares(struct supertype *st, +- unsigned long long min_size, ++ struct spare_criteria *criteria, + struct domainlist *domlist, + char *spare_group, + const char *metadata, int get_one) +@@ -2131,9 +2131,9 @@ struct mdinfo *container_choose_spares(struct supertype *st, + unsigned long long dev_size; + dev_t dev = makedev(d->disk.major,d->disk.minor); + +- if (!min_size || ++ if (!criteria->min_size || + (dev_size_from_id(dev, &dev_size) && +- dev_size >= min_size)) ++ dev_size >= criteria->min_size)) + found = 1; + /* check if domain matches */ + if (found && domlist) { diff --git a/SOURCES/Correct-examine-output-for-4k-disks.patch b/SOURCES/Correct-examine-output-for-4k-disks.patch new file mode 100644 index 0000000..b82b2f3 --- /dev/null +++ b/SOURCES/Correct-examine-output-for-4k-disks.patch @@ -0,0 +1,39 @@ +commit 84918897ee8bb450ea09f7c95b9da44df8e925e4 +Author: Maksymilian Kunt +Date: Tue May 9 14:03:27 2017 +0200 + + IMSM: Correct --examine output for 4k disks + + "Array Size" and "Per Dev Size" are incorrect for disks with sector size + different than 512B. + + Calculate "Array Size" and "Per Dev Size" based on sector size. Additionally + print "Sector Size". + + Signed-off-by: Maksymilian Kunt + Signed-off-by: Mariusz Dabrowski + Signed-off-by: Jes Sorensen + +diff --git a/super-intel.c b/super-intel.c +index ba6f810..8ca80d3 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -1482,13 +1482,16 @@ static void print_imsm_dev(struct intel_super *super, + ord & IMSM_ORD_REBUILD ? " (out-of-sync)" : ""); + } else + printf(" This Slot : ?\n"); ++ printf(" Sector Size : %u\n", super->sector_size); + sz = __le32_to_cpu(dev->size_high); + sz <<= 32; + sz += __le32_to_cpu(dev->size_low); +- printf(" Array Size : %llu%s\n", (unsigned long long)sz, ++ printf(" Array Size : %llu%s\n", ++ (unsigned long long)sz * 512 / super->sector_size, + human_size(sz * 512)); + sz = blocks_per_member(map); +- printf(" Per Dev Size : %llu%s\n", (unsigned long long)sz, ++ printf(" Per Dev Size : %llu%s\n", ++ (unsigned long long)sz * 512 / super->sector_size, + human_size(sz * 512)); + printf(" Sector Offset : %llu\n", + pba_of_lba0(map)); diff --git a/SOURCES/add-man-page-for-symlinks.patch b/SOURCES/add-man-page-for-symlinks.patch new file mode 100644 index 0000000..f5e4803 --- /dev/null +++ b/SOURCES/add-man-page-for-symlinks.patch @@ -0,0 +1,44 @@ +commit d64c2283633cd4d7569690d1df8d1a10f3b6b040 +Author: Zhilong Liu +Date: Mon Mar 6 10:39:57 2017 +0800 + + mdadm:add man page for --symlinks + + In build and create mode: + --symlinks + Auto creation of symlinks in /dev to /dev/md, option --symlinks + must be 'no' or 'yes' and work with --create and --build. + In assemble mode: + --symlinks + See this option under Create and Build options. + + Signed-off-by: Zhilong Liu + Signed-off-by: Jes Sorensen + +diff --git a/mdadm.8.in b/mdadm.8.in +index 1e4f91d..df1d460 100644 +--- a/mdadm.8.in ++++ b/mdadm.8.in +@@ -1015,6 +1015,11 @@ simultaneously. If not specified, this defaults to 4. + Specify journal device for the RAID-4/5/6 array. The journal device + should be a SSD with reasonable lifetime. + ++.TP ++.BR \-\-symlinks ++Auto creation of symlinks in /dev to /dev/md, option --symlinks must ++be 'no' or 'yes' and work with --create and --build. ++ + + .SH For assemble: + +@@ -1291,6 +1296,10 @@ Reshape can be continued later using the + .B \-\-continue + option for the grow command. + ++.TP ++.BR \-\-symlinks ++See this option under Create and Build options. ++ + .SH For Manage mode: + + .TP diff --git a/SOURCES/add-ppl-and-no-ppl-options-for-update.patch b/SOURCES/add-ppl-and-no-ppl-options-for-update.patch new file mode 100644 index 0000000..f699ccb --- /dev/null +++ b/SOURCES/add-ppl-and-no-ppl-options-for-update.patch @@ -0,0 +1,266 @@ +commit e6e9dd3f1b255f9921ebc023c1e5b65601a637e2 +Author: Artur Paszkiewicz +Date: Wed Mar 29 11:54:19 2017 +0200 + + Add 'ppl' and 'no-ppl' options for --update= + + This can be used with --assemble for super1 and with --update-subarray + for imsm to enable or disable PPL in the metadata. + + Signed-off-by: Artur Paszkiewicz + Signed-off-by: Jes Sorensen + +diff --git a/Assemble.c b/Assemble.c +index c098420..6a6a56b 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -602,6 +602,12 @@ static int load_devices(struct devs *devices, char *devmap, + if (strcmp(c->update, "uuid") == 0 && !ident->uuid_set) + random_uuid((__u8 *)ident->uuid); + ++ if (strcmp(c->update, "ppl") == 0 && ++ ident->bitmap_fd >= 0) { ++ pr_err("PPL is not compatible with bitmap\n"); ++ return -1; ++ } ++ + dfd = dev_open(devname, + tmpdev->disposition == 'I' + ? O_RDWR : (O_RDWR|O_EXCL)); +diff --git a/mdadm.8.in b/mdadm.8.in +index cad5db5..1178ed9 100644 +--- a/mdadm.8.in ++++ b/mdadm.8.in +@@ -1176,6 +1176,8 @@ argument given to this flag can be one of + .BR no\-bitmap , + .BR bbl , + .BR no\-bbl , ++.BR ppl , ++.BR no\-ppl , + .BR metadata , + or + .BR super\-minor . +@@ -1316,6 +1318,16 @@ option will cause any reservation of space for a bad block list to be + removed. If the bad block list contains entries, this will fail, as + removing the list could cause data corruption. + ++The ++.B ppl ++option will enable PPL for a RAID5 array and reserve space for PPL on each ++device. There must be enough free space between the data and superblock and a ++write-intent bitmap or journal must not be used. ++ ++The ++.B no\-ppl ++option will disable PPL in the superblock. ++ + .TP + .BR \-\-freeze\-reshape + Option is intended to be used in start-up scripts during initrd boot phase. +@@ -2327,9 +2339,11 @@ superblock field in the subarray. Similar to updating an array in + .B \-U + or + .B \-\-update= +-option. Currently only +-.B name +-is supported. ++option. The supported options are ++.BR name , ++.B ppl ++and ++.BR no\-ppl . + + The + .B name +@@ -2340,6 +2354,13 @@ re\-assembled. If updating + would change the UUID of an active subarray this operation is blocked, + and the command will end in an error. + ++The ++.B ppl ++and ++.B no\-ppl ++options enable and disable PPL in the metadata. Currently supported only for ++IMSM subarrays. ++ + .TP + .B \-\-examine + The device should be a component of an md array. +diff --git a/mdadm.c b/mdadm.c +index d4e8286..6edf3ab 100644 +--- a/mdadm.c ++++ b/mdadm.c +@@ -769,6 +769,10 @@ int main(int argc, char *argv[]) + continue; + if (strcmp(c.update, "force-no-bbl") == 0) + continue; ++ if (strcmp(c.update, "ppl") == 0) ++ continue; ++ if (strcmp(c.update, "no-ppl") == 0) ++ continue; + if (strcmp(c.update, "metadata") == 0) + continue; + if (strcmp(c.update, "revert-reshape") == 0) +@@ -802,7 +806,7 @@ int main(int argc, char *argv[]) + " 'sparc2.2', 'super-minor', 'uuid', 'name', 'nodes', 'resync',\n" + " 'summaries', 'homehost', 'home-cluster', 'byteorder', 'devicesize',\n" + " 'no-bitmap', 'metadata', 'revert-reshape'\n" +- " 'bbl', 'no-bbl', 'force-no-bbl'\n" ++ " 'bbl', 'no-bbl', 'force-no-bbl', 'ppl', 'no-ppl'\n" + ); + exit(outf == stdout ? 0 : 2); + +diff --git a/super-intel.c b/super-intel.c +index 87fec8b..785488a 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -451,6 +451,7 @@ enum imsm_update_type { + update_general_migration_checkpoint, + update_size_change, + update_prealloc_badblocks_mem, ++ update_rwh_policy, + }; + + struct imsm_update_activate_spare { +@@ -543,6 +544,12 @@ struct imsm_update_prealloc_bb_mem { + enum imsm_update_type type; + }; + ++struct imsm_update_rwh_policy { ++ enum imsm_update_type type; ++ int new_policy; ++ int dev_idx; ++}; ++ + static const char *_sys_dev_type[] = { + [SYS_DEV_UNKNOWN] = "Unknown", + [SYS_DEV_SAS] = "SAS", +@@ -7373,6 +7380,34 @@ static int update_subarray_imsm(struct supertype *st, char *subarray, + } + super->updates_pending++; + } ++ } else if (strcmp(update, "ppl") == 0 || ++ strcmp(update, "no-ppl") == 0) { ++ int new_policy; ++ char *ep; ++ int vol = strtoul(subarray, &ep, 10); ++ ++ if (*ep != '\0' || vol >= super->anchor->num_raid_devs) ++ return 2; ++ ++ if (strcmp(update, "ppl") == 0) ++ new_policy = RWH_DISTRIBUTED; ++ else ++ new_policy = RWH_OFF; ++ ++ if (st->update_tail) { ++ struct imsm_update_rwh_policy *u = xmalloc(sizeof(*u)); ++ ++ u->type = update_rwh_policy; ++ u->dev_idx = vol; ++ u->new_policy = new_policy; ++ append_metadata_update(st, u, sizeof(*u)); ++ } else { ++ struct imsm_dev *dev; ++ ++ dev = get_imsm_dev(super, vol); ++ dev->rwh_policy = new_policy; ++ super->updates_pending++; ++ } + } else + return 2; + +@@ -9599,6 +9634,21 @@ static void imsm_process_update(struct supertype *st, + } + case update_prealloc_badblocks_mem: + break; ++ case update_rwh_policy: { ++ struct imsm_update_rwh_policy *u = (void *)update->buf; ++ int target = u->dev_idx; ++ struct imsm_dev *dev = get_imsm_dev(super, target); ++ if (!dev) { ++ dprintf("could not find subarray-%d\n", target); ++ break; ++ } ++ ++ if (dev->rwh_policy != u->new_policy) { ++ dev->rwh_policy = u->new_policy; ++ super->updates_pending++; ++ } ++ break; ++ } + default: + pr_err("error: unsuported process update type:(type: %d)\n", type); + } +@@ -9844,6 +9894,11 @@ static int imsm_prepare_update(struct supertype *st, + super->extra_space += sizeof(struct bbm_log) - + get_imsm_bbm_log_size(super->bbm_log); + break; ++ case update_rwh_policy: { ++ if (update->len < (int)sizeof(struct imsm_update_rwh_policy)) ++ return 0; ++ break; ++ } + default: + return 0; + } +diff --git a/super1.c b/super1.c +index 409b6c3..e76f777 100644 +--- a/super1.c ++++ b/super1.c +@@ -1325,6 +1325,55 @@ static int update_super1(struct supertype *st, struct mdinfo *info, + sb->bblog_size = 0; + sb->bblog_shift = 0; + sb->bblog_offset = 0; ++ } else if (strcmp(update, "ppl") == 0) { ++ unsigned long long sb_offset = __le64_to_cpu(sb->super_offset); ++ unsigned long long data_offset = __le64_to_cpu(sb->data_offset); ++ unsigned long long data_size = __le64_to_cpu(sb->data_size); ++ long bb_offset = __le32_to_cpu(sb->bblog_offset); ++ int space; ++ int optimal_space; ++ int offset; ++ ++ if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) { ++ pr_err("Cannot add PPL to array with bitmap\n"); ++ return -2; ++ } ++ ++ if (sb->feature_map & __cpu_to_le32(MD_FEATURE_JOURNAL)) { ++ pr_err("Cannot add PPL to array with journal\n"); ++ return -2; ++ } ++ ++ if (sb_offset < data_offset) { ++ if (bb_offset) ++ space = bb_offset - 8; ++ else ++ space = data_offset - sb_offset - 8; ++ offset = 8; ++ } else { ++ offset = -(sb_offset - data_offset - data_size); ++ if (offset < INT16_MIN) ++ offset = INT16_MIN; ++ space = -(offset - bb_offset); ++ } ++ ++ if (space < (PPL_HEADER_SIZE >> 9) + 8) { ++ pr_err("Not enough space to add ppl\n"); ++ return -2; ++ } ++ ++ optimal_space = choose_ppl_space(__le32_to_cpu(sb->chunksize)); ++ ++ if (space > optimal_space) ++ space = optimal_space; ++ if (space > UINT16_MAX) ++ space = UINT16_MAX; ++ ++ sb->ppl.offset = __cpu_to_le16(offset); ++ sb->ppl.size = __cpu_to_le16(space); ++ sb->feature_map |= __cpu_to_le32(MD_FEATURE_PPL); ++ } else if (strcmp(update, "no-ppl") == 0) { ++ sb->feature_map &= ~ __cpu_to_le32(MD_FEATURE_PPL); + } else if (strcmp(update, "name") == 0) { + if (info->name[0] == 0) + sprintf(info->name, "%d", info->array.md_minor); diff --git a/SOURCES/allocate-buffer-to-support-maximum-sector-size.patch b/SOURCES/allocate-buffer-to-support-maximum-sector-size.patch new file mode 100644 index 0000000..a93e737 --- /dev/null +++ b/SOURCES/allocate-buffer-to-support-maximum-sector-size.patch @@ -0,0 +1,78 @@ +commit 853375734edcfd70ba64b444b9e69f7e336a30b7 +Author: Alexey Obitotskiy +Date: Tue May 9 12:25:44 2017 +0200 + + imsm: allocate buffer to support maximum sector size + + Allocate migration record buffer to support maximum sector size. Disk with + non-matching sector size is not going to be included in the array, however + some preparation/cleanup actions still take place on it and they would + cause a crash. Clear migration record using sector size of the disk (not + array) as they might not match. + + Signed-off-by: Alexey Obitotskiy + Signed-off-by: Tomasz Majchrzak + Signed-off-by: Jes Sorensen + +diff --git a/super-intel.c b/super-intel.c +index 2a5d848..cfb10d5 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -4229,8 +4229,8 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname) + sectors = mpb_sectors(anchor, sector_size) - 1; + free(anchor); + +- if (posix_memalign(&super->migr_rec_buf, sector_size, +- MIGR_REC_BUF_SECTORS*sector_size) != 0) { ++ if (posix_memalign(&super->migr_rec_buf, MAX_SECTOR_SIZE, ++ MIGR_REC_BUF_SECTORS*MAX_SECTOR_SIZE) != 0) { + pr_err("could not allocate migr_rec buffer\n"); + free(super->buf); + return 2; +@@ -5258,8 +5258,9 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, + pr_err("could not allocate new mpb\n"); + return 0; + } +- if (posix_memalign(&super->migr_rec_buf, sector_size, +- MIGR_REC_BUF_SECTORS*sector_size) != 0) { ++ if (posix_memalign(&super->migr_rec_buf, MAX_SECTOR_SIZE, ++ MIGR_REC_BUF_SECTORS* ++ MAX_SECTOR_SIZE) != 0) { + pr_err("could not allocate migr_rec buffer\n"); + free(super->buf); + free(super); +@@ -5719,12 +5720,12 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, + } + + /* clear migr_rec when adding disk to container */ +- memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SECTORS*super->sector_size); +- if (lseek64(fd, size - MIGR_REC_SECTOR_POSITION*super->sector_size, ++ memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SECTORS*MAX_SECTOR_SIZE); ++ if (lseek64(fd, size - MIGR_REC_SECTOR_POSITION*member_sector_size, + SEEK_SET) >= 0) { + if ((unsigned int)write(fd, super->migr_rec_buf, +- MIGR_REC_BUF_SECTORS*super->sector_size) != +- MIGR_REC_BUF_SECTORS*super->sector_size) ++ MIGR_REC_BUF_SECTORS*member_sector_size) != ++ MIGR_REC_BUF_SECTORS*member_sector_size) + perror("Write migr_rec failed"); + } + +@@ -5916,7 +5917,7 @@ static int write_super_imsm(struct supertype *st, int doclose) + } + if (clear_migration_record) + memset(super->migr_rec_buf, 0, +- MIGR_REC_BUF_SECTORS*sector_size); ++ MIGR_REC_BUF_SECTORS*MAX_SECTOR_SIZE); + + if (sector_size == 4096) + convert_to_4k(super); +@@ -11770,7 +11771,7 @@ static int imsm_manage_reshape( + /* clear migr_rec on disks after successful migration */ + struct dl *d; + +- memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SECTORS*sector_size); ++ memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SECTORS*MAX_SECTOR_SIZE); + for (d = super->disks; d; d = d->next) { + if (d->index < 0 || is_failed(&d->disk)) + continue; diff --git a/SOURCES/allow-drives-in-a-container-regardless-of-sector-size.patch b/SOURCES/allow-drives-in-a-container-regardless-of-sector-size.patch new file mode 100644 index 0000000..cdc863a --- /dev/null +++ b/SOURCES/allow-drives-in-a-container-regardless-of-sector-size.patch @@ -0,0 +1,37 @@ +commit 5c5ea85b4deedf5e7491a905bbb4f4a3bc284f2c +Author: Alexey Obitotskiy +Date: Tue May 9 12:25:43 2017 +0200 + + imsm: allow drives in a container regardless of sector size + + IMSM doesn't allow to create arrays including drives with different + sector sizes. The initial idea was not to permit to combine drives + with different sector size in the same container. The problem is it + only worked for array creation. On array assemble there are no + calls to metadata handlers to see if drive is suitable for a container + (e.g. as a spare) and it leads to wrong configuration. + + Revert the change and allow adding drives with different sector size + to the container. + + Signed-off-by: Alexey Obitotskiy + Signed-off-by: Tomasz Majchrzak + Signed-off-by: Jes Sorensen + +diff --git a/super-intel.c b/super-intel.c +index e13c940..2a5d848 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -5716,12 +5716,6 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, + if (super->sector_size == 0) { + /* this a first device, so sector_size is not set yet */ + super->sector_size = member_sector_size; +- } else if (member_sector_size != super->sector_size) { +- pr_err("Mixing between different sector size is forbidden, aborting...\n"); +- if (dd->devname) +- free(dd->devname); +- free(dd); +- return 1; + } + + /* clear migr_rec when adding disk to container */ diff --git a/SOURCES/detail-show-consistency-policy.patch b/SOURCES/detail-show-consistency-policy.patch new file mode 100644 index 0000000..66051c5 --- /dev/null +++ b/SOURCES/detail-show-consistency-policy.patch @@ -0,0 +1,322 @@ +commit 65884368cd42d79b567f12d3e84adc7009e12d72 +Author: Artur Paszkiewicz +Date: Wed Mar 29 11:54:16 2017 +0200 + + Detail: show consistency policy + + Show the currently enabled consistency policy in the output from + --detail. Add 3 spaces to all existing items in Detail output to align + with "Consistency Policy : ". + + Signed-off-by: Artur Paszkiewicz + Signed-off-by: Jes Sorensen + +diff --git a/Detail.c b/Detail.c +index 3d92855..136875b 100644 +--- a/Detail.c ++++ b/Detail.c +@@ -402,24 +402,25 @@ int Detail(char *dev, struct context *c) + printf("%s:\n", dev); + + if (container) +- printf(" Container : %s, member %s\n", container, member); ++ printf(" Container : %s, member %s\n", container, ++ member); + else { + if (sra && sra->array.major_version < 0) +- printf(" Version : %s\n", sra->text_version); ++ printf(" Version : %s\n", sra->text_version); + else +- printf(" Version : %d.%d\n", ++ printf(" Version : %d.%d\n", + array.major_version, array.minor_version); + } + + atime = array.ctime; + if (atime) +- printf(" Creation Time : %.24s\n", ctime(&atime)); ++ printf(" Creation Time : %.24s\n", ctime(&atime)); + if (array.raid_disks == 0 && external) + str = "container"; + if (str) +- printf(" Raid Level : %s\n", str); ++ printf(" Raid Level : %s\n", str); + if (larray_size) +- printf(" Array Size : %llu%s\n", (larray_size>>10), ++ printf(" Array Size : %llu%s\n", (larray_size>>10), + human_size(larray_size)); + if (array.level >= 1) { + if (sra) +@@ -428,38 +429,38 @@ int Detail(char *dev, struct context *c) + (larray_size >= 0xFFFFFFFFULL|| array.size == 0)) { + unsigned long long dsize = get_component_size(fd); + if (dsize > 0) +- printf(" Used Dev Size : %llu%s\n", ++ printf(" Used Dev Size : %llu%s\n", + dsize/2, + human_size((long long)dsize<<9)); + else +- printf(" Used Dev Size : unknown\n"); ++ printf(" Used Dev Size : unknown\n"); + } else +- printf(" Used Dev Size : %lu%s\n", ++ printf(" Used Dev Size : %lu%s\n", + (unsigned long)array.size, + human_size((unsigned long long)array.size<<10)); + } + if (array.raid_disks) +- printf(" Raid Devices : %d\n", array.raid_disks); +- printf(" Total Devices : %d\n", array.nr_disks); ++ printf(" Raid Devices : %d\n", array.raid_disks); ++ printf(" Total Devices : %d\n", array.nr_disks); + if (!container && + ((sra == NULL && array.major_version == 0) || + (sra && sra->array.major_version == 0))) +- printf("Preferred Minor : %d\n", array.md_minor); ++ printf(" Preferred Minor : %d\n", array.md_minor); + if (sra == NULL || sra->array.major_version >= 0) +- printf(" Persistence : Superblock is %spersistent\n", ++ printf(" Persistence : Superblock is %spersistent\n", + array.not_persistent?"not ":""); + printf("\n"); + /* Only try GET_BITMAP_FILE for 0.90.01 and later */ + if (vers >= 9001 && + ioctl(fd, GET_BITMAP_FILE, &bmf) == 0 && + bmf.pathname[0]) { +- printf(" Intent Bitmap : %s\n", bmf.pathname); ++ printf(" Intent Bitmap : %s\n", bmf.pathname); + printf("\n"); + } else if (array.state & (1<percent < 0 && e->percent != RESYNC_PENDING && + e->percent != RESYNC_DELAYED)) ? "" : sync_action[e->resync], +@@ -481,27 +482,27 @@ int Detail(char *dev, struct context *c) + (e && e->percent == RESYNC_DELAYED) ? " (DELAYED)": "", + (e && e->percent == RESYNC_PENDING) ? " (PENDING)": ""); + } else if (inactive) { +- printf(" State : inactive\n"); ++ printf(" State : inactive\n"); + } + if (array.raid_disks) +- printf(" Active Devices : %d\n", array.active_disks); ++ printf(" Active Devices : %d\n", array.active_disks); + if (array.working_disks > 0) +- printf("Working Devices : %d\n", array.working_disks); ++ printf(" Working Devices : %d\n", array.working_disks); + if (array.raid_disks) { +- printf(" Failed Devices : %d\n", array.failed_disks); +- printf(" Spare Devices : %d\n", array.spare_disks); ++ printf(" Failed Devices : %d\n", array.failed_disks); ++ printf(" Spare Devices : %d\n", array.spare_disks); + } + printf("\n"); + if (array.level == 5) { + str = map_num(r5layout, array.layout); +- printf(" Layout : %s\n", str?str:"-unknown-"); ++ printf(" Layout : %s\n", str?str:"-unknown-"); + } + if (array.level == 6) { + str = map_num(r6layout, array.layout); +- printf(" Layout : %s\n", str?str:"-unknown-"); ++ printf(" Layout : %s\n", str?str:"-unknown-"); + } + if (array.level == 10) { +- printf(" Layout :"); ++ printf(" Layout :"); + print_r10_layout(array.layout); + printf("\n"); + } +@@ -512,20 +513,35 @@ int Detail(char *dev, struct context *c) + case 10: + case 6: + if (array.chunk_size) +- printf(" Chunk Size : %dK\n\n", ++ printf(" Chunk Size : %dK\n\n", + array.chunk_size/1024); + break; + case -1: +- printf(" Rounding : %dK\n\n", array.chunk_size/1024); ++ printf(" Rounding : %dK\n\n", ++ array.chunk_size/1024); + break; + default: break; + } + ++ if (array.raid_disks) { ++ struct mdinfo *mdi = sysfs_read(fd, NULL, ++ GET_CONSISTENCY_POLICY); ++ if (mdi) { ++ char *policy = map_num(consistency_policies, ++ mdi->consistency_policy); ++ sysfs_free(mdi); ++ if (policy) ++ printf("Consistency Policy : %s\n\n", ++ policy); ++ } ++ } ++ + if (e && e->percent >= 0) { + static char *sync_action[] = { + "Rebuild", "Resync", + "Reshape", "Check"}; +- printf(" %7s Status : %d%% complete\n", sync_action[e->resync], e->percent); ++ printf(" %7s Status : %d%% complete\n", ++ sync_action[e->resync], e->percent); + is_rebuilding = 1; + } + free_mdstat(ms); +@@ -533,39 +549,41 @@ int Detail(char *dev, struct context *c) + if ((st && st->sb) && (info && info->reshape_active)) { + #if 0 + This is pretty boring +- printf(" Reshape pos'n : %llu%s\n", (unsigned long long) info->reshape_progress<<9, ++ printf(" Reshape pos'n : %llu%s\n", ++ (unsigned long long) info->reshape_progress<<9, + human_size((unsigned long long)info->reshape_progress<<9)); + #endif + if (info->delta_disks != 0) +- printf(" Delta Devices : %d, (%d->%d)\n", ++ printf(" Delta Devices : %d, (%d->%d)\n", + info->delta_disks, + array.raid_disks - info->delta_disks, + array.raid_disks); + if (info->new_level != array.level) { + str = map_num(pers, info->new_level); +- printf(" New Level : %s\n", str?str:"-unknown-"); ++ printf(" New Level : %s\n", str?str:"-unknown-"); + } + if (info->new_level != array.level || + info->new_layout != array.layout) { + if (info->new_level == 5) { + str = map_num(r5layout, info->new_layout); +- printf(" New Layout : %s\n", ++ printf(" New Layout : %s\n", + str?str:"-unknown-"); + } + if (info->new_level == 6) { + str = map_num(r6layout, info->new_layout); +- printf(" New Layout : %s\n", ++ printf(" New Layout : %s\n", + str?str:"-unknown-"); + } + if (info->new_level == 10) { +- printf(" New Layout : near=%d, %s=%d\n", ++ printf(" New Layout : near=%d, %s=%d\n", + info->new_layout&255, + (info->new_layout&0x10000)?"offset":"far", + (info->new_layout>>8)&255); + } + } + if (info->new_chunk != array.chunk_size) +- printf(" New Chunksize : %dK\n", info->new_chunk/1024); ++ printf(" New Chunksize : %dK\n", ++ info->new_chunk/1024); + printf("\n"); + } else if (e && e->percent >= 0) + printf("\n"); +@@ -580,7 +598,7 @@ This is pretty boring + DIR *dir = opendir("/sys/block"); + struct dirent *de; + +- printf(" Member Arrays :"); ++ printf(" Member Arrays :"); + + while (dir && (de = readdir(dir)) != NULL) { + char path[287]; +diff --git a/super-ddf.c b/super-ddf.c +index cdd16a4..c6037c1 100644 +--- a/super-ddf.c ++++ b/super-ddf.c +@@ -1742,10 +1742,10 @@ static void detail_super_ddf(struct supertype *st, char *homehost) + struct ddf_super *sb = st->sb; + int cnt = be16_to_cpu(sb->virt->populated_vdes); + +- printf(" Container GUID : "); print_guid(sb->anchor.guid, 1); ++ printf(" Container GUID : "); print_guid(sb->anchor.guid, 1); + printf("\n"); +- printf(" Seq : %08x\n", be32_to_cpu(sb->active->seq)); +- printf(" Virtual Disks : %d\n", cnt); ++ printf(" Seq : %08x\n", be32_to_cpu(sb->active->seq)); ++ printf(" Virtual Disks : %d\n", cnt); + printf("\n"); + } + #endif +diff --git a/super-intel.c b/super-intel.c +index 5d0f131..2d92c8e 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -1987,7 +1987,7 @@ static void detail_super_imsm(struct supertype *st, char *homehost) + + getinfo_super_imsm(st, &info, NULL); + fname_from_uuid(st, &info, nbuf, ':'); +- printf("\n UUID : %s\n", nbuf + 5); ++ printf("\n UUID : %s\n", nbuf + 5); + } + + static void brief_detail_super_imsm(struct supertype *st) +diff --git a/super0.c b/super0.c +index 7a555e3..10d9c40 100644 +--- a/super0.c ++++ b/super0.c +@@ -353,7 +353,7 @@ err: + static void detail_super0(struct supertype *st, char *homehost) + { + mdp_super_t *sb = st->sb; +- printf(" UUID : "); ++ printf(" UUID : "); + if (sb->minor_version >= 90) + printf("%08x:%08x:%08x:%08x", sb->set_uuid0, sb->set_uuid1, + sb->set_uuid2, sb->set_uuid3); +@@ -367,7 +367,7 @@ static void detail_super0(struct supertype *st, char *homehost) + if (memcmp(&sb->set_uuid2, hash, 8)==0) + printf(" (local to host %s)", homehost); + } +- printf("\n Events : %d.%d\n\n", sb->events_hi, sb->events_lo); ++ printf("\n Events : %d.%d\n\n", sb->events_hi, sb->events_lo); + } + + static void brief_detail_super0(struct supertype *st) +diff --git a/super1.c b/super1.c +index 4a0f041..8df17a1 100644 +--- a/super1.c ++++ b/super1.c +@@ -780,19 +780,20 @@ static void detail_super1(struct supertype *st, char *homehost) + int i; + int l = homehost ? strlen(homehost) : 0; + +- printf(" Name : %.32s", sb->set_name); ++ printf(" Name : %.32s", sb->set_name); + if (l > 0 && l < 32 && + sb->set_name[l] == ':' && + strncmp(sb->set_name, homehost, l) == 0) + printf(" (local to host %s)", homehost); + if (bms->nodes > 0 && (__le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET)) +- printf("\n Cluster Name : %-64s", bms->cluster_name); +- printf("\n UUID : "); ++ printf("\n Cluster Name : %-64s", bms->cluster_name); ++ printf("\n UUID : "); + for (i=0; i<16; i++) { + if ((i&3)==0 && i != 0) printf(":"); + printf("%02x", sb->set_uuid[i]); + } +- printf("\n Events : %llu\n\n", (unsigned long long)__le64_to_cpu(sb->events)); ++ printf("\n Events : %llu\n\n", ++ (unsigned long long)__le64_to_cpu(sb->events)); + } + + static void brief_detail_super1(struct supertype *st) diff --git a/SOURCES/disable-journal.patch b/SOURCES/disable-journal.patch new file mode 100644 index 0000000..7631164 --- /dev/null +++ b/SOURCES/disable-journal.patch @@ -0,0 +1,34 @@ +diff --git a/ReadMe.c b/ReadMe.c +index eb8fb4b..2de30e1 100644 +--- a/ReadMe.c ++++ b/ReadMe.c +@@ -147,7 +147,9 @@ struct option long_options[] = { + {"data-offset",1, 0, DataOffset}, + {"nodes",1, 0, Nodes}, /* also for --assemble */ + {"home-cluster",1, 0, ClusterName}, ++#if 0 /* Disable for RHEL */ + {"write-journal",1, 0, WriteJournal}, ++#endif + {"consistency-policy", 1, 0, 'k'}, + + /* For assemble */ +@@ -163,7 +165,9 @@ struct option long_options[] = { + /* Management */ + {"add", 0, 0, Add}, + {"add-spare", 0, 0, AddSpare}, ++#if 0 /* Disable for RHEL */ + {"add-journal", 0, 0, AddJournal}, ++#endif + {"remove", 0, 0, Remove}, + {"fail", 0, 0, Fail}, + {"set-faulty",0, 0, Fail}, +@@ -383,7 +387,9 @@ char Help_create[] = + " --name= -N : Textual name for array - max 32 characters\n" + " --bitmap-chunk= : bitmap chunksize in Kilobytes.\n" + " --delay= -d : bitmap update delay in seconds.\n" ++#if 0 /* Disable for RHEL */ + " --write-journal= : Specify journal device for RAID-4/5/6 array\n" ++#endif + " --consistency-policy= : Specify the policy that determines how the array\n" + " -k : maintains consistency in case of unexpected shutdown.\n" + "\n" diff --git a/SOURCES/dont-allow-array-geometry-change-with-ppl-enabled.patch b/SOURCES/dont-allow-array-geometry-change-with-ppl-enabled.patch new file mode 100644 index 0000000..fd9a06d --- /dev/null +++ b/SOURCES/dont-allow-array-geometry-change-with-ppl-enabled.patch @@ -0,0 +1,31 @@ +commit b208f817ec538e56df7280f0353e6bda532b9432 +Author: Tomasz Majchrzak +Date: Thu Jun 8 16:05:51 2017 +0200 + + Grow: don't allow array geometry change with ppl enabled + + Don't allow array geometry change (size expand, disk adding) when PPL + consistency policy is enabled. Current PPL implementation doesn't work when + reshape is taking place. + + Signed-off-by: Tomasz Majchrzak + Signed-off-by: Jes Sorensen + +diff --git a/Grow.c b/Grow.c +index 4ecb1d8..f7325cb 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -1880,6 +1880,13 @@ int Grow_reshape(char *devname, int fd, + free(subarray); + return 1; + } ++ if (content->consistency_policy == ++ CONSISTENCY_POLICY_PPL) { ++ pr_err("Operation not supported when ppl consistency policy is enabled\n"); ++ sysfs_free(cc); ++ free(subarray); ++ return 1; ++ } + } + sysfs_free(cc); + } diff --git a/SOURCES/dont-allow-disks-with-different-sector-size-in-one.patch b/SOURCES/dont-allow-disks-with-different-sector-size-in-one.patch new file mode 100644 index 0000000..6b2ec98 --- /dev/null +++ b/SOURCES/dont-allow-disks-with-different-sector-size-in-one.patch @@ -0,0 +1,64 @@ +commit f2cc4f7d829e1b849e78bdf6c38b7bd6e234c600 +Author: Alexey Obitotskiy +Date: Tue May 9 12:25:45 2017 +0200 + + imsm: don't allow disks with different sector size in one array + + As there is no support in IMSM for arrays including disks with different + sector sizes, don't allow to create such configuration. Also skip the + disk with unsuitable sector size when looking for spares in the same + container. + + Signed-off-by: Alexey Obitotskiy + Signed-off-by: Tomasz Majchrzak + Signed-off-by: Jes Sorensen + +diff --git a/super-intel.c b/super-intel.c +index cfb10d5..e88fe82 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -5483,6 +5483,22 @@ + return 1; + } + ++static int drive_validate_sector_size(struct intel_super *super, struct dl *dl) ++{ ++ unsigned int member_sector_size; ++ ++ if (dl->fd < 0) { ++ pr_err("Invalid file descriptor for %s\n", dl->devname); ++ return 0; ++ } ++ ++ if (!get_dev_sector_size(dl->fd, dl->devname, &member_sector_size)) ++ return 0; ++ if (member_sector_size != super->sector_size) ++ return 0; ++ return 1; ++} ++ + #ifndef MDASSEMBLE + static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk, + int fd, char *devname) +@@ -5523,6 +5539,11 @@ + return 1; + } + ++ if (!drive_validate_sector_size(super, dl)) { ++ pr_err("Combining drives of different sector size in one volume is not allowed\n"); ++ return 1; ++ } ++ + /* add a pristine spare to the metadata */ + if (dl->index < 0) { + dl->index = super->anchor->num_disks; +@@ -8484,6 +8505,9 @@ + if (dl->index == -1 && !activate_new) + continue; + ++ if (!drive_validate_sector_size(super, dl)) ++ continue; ++ + /* Does this unused device have the requisite free space? + * It needs to be able to cover all member volumes + */ diff --git a/SOURCES/dont-allow-to-enable-PPL-reshape-in-progress.patch b/SOURCES/dont-allow-to-enable-PPL-reshape-in-progress.patch new file mode 100644 index 0000000..86ca312 --- /dev/null +++ b/SOURCES/dont-allow-to-enable-PPL-reshape-in-progress.patch @@ -0,0 +1,42 @@ +commit 922a58292fafa4efcfcd44fbc46b0665681c955a +Author: Tomasz Majchrzak +Date: Fri Jun 9 16:20:19 2017 +0200 + + Grow: don't allow to enable PPL when reshape is in progress + + Don't allow to enable PPL consistency policy when reshape is in progress. + Current PPL implementation doesn't work when reshape is taking place. + + Signed-off-by: Tomasz Majchrzak + Signed-off-by: Jes Sorensen + +diff --git a/Grow.c b/Grow.c +index f7325cb..b1cb306 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -530,6 +530,7 @@ int Grow_consistency_policy(char *devname, int fd, struct context *c, struct sha + char *subarray = NULL; + int ret = 0; + char container_dev[PATH_MAX]; ++ char buf[20]; + + if (s->consistency_policy != CONSISTENCY_POLICY_RESYNC && + s->consistency_policy != CONSISTENCY_POLICY_PPL) { +@@ -577,6 +578,17 @@ int Grow_consistency_policy(char *devname, int fd, struct context *c, struct sha + goto free_info; + } + ++ if (s->consistency_policy == CONSISTENCY_POLICY_PPL) { ++ if (sysfs_get_str(sra, NULL, "sync_action", buf, 20) <= 0) { ++ ret = 1; ++ goto free_info; ++ } else if (strcmp(buf, "reshape\n") == 0) { ++ pr_err("PPL cannot be enabled when reshape is in progress\n"); ++ ret = 1; ++ goto free_info; ++ } ++ } ++ + if (subarray) { + char *update; + diff --git a/SOURCES/generic-support-for-consistency-policy-and-PPL.patch b/SOURCES/generic-support-for-consistency-policy-and-PPL.patch new file mode 100644 index 0000000..d315510 --- /dev/null +++ b/SOURCES/generic-support-for-consistency-policy-and-PPL.patch @@ -0,0 +1,638 @@ +commit 5308f11727b889965efe5ac0e854d197c2b51f6d +Author: Artur Paszkiewicz +Date: Wed Mar 29 11:54:15 2017 +0200 + + Generic support for --consistency-policy and PPL + + Add a new parameter to mdadm: --consistency-policy=. It determines how + the array maintains consistency in case of unexpected shutdown. This + maps to the md sysfs attribute 'consistency_policy'. It can be used to + create a raid5 array using PPL. Add the necessary plumbing to pass this + option to metadata handlers. The write journal and bitmap + functionalities are treated as different policies, which are implicitly + selected when using --write-journal or --bitmap options. + + Signed-off-by: Artur Paszkiewicz + Signed-off-by: Jes Sorensen + +diff --git a/Create.c b/Create.c +index 2721884..4080bf6 100644 +--- a/Create.c ++++ b/Create.c +@@ -259,7 +259,8 @@ int Create(struct supertype *st, char *mddev, + if (st && ! st->ss->validate_geometry(st, s->level, s->layout, s->raiddisks, + &s->chunk, s->size*2, + data_offset, NULL, +- &newsize, c->verbose>=0)) ++ &newsize, s->consistency_policy, ++ c->verbose>=0)) + return 1; + + if (s->chunk && s->chunk != UnSet) { +@@ -358,7 +359,8 @@ int Create(struct supertype *st, char *mddev, + st, s->level, s->layout, s->raiddisks, + &s->chunk, s->size*2, + dv->data_offset, dname, +- &freesize, c->verbose > 0)) { ++ &freesize, s->consistency_policy, ++ c->verbose > 0)) { + case -1: /* Not valid, message printed, and not + * worth checking any further */ + exit(2); +@@ -395,6 +397,7 @@ int Create(struct supertype *st, char *mddev, + &s->chunk, s->size*2, + dv->data_offset, + dname, &freesize, ++ s->consistency_policy, + c->verbose >= 0)) { + + pr_err("%s is not suitable for this array.\n", +@@ -501,7 +504,8 @@ int Create(struct supertype *st, char *mddev, + s->raiddisks, + &s->chunk, minsize*2, + data_offset, +- NULL, NULL, 0)) { ++ NULL, NULL, ++ s->consistency_policy, 0)) { + pr_err("devices too large for RAID level %d\n", s->level); + return 1; + } +@@ -528,6 +532,12 @@ int Create(struct supertype *st, char *mddev, + if (s->bitmap_file && strcmp(s->bitmap_file, "none") == 0) + s->bitmap_file = NULL; + ++ if (s->consistency_policy == CONSISTENCY_POLICY_PPL && ++ !st->ss->write_init_ppl) { ++ pr_err("%s metadata does not support PPL\n", st->ss->name); ++ return 1; ++ } ++ + if (!have_container && s->level > 0 && ((maxsize-s->size)*100 > maxsize)) { + if (c->runstop != 1 || c->verbose >= 0) + pr_err("largest drive (%s) exceeds size (%lluK) by more than 1%%\n", +@@ -720,7 +730,7 @@ int Create(struct supertype *st, char *mddev, + name += 2; + } + } +- if (!st->ss->init_super(st, &info.array, s->size, name, c->homehost, uuid, ++ if (!st->ss->init_super(st, &info.array, s, name, c->homehost, uuid, + data_offset)) + goto abort_locked; + +diff --git a/Kill.c b/Kill.c +index f2fdb85..ff52561 100644 +--- a/Kill.c ++++ b/Kill.c +@@ -63,7 +63,7 @@ int Kill(char *dev, struct supertype *st, int force, int verbose, int noexcl) + rv = st->ss->load_super(st, fd, dev); + if (rv == 0 || (force && rv >= 2)) { + st->ss->free_super(st); +- st->ss->init_super(st, NULL, 0, "", NULL, NULL, ++ st->ss->init_super(st, NULL, NULL, "", NULL, NULL, + INVALID_SECTORS); + if (st->ss->store_super(st, fd)) { + if (verbose >= 0) +diff --git a/ReadMe.c b/ReadMe.c +index 50d3807..fc04c2c 100644 +--- a/ReadMe.c ++++ b/ReadMe.c +@@ -78,11 +78,11 @@ char Version[] = "mdadm - v" VERSION " - " VERS_DATE "\n"; + * found, it is started. + */ + +-char short_options[]="-ABCDEFGIQhVXYWZ:vqbc:i:l:p:m:n:x:u:c:d:z:U:N:sarfRSow1tye:"; ++char short_options[]="-ABCDEFGIQhVXYWZ:vqbc:i:l:p:m:n:x:u:c:d:z:U:N:sarfRSow1tye:k:"; + char short_bitmap_options[]= +- "-ABCDEFGIQhVXYWZ:vqb:c:i:l:p:m:n:x:u:c:d:z:U:N:sarfRSow1tye:"; ++ "-ABCDEFGIQhVXYWZ:vqb:c:i:l:p:m:n:x:u:c:d:z:U:N:sarfRSow1tye:k:"; + char short_bitmap_auto_options[]= +- "-ABCDEFGIQhVXYWZ:vqb:c:i:l:p:m:n:x:u:c:d:z:U:N:sa:rfRSow1tye:"; ++ "-ABCDEFGIQhVXYWZ:vqb:c:i:l:p:m:n:x:u:c:d:z:U:N:sa:rfRSow1tye:k:"; + + struct option long_options[] = { + {"manage", 0, 0, ManageOpt}, +@@ -148,6 +148,7 @@ struct option long_options[] = { + {"nodes",1, 0, Nodes}, /* also for --assemble */ + {"home-cluster",1, 0, ClusterName}, + {"write-journal",1, 0, WriteJournal}, ++ {"consistency-policy", 1, 0, 'k'}, + + /* For assemble */ + {"uuid", 1, 0, 'u'}, +@@ -362,27 +363,29 @@ char Help_create[] = + " other levels.\n" + "\n" + " Options that are valid with --create (-C) are:\n" +-" --bitmap= : Create a bitmap for the array with the given filename\n" +-" : or an internal bitmap is 'internal' is given\n" +-" --chunk= -c : chunk size in kibibytes\n" +-" --rounding= : rounding factor for linear array (==chunk size)\n" +-" --level= -l : raid level: 0,1,4,5,6,10,linear,multipath and synonyms\n" +-" --parity= -p : raid5/6 parity algorithm: {left,right}-{,a}symmetric\n" +-" --layout= : same as --parity, for RAID10: [fno]NN \n" +-" --raid-devices= -n : number of active devices in array\n" +-" --spare-devices= -x: number of spare (eXtra) devices in initial array\n" +-" --size= -z : Size (in K) of each drive in RAID1/4/5/6/10 - optional\n" +-" --data-offset= : Space to leave between start of device and start\n" +-" : of array data.\n" +-" --force -f : Honour devices as listed on command line. Don't\n" +-" : insert a missing drive for RAID5.\n" +-" --run -R : insist of running the array even if not all\n" +-" : devices are present or some look odd.\n" +-" --readonly -o : start the array readonly - not supported yet.\n" +-" --name= -N : Textual name for array - max 32 characters\n" +-" --bitmap-chunk= : bitmap chunksize in Kilobytes.\n" +-" --delay= -d : bitmap update delay in seconds.\n" +-" --write-journal= : Specify journal device for RAID-4/5/6 array\n" ++" --bitmap= -b : Create a bitmap for the array with the given filename\n" ++" : or an internal bitmap if 'internal' is given\n" ++" --chunk= -c : chunk size in kibibytes\n" ++" --rounding= : rounding factor for linear array (==chunk size)\n" ++" --level= -l : raid level: 0,1,4,5,6,10,linear,multipath and synonyms\n" ++" --parity= -p : raid5/6 parity algorithm: {left,right}-{,a}symmetric\n" ++" --layout= : same as --parity, for RAID10: [fno]NN \n" ++" --raid-devices= -n : number of active devices in array\n" ++" --spare-devices= -x : number of spare (eXtra) devices in initial array\n" ++" --size= -z : Size (in K) of each drive in RAID1/4/5/6/10 - optional\n" ++" --data-offset= : Space to leave between start of device and start\n" ++" : of array data.\n" ++" --force -f : Honour devices as listed on command line. Don't\n" ++" : insert a missing drive for RAID5.\n" ++" --run -R : insist of running the array even if not all\n" ++" : devices are present or some look odd.\n" ++" --readonly -o : start the array readonly - not supported yet.\n" ++" --name= -N : Textual name for array - max 32 characters\n" ++" --bitmap-chunk= : bitmap chunksize in Kilobytes.\n" ++" --delay= -d : bitmap update delay in seconds.\n" ++" --write-journal= : Specify journal device for RAID-4/5/6 array\n" ++" --consistency-policy= : Specify the policy that determines how the array\n" ++" -k : maintains consistency in case of unexpected shutdown.\n" + "\n" + ; + +diff --git a/maps.c b/maps.c +index 64f1df2..d9ee7de 100644 +--- a/maps.c ++++ b/maps.c +@@ -129,6 +129,16 @@ mapping_t faultylayout[] = { + { NULL, 0} + }; + ++mapping_t consistency_policies[] = { ++ { "unknown", CONSISTENCY_POLICY_UNKNOWN}, ++ { "none", CONSISTENCY_POLICY_NONE}, ++ { "resync", CONSISTENCY_POLICY_RESYNC}, ++ { "bitmap", CONSISTENCY_POLICY_BITMAP}, ++ { "journal", CONSISTENCY_POLICY_JOURNAL}, ++ { "ppl", CONSISTENCY_POLICY_PPL}, ++ { NULL, 0} ++}; ++ + char *map_num(mapping_t *map, int num) + { + while (map->name) { +diff --git a/mdadm.8.in b/mdadm.8.in +index df1d460..cad5db5 100644 +--- a/mdadm.8.in ++++ b/mdadm.8.in +@@ -724,7 +724,9 @@ When creating an array on devices which are 100G or larger, + .I mdadm + automatically adds an internal bitmap as it will usually be + beneficial. This can be suppressed with +-.B "\-\-bitmap=none". ++.B "\-\-bitmap=none" ++or by selecting a different consistency policy with ++.BR \-\-consistency\-policy . + + .TP + .BR \-\-bitmap\-chunk= +@@ -1020,6 +1022,36 @@ should be a SSD with reasonable lifetime. + Auto creation of symlinks in /dev to /dev/md, option --symlinks must + be 'no' or 'yes' and work with --create and --build. + ++.TP ++.BR \-k ", " \-\-consistency\-policy= ++Specify how the array maintains consistency in case of unexpected shutdown. ++Only relevant for RAID levels with redundancy. ++Currently supported options are: ++.RS ++ ++.TP ++.B resync ++Full resync is performed and all redundancy is regenerated when the array is ++started after unclean shutdown. ++ ++.TP ++.B bitmap ++Resync assisted by a write-intent bitmap. Implicitly selected when using ++.BR \-\-bitmap . ++ ++.TP ++.B journal ++For RAID levels 4/5/6, journal device is used to log transactions and replay ++after unclean shutdown. Implicitly selected when using ++.BR \-\-write\-journal . ++ ++.TP ++.B ppl ++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. ++.RE ++ + + .SH For assemble: + +@@ -2153,8 +2185,10 @@ in the array exceed 100G is size, an internal write-intent bitmap + will automatically be added unless some other option is explicitly + requested with the + .B \-\-bitmap +-option. In any case space for a bitmap will be reserved so that one +-can be added layer with ++option or a different consistency policy is selected with the ++.B \-\-consistency\-policy ++option. In any case space for a bitmap will be reserved so that one ++can be added later with + .BR "\-\-grow \-\-bitmap=internal" . + + If the metadata type supports it (currently only 1.x metadata), space +diff --git a/mdadm.c b/mdadm.c +index 08ddcab..d4e8286 100644 +--- a/mdadm.c ++++ b/mdadm.c +@@ -78,6 +78,7 @@ int main(int argc, char *argv[]) + .level = UnSet, + .layout = UnSet, + .bitmap_chunk = UnSet, ++ .consistency_policy = UnSet, + }; + + char sys_hostname[256]; +@@ -1215,6 +1216,16 @@ int main(int argc, char *argv[]) + + s.journaldisks = 1; + continue; ++ case O(CREATE, 'k'): ++ s.consistency_policy = map_name(consistency_policies, ++ optarg); ++ if (s.consistency_policy == UnSet || ++ s.consistency_policy < CONSISTENCY_POLICY_RESYNC) { ++ pr_err("Invalid consistency policy: %s\n", ++ optarg); ++ exit(2); ++ } ++ continue; + } + /* We have now processed all the valid options. Anything else is + * an error +@@ -1242,9 +1253,47 @@ int main(int argc, char *argv[]) + exit(0); + } + +- if (s.journaldisks && (s.level < 4 || s.level > 6)) { +- pr_err("--write-journal is only supported for RAID level 4/5/6.\n"); +- exit(2); ++ if (s.journaldisks) { ++ if (s.level < 4 || s.level > 6) { ++ pr_err("--write-journal is only supported for RAID level 4/5/6.\n"); ++ exit(2); ++ } ++ if (s.consistency_policy != UnSet && ++ s.consistency_policy != CONSISTENCY_POLICY_JOURNAL) { ++ pr_err("--write-journal is not supported with consistency policy: %s\n", ++ map_num(consistency_policies, s.consistency_policy)); ++ exit(2); ++ } ++ } ++ ++ if (mode == CREATE && s.consistency_policy != UnSet) { ++ if (s.level <= 0) { ++ pr_err("--consistency-policy not meaningful with level %s.\n", ++ map_num(pers, s.level)); ++ exit(2); ++ } else if (s.consistency_policy == CONSISTENCY_POLICY_JOURNAL && ++ !s.journaldisks) { ++ pr_err("--write-journal is required for consistency policy: %s\n", ++ map_num(consistency_policies, s.consistency_policy)); ++ exit(2); ++ } else if (s.consistency_policy == CONSISTENCY_POLICY_PPL && ++ s.level != 5) { ++ pr_err("PPL consistency policy is only supported for RAID level 5.\n"); ++ exit(2); ++ } else if (s.consistency_policy == CONSISTENCY_POLICY_BITMAP && ++ (!s.bitmap_file || ++ strcmp(s.bitmap_file, "none") == 0)) { ++ pr_err("--bitmap is required for consistency policy: %s\n", ++ map_num(consistency_policies, s.consistency_policy)); ++ exit(2); ++ } else if (s.bitmap_file && ++ strcmp(s.bitmap_file, "none") != 0 && ++ s.consistency_policy != CONSISTENCY_POLICY_BITMAP && ++ s.consistency_policy != CONSISTENCY_POLICY_JOURNAL) { ++ pr_err("--bitmap is not compatible with consistency policy: %s\n", ++ map_num(consistency_policies, s.consistency_policy)); ++ exit(2); ++ } + } + + if (!mode && devs_found) { +diff --git a/mdadm.h b/mdadm.h +index cebc0c0..b52d4d3 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -279,6 +279,15 @@ struct mdinfo { + int journal_device_required; + int journal_clean; + ++ enum { ++ CONSISTENCY_POLICY_UNKNOWN, ++ CONSISTENCY_POLICY_NONE, ++ CONSISTENCY_POLICY_RESYNC, ++ CONSISTENCY_POLICY_BITMAP, ++ CONSISTENCY_POLICY_JOURNAL, ++ CONSISTENCY_POLICY_PPL, ++ } consistency_policy; ++ + /* During reshape we can sometimes change the data_offset to avoid + * over-writing still-valid data. We need to know if there is space. + * So getinfo_super will fill in space_before and space_after in sectors. +@@ -426,6 +435,7 @@ enum special_options { + ClusterName, + ClusterConfirm, + WriteJournal, ++ ConsistencyPolicy, + }; + + enum prefix_standard { +@@ -527,6 +537,7 @@ struct shape { + int assume_clean; + int write_behind; + unsigned long long size; ++ int consistency_policy; + }; + + /* List of device names - wildcards expanded */ +@@ -618,6 +629,7 @@ enum sysfs_read_flags { + GET_STATE = (1 << 23), + GET_ERROR = (1 << 24), + GET_ARRAY_STATE = (1 << 25), ++ GET_CONSISTENCY_POLICY = (1 << 26), + }; + + /* If fd >= 0, get the array it is open on, +@@ -701,7 +713,7 @@ extern int restore_stripes(int *dest, unsigned long long *offsets, + + extern char *map_num(mapping_t *map, int num); + extern int map_name(mapping_t *map, char *name); +-extern mapping_t r5layout[], r6layout[], pers[], modes[], faultylayout[]; ++extern mapping_t r5layout[], r6layout[], pers[], modes[], faultylayout[], consistency_policies[]; + + extern char *map_dev_preferred(int major, int minor, int create, + char *prefer); +@@ -863,7 +875,7 @@ extern struct superswitch { + * metadata. + */ + int (*init_super)(struct supertype *st, mdu_array_info_t *info, +- unsigned long long size, char *name, ++ struct shape *s, char *name, + char *homehost, int *uuid, + unsigned long long data_offset); + +@@ -961,7 +973,7 @@ extern struct superswitch { + int *chunk, unsigned long long size, + unsigned long long data_offset, + char *subdev, unsigned long long *freesize, +- int verbose); ++ int consistency_policy, int verbose); + + /* Return a linked list of 'mdinfo' structures for all arrays + * in the container. For non-containers, it is like +@@ -1059,6 +1071,9 @@ extern struct superswitch { + /* validate container after assemble */ + int (*validate_container)(struct mdinfo *info); + ++ /* write initial empty PPL on device */ ++ int (*write_init_ppl)(struct supertype *st, struct mdinfo *info, int fd); ++ + /* records new bad block in metadata */ + int (*record_bad_block)(struct active_array *a, int n, + unsigned long long sector, int length); +diff --git a/super-ddf.c b/super-ddf.c +index 1707ad1..cdd16a4 100644 +--- a/super-ddf.c ++++ b/super-ddf.c +@@ -2290,7 +2290,7 @@ static unsigned int find_vde_by_guid(const struct ddf_super *ddf, + + static int init_super_ddf(struct supertype *st, + mdu_array_info_t *info, +- unsigned long long size, char *name, char *homehost, ++ struct shape *s, char *name, char *homehost, + int *uuid, unsigned long long data_offset) + { + /* This is primarily called by Create when creating a new array. +@@ -2328,7 +2328,7 @@ static int init_super_ddf(struct supertype *st, + struct virtual_disk *vd; + + if (st->sb) +- return init_super_ddf_bvd(st, info, size, name, homehost, uuid, ++ return init_super_ddf_bvd(st, info, s->size, name, homehost, uuid, + data_offset); + + if (posix_memalign((void**)&ddf, 512, sizeof(*ddf)) != 0) { +@@ -3347,7 +3347,7 @@ static int validate_geometry_ddf(struct supertype *st, + int *chunk, unsigned long long size, + unsigned long long data_offset, + char *dev, unsigned long long *freesize, +- int verbose) ++ int consistency_policy, int verbose) + { + int fd; + struct mdinfo *sra; +diff --git a/super-gpt.c b/super-gpt.c +index 8b080a0..bb38a97 100644 +--- a/super-gpt.c ++++ b/super-gpt.c +@@ -205,7 +205,7 @@ static int validate_geometry(struct supertype *st, int level, + int *chunk, unsigned long long size, + unsigned long long data_offset, + char *subdev, unsigned long long *freesize, +- int verbose) ++ int consistency_policy, int verbose) + { + pr_err("gpt metadata cannot be used this way\n"); + return 0; +diff --git a/super-intel.c b/super-intel.c +index e1618f1..5d0f131 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -5155,7 +5155,7 @@ static int check_name(struct intel_super *super, char *name, int quiet) + } + + static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, +- unsigned long long size, char *name, ++ struct shape *s, char *name, + char *homehost, int *uuid, + long long data_offset) + { +@@ -5250,7 +5250,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, + strncpy((char *) dev->volume, name, MAX_RAID_SERIAL_LEN); + array_blocks = calc_array_size(info->level, info->raid_disks, + info->layout, info->chunk_size, +- size * 2); ++ s->size * 2); + /* round array size down to closest MB */ + array_blocks = (array_blocks >> SECT_PER_MB_SHIFT) << SECT_PER_MB_SHIFT; + +@@ -5264,7 +5264,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, + vol->curr_migr_unit = 0; + map = get_imsm_map(dev, MAP_0); + set_pba_of_lba0(map, super->create_offset); +- set_blocks_per_member(map, info_to_blocks_per_member(info, size)); ++ set_blocks_per_member(map, info_to_blocks_per_member(info, s->size)); + map->blocks_per_strip = __cpu_to_le16(info_to_blocks_per_strip(info)); + map->failed_disk_num = ~0; + if (info->level > 0) +@@ -5292,7 +5292,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, + map->num_domains = 1; + + /* info->size is only int so use the 'size' parameter instead */ +- num_data_stripes = (size * 2) / info_to_blocks_per_strip(info); ++ num_data_stripes = (s->size * 2) / info_to_blocks_per_strip(info); + num_data_stripes /= map->num_domains; + set_num_data_stripes(map, num_data_stripes); + +@@ -5314,7 +5314,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, + } + + static int init_super_imsm(struct supertype *st, mdu_array_info_t *info, +- unsigned long long size, char *name, ++ struct shape *s, char *name, + char *homehost, int *uuid, + unsigned long long data_offset) + { +@@ -5337,7 +5337,7 @@ static int init_super_imsm(struct supertype *st, mdu_array_info_t *info, + } + + if (st->sb) +- return init_super_imsm_volume(st, info, size, name, homehost, uuid, ++ return init_super_imsm_volume(st, info, s, name, homehost, uuid, + data_offset); + + if (info) +@@ -6914,7 +6914,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, + int raiddisks, int *chunk, unsigned long long size, + unsigned long long data_offset, + char *dev, unsigned long long *freesize, +- int verbose) ++ int consistency_policy, int verbose) + { + int fd, cfd; + struct mdinfo *sra; +@@ -10953,7 +10953,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, + geo->raid_disks + devNumChange, + &chunk, + geo->size, INVALID_SECTORS, +- 0, 0, 1)) ++ 0, 0, info.consistency_policy, 1)) + change = -1; + + if (check_devs) { +diff --git a/super-mbr.c b/super-mbr.c +index f5e4cea..1bbe57a 100644 +--- a/super-mbr.c ++++ b/super-mbr.c +@@ -193,7 +193,7 @@ static int validate_geometry(struct supertype *st, int level, + int *chunk, unsigned long long size, + unsigned long long data_offset, + char *subdev, unsigned long long *freesize, +- int verbose) ++ int consistency_policy, int verbose) + { + pr_err("mbr metadata cannot be used this way\n"); + return 0; +diff --git a/super0.c b/super0.c +index f5b4507..7a555e3 100644 +--- a/super0.c ++++ b/super0.c +@@ -725,7 +725,7 @@ static int update_super0(struct supertype *st, struct mdinfo *info, + * We use the first 8 bytes (64bits) of the sha1 of the host name + */ + static int init_super0(struct supertype *st, mdu_array_info_t *info, +- unsigned long long size, char *ignored_name, ++ struct shape *s, char *ignored_name, + char *homehost, int *uuid, + unsigned long long data_offset) + { +@@ -764,8 +764,8 @@ static int init_super0(struct supertype *st, mdu_array_info_t *info, + sb->gvalid_words = 0; /* ignored */ + sb->ctime = time(0); + sb->level = info->level; +- sb->size = size; +- if (size != (unsigned long long)sb->size) ++ sb->size = s->size; ++ if (s->size != (unsigned long long)sb->size) + return 0; + sb->nr_disks = info->nr_disks; + sb->raid_disks = info->raid_disks; +@@ -1267,7 +1267,7 @@ static int validate_geometry0(struct supertype *st, int level, + int *chunk, unsigned long long size, + unsigned long long data_offset, + char *subdev, unsigned long long *freesize, +- int verbose) ++ int consistency_policy, int verbose) + { + unsigned long long ldsize; + int fd; +diff --git a/super1.c b/super1.c +index f3520ac..4a0f041 100644 +--- a/super1.c ++++ b/super1.c +@@ -1397,7 +1397,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info, + } + + static int init_super1(struct supertype *st, mdu_array_info_t *info, +- unsigned long long size, char *name, char *homehost, ++ struct shape *s, char *name, char *homehost, + int *uuid, unsigned long long data_offset) + { + struct mdp_superblock_1 *sb; +@@ -1450,7 +1450,7 @@ static int init_super1(struct supertype *st, mdu_array_info_t *info, + sb->ctime = __cpu_to_le64((unsigned long long)time(0)); + sb->level = __cpu_to_le32(info->level); + sb->layout = __cpu_to_le32(info->layout); +- sb->size = __cpu_to_le64(size*2ULL); ++ sb->size = __cpu_to_le64(s->size*2ULL); + sb->chunksize = __cpu_to_le32(info->chunk_size>>9); + sb->raid_disks = __cpu_to_le32(info->raid_disks); + +@@ -2487,7 +2487,7 @@ static int validate_geometry1(struct supertype *st, int level, + int *chunk, unsigned long long size, + unsigned long long data_offset, + char *subdev, unsigned long long *freesize, +- int verbose) ++ int consistency_policy, int verbose) + { + unsigned long long ldsize, devsize; + int bmspace; +diff --git a/sysfs.c b/sysfs.c +index b0657a0..53589a7 100644 +--- a/sysfs.c ++++ b/sysfs.c +@@ -242,6 +242,17 @@ struct mdinfo *sysfs_read(int fd, char *devnm, unsigned long options) + } else + sra->sysfs_array_state[0] = 0; + ++ if (options & GET_CONSISTENCY_POLICY) { ++ strcpy(base, "consistency_policy"); ++ if (load_sys(fname, buf, sizeof(buf))) { ++ sra->consistency_policy = CONSISTENCY_POLICY_UNKNOWN; ++ } else { ++ sra->consistency_policy = map_name(consistency_policies, buf); ++ if (sra->consistency_policy == UnSet) ++ sra->consistency_policy = CONSISTENCY_POLICY_UNKNOWN; ++ } ++ } ++ + if (! (options & GET_DEVS)) + return sra; + diff --git a/SOURCES/imsm-use-rounded-size-for-metadata-initialization.patch b/SOURCES/imsm-use-rounded-size-for-metadata-initialization.patch new file mode 100644 index 0000000..ac7706f --- /dev/null +++ b/SOURCES/imsm-use-rounded-size-for-metadata-initialization.patch @@ -0,0 +1,134 @@ +commit b53bfba6119d3f6f56eb9e10e5a59da6901af159 +Author: Tomasz Majchrzak +Date: Thu Mar 30 16:25:41 2017 +0200 + + imsm: use rounded size for metadata initialization + + Array size is rounded to the nearest MB, however number of data stripes + and blocks per disk are calculated using size passed by the user. If + given size is not aligned, there is a mismatch. It's not possible to + assemble raid0 migrated to raid5 since raid5 arrays use number of data + stripes to calculate array size. + + Signed-off-by: Tomasz Majchrzak + Signed-off-by: Jes Sorensen + +diff --git a/super-intel.c b/super-intel.c +index 785488a..84dfe2b 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -264,6 +264,8 @@ struct bbm_log { + static char *map_state_str[] = { "normal", "uninitialized", "degraded", "failed" }; + #endif + ++#define BLOCKS_PER_KB (1024/512) ++ + #define RAID_DISK_RESERVED_BLOCKS_IMSM_HI 2209 + + #define GEN_MIGR_AREA_SIZE 2048 /* General Migration Copy Area size in blocks */ +@@ -1324,6 +1326,19 @@ static int is_journal(struct imsm_disk *disk) + return (disk->status & JOURNAL_DISK) == JOURNAL_DISK; + } + ++/* round array size down to closest MB and ensure it splits evenly ++ * between members ++ */ ++static unsigned long long round_size_to_mb(unsigned long long size, unsigned int ++ disk_count) ++{ ++ size /= disk_count; ++ size = (size >> SECT_PER_MB_SHIFT) << SECT_PER_MB_SHIFT; ++ size *= disk_count; ++ ++ return size; ++} ++ + /* try to determine how much space is reserved for metadata from + * the last get_extents() entry on the smallest active disk, + * otherwise fallback to the default +@@ -3330,11 +3345,10 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, + if (used_disks > 0) { + array_blocks = blocks_per_member(map) * + used_disks; +- /* round array size down to closest MB +- */ +- info->custom_array_size = (array_blocks +- >> SECT_PER_MB_SHIFT) +- << SECT_PER_MB_SHIFT; ++ info->custom_array_size = ++ round_size_to_mb(array_blocks, ++ used_disks); ++ + } + } + case MIGR_VERIFY: +@@ -5241,6 +5255,8 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, + unsigned long long array_blocks; + size_t size_old, size_new; + unsigned long long num_data_stripes; ++ unsigned int data_disks; ++ unsigned long long size_per_member; + + if (super->orom && mpb->num_raid_devs >= super->orom->vpa) { + pr_err("This imsm-container already has the maximum of %d volumes\n", super->orom->vpa); +@@ -5317,9 +5333,11 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, + strncpy((char *) dev->volume, name, MAX_RAID_SERIAL_LEN); + array_blocks = calc_array_size(info->level, info->raid_disks, + info->layout, info->chunk_size, +- s->size * 2); +- /* round array size down to closest MB */ +- array_blocks = (array_blocks >> SECT_PER_MB_SHIFT) << SECT_PER_MB_SHIFT; ++ s->size * BLOCKS_PER_KB); ++ data_disks = get_data_disks(info->level, info->layout, ++ info->raid_disks); ++ array_blocks = round_size_to_mb(array_blocks, data_disks); ++ size_per_member = array_blocks / data_disks; + + dev->size_low = __cpu_to_le32((__u32) array_blocks); + dev->size_high = __cpu_to_le32((__u32) (array_blocks >> 32)); +@@ -5331,7 +5349,9 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, + vol->curr_migr_unit = 0; + map = get_imsm_map(dev, MAP_0); + set_pba_of_lba0(map, super->create_offset); +- set_blocks_per_member(map, info_to_blocks_per_member(info, s->size)); ++ set_blocks_per_member(map, info_to_blocks_per_member(info, ++ size_per_member / ++ BLOCKS_PER_KB)); + map->blocks_per_strip = __cpu_to_le16(info_to_blocks_per_strip(info)); + map->failed_disk_num = ~0; + if (info->level > 0) +@@ -5359,7 +5379,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, + map->num_domains = 1; + + /* info->size is only int so use the 'size' parameter instead */ +- num_data_stripes = (s->size * 2) / info_to_blocks_per_strip(info); ++ num_data_stripes = size_per_member / info_to_blocks_per_strip(info); + num_data_stripes /= map->num_domains; + set_num_data_stripes(map, num_data_stripes); + +@@ -7981,9 +8001,7 @@ static unsigned long long imsm_set_array_size(struct imsm_dev *dev, + array_blocks = new_size; + } + +- /* round array size down to closest MB +- */ +- array_blocks = (array_blocks >> SECT_PER_MB_SHIFT) << SECT_PER_MB_SHIFT; ++ array_blocks = round_size_to_mb(array_blocks, used_disks); + dev->size_low = __cpu_to_le32((__u32)array_blocks); + dev->size_high = __cpu_to_le32((__u32)(array_blocks >> 32)); + +@@ -8096,11 +8114,9 @@ static int imsm_set_array_state(struct active_array *a, int consistent) + array_blocks = + blocks_per_member(map) * + used_disks; +- /* round array size down to closest MB +- */ +- array_blocks = (array_blocks +- >> SECT_PER_MB_SHIFT) +- << SECT_PER_MB_SHIFT; ++ array_blocks = ++ round_size_to_mb(array_blocks, ++ used_disks); + a->info.custom_array_size = array_blocks; + /* encourage manager to update array + * size diff --git a/SOURCES/imsmppl-support.patch b/SOURCES/imsmppl-support.patch new file mode 100644 index 0000000..55bc0c3 --- /dev/null +++ b/SOURCES/imsmppl-support.patch @@ -0,0 +1,637 @@ +commit 2432ce9b3235f34d00ef6c28ef6b624a32b85530 +Author: Artur Paszkiewicz +Date: Wed Mar 29 11:54:17 2017 +0200 + + imsm: PPL support + + Enable creating and assembling IMSM raid5 arrays with PPL. Update the + IMSM metadata format to include new fields used for PPL. + + Add structures for PPL metadata. They are used also by super1 and shared + with the kernel, so put them in md_p.h. + + Write the initial empty PPL header when creating an array. When + assembling an array with PPL, validate the PPL header and in case it is + not correct allow to overwrite it if --force was provided. + + Write the PPL location and size for a device to the new rdev sysfs + attributes 'ppl_sector' and 'ppl_size'. Enable PPL in the kernel by + writing to 'consistency_policy' before the array is activated. + + Signed-off-by: Artur Paszkiewicz + Signed-off-by: Jes Sorensen + +diff --git a/Assemble.c b/Assemble.c +index 3da0903..8e55b49 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -1942,6 +1942,55 @@ int assemble_container_content(struct supertype *st, int mdfd, + map_update(NULL, fd2devnm(mdfd), content->text_version, + content->uuid, chosen_name); + ++ if (content->consistency_policy == CONSISTENCY_POLICY_PPL && ++ st->ss->validate_ppl) { ++ content->array.state |= 1; ++ err = 0; ++ ++ for (dev = content->devs; dev; dev = dev->next) { ++ int dfd; ++ char *devpath; ++ int ret; ++ ++ ret = st->ss->validate_ppl(st, content, dev); ++ if (ret == 0) ++ continue; ++ ++ if (ret < 0) { ++ err = 1; ++ break; ++ } ++ ++ if (!c->force) { ++ pr_err("%s contains invalid PPL - consider --force or --update-subarray with --update=no-ppl\n", ++ chosen_name); ++ content->array.state &= ~1; ++ avail[dev->disk.raid_disk] = 0; ++ break; ++ } ++ ++ /* have --force - overwrite the invalid ppl */ ++ devpath = map_dev(dev->disk.major, dev->disk.minor, 0); ++ dfd = dev_open(devpath, O_RDWR); ++ if (dfd < 0) { ++ pr_err("Failed to open %s\n", devpath); ++ err = 1; ++ break; ++ } ++ ++ err = st->ss->write_init_ppl(st, content, dfd); ++ close(dfd); ++ ++ if (err) ++ break; ++ } ++ ++ if (err) { ++ free(avail); ++ return err; ++ } ++ } ++ + if (enough(content->array.level, content->array.raid_disks, + content->array.layout, content->array.state & 1, avail) == 0) { + if (c->export && result) +diff --git a/Makefile b/Makefile +index d1a6ac4..5ff6cc0 100644 +--- a/Makefile ++++ b/Makefile +@@ -151,7 +151,7 @@ MON_OBJS = mdmon.o monitor.o managemon.o util.o maps.o mdstat.o sysfs.o \ + Kill.o sg_io.o dlink.o ReadMe.o super-intel.o \ + super-mbr.o super-gpt.o \ + super-ddf.o sha1.o crc32.o msg.o bitmap.o xmalloc.o \ +- platform-intel.o probe_roms.o ++ platform-intel.o probe_roms.o crc32c.o + + MON_SRCS = $(patsubst %.o,%.c,$(MON_OBJS)) + +@@ -161,7 +161,8 @@ STATICOBJS = pwgr.o + ASSEMBLE_SRCS := mdassemble.c Assemble.c Manage.c config.c policy.c dlink.c util.c \ + maps.c lib.c xmalloc.c \ + super0.c super1.c super-ddf.c super-intel.c sha1.c crc32.c sg_io.c mdstat.c \ +- platform-intel.c probe_roms.c sysfs.c super-mbr.c super-gpt.c mapfile.c ++ platform-intel.c probe_roms.c sysfs.c super-mbr.c super-gpt.c mapfile.c \ ++ crc32c.c + ASSEMBLE_AUTO_SRCS := mdopen.c + ASSEMBLE_FLAGS:= $(CFLAGS) -DMDASSEMBLE + ifdef MDASSEMBLE_AUTO +diff --git a/md_p.h b/md_p.h +index dc9fec1..358a28c 100644 +--- a/md_p.h ++++ b/md_p.h +@@ -267,4 +267,29 @@ struct r5l_meta_block { + #define R5LOG_VERSION 0x1 + #define R5LOG_MAGIC 0x6433c509 + ++struct ppl_header_entry { ++ __u64 data_sector; /* raid sector of the new data */ ++ __u32 pp_size; /* length of partial parity */ ++ __u32 data_size; /* length of data */ ++ __u32 parity_disk; /* member disk containing parity */ ++ __u32 checksum; /* checksum of this entry's partial parity */ ++} __attribute__ ((__packed__)); ++ ++#define PPL_HEADER_SIZE 4096 ++#define PPL_HDR_RESERVED 512 ++#define PPL_HDR_ENTRY_SPACE \ ++ (PPL_HEADER_SIZE - PPL_HDR_RESERVED - 4 * sizeof(__u32) - sizeof(__u64)) ++#define PPL_HDR_MAX_ENTRIES \ ++ (PPL_HDR_ENTRY_SPACE / sizeof(struct ppl_header_entry)) ++ ++struct ppl_header { ++ __u8 reserved[PPL_HDR_RESERVED];/* reserved space, fill with 0xff */ ++ __u32 signature; /* signature (family number of volume) */ ++ __u32 padding; /* zero pad */ ++ __u64 generation; /* generation number of the header */ ++ __u32 entries_count; /* number of entries in entry array */ ++ __u32 checksum; /* checksum of the header */ ++ struct ppl_header_entry entries[PPL_HDR_MAX_ENTRIES]; ++} __attribute__ ((__packed__)); ++ + #endif +diff --git a/mdadm.h b/mdadm.h +index b52d4d3..d222cc3 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -300,6 +300,8 @@ struct mdinfo { + #define MaxSector (~0ULL) /* resync/recovery complete position */ + }; + long bitmap_offset; /* 0 == none, 1 == a file */ ++ unsigned int ppl_size; ++ unsigned long long ppl_sector; + unsigned long safe_mode_delay; /* ms delay to mark clean */ + int new_level, delta_disks, new_layout, new_chunk; + int errors; +@@ -1074,6 +1076,10 @@ extern struct superswitch { + /* write initial empty PPL on device */ + int (*write_init_ppl)(struct supertype *st, struct mdinfo *info, int fd); + ++ /* validate ppl before assemble */ ++ int (*validate_ppl)(struct supertype *st, struct mdinfo *info, ++ struct mdinfo *disk); ++ + /* records new bad block in metadata */ + int (*record_bad_block)(struct active_array *a, int n, + unsigned long long sector, int length); +diff --git a/super-intel.c b/super-intel.c +index 2d92c8e..87fec8b 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -102,6 +102,7 @@ struct imsm_disk { + #define SPARE_DISK __cpu_to_le32(0x01) /* Spare */ + #define CONFIGURED_DISK __cpu_to_le32(0x02) /* Member of some RaidDev */ + #define FAILED_DISK __cpu_to_le32(0x04) /* Permanent failure */ ++#define JOURNAL_DISK __cpu_to_le32(0x2000000) /* Device marked as Journaling Drive */ + __u32 status; /* 0xF0 - 0xF3 */ + __u32 owner_cfg_num; /* which config 0,1,2... owns this disk */ + __u32 total_blocks_hi; /* 0xF4 - 0xF5 total blocks hi */ +@@ -155,6 +156,9 @@ struct imsm_vol { + #define MIGR_STATE_CHANGE 4 + #define MIGR_REPAIR 5 + __u8 migr_type; /* Initializing, Rebuilding, ... */ ++#define RAIDVOL_CLEAN 0 ++#define RAIDVOL_DIRTY 1 ++#define RAIDVOL_DSRECORD_VALID 2 + __u8 dirty; + __u8 fs_state; /* fast-sync state for CnG (0xff == disabled) */ + __u16 verify_errors; /* number of mismatches */ +@@ -190,7 +194,24 @@ struct imsm_dev { + __u16 cache_policy; + __u8 cng_state; + __u8 cng_sub_state; +-#define IMSM_DEV_FILLERS 10 ++ __u16 my_vol_raid_dev_num; /* Used in Unique volume Id for this RaidDev */ ++ ++ /* NVM_EN */ ++ __u8 nv_cache_mode; ++ __u8 nv_cache_flags; ++ ++ /* Unique Volume Id of the NvCache Volume associated with this volume */ ++ __u32 nvc_vol_orig_family_num; ++ __u16 nvc_vol_raid_dev_num; ++ ++#define RWH_OFF 0 ++#define RWH_DISTRIBUTED 1 ++#define RWH_JOURNALING_DRIVE 2 ++ __u8 rwh_policy; /* Raid Write Hole Policy */ ++ __u8 jd_serial[MAX_RAID_SERIAL_LEN]; /* Journal Drive serial number */ ++ __u8 filler1; ++ ++#define IMSM_DEV_FILLERS 3 + __u32 filler[IMSM_DEV_FILLERS]; + struct imsm_vol vol; + } __attribute__ ((packed)); +@@ -257,6 +278,9 @@ static char *map_state_str[] = { "normal", "uninitialized", "degraded", "failed" + #define UNIT_SRC_IN_CP_AREA 1 /* Source data for curr_migr_unit has + * already been migrated and must + * be recovered from checkpoint area */ ++ ++#define PPL_ENTRY_SPACE (128 * 1024) /* Size of the PPL, without the header */ ++ + struct migr_record { + __u32 rec_status; /* Status used to determine how to restart + * migration in case it aborts +@@ -1288,6 +1312,11 @@ static int is_failed(struct imsm_disk *disk) + return (disk->status & FAILED_DISK) == FAILED_DISK; + } + ++static int is_journal(struct imsm_disk *disk) ++{ ++ return (disk->status & JOURNAL_DISK) == JOURNAL_DISK; ++} ++ + /* try to determine how much space is reserved for metadata from + * the last get_extents() entry on the smallest active disk, + * otherwise fallback to the default +@@ -1477,7 +1506,17 @@ static void print_imsm_dev(struct intel_super *super, + blocks_per_migr_unit(super, dev)); + } + printf("\n"); +- printf(" Dirty State : %s\n", dev->vol.dirty ? "dirty" : "clean"); ++ printf(" Dirty State : %s\n", (dev->vol.dirty & RAIDVOL_DIRTY) ? ++ "dirty" : "clean"); ++ printf(" RWH Policy : "); ++ if (dev->rwh_policy == RWH_OFF) ++ printf("off\n"); ++ else if (dev->rwh_policy == RWH_DISTRIBUTED) ++ printf("PPL distributed\n"); ++ else if (dev->rwh_policy == RWH_JOURNALING_DRIVE) ++ printf("PPL journaling drive\n"); ++ else ++ printf("\n", dev->rwh_policy); + } + + static void print_imsm_disk(struct imsm_disk *disk, +@@ -1496,9 +1535,10 @@ static void print_imsm_disk(struct imsm_disk *disk, + printf(" Disk%02d Serial : %s\n", index, str); + else + printf(" Disk Serial : %s\n", str); +- printf(" State :%s%s%s\n", is_spare(disk) ? " spare" : "", +- is_configured(disk) ? " active" : "", +- is_failed(disk) ? " failed" : ""); ++ printf(" State :%s%s%s%s\n", is_spare(disk) ? " spare" : "", ++ is_configured(disk) ? " active" : "", ++ is_failed(disk) ? " failed" : "", ++ is_journal(disk) ? " journal" : ""); + printf(" Id : %08x\n", __le32_to_cpu(disk->scsi_id)); + sz = total_blocks(disk) - reserved; + printf(" Usable Size : %llu%s\n", +@@ -3114,6 +3154,15 @@ static unsigned long long imsm_component_size_aligment_check(int level, + return component_size; + } + ++static unsigned long long get_ppl_sector(struct intel_super *super, int dev_idx) ++{ ++ struct imsm_dev *dev = get_imsm_dev(super, dev_idx); ++ struct imsm_map *map = get_imsm_map(dev, MAP_0); ++ ++ return pba_of_lba0(map) + ++ (num_data_stripes(map) * map->blocks_per_strip); ++} ++ + static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, char *dmap) + { + struct intel_super *super = st->sb; +@@ -3140,7 +3189,7 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, + info->array.utime = 0; + info->array.chunk_size = + __le16_to_cpu(map_to_analyse->blocks_per_strip) << 9; +- info->array.state = !dev->vol.dirty; ++ info->array.state = !(dev->vol.dirty & RAIDVOL_DIRTY); + info->custom_array_size = __le32_to_cpu(dev->size_high); + info->custom_array_size <<= 32; + info->custom_array_size |= __le32_to_cpu(dev->size_low); +@@ -3221,10 +3270,20 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, + memset(info->uuid, 0, sizeof(info->uuid)); + info->recovery_start = MaxSector; + ++ if (info->array.level == 5 && dev->rwh_policy == RWH_DISTRIBUTED) { ++ info->consistency_policy = CONSISTENCY_POLICY_PPL; ++ info->ppl_sector = get_ppl_sector(super, super->current_vol); ++ info->ppl_size = (PPL_HEADER_SIZE + PPL_ENTRY_SPACE) >> 9; ++ } else if (info->array.level <= 0) { ++ info->consistency_policy = CONSISTENCY_POLICY_NONE; ++ } else { ++ info->consistency_policy = CONSISTENCY_POLICY_RESYNC; ++ } ++ + info->reshape_progress = 0; + info->resync_start = MaxSector; + if ((map_to_analyse->map_state == IMSM_T_STATE_UNINITIALIZED || +- dev->vol.dirty) && ++ !(info->array.state & 1)) && + imsm_reshape_blocks_arrays_changes(super) == 0) { + info->resync_start = 0; + } +@@ -3451,7 +3510,8 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char * + * found the 'most fresh' version of the metadata + */ + info->disk.state |= is_failed(disk) ? (1 << MD_DISK_FAULTY) : 0; +- info->disk.state |= is_spare(disk) ? 0 : (1 << MD_DISK_SYNC); ++ info->disk.state |= (is_spare(disk) || is_journal(disk)) ? ++ 0 : (1 << MD_DISK_SYNC); + } + + /* only call uuid_from_super_imsm when this disk is part of a populated container, +@@ -3906,7 +3966,7 @@ load_imsm_disk(int fd, struct intel_super *super, char *devname, int keep_fd) + */ + if (is_failed(&dl->disk)) + dl->index = -2; +- else if (is_spare(&dl->disk)) ++ else if (is_spare(&dl->disk) || is_journal(&dl->disk)) + dl->index = -1; + } + +@@ -5303,6 +5363,20 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, + } + mpb->num_raid_devs++; + ++ if (s->consistency_policy == UnSet || ++ s->consistency_policy == CONSISTENCY_POLICY_RESYNC || ++ s->consistency_policy == CONSISTENCY_POLICY_NONE) { ++ dev->rwh_policy = RWH_OFF; ++ } else if (s->consistency_policy == CONSISTENCY_POLICY_PPL) { ++ dev->rwh_policy = RWH_DISTRIBUTED; ++ } else { ++ free(dev); ++ free(dv); ++ pr_err("imsm does not support consistency policy %s\n", ++ map_num(consistency_policies, s->consistency_policy)); ++ return 0; ++ } ++ + dv->dev = dev; + dv->index = super->current_vol; + dv->next = super->devlist; +@@ -5927,11 +6001,146 @@ static int mgmt_disk(struct supertype *st) + + return 0; + } ++#endif ++ ++__u32 crc32c_le(__u32 crc, unsigned char const *p, size_t len); ++ ++static int write_init_ppl_imsm(struct supertype *st, struct mdinfo *info, int fd) ++{ ++ struct intel_super *super = st->sb; ++ void *buf; ++ struct ppl_header *ppl_hdr; ++ int ret; ++ ++ ret = posix_memalign(&buf, 4096, PPL_HEADER_SIZE); ++ if (ret) { ++ pr_err("Failed to allocate PPL header buffer\n"); ++ return ret; ++ } ++ ++ memset(buf, 0, PPL_HEADER_SIZE); ++ ppl_hdr = buf; ++ memset(ppl_hdr->reserved, 0xff, PPL_HDR_RESERVED); ++ ppl_hdr->signature = __cpu_to_le32(super->anchor->orig_family_num); ++ ppl_hdr->checksum = __cpu_to_le32(~crc32c_le(~0, buf, PPL_HEADER_SIZE)); ++ ++ if (lseek64(fd, info->ppl_sector * 512, SEEK_SET) < 0) { ++ ret = errno; ++ perror("Failed to seek to PPL header location"); ++ } ++ ++ if (!ret && write(fd, buf, PPL_HEADER_SIZE) != PPL_HEADER_SIZE) { ++ ret = errno; ++ perror("Write PPL header failed"); ++ } ++ ++ if (!ret) ++ fsync(fd); ++ ++ free(buf); ++ return ret; ++} ++ ++static int validate_ppl_imsm(struct supertype *st, struct mdinfo *info, ++ struct mdinfo *disk) ++{ ++ struct intel_super *super = st->sb; ++ struct dl *d; ++ void *buf; ++ int ret = 0; ++ struct ppl_header *ppl_hdr; ++ __u32 crc; ++ struct imsm_dev *dev; ++ struct imsm_map *map; ++ __u32 idx; ++ ++ if (disk->disk.raid_disk < 0) ++ return 0; ++ ++ if (posix_memalign(&buf, 4096, PPL_HEADER_SIZE)) { ++ pr_err("Failed to allocate PPL header buffer\n"); ++ return -1; ++ } ++ ++ dev = get_imsm_dev(super, info->container_member); ++ map = get_imsm_map(dev, MAP_X); ++ idx = get_imsm_disk_idx(dev, disk->disk.raid_disk, MAP_X); ++ d = get_imsm_dl_disk(super, idx); ++ ++ if (!d || d->index < 0 || is_failed(&d->disk)) ++ goto out; ++ ++ if (lseek64(d->fd, info->ppl_sector * 512, SEEK_SET) < 0) { ++ perror("Failed to seek to PPL header location"); ++ ret = -1; ++ goto out; ++ } ++ ++ if (read(d->fd, buf, PPL_HEADER_SIZE) != PPL_HEADER_SIZE) { ++ perror("Read PPL header failed"); ++ ret = -1; ++ goto out; ++ } ++ ++ ppl_hdr = buf; ++ ++ crc = __le32_to_cpu(ppl_hdr->checksum); ++ ppl_hdr->checksum = 0; ++ ++ if (crc != ~crc32c_le(~0, buf, PPL_HEADER_SIZE)) { ++ dprintf("Wrong PPL header checksum on %s\n", ++ d->devname); ++ ret = 1; ++ } ++ ++ if (!ret && (__le32_to_cpu(ppl_hdr->signature) != ++ super->anchor->orig_family_num)) { ++ dprintf("Wrong PPL header signature on %s\n", ++ d->devname); ++ ret = 1; ++ } ++ ++out: ++ free(buf); ++ ++ if (ret == 1 && map->map_state == IMSM_T_STATE_UNINITIALIZED) ++ return st->ss->write_init_ppl(st, info, d->fd); ++ ++ return ret; ++} ++ ++#ifndef MDASSEMBLE ++ ++static int write_init_ppl_imsm_all(struct supertype *st, struct mdinfo *info) ++{ ++ struct intel_super *super = st->sb; ++ struct dl *d; ++ int ret = 0; ++ ++ if (info->consistency_policy != CONSISTENCY_POLICY_PPL || ++ info->array.level != 5) ++ return 0; ++ ++ for (d = super->disks; d ; d = d->next) { ++ if (d->index < 0 || is_failed(&d->disk)) ++ continue; ++ ++ ret = st->ss->write_init_ppl(st, info, d->fd); ++ if (ret) ++ break; ++ } ++ ++ return ret; ++} + + static int write_init_super_imsm(struct supertype *st) + { + struct intel_super *super = st->sb; + int current_vol = super->current_vol; ++ int rv = 0; ++ struct mdinfo info; ++ ++ getinfo_super_imsm(st, &info, NULL); + + /* we are done with current_vol reset it to point st at the container */ + super->current_vol = -1; +@@ -5939,24 +6148,29 @@ static int write_init_super_imsm(struct supertype *st) + if (st->update_tail) { + /* queue the recently created array / added disk + * as a metadata update */ +- int rv; + + /* determine if we are creating a volume or adding a disk */ + if (current_vol < 0) { + /* in the mgmt (add/remove) disk case we are running + * in mdmon context, so don't close fd's + */ +- return mgmt_disk(st); +- } else +- rv = create_array(st, current_vol); +- +- return rv; ++ rv = mgmt_disk(st); ++ } else { ++ rv = write_init_ppl_imsm_all(st, &info); ++ if (!rv) ++ rv = create_array(st, current_vol); ++ } + } else { + struct dl *d; + for (d = super->disks; d; d = d->next) + Kill(d->devname, NULL, 0, -1, 1); +- return write_super_imsm(st, 1); ++ if (current_vol >= 0) ++ rv = write_init_ppl_imsm_all(st, &info); ++ if (!rv) ++ rv = write_super_imsm(st, 1); + } ++ ++ return rv; + } + #endif + +@@ -7375,7 +7589,8 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra + * + * FIXME handle dirty degraded + */ +- if ((skip || recovery_start == 0) && !dev->vol.dirty) ++ if ((skip || recovery_start == 0) && ++ !(dev->vol.dirty & RAIDVOL_DIRTY)) + this->resync_start = MaxSector; + if (skip) + continue; +@@ -7410,9 +7625,12 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra + info_d->component_size = + num_data_stripes(map) * + map->blocks_per_strip; ++ info_d->ppl_sector = this->ppl_sector; ++ info_d->ppl_size = this->ppl_size; + } else { + info_d->component_size = blocks_per_member(map); + } ++ info_d->consistency_policy = this->consistency_policy; + + info_d->bb.supported = 1; + get_volume_badblocks(super->bbm_log, ord_to_idx(ord), +@@ -7928,12 +8146,16 @@ mark_checkpoint: + + skip_mark_checkpoint: + /* mark dirty / clean */ +- if (dev->vol.dirty != !consistent) { ++ if (((dev->vol.dirty & RAIDVOL_DIRTY) && consistent) || ++ (!(dev->vol.dirty & RAIDVOL_DIRTY) && !consistent)) { + dprintf("imsm: mark '%s'\n", consistent ? "clean" : "dirty"); +- if (consistent) +- dev->vol.dirty = 0; +- else +- dev->vol.dirty = 1; ++ if (consistent) { ++ dev->vol.dirty = RAIDVOL_CLEAN; ++ } else { ++ dev->vol.dirty = RAIDVOL_DIRTY; ++ if (dev->rwh_policy == RWH_DISTRIBUTED) ++ dev->vol.dirty |= RAIDVOL_DSRECORD_VALID; ++ } + super->updates_pending++; + } + +@@ -8445,6 +8667,11 @@ static struct mdinfo *imsm_activate_spare(struct active_array *a, + di->component_size = a->info.component_size; + di->container_member = inst; + di->bb.supported = 1; ++ if (dev->rwh_policy == RWH_DISTRIBUTED) { ++ di->consistency_policy = CONSISTENCY_POLICY_PPL; ++ di->ppl_sector = get_ppl_sector(super, inst); ++ di->ppl_size = (PPL_HEADER_SIZE + PPL_ENTRY_SPACE) >> 9; ++ } + super->random = random32(); + di->next = rv; + rv = di; +@@ -11600,6 +11827,9 @@ struct superswitch super_imsm = { + .container_content = container_content_imsm, + .validate_container = validate_container_imsm, + ++ .write_init_ppl = write_init_ppl_imsm, ++ .validate_ppl = validate_ppl_imsm, ++ + .external = 1, + .name = "imsm", + +diff --git a/sysfs.c b/sysfs.c +index 53589a7..2a91ba0 100644 +--- a/sysfs.c ++++ b/sysfs.c +@@ -689,6 +689,16 @@ int sysfs_set_array(struct mdinfo *info, int vers) + * once the reshape completes. + */ + } ++ ++ if (info->consistency_policy == CONSISTENCY_POLICY_PPL) { ++ if (sysfs_set_str(info, NULL, "consistency_policy", ++ map_num(consistency_policies, ++ info->consistency_policy))) { ++ pr_err("This kernel does not support PPL\n"); ++ return 1; ++ } ++ } ++ + return rv; + } + +@@ -720,6 +730,10 @@ int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd, int resume) + rv = sysfs_set_num(sra, sd, "offset", sd->data_offset); + rv |= sysfs_set_num(sra, sd, "size", (sd->component_size+1) / 2); + if (sra->array.level != LEVEL_CONTAINER) { ++ if (sd->consistency_policy == CONSISTENCY_POLICY_PPL) { ++ rv |= sysfs_set_num(sra, sd, "ppl_sector", sd->ppl_sector); ++ rv |= sysfs_set_num(sra, sd, "ppl_size", sd->ppl_size); ++ } + if (sd->recovery_start == MaxSector) + /* This can correctly fail if array isn't started, + * yet, so just ignore status for now. diff --git a/SOURCES/mdadm-3.4-Change-behavior-in-find_free_devnm-when-wrapping-aro.patch b/SOURCES/mdadm-3.4-Change-behavior-in-find_free_devnm-when-wrapping-aro.patch deleted file mode 100644 index 2759046..0000000 --- a/SOURCES/mdadm-3.4-Change-behavior-in-find_free_devnm-when-wrapping-aro.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 2e466cce45ac2397ea426a765c829c621901664b Mon Sep 17 00:00:00 2001 -From: Mike Lovell -Date: Wed, 18 May 2016 12:23:14 -0600 -Subject: [PATCH 2/2] Change behavior in find_free_devnm when wrapping around. - -Newer kernels don't allow for specifying an array larger than 511. This -makes it so find_free_devnm wraps to 511 instead of 2^20 - 1. - -Signed-off-by: Mike Lovell -Signed-off-by: Jes Sorensen ---- - mdopen.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/mdopen.c b/mdopen.c -index e71d758..f818fdf 100644 ---- a/mdopen.c -+++ b/mdopen.c -@@ -439,7 +439,7 @@ char *find_free_devnm(int use_partitions) - static char devnm[32]; - int devnum; - for (devnum = 127; devnum != 128; -- devnum = devnum ? devnum-1 : (1<<20)-1) { -+ devnum = devnum ? devnum-1 : (1<<9)-1) { - - if (use_partitions) - sprintf(devnm, "md_d%d", devnum); --- -2.7.4 - diff --git a/SOURCES/mdadm-3.4-Grow_continue_command-remove-dead-code.patch b/SOURCES/mdadm-3.4-Grow_continue_command-remove-dead-code.patch deleted file mode 100644 index 5210d47..0000000 --- a/SOURCES/mdadm-3.4-Grow_continue_command-remove-dead-code.patch +++ /dev/null @@ -1,51 +0,0 @@ -commit 12add44564f195878c3e346e4bbae845dec67db3 -Author: Jes Sorensen -Date: Fri Mar 4 16:30:22 2016 -0500 - - Grow: Grow_continue_command() remove dead code - - All cases where fd2 is used are completed with a close(fd2), so there - is no need to set fd2 = -1 or check for it before exiting. - - Reviewed-by: NeilBrown - Signed-off-by: Jes Sorensen - -diff --git a/Grow.c b/Grow.c -index c4f417e..c4af5c0 100755 ---- a/Grow.c -+++ b/Grow.c -@@ -4752,7 +4752,7 @@ int Grow_continue_command(char *devname, int fd, - struct mdinfo *cc = NULL; - struct mdstat_ent *mdstat = NULL; - int cfd = -1; -- int fd2 = -1; -+ int fd2; - - dprintf("Grow continue from command line called for %s\n", - devname); -@@ -4796,8 +4796,6 @@ int Grow_continue_command(char *devname, int fd, - continue; - err = st->ss->load_super(st, fd2, NULL); - close(fd2); -- /* invalidate fd2 to avoid possible double close() */ -- fd2 = -1; - if (err) - continue; - break; -@@ -4894,7 +4892,6 @@ int Grow_continue_command(char *devname, int fd, - sysfs_init(content, fd2, mdstat->devnm); - - close(fd2); -- fd2 = -1; - - /* start mdmon in case it is not running - */ -@@ -4924,8 +4921,6 @@ int Grow_continue_command(char *devname, int fd, - ret_val = Grow_continue(fd, st, content, backup_file, 1, 0); - - Grow_continue_command_exit: -- if (fd2 > -1) -- close(fd2); - if (cfd > -1) - close(cfd); - st->ss->free_super(st); diff --git a/SOURCES/mdadm-3.4-IMSM-retry-reading-sync_completed-during-reshape.patch b/SOURCES/mdadm-3.4-IMSM-retry-reading-sync_completed-during-reshape.patch deleted file mode 100644 index a3dd86e..0000000 --- a/SOURCES/mdadm-3.4-IMSM-retry-reading-sync_completed-during-reshape.patch +++ /dev/null @@ -1,56 +0,0 @@ -From df2647fa5bbe84960dae11531e34bafef549b8ff Mon Sep 17 00:00:00 2001 -From: Pawel Baldysiak -Date: Tue, 17 May 2016 13:24:41 +0200 -Subject: [PATCH] IMSM: retry reading sync_completed during reshape - -The sync_completed after restarting a reshape -(for example - after reboot) is set to "delayed" until -mdmon changes the state. Mdadm does not wait for that change with -old kernels. If this condition occurs - it exits and reshape -is not continuing. This patch adds retry of reading sync_complete -with a delay. It gives time for mdmon to change the "delayed" state. - -Signed-off-by: Pawel Baldysiak -Signed-off-by: Jes Sorensen ---- - super-intel.c | 17 ++++++++++++----- - 1 file changed, 12 insertions(+), 5 deletions(-) - -diff --git a/super-intel.c b/super-intel.c -index ba3ee48..7e2860c 100644 ---- a/super-intel.c -+++ b/super-intel.c -@@ -10378,6 +10378,7 @@ exit_imsm_reshape_super: - int wait_for_reshape_imsm(struct mdinfo *sra, int ndata) - { - int fd = sysfs_get_fd(sra, NULL, "sync_completed"); -+ int retry = 3; - unsigned long long completed; - /* to_complete : new sync_max position */ - unsigned long long to_complete = sra->reshape_progress; -@@ -10388,11 +10389,17 @@ int wait_for_reshape_imsm(struct mdinfo *sra, int ndata) - return 1; - } - -- if (sysfs_fd_get_ll(fd, &completed) < 0) { -- dprintf("cannot read reshape_position (no reshape in progres)\n"); -- close(fd); -- return 1; -- } -+ do { -+ if (sysfs_fd_get_ll(fd, &completed) < 0) { -+ if (!retry) { -+ dprintf("cannot read reshape_position (no reshape in progres)\n"); -+ close(fd); -+ return 1; -+ } -+ usleep(30000); -+ } else -+ break; -+ } while (retry--); - - if (completed > position_to_set) { - dprintf("wrong next position to set %llu (%llu)\n", --- -2.5.5 - diff --git a/SOURCES/mdadm-3.4-The-sys_name-array-in-the-mdinfo-structure-is-20-byt.patch b/SOURCES/mdadm-3.4-The-sys_name-array-in-the-mdinfo-structure-is-20-byt.patch deleted file mode 100644 index 91d89d6..0000000 --- a/SOURCES/mdadm-3.4-The-sys_name-array-in-the-mdinfo-structure-is-20-byt.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 6e6e98746dba7e900f23e92bbb0da01fe7a169da Mon Sep 17 00:00:00 2001 -From: Nikhil Kshirsagar -Date: Fri, 10 Jun 2016 08:50:10 +0530 -Subject: [PATCH] The sys_name array in the mdinfo structure is 20 bytes of - storage. - -Increasing the size of this array to 32 bytes to handle cases with -longer device names. - -Signed-off-by: Nikhil Kshirsagar -Signed-off-by: Jes Sorensen ---- - mdadm.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/mdadm.h b/mdadm.h -index 3d6c638..1fd38a3 100755 ---- a/mdadm.h -+++ b/mdadm.h -@@ -289,7 +289,7 @@ struct mdinfo { - int container_enough; /* flag external handlers can set to - * indicate that subarrays have not enough (-1), - * enough to start (0), or all expected disks (1) */ -- char sys_name[20]; -+ char sys_name[32]; - struct mdinfo *devs; - struct mdinfo *next; - --- -2.5.5 - diff --git a/SOURCES/mdadm-3.4-Use-dev_t-for-devnm2devid-and-devid2devnm.patch b/SOURCES/mdadm-3.4-Use-dev_t-for-devnm2devid-and-devid2devnm.patch deleted file mode 100644 index 946f19a..0000000 --- a/SOURCES/mdadm-3.4-Use-dev_t-for-devnm2devid-and-devid2devnm.patch +++ /dev/null @@ -1,163 +0,0 @@ -From 13db17bd1fcd68b5e5618fcd051ff4137f1ea413 Mon Sep 17 00:00:00 2001 -From: Mike Lovell -Date: Wed, 18 May 2016 12:23:13 -0600 -Subject: [PATCH 1/2] Use dev_t for devnm2devid and devid2devnm - -Commit 4dd2df0966ec added a trip through makedev(), major(), and minor() for -device major and minor numbers. This would cause mdadm to fail in operating -on a device with a minor number bigger than (2^19)-1 due to it changing -from dev_t to a signed int and back. - -Where this was found as a problem was when a array was created with a device -specified as a name like /dev/md/raidname and there were already 128 arrays -on the system. In this case, mdadm would chose 1048575 ((2^20)-1) for the -array and minor number. This would cause the major and minor number to become -negative when generated from devnm2devid() and passed to major() and minor() -in open_dev_excl(). open_dev_excl() would then call dev_open() which would -detect the negative minor number and call open() on the *char containing the -major:minor pair which isn't a valid file. - -Signed-off-by: Mike Lovell -Signed-off-by: Jes Sorensen ---- - Detail.c | 4 ++-- - Grow.c | 2 +- - lib.c | 2 +- - mapfile.c | 2 +- - mdadm.h | 4 ++-- - mdopen.c | 4 ++-- - util.c | 6 +++--- - 7 files changed, 12 insertions(+), 12 deletions(-) - -diff --git a/Detail.c b/Detail.c -index 20c4553..7a984c8 100644 ---- a/Detail.c -+++ b/Detail.c -@@ -130,7 +130,7 @@ int Detail(char *dev, struct context *c) - /* This is a subarray of some container. - * We want the name of the container, and the member - */ -- int devid = devnm2devid(st->container_devnm); -+ dev_t devid = devnm2devid(st->container_devnm); - int cfd, err; - - member = subarray; -@@ -577,7 +577,7 @@ This is pretty boring - char path[200]; - char vbuf[1024]; - int nlen = strlen(sra->sys_name); -- int devid; -+ dev_t devid; - if (de->d_name[0] == '.') - continue; - sprintf(path, "/sys/block/%s/md/metadata_version", -diff --git a/Grow.c b/Grow.c -index 98b0fab..f184d9c 100755 ---- a/Grow.c -+++ b/Grow.c -@@ -3533,7 +3533,7 @@ int reshape_container(char *container, char *devname, - int fd; - struct mdstat_ent *mdstat; - char *adev; -- int devid; -+ dev_t devid; - - sysfs_free(cc); - -diff --git a/lib.c b/lib.c -index 621edf3..3ee7659 100644 ---- a/lib.c -+++ b/lib.c -@@ -99,7 +99,7 @@ char *fd2kname(int fd) - return NULL; - } - --char *devid2devnm(int devid) -+char *devid2devnm(dev_t devid) - { - char path[30]; - char link[200]; -diff --git a/mapfile.c b/mapfile.c -index 243ded1..c89d403 100644 ---- a/mapfile.c -+++ b/mapfile.c -@@ -374,7 +374,7 @@ void RebuildMap(void) - char dn[30]; - int dfd; - int ok; -- int devid; -+ dev_t devid; - struct supertype *st; - char *subarray = NULL; - char *path; -diff --git a/mdadm.h b/mdadm.h -index b870585..3d6c638 100755 ---- a/mdadm.h -+++ b/mdadm.h -@@ -1440,8 +1440,8 @@ extern char *find_free_devnm(int use_partitions); - - extern void put_md_name(char *name); - extern char *devid2kname(int devid); --extern char *devid2devnm(int devid); --extern int devnm2devid(char *devnm); -+extern char *devid2devnm(dev_t devid); -+extern dev_t devnm2devid(char *devnm); - extern char *get_md_name(char *devnm); - - extern char DefaultConfFile[]; -diff --git a/mdopen.c b/mdopen.c -index 28410f4..e71d758 100644 ---- a/mdopen.c -+++ b/mdopen.c -@@ -348,7 +348,7 @@ int create_mddev(char *dev, char *name, int autof, int trustworthy, - if (lstat(devname, &stb) == 0) { - /* Must be the correct device, else error */ - if ((stb.st_mode&S_IFMT) != S_IFBLK || -- stb.st_rdev != (dev_t)devnm2devid(devnm)) { -+ stb.st_rdev != devnm2devid(devnm)) { - pr_err("%s exists but looks wrong, please fix\n", - devname); - return -1; -@@ -452,7 +452,7 @@ char *find_free_devnm(int use_partitions) - if (!use_udev()) { - /* make sure it is new to /dev too, at least as a - * non-standard */ -- int devid = devnm2devid(devnm); -+ dev_t devid = devnm2devid(devnm); - if (devid) { - char *dn = map_dev(major(devid), - minor(devid), 0); -diff --git a/util.c b/util.c -index 2bcb81f..31c407a 100644 ---- a/util.c -+++ b/util.c -@@ -928,7 +928,7 @@ int get_data_disks(int level, int layout, int raid_disks) - return data_disks; - } - --int devnm2devid(char *devnm) -+dev_t devnm2devid(char *devnm) - { - /* First look in /sys/block/$DEVNM/dev for %d:%d - * If that fails, try parsing out a number -@@ -1065,7 +1065,7 @@ int dev_open(char *dev, int flags) - - int open_dev_flags(char *devnm, int flags) - { -- int devid; -+ dev_t devid; - char buf[20]; - - devid = devnm2devid(devnm); -@@ -1083,7 +1083,7 @@ int open_dev_excl(char *devnm) - char buf[20]; - int i; - int flags = O_RDWR; -- int devid = devnm2devid(devnm); -+ dev_t devid = devnm2devid(devnm); - long delay = 1000; - - sprintf(buf, "%d:%d", major(devid), minor(devid)); --- -2.7.4 - diff --git a/SOURCES/mdadm-3.4-check-reshape_active-more-times-before-Grow_continue.patch b/SOURCES/mdadm-3.4-check-reshape_active-more-times-before-Grow_continue.patch deleted file mode 100644 index df95841..0000000 --- a/SOURCES/mdadm-3.4-check-reshape_active-more-times-before-Grow_continue.patch +++ /dev/null @@ -1,106 +0,0 @@ -commit 8800f85381d0cd9689dee62bbbdafdb359100389 -Author: Xiao Ni -Date: Thu Jun 16 09:41:02 2016 +0800 - - MDADM:Check mdinfo->reshape_active more times before calling Grow_continue - - When reshaping a 3 drives raid5 to 4 drives raid5, there is a chance that - it can't start the reshape. If the disks are not enough to have spaces for - relocating the data_offset, it needs to call start_reshape and then run - mdadm --grow --continue by systemd. But mdadm --grow --continue fails - because it checkes that info->reshape_active is 0. - - The info->reshape_active is got from the superblock of underlying devices. - Function start_reshape write reshape to /sys/../sync_action. Before writing - latest superblock to underlying devices, mdadm --grow --continue is called. - There is a chance info->reshape_active is 0. We should wait for superblock - updating more time before calling Grow_continue. - - Signed-off-by: Xiao Ni - Signed-off-by: Jes Sorensen - -diff --git a/Grow.c b/Grow.c -index f184d9c..628f0e7 100755 ---- a/Grow.c -+++ b/Grow.c -@@ -4788,6 +4788,7 @@ int Grow_continue_command(char *devname, int fd, - dprintf("Grow continue is run for "); - if (st->ss->external == 0) { - int d; -+ int cnt = 5; - dprintf_cont("native array (%s)\n", devname); - if (ioctl(fd, GET_ARRAY_INFO, &array.array) < 0) { - pr_err("%s is not an active md array - aborting\n", devname); -@@ -4799,36 +4800,42 @@ int Grow_continue_command(char *devname, int fd, - * FIXME we should really get what we need from - * sysfs - */ -- for (d = 0; d < MAX_DISKS; d++) { -- mdu_disk_info_t disk; -- char *dv; -- int err; -- disk.number = d; -- if (ioctl(fd, GET_DISK_INFO, &disk) < 0) -- continue; -- if (disk.major == 0 && disk.minor == 0) -- continue; -- if ((disk.state & (1 << MD_DISK_ACTIVE)) == 0) -- continue; -- dv = map_dev(disk.major, disk.minor, 1); -- if (!dv) -- continue; -- fd2 = dev_open(dv, O_RDONLY); -- if (fd2 < 0) -- continue; -- err = st->ss->load_super(st, fd2, NULL); -- close(fd2); -- if (err) -- continue; -- break; -- } -- if (d == MAX_DISKS) { -- pr_err("Unable to load metadata for %s\n", -- devname); -- ret_val = 1; -- goto Grow_continue_command_exit; -- } -- st->ss->getinfo_super(st, content, NULL); -+ do { -+ for (d = 0; d < MAX_DISKS; d++) { -+ mdu_disk_info_t disk; -+ char *dv; -+ int err; -+ disk.number = d; -+ if (ioctl(fd, GET_DISK_INFO, &disk) < 0) -+ continue; -+ if (disk.major == 0 && disk.minor == 0) -+ continue; -+ if ((disk.state & (1 << MD_DISK_ACTIVE)) == 0) -+ continue; -+ dv = map_dev(disk.major, disk.minor, 1); -+ if (!dv) -+ continue; -+ fd2 = dev_open(dv, O_RDONLY); -+ if (fd2 < 0) -+ continue; -+ err = st->ss->load_super(st, fd2, NULL); -+ close(fd2); -+ if (err) -+ continue; -+ break; -+ } -+ if (d == MAX_DISKS) { -+ pr_err("Unable to load metadata for %s\n", -+ devname); -+ ret_val = 1; -+ goto Grow_continue_command_exit; -+ } -+ st->ss->getinfo_super(st, content, NULL); -+ if (!content->reshape_active) -+ sleep(3); -+ else -+ break; -+ } while (cnt-- > 0); - } else { - char *container; - diff --git a/SOURCES/mdadm-3.4-disable-journal.patch b/SOURCES/mdadm-3.4-disable-journal.patch deleted file mode 100644 index 0599820..0000000 --- a/SOURCES/mdadm-3.4-disable-journal.patch +++ /dev/null @@ -1,32 +0,0 @@ ---- mdadm-3.4/ReadMe.c~ 2016-01-28 01:14:56.000000000 -0500 -+++ mdadm-3.4/ReadMe.c 2016-08-05 10:09:15.412366777 -0400 -@@ -142,7 +142,9 @@ - {"data-offset",1, 0, DataOffset}, - {"nodes",1, 0, Nodes}, /* also for --assemble */ - {"home-cluster",1, 0, ClusterName}, -+#if 0 /* Disable for RHEL */ - {"write-journal",1, 0, WriteJournal}, -+#endif - - /* For assemble */ - {"uuid", 1, 0, 'u'}, -@@ -157,7 +159,9 @@ - /* Management */ - {"add", 0, 0, Add}, - {"add-spare", 0, 0, AddSpare}, -+#if 0 /* Disable for RHEL */ - {"add-journal", 0, 0, AddJournal}, -+#endif - {"remove", 0, 0, Remove}, - {"fail", 0, 0, Fail}, - {"set-faulty",0, 0, Fail}, -@@ -377,7 +381,9 @@ - " --name= -N : Textual name for array - max 32 characters\n" - " --bitmap-chunk= : bitmap chunksize in Kilobytes.\n" - " --delay= -d : bitmap update delay in seconds.\n" -+#if 0 /* Disable for RHEL */ - " --write-journal= : Specify journal device for RAID-4/5/6 array\n" -+#endif - "\n" - ; - diff --git a/SOURCES/mdadm-3.4-imsm-add-handling-of-sync_action-is-equal-to-idle.patch b/SOURCES/mdadm-3.4-imsm-add-handling-of-sync_action-is-equal-to-idle.patch deleted file mode 100644 index a6e801c..0000000 --- a/SOURCES/mdadm-3.4-imsm-add-handling-of-sync_action-is-equal-to-idle.patch +++ /dev/null @@ -1,42 +0,0 @@ -From b2be2b628b6305712c8df0b3a20ddddc0ac410fb Mon Sep 17 00:00:00 2001 -From: Alexey Obitotskiy -Date: Thu, 16 Jun 2016 11:31:36 +0200 -Subject: [PATCH 1/2] imsm: add handling of sync_action is equal to 'idle' - -After resync is stopped sync_action value become 'idle'. -We treat this case as normal termination of waiting, not as error. - -Signed-off-by: Alexey Obitotskiy -Reviewed-by: Pawel Baldysiak -Signed-off-by: Jes Sorensen ---- - super-intel.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/super-intel.c b/super-intel.c -index 7e2860c..7950bef 100644 ---- a/super-intel.c -+++ b/super-intel.c -@@ -10423,6 +10423,8 @@ int wait_for_reshape_imsm(struct mdinfo *sra, int ndata) - if (sysfs_get_str(sra, NULL, "sync_action", - action, 20) > 0 && - strncmp(action, "reshape", 7) != 0) { -+ if (strncmp(action, "idle", 4) == 0) -+ break; - close(fd); - return -1; - } -@@ -10432,9 +10434,9 @@ int wait_for_reshape_imsm(struct mdinfo *sra, int ndata) - return 1; - } - } while (completed < position_to_set); -+ - close(fd); - return 0; -- - } - - /******************************************************************************* --- -2.5.5 - diff --git a/SOURCES/mdadm-3.4-imsm-properly-handle-values-of-sync_completed.patch b/SOURCES/mdadm-3.4-imsm-properly-handle-values-of-sync_completed.patch deleted file mode 100644 index 182a211..0000000 --- a/SOURCES/mdadm-3.4-imsm-properly-handle-values-of-sync_completed.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0febb20c458a488460eadade74a6c283aadaf96a Mon Sep 17 00:00:00 2001 -From: Alexey Obitotskiy -Date: Thu, 16 Jun 2016 11:31:37 +0200 -Subject: [PATCH 2/2] imsm: properly handle values of sync_completed - -The sync_completed can be set to such values: -- two numbers of processed sectors and total during synchronization, -separated with '/'; -- 'none' if synchronization process is stopped; -- 'delayed' if synchronization process is delayed. -Handle value of sync_completed not only as numbers but -also check for 'none' and 'delayed'. - -Signed-off-by: Alexey Obitotskiy -Reviewed-by: Pawel Baldysiak -Signed-off-by: Jes Sorensen ---- - super-intel.c | 36 ++++++++++++++++++++++++++++++++++-- - 1 file changed, 34 insertions(+), 2 deletions(-) - -diff --git a/super-intel.c b/super-intel.c -index 7950bef..92817e9 100644 ---- a/super-intel.c -+++ b/super-intel.c -@@ -10363,6 +10363,33 @@ exit_imsm_reshape_super: - return ret_val; - } - -+#define COMPLETED_OK 0 -+#define COMPLETED_NONE 1 -+#define COMPLETED_DELAYED 2 -+ -+static int read_completed(int fd, unsigned long long *val) -+{ -+ int ret; -+ char buf[50]; -+ -+ ret = sysfs_fd_get_str(fd, buf, 50); -+ if (ret < 0) -+ return ret; -+ -+ ret = COMPLETED_OK; -+ if (strncmp(buf, "none", 4) == 0) { -+ ret = COMPLETED_NONE; -+ } else if (strncmp(buf, "delayed", 7) == 0) { -+ ret = COMPLETED_DELAYED; -+ } else { -+ char *ep; -+ *val = strtoull(buf, &ep, 0); -+ if (ep == buf || (*ep != 0 && *ep != '\n' && *ep != ' ')) -+ ret = -1; -+ } -+ return ret; -+} -+ - /******************************************************************************* - * Function: wait_for_reshape_imsm - * Description: Function writes new sync_max value and waits until -@@ -10417,8 +10444,10 @@ int wait_for_reshape_imsm(struct mdinfo *sra, int ndata) - } - - do { -+ int rc; - char action[20]; - int timeout = 3000; -+ - sysfs_wait(fd, &timeout); - if (sysfs_get_str(sra, NULL, "sync_action", - action, 20) > 0 && -@@ -10428,11 +10457,14 @@ int wait_for_reshape_imsm(struct mdinfo *sra, int ndata) - close(fd); - return -1; - } -- if (sysfs_fd_get_ll(fd, &completed) < 0) { -+ -+ rc = read_completed(fd, &completed); -+ if (rc < 0) { - dprintf("cannot read reshape_position (in loop)\n"); - close(fd); - return 1; -- } -+ } else if (rc == COMPLETED_NONE) -+ break; - } while (completed < position_to_set); - - close(fd); --- -2.5.5 - diff --git a/SOURCES/mdadm-3.4-mdopen-Prevent-overrunning-the-devname-buffer-when-c.patch b/SOURCES/mdadm-3.4-mdopen-Prevent-overrunning-the-devname-buffer-when-c.patch deleted file mode 100644 index 72e6fbb..0000000 --- a/SOURCES/mdadm-3.4-mdopen-Prevent-overrunning-the-devname-buffer-when-c.patch +++ /dev/null @@ -1,33 +0,0 @@ -From bd1fd72e13652416da4c646ea47549fcfdf49b26 Mon Sep 17 00:00:00 2001 -From: Robert LeBlanc -Date: Wed, 24 Aug 2016 10:10:44 -0600 -Subject: [PATCH] mdopen: Prevent overrunning the devname buffer when copying - devnm into it for long md names. - -Linux allows for 32 character device names. When using the maximum -size device name and also storing "/dev/", devname needs to be 37 -character long to store the complete device name. -i.e. "/dev/md_abcdefghijklmnopqrstuvwxyz12\0" - -Signed-off-by: Robert LeBlanc -Signed-off-by: Jes Sorensen ---- - mdopen.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/mdopen.c b/mdopen.c -index f818fdf..5af344b 100644 ---- a/mdopen.c -+++ b/mdopen.c -@@ -144,7 +144,7 @@ int create_mddev(char *dev, char *name, int autof, int trustworthy, - struct createinfo *ci = conf_get_create_info(); - int parts; - char *cname; -- char devname[20]; -+ char devname[37]; - char devnm[32]; - char cbuf[400]; - if (chosen == NULL) --- -2.7.4 - diff --git a/SOURCES/mdadm-3.4-monitor-Make-sure-that-last_checkpoint-is-set-to-0-a.patch b/SOURCES/mdadm-3.4-monitor-Make-sure-that-last_checkpoint-is-set-to-0-a.patch deleted file mode 100644 index 4199a1c..0000000 --- a/SOURCES/mdadm-3.4-monitor-Make-sure-that-last_checkpoint-is-set-to-0-a.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 955aa6cf75a5f8a6def83189a839c5b75d5ecff9 Mon Sep 17 00:00:00 2001 -From: Pawel Baldysiak -Date: Thu, 16 Jun 2016 11:12:20 +0200 -Subject: [PATCH] monitor: Make sure that last_checkpoint is set to 0 after - sync - -In a case of successful completion of a resync (in the last step) -- read_and_act sometimes still reads sync_action as "resync" -but sync_completed already is set to component_size. -When this race occurs, sync operation is -marked as finished, but last_checkpoint is -overwritten with sync_completed. It will cause next -sync operation (ie. reshape) to be reported as complete immediately -after start - mdmon will write successful completion of the reshape -to metadata. This patch sets last_checkpoint to 0 once the sync -is completed to stop it happening. - -Signed-off-by: Pawel Baldysiak -Signed-off-by: Jes Sorensen ---- - monitor.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/monitor.c b/monitor.c -index 870cc1a..4c79ce2 100644 ---- a/monitor.c -+++ b/monitor.c -@@ -420,6 +420,9 @@ static int read_and_act(struct active_array *a) - if (sync_completed > a->last_checkpoint) - a->last_checkpoint = sync_completed; - -+ if (sync_completed >= a->info.component_size) -+ a->last_checkpoint = 0; -+ - a->container->ss->sync_metadata(a->container); - dprintf("(%d): state:%s action:%s next(", a->info.container_member, - array_states[a->curr_state], sync_actions[a->curr_action]); --- -2.7.4 - diff --git a/SOURCES/mdadm-3.4-super-intel-ensure-suspended-region-is-removed-when-.patch b/SOURCES/mdadm-3.4-super-intel-ensure-suspended-region-is-removed-when-.patch deleted file mode 100644 index 3c52825..0000000 --- a/SOURCES/mdadm-3.4-super-intel-ensure-suspended-region-is-removed-when-.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 942e1cdb4a6a5be02672bc686169c679e775c2be Mon Sep 17 00:00:00 2001 -From: NeilBrown -Date: Thu, 18 Feb 2016 15:53:32 +1100 -Subject: [PATCH] super-intel: ensure suspended region is removed when reshape - completes. - -A recent commit removed a call to abort_reshape() when IMSM reshape -completed. An unanticipated result of this is that the suspended -region is not cleared as it should be. -So after a reshape, a region of the array will cause all IO to block. - -Re-instate the required updates to suspend_{lo,hi} coped from -abort_reshape(). - -This is caught (sometimes) by the test suite. - -Also fix a couple of typos found while exploring the code. - -Reported-by: Ken Moffat -Cc: Artur Paszkiewicz -Fixes: 2139b03c2080 ("imsm: don't call abort_reshape() in imsm_manage_reshape()") -Signed-off-by: NeilBrown -Signed-off-by: Jes Sorensen ---- - super-intel.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/super-intel.c b/super-intel.c -index 90b7b6d..ff0506d 100644 ---- a/super-intel.c -+++ b/super-intel.c -@@ -10465,7 +10465,7 @@ int check_degradation_change(struct mdinfo *info, - * Function: imsm_manage_reshape - * Description: Function finds array under reshape and it manages reshape - * process. It creates stripes backups (if required) and sets -- * checheckpoits. -+ * checkpoints. - * Parameters: - * afd : Backup handle (nattive) - not used - * sra : general array info -@@ -10595,7 +10595,7 @@ static int imsm_manage_reshape( - - start = current_position * 512; - -- /* allign reading start to old geometry */ -+ /* align reading start to old geometry */ - start_buf_shift = start % old_data_stripe_length; - start_src = start - start_buf_shift; - -@@ -10700,6 +10700,10 @@ static int imsm_manage_reshape( - ret_val = 1; - abort: - free(buf); -+ /* See Grow.c: abort_reshape() for further explanation */ -+ sysfs_set_num(sra, NULL, "suspend_lo", 0x7FFFFFFFFFFFFFFFULL); -+ sysfs_set_num(sra, NULL, "suspend_hi", 0); -+ sysfs_set_num(sra, NULL, "suspend_lo", 0); - - return ret_val; - } --- -2.5.0 - diff --git a/SOURCES/mdadm-3.4-super1-Clear-memory-allocated-for-superblock-bitmap-.patch b/SOURCES/mdadm-3.4-super1-Clear-memory-allocated-for-superblock-bitmap-.patch deleted file mode 100644 index 65ba514..0000000 --- a/SOURCES/mdadm-3.4-super1-Clear-memory-allocated-for-superblock-bitmap-.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 1dcee1c9cbcf9592275914706b76b1931490092c Mon Sep 17 00:00:00 2001 -From: Jes Sorensen -Date: Wed, 6 Apr 2016 16:13:59 -0400 -Subject: [PATCH] super1: Clear memory allocated for superblock + bitmap before - use - -load_super1() did not clear memory allocated for the superblock + -bitmap. This causes issues if the superblock does not contain a bitmap -as later checks of bitmap features would rely on the bits being -cleared. - -This bug has been around for a long time, but was only exposed in -mdadm-3.4 with the introduction of the clustering code. - -Reported-by: Jan Stodola -Signed-off-by: Jes Sorensen ---- - super1.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/super1.c b/super1.c -index d6f3c93..8d5543f 100644 ---- a/super1.c -+++ b/super1.c -@@ -2016,6 +2016,8 @@ static int load_super1(struct supertype *st, int fd, char *devname) - return 1; - } - -+ memset(super, 0, SUPER1_SIZE); -+ - if (aread(&afd, super, MAX_SB_SIZE) != MAX_SB_SIZE) { - if (devname) - pr_err("Cannot read superblock on %s\n", --- -2.5.5 - diff --git a/SOURCES/mdadm-3.4.1-fix-some-type-comparison.patch b/SOURCES/mdadm-3.4.1-fix-some-type-comparison.patch deleted file mode 100644 index 39a6d37..0000000 --- a/SOURCES/mdadm-3.4.1-fix-some-type-comparison.patch +++ /dev/null @@ -1,41 +0,0 @@ -commit 1d13b599607e48446273913ce594931ba53df9fd -Author: Xiao Ni -Date: Sat Feb 6 09:18:41 2016 +0800 - - Fix some type comparison problems - - As 26714713cd2bad9e0bf7f4669f6cc4659ceaab6c said, 32 bit signed - timestamps will overflow in the year 2038. It already changed the - utime and ctime in struct mdu_array_info_s from int to unsigned - int. So we need to change the values that compared with them to - unsigned int too. - - Signed-off-by : Xiao Ni - Signed-off-by: Jes Sorensen - -diff --git a/Monitor.c b/Monitor.c -index f19c2e5..6df80f9 100644 ---- a/Monitor.c -+++ b/Monitor.c -@@ -33,7 +33,7 @@ - struct state { - char *devname; - char devnm[32]; /* to sync with mdstat info */ -- long utime; -+ unsigned int utime; - int err; - char *spare_group; - int active, working, failed, spare, raid; -diff --git a/util.c b/util.c -index 970d484..6e7d3fb 100644 ---- a/util.c -+++ b/util.c -@@ -1267,7 +1267,7 @@ struct supertype *guess_super_type(int fd, enum guess_types guess_type) - */ - struct superswitch *ss; - struct supertype *st; -- time_t besttime = 0; -+ unsigned int besttime = 0; - int bestsuper = -1; - int i; - diff --git a/SOURCES/specify-enough-length-when-write-to-buffer.patch b/SOURCES/specify-enough-length-when-write-to-buffer.patch new file mode 100644 index 0000000..c67169c --- /dev/null +++ b/SOURCES/specify-enough-length-when-write-to-buffer.patch @@ -0,0 +1,74 @@ +From ff9239ee3177630d62c7a58408992af7a779763c Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Fri, 17 Mar 2017 19:55:43 +0800 +Subject: [RHEL6.9 PATCH 1/1] mdadm: Specify enough length when write to buffer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In Detail.c the buffer path in function Detail is defined as path[200], +in fact the max lenth of content which needs to write to the buffer is +287. Because the length of dname of struct dirent is 255. +During building it reports error: +error: ā€˜%sā€™ directive writing up to 255 bytes into a region of size 189 +[-Werror=format-overflow=] + +In function examine_super0 there is a buffer nb with length 5. +But it need to show a int type argument. The lenght of max +number of int is 10. So the buffer length should be 11. + +In human_size function the length of buf is 30. During building +there is a error: +output between 20 and 47 bytes into a destination of size 30. +Change the length to 47. + +Signed-off-by: Xiao Ni +Signed-off-by: Jes Sorensen +--- + Detail.c | 2 +- + super0.c | 2 +- + util.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/Detail.c b/Detail.c +index 509b0d4..cb33794 100644 +--- a/Detail.c ++++ b/Detail.c +@@ -575,7 +575,7 @@ This is pretty boring + printf(" Member Arrays :"); + + while (dir && (de = readdir(dir)) != NULL) { +- char path[200]; ++ char path[287]; + char vbuf[1024]; + int nlen = strlen(sra->sys_name); + dev_t devid; +diff --git a/super0.c b/super0.c +index 938cfd9..f5b4507 100644 +--- a/super0.c ++++ b/super0.c +@@ -231,7 +231,7 @@ static void examine_super0(struct supertype *st, char *homehost) + d++) { + mdp_disk_t *dp; + char *dv; +- char nb[5]; ++ char nb[11]; + int wonly, failfast; + if (d>=0) dp = &sb->disks[d]; + else dp = &sb->this_disk; +diff --git a/util.c b/util.c +index f100972..32bd909 100644 +--- a/util.c ++++ b/util.c +@@ -811,7 +811,7 @@ unsigned long calc_csum(void *super, int bytes) + #ifndef MDASSEMBLE + char *human_size(long long bytes) + { +- static char buf[30]; ++ static char buf[47]; + + /* We convert bytes to either centi-M{ega,ibi}bytes or + * centi-G{igi,ibi}bytes, with appropriate rounding, +-- +2.7.4 + diff --git a/SOURCES/super1-ppl-support.patch b/SOURCES/super1-ppl-support.patch new file mode 100644 index 0000000..665387d --- /dev/null +++ b/SOURCES/super1-ppl-support.patch @@ -0,0 +1,430 @@ +commit e97a7cd011345e5dead736de51b33968da49d876 +Author: Artur Paszkiewicz +Date: Wed Mar 29 11:54:18 2017 +0200 + + super1: PPL support + + Enable creating and assembling raid5 arrays with PPL for 1.x metadata. + + When creating, reserve enough space for PPL and store its size and + location in the superblock and set MD_FEATURE_PPL bit. Write an initial + empty header in the PPL area on each device. PPL is stored in the + metadata region reserved for internal write-intent bitmap, so don't + allow using bitmap and PPL together. + + While at it, fix two endianness issues in write_empty_r5l_meta_block() + and write_init_super1(). + + Signed-off-by: Artur Paszkiewicz + Signed-off-by: Jes Sorensen + +diff --git a/Assemble.c b/Assemble.c +index 8e55b49..c098420 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -962,6 +962,9 @@ static int start_array(int mdfd, + c->readonly = 1; + } + ++ if (content->consistency_policy == CONSISTENCY_POLICY_PPL) ++ clean = 1; ++ + rv = set_array_info(mdfd, st, content); + if (rv && !err_ok) { + pr_err("failed to set array info for %s: %s\n", +diff --git a/Create.c b/Create.c +index 4080bf6..10e7d10 100644 +--- a/Create.c ++++ b/Create.c +@@ -524,6 +524,8 @@ int Create(struct supertype *st, char *mddev, + if (!s->bitmap_file && + s->level >= 1 && + st->ss->add_internal_bitmap && ++ (s->consistency_policy != CONSISTENCY_POLICY_RESYNC && ++ s->consistency_policy != CONSISTENCY_POLICY_PPL) && + (s->write_behind || s->size > 100*1024*1024ULL)) { + if (c->verbose > 0) + pr_err("automatically enabling write-intent bitmap on large array\n"); +diff --git a/Grow.c b/Grow.c +index e22661c..a849012 100755 +--- a/Grow.c ++++ b/Grow.c +@@ -290,6 +290,7 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s) + int major = BITMAP_MAJOR_HI; + int vers = md_get_version(fd); + unsigned long long bitmapsize, array_size; ++ struct mdinfo *mdi; + + if (vers < 9003) { + major = BITMAP_MAJOR_HOSTENDIAN; +@@ -389,12 +390,23 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s) + free(st); + return 1; + } ++ ++ mdi = sysfs_read(fd, NULL, GET_CONSISTENCY_POLICY); ++ if (mdi) { ++ if (mdi->consistency_policy == CONSISTENCY_POLICY_PPL) { ++ pr_err("Cannot add bitmap to array with PPL\n"); ++ free(mdi); ++ free(st); ++ return 1; ++ } ++ free(mdi); ++ } ++ + if (strcmp(s->bitmap_file, "internal") == 0 || + strcmp(s->bitmap_file, "clustered") == 0) { + int rv; + int d; + int offset_setable = 0; +- struct mdinfo *mdi; + if (st->ss->add_internal_bitmap == NULL) { + pr_err("Internal bitmaps not supported with %s metadata\n", st->ss->name); + return 1; +@@ -446,6 +458,7 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s) + sysfs_init(mdi, fd, NULL); + rv = sysfs_set_num_signed(mdi, NULL, "bitmap/location", + mdi->bitmap_offset); ++ free(mdi); + } else { + if (strcmp(s->bitmap_file, "clustered") == 0) + array.state |= (1 << MD_SB_CLUSTERED); +diff --git a/Incremental.c b/Incremental.c +index 0f507bb..81afc7e 100644 +--- a/Incremental.c ++++ b/Incremental.c +@@ -528,6 +528,9 @@ int Incremental(struct mddev_dev *devlist, struct context *c, + + journal_device_missing = (info.journal_device_required) && (info.journal_clean == 0); + ++ if (info.consistency_policy == CONSISTENCY_POLICY_PPL) ++ info.array.state |= 1; ++ + if (enough(info.array.level, info.array.raid_disks, + info.array.layout, info.array.state & 1, + avail) == 0) { +diff --git a/mdadm.h b/mdadm.h +index d222cc3..2c7066d 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -302,6 +302,7 @@ struct mdinfo { + long bitmap_offset; /* 0 == none, 1 == a file */ + unsigned int ppl_size; + unsigned long long ppl_sector; ++ int ppl_offset; + unsigned long safe_mode_delay; /* ms delay to mark clean */ + int new_level, delta_disks, new_layout, new_chunk; + int errors; +diff --git a/super1.c b/super1.c +index 8df17a1..409b6c3 100644 +--- a/super1.c ++++ b/super1.c +@@ -48,10 +48,18 @@ struct mdp_superblock_1 { + + __u32 chunksize; /* in 512byte sectors */ + __u32 raid_disks; +- __u32 bitmap_offset; /* sectors after start of superblock that bitmap starts +- * NOTE: signed, so bitmap can be before superblock +- * only meaningful of feature_map[0] is set. +- */ ++ union { ++ __u32 bitmap_offset; /* sectors after start of superblock that bitmap starts ++ * NOTE: signed, so bitmap can be before superblock ++ * only meaningful of feature_map[0] is set. ++ */ ++ ++ /* only meaningful when feature_map[MD_FEATURE_PPL] is set */ ++ struct { ++ __s16 offset; /* sectors from start of superblock that ppl starts */ ++ __u16 size; /* ppl size in sectors */ ++ } ppl; ++ }; + + /* These are only valid with feature bit '4' */ + __u32 new_level; /* new level we are reshaping to */ +@@ -131,6 +139,7 @@ struct misc_dev_info { + #define MD_FEATURE_NEW_OFFSET 64 /* new_offset must be honoured */ + #define MD_FEATURE_BITMAP_VERSIONED 256 /* bitmap version number checked properly */ + #define MD_FEATURE_JOURNAL 512 /* support write journal */ ++#define MD_FEATURE_PPL 1024 /* support PPL */ + #define MD_FEATURE_ALL (MD_FEATURE_BITMAP_OFFSET \ + |MD_FEATURE_RECOVERY_OFFSET \ + |MD_FEATURE_RESHAPE_ACTIVE \ +@@ -140,6 +149,7 @@ struct misc_dev_info { + |MD_FEATURE_NEW_OFFSET \ + |MD_FEATURE_BITMAP_VERSIONED \ + |MD_FEATURE_JOURNAL \ ++ |MD_FEATURE_PPL \ + ) + + #ifndef MDASSEMBLE +@@ -289,6 +299,11 @@ static int awrite(struct align_fd *afd, void *buf, int len) + return len; + } + ++static inline unsigned int choose_ppl_space(int chunk) ++{ ++ return (PPL_HEADER_SIZE >> 9) + (chunk > 128*2 ? chunk : 128*2); ++} ++ + #ifndef MDASSEMBLE + static void examine_super1(struct supertype *st, char *homehost) + { +@@ -392,6 +407,10 @@ static void examine_super1(struct supertype *st, char *homehost) + if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) { + printf("Internal Bitmap : %ld sectors from superblock\n", + (long)(int32_t)__le32_to_cpu(sb->bitmap_offset)); ++ } else if (sb->feature_map & __cpu_to_le32(MD_FEATURE_PPL)) { ++ printf(" PPL : %u sectors at offset %d sectors from superblock\n", ++ __le16_to_cpu(sb->ppl.size), ++ __le16_to_cpu(sb->ppl.offset)); + } + if (sb->feature_map & __cpu_to_le32(MD_FEATURE_RESHAPE_ACTIVE)) { + printf(" Reshape pos'n : %llu%s\n", (unsigned long long)__le64_to_cpu(sb->reshape_position)/2, +@@ -934,10 +953,16 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map) + if (__le32_to_cpu(bsb->nodes) > 1) + info->array.state |= (1 << MD_SB_CLUSTERED); + ++ super_offset = __le64_to_cpu(sb->super_offset); + info->data_offset = __le64_to_cpu(sb->data_offset); + info->component_size = __le64_to_cpu(sb->size); +- if (sb->feature_map & __le32_to_cpu(MD_FEATURE_BITMAP_OFFSET)) ++ if (sb->feature_map & __le32_to_cpu(MD_FEATURE_BITMAP_OFFSET)) { + info->bitmap_offset = (int32_t)__le32_to_cpu(sb->bitmap_offset); ++ } else if (sb->feature_map & __le32_to_cpu(MD_FEATURE_PPL)) { ++ info->ppl_offset = __le16_to_cpu(sb->ppl.offset); ++ info->ppl_size = __le16_to_cpu(sb->ppl.size); ++ info->ppl_sector = super_offset + info->ppl_offset; ++ } + + info->disk.major = 0; + info->disk.minor = 0; +@@ -948,7 +973,6 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map) + else + role = __le16_to_cpu(sb->dev_roles[__le32_to_cpu(sb->dev_number)]); + +- super_offset = __le64_to_cpu(sb->super_offset); + if (info->array.level <= 0) + data_size = __le64_to_cpu(sb->data_size); + else +@@ -965,8 +989,8 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map) + end = bboffset; + } + +- if (super_offset + info->bitmap_offset < end) +- end = super_offset + info->bitmap_offset; ++ if (super_offset + info->bitmap_offset + info->ppl_offset < end) ++ end = super_offset + info->bitmap_offset + info->ppl_offset; + + if (info->data_offset + data_size < end) + info->space_after = end - data_size - info->data_offset; +@@ -982,6 +1006,11 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map) + bmend += size; + if (bmend > earliest) + earliest = bmend; ++ } else if (info->ppl_offset > 0) { ++ unsigned long long pplend = info->ppl_offset + ++ info->ppl_size; ++ if (pplend > earliest) ++ earliest = pplend; + } + if (sb->bblog_offset && sb->bblog_size) { + unsigned long long bbend = super_offset; +@@ -1075,8 +1104,20 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map) + } + + info->array.working_disks = working; +- if (sb->feature_map & __le32_to_cpu(MD_FEATURE_JOURNAL)) ++ ++ if (sb->feature_map & __le32_to_cpu(MD_FEATURE_JOURNAL)) { + info->journal_device_required = 1; ++ info->consistency_policy = CONSISTENCY_POLICY_JOURNAL; ++ } else if (sb->feature_map & __le32_to_cpu(MD_FEATURE_PPL)) { ++ info->consistency_policy = CONSISTENCY_POLICY_PPL; ++ } else if (sb->feature_map & __le32_to_cpu(MD_FEATURE_BITMAP_OFFSET)) { ++ info->consistency_policy = CONSISTENCY_POLICY_BITMAP; ++ } else if (info->array.level <= 0) { ++ info->consistency_policy = CONSISTENCY_POLICY_NONE; ++ } else { ++ info->consistency_policy = CONSISTENCY_POLICY_RESYNC; ++ } ++ + info->journal_clean = 0; + } + +@@ -1239,6 +1280,9 @@ static int update_super1(struct supertype *st, struct mdinfo *info, + if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) { + bitmap_offset = (long)__le32_to_cpu(sb->bitmap_offset); + bm_sectors = calc_bitmap_size(bms, 4096) >> 9; ++ } else if (sb->feature_map & __cpu_to_le32(MD_FEATURE_PPL)) { ++ bitmap_offset = (long)__le16_to_cpu(sb->ppl.offset); ++ bm_sectors = (long)__le16_to_cpu(sb->ppl.size); + } + #endif + if (sb_offset < data_offset) { +@@ -1472,6 +1516,9 @@ static int init_super1(struct supertype *st, mdu_array_info_t *info, + + memset(sb->dev_roles, 0xff, MAX_SB_SIZE - sizeof(struct mdp_superblock_1)); + ++ if (s->consistency_policy == CONSISTENCY_POLICY_PPL) ++ sb->feature_map |= __cpu_to_le32(MD_FEATURE_PPL); ++ + return 1; + } + +@@ -1645,10 +1692,49 @@ static unsigned long choose_bm_space(unsigned long devsize) + + static void free_super1(struct supertype *st); + +-#define META_BLOCK_SIZE 4096 ++#ifndef MDASSEMBLE ++ + __u32 crc32c_le(__u32 crc, unsigned char const *p, size_t len); + +-#ifndef MDASSEMBLE ++static int write_init_ppl1(struct supertype *st, struct mdinfo *info, int fd) ++{ ++ struct mdp_superblock_1 *sb = st->sb; ++ void *buf; ++ struct ppl_header *ppl_hdr; ++ int ret; ++ ++ ret = posix_memalign(&buf, 4096, PPL_HEADER_SIZE); ++ if (ret) { ++ pr_err("Failed to allocate PPL header buffer\n"); ++ return ret; ++ } ++ ++ memset(buf, 0, PPL_HEADER_SIZE); ++ ppl_hdr = buf; ++ memset(ppl_hdr->reserved, 0xff, PPL_HDR_RESERVED); ++ ppl_hdr->signature = __cpu_to_le32(~crc32c_le(~0, sb->set_uuid, ++ sizeof(sb->set_uuid))); ++ ppl_hdr->checksum = __cpu_to_le32(~crc32c_le(~0, buf, PPL_HEADER_SIZE)); ++ ++ if (lseek64(fd, info->ppl_sector * 512, SEEK_SET) < 0) { ++ ret = errno; ++ perror("Failed to seek to PPL header location"); ++ } ++ ++ if (!ret && write(fd, buf, PPL_HEADER_SIZE) != PPL_HEADER_SIZE) { ++ ret = errno; ++ perror("Write PPL header failed"); ++ } ++ ++ if (!ret) ++ fsync(fd); ++ ++ free(buf); ++ return ret; ++} ++ ++#define META_BLOCK_SIZE 4096 ++ + static int write_empty_r5l_meta_block(struct supertype *st, int fd) + { + struct r5l_meta_block *mb; +@@ -1675,7 +1761,7 @@ static int write_empty_r5l_meta_block(struct supertype *st, int fd) + crc = crc32c_le(crc, (void *)mb, META_BLOCK_SIZE); + mb->checksum = crc; + +- if (lseek64(fd, (sb->data_offset) * 512, 0) < 0LL) { ++ if (lseek64(fd, __le64_to_cpu(sb->data_offset) * 512, 0) < 0LL) { + pr_err("cannot seek to offset of the meta block\n"); + goto fail_to_write; + } +@@ -1708,7 +1794,7 @@ static int write_init_super1(struct supertype *st) + + for (di = st->info; di; di = di->next) { + if (di->disk.state & (1 << MD_DISK_JOURNAL)) +- sb->feature_map |= MD_FEATURE_JOURNAL; ++ sb->feature_map |= __cpu_to_le32(MD_FEATURE_JOURNAL); + } + + for (di = st->info; di; di = di->next) { +@@ -1783,6 +1869,21 @@ static int write_init_super1(struct supertype *st) + (((char *)sb) + MAX_SB_SIZE); + bm_space = calc_bitmap_size(bms, 4096) >> 9; + bm_offset = (long)__le32_to_cpu(sb->bitmap_offset); ++ } else if (sb->feature_map & __cpu_to_le32(MD_FEATURE_PPL)) { ++ bm_space = choose_ppl_space(__le32_to_cpu(sb->chunksize)); ++ if (bm_space > UINT16_MAX) ++ bm_space = UINT16_MAX; ++ if (st->minor_version == 0) { ++ bm_offset = -bm_space - 8; ++ if (bm_offset < INT16_MIN) { ++ bm_offset = INT16_MIN; ++ bm_space = -bm_offset - 8; ++ } ++ } else { ++ bm_offset = 8; ++ } ++ sb->ppl.offset = __cpu_to_le16(bm_offset); ++ sb->ppl.size = __cpu_to_le16(bm_space); + } else { + bm_space = choose_bm_space(array_size); + bm_offset = 8; +@@ -1854,8 +1955,17 @@ static int write_init_super1(struct supertype *st) + goto error_out; + } + +- if (rv == 0 && (__le32_to_cpu(sb->feature_map) & 1)) ++ if (rv == 0 && ++ (__le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET)) { + rv = st->ss->write_bitmap(st, di->fd, NodeNumUpdate); ++ } else if (rv == 0 && ++ (__le32_to_cpu(sb->feature_map) & MD_FEATURE_PPL)) { ++ struct mdinfo info; ++ ++ st->ss->getinfo_super(st, &info, NULL); ++ rv = st->ss->write_init_ppl(st, &info, di->fd); ++ } ++ + close(di->fd); + di->fd = -1; + if (rv) +@@ -2123,11 +2233,13 @@ static __u64 avail_size1(struct supertype *st, __u64 devsize, + return 0; + + #ifndef MDASSEMBLE +- if (__le32_to_cpu(super->feature_map)&MD_FEATURE_BITMAP_OFFSET) { ++ if (__le32_to_cpu(super->feature_map) & MD_FEATURE_BITMAP_OFFSET) { + /* hot-add. allow for actual size of bitmap */ + struct bitmap_super_s *bsb; + bsb = (struct bitmap_super_s *)(((char*)super)+MAX_SB_SIZE); + bmspace = calc_bitmap_size(bsb, 4096) >> 9; ++ } else if (__le32_to_cpu(super->feature_map) & MD_FEATURE_PPL) { ++ bmspace = __le16_to_cpu(super->ppl.size); + } + #endif + /* Allow space for bad block log */ +@@ -2530,8 +2642,9 @@ static int validate_geometry1(struct supertype *st, int level, + return 0; + } + +- /* creating: allow suitable space for bitmap */ +- bmspace = choose_bm_space(devsize); ++ /* creating: allow suitable space for bitmap or PPL */ ++ bmspace = consistency_policy == CONSISTENCY_POLICY_PPL ? ++ choose_ppl_space((*chunk)*2) : choose_bm_space(devsize); + + if (data_offset == INVALID_SECTORS) + data_offset = st->data_offset; +@@ -2566,7 +2679,7 @@ static int validate_geometry1(struct supertype *st, int level, + switch(st->minor_version) { + case 0: /* metadata at end. Round down and subtract space to reserve */ + devsize = (devsize & ~(4ULL*2-1)); +- /* space for metadata, bblog, bitmap */ ++ /* space for metadata, bblog, bitmap/ppl */ + devsize -= 8*2 + 8 + bmspace; + break; + case 1: +@@ -2642,6 +2755,7 @@ struct superswitch super1 = { + .add_to_super = add_to_super1, + .examine_badblocks = examine_badblocks_super1, + .copy_metadata = copy_metadata1, ++ .write_init_ppl = write_init_ppl1, + #endif + .match_home = match_home1, + .uuid_from_super = uuid_from_super1, diff --git a/SOURCES/support-consistency-policy-change.patch b/SOURCES/support-consistency-policy-change.patch new file mode 100644 index 0000000..26861a7 --- /dev/null +++ b/SOURCES/support-consistency-policy-change.patch @@ -0,0 +1,339 @@ +commit 860f11ed4d6a7bac6f2d698a30a13371c0aa7924 +Author: Artur Paszkiewicz +Date: Wed Mar 29 11:54:20 2017 +0200 + + Grow: support consistency policy change + + 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 + Signed-off-by: Jes Sorensen + +diff --git a/Grow.c b/Grow.c +index a849012..b86b53e 100755 +--- 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; + } + ++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. +diff --git a/ReadMe.c b/ReadMe.c +index fc04c2c..eb8fb4b 100644 +--- 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" +-" --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[] = +diff --git a/mdadm.8.in b/mdadm.8.in +index 1178ed9..744c12b 100644 +--- a/mdadm.8.in ++++ b/mdadm.8.in +@@ -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 +-removing a write-intent bitmap. ++removing a write-intent bitmap and changing the array's consistency policy. + + .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. ++ ++.PP ++Can be used with \-\-grow to change the consistency policy of an active array ++in some cases. See CONSISTENCY POLICY CHANGES below. + .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 ++change the array's consistency policy. + .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. + ++.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 +diff --git a/mdadm.c b/mdadm.c +index 6edf3ab..5ebf117 100644 +--- a/mdadm.c ++++ b/mdadm.c +@@ -1221,6 +1221,7 @@ int main(int argc, char *argv[]) + 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 || +@@ -1679,6 +1680,8 @@ int main(int argc, char *argv[]) + 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; +diff --git a/mdadm.h b/mdadm.h +index 2c7066d..4891acf 100644 +--- 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_consistency_policy(char *devname, int fd, ++ struct context *c, struct shape *s); + + extern int restore_backup(struct supertype *st, + struct mdinfo *content, diff --git a/SPECS/mdadm.spec b/SPECS/mdadm.spec index cc14a91..a8f19b8 100644 --- a/SPECS/mdadm.spec +++ b/SPECS/mdadm.spec @@ -1,7 +1,7 @@ Summary: The mdadm program controls Linux md devices (software RAID arrays) Name: mdadm -Version: 3.4 -Release: 14%{?dist}.1 +Version: 4.0 +Release: 5%{?dist} Source: http://www.kernel.org/pub/linux/utils/raid/mdadm/mdadm-%{version}.tar.xz Source1: mdmonitor.init Source2: raid-check @@ -11,25 +11,31 @@ Source5: mdadm-cron Source6: mdmonitor.service Source7: mdadm.conf Source8: mdadm_event.conf -Patch1: mdadm-3.4.1-fix-some-type-comparison.patch -Patch2: mdadm-3.4-super-intel-ensure-suspended-region-is-removed-when-.patch -Patch3: mdadm-3.4-super1-Clear-memory-allocated-for-superblock-bitmap-.patch + +Patch1: add-man-page-for-symlinks.patch +Patch2: specify-enough-length-when-write-to-buffer.patch +Patch3: generic-support-for-consistency-policy-and-PPL.patch +Patch4: detail-show-consistency-policy.patch +Patch5: imsmppl-support.patch +Patch6: super1-ppl-support.patch +Patch7: add-ppl-and-no-ppl-options-for-update.patch +Patch8: support-consistency-policy-change.patch +Patch9: imsm-use-rounded-size-for-metadata-initialization.patch +Patch10: allow-drives-in-a-container-regardless-of-sector-size.patch +Patch11: allocate-buffer-to-support-maximum-sector-size.patch +Patch12: dont-allow-disks-with-different-sector-size-in-one.patch +Patch13: Allow-more-spare-selection-criteria.patch +Patch14: Add-sector-size-as-spare-selection-criterion.patch +Patch15: Correct-examine-output-for-4k-disks.patch +Patch16: dont-allow-array-geometry-change-with-ppl-enabled.patch +Patch17: dont-allow-to-enable-PPL-reshape-in-progress.patch + # RHEL customization patches -Patch4: mdadm-3.4-IMSM-retry-reading-sync_completed-during-reshape.patch -Patch5: mdadm-3.4-imsm-add-handling-of-sync_action-is-equal-to-idle.patch -Patch6: mdadm-3.4-imsm-properly-handle-values-of-sync_completed.patch -Patch7: mdadm-3.4-The-sys_name-array-in-the-mdinfo-structure-is-20-byt.patch -Patch8: mdadm-3.4-Grow_continue_command-remove-dead-code.patch -Patch9: mdadm-3.4-check-reshape_active-more-times-before-Grow_continue.patch -Patch10: mdadm-3.4-Use-dev_t-for-devnm2devid-and-devid2devnm.patch -Patch11: mdadm-3.4-Change-behavior-in-find_free_devnm-when-wrapping-aro.patch -Patch12: mdadm-3.4-mdopen-Prevent-overrunning-the-devname-buffer-when-c.patch -Patch13: mdadm-3.4-monitor-Make-sure-that-last_checkpoint-is-set-to-0-a.patch Patch95: mdadm-3.4-udev-race.patch Patch96: mdadm-3.3.2-skip-rules.patch Patch97: mdadm-3.3-udev.patch Patch98: mdadm-2.5.2-static.patch -Patch99: mdadm-3.4-disable-journal.patch +Patch99: disable-journal.patch URL: http://www.kernel.org/pub/linux/utils/raid/mdadm/ License: GPLv2+ Group: System Environment/Base @@ -55,19 +61,23 @@ file can be used to help with some common tasks. %prep %setup -q -%patch1 -p1 -b .comparision -%patch2 -p1 -b .stop-reshape -%patch3 -p1 -b .clear -%patch4 -p1 -b .retry -%patch5 -p1 -b .syncaction -%patch6 -p1 -b .synccompleted -%patch7 -p1 -b .sysname -%patch8 -p1 -b .dead -%patch9 -p1 -b .before -%patch10 -p1 -b .devt -%patch11 -p1 -b .wrap -%patch12 -p1 -b .overrun -%patch13 -p1 -b .monitorresync +%patch1 -p1 -b .symlinks +%patch2 -p1 -b .specify +%patch3 -p1 -b .generic +%patch4 -p1 -b .detail +%patch5 -p1 -b .imsmppl +%patch6 -p1 -b .super1 +%patch7 -p1 -b .options +%patch8 -p1 -b .change +%patch9 -p1 -b .rounded +%patch10 -p1 -b .regardless +%patch11 -p1 -b .maximum +%patch12 -p1 -b .different +%patch13 -p1 -b .criteria +%patch14 -p1 -b .criterion +%patch15 -p1 -b .output +%patch16 -p1 -b .pplgeometry +%patch17 -p1 -b .pplreshape # RHEL customization patches %patch95 -p1 -b .race @@ -136,10 +146,32 @@ rm -rf %{buildroot} /etc/libreport/events.d/* %changelog -* Fri Dec 9 2016 Jes Sorensen - 3.4-14.1 +* Mon Jun 12 2017 Nigel Croxon - 4.0-5 +- RAID array grow not blocked when PPL is enabled +- Resolves rhbz#1460141 + +* Wed May 31 2017 Xiao Ni - 4.0-4 +- Imsm should not allow combing 512 and 4096 sector size disks in + one volume and Wrong array size shown for array built on 4096 + sector size disks +- Resolves rhbz#1454390 and rhbz#1454379 + +* Wed May 17 2017 Xiao Ni - 4.0-3 +- Support for Partial Parity Log +- Resolves rhbz#1450057 + +* Thu Apr 13 2017 Nigel Croxon - 4.0-2 +- Rebuilt for submission +- Resolves rhbz#1385946 + +* Sun Feb 26 2017 Xiao Ni - 4.0-1 +- Update to upstream 4.0 +- Resolves rhbz#1380017 + +* Wed Nov 16 2016 Jes Sorensen - 3.4-15 - Resolve case where a reshape could hang if started right after the - completion of a resync. z-stream fix -- Resolves rhbz#1402434 + completion of a resync. +- Resolves rhbz#1386700 * Tue Sep 27 2016 Jes Sorensen - 3.4-14 - The fix for 1331709 caused a problem with container arrays (IMSM) as