From b959dcfcd0319d4311e67fa40ebb407605efc9d9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 12 May 2023 14:47:09 +0200 Subject: Merging upstream version 4.2+20230508. Signed-off-by: Daniel Baumann --- Create.c | 14 ++-- Detail.c | 9 ++- Grow.c | 20 +----- Incremental.c | 13 ++-- Manage.c | 17 ----- Monitor.c | 34 +++++----- config.c | 43 ++++++------ lib.c | 4 +- mapfile.c | 12 ++-- mdadm.8.in | 5 ++ mdadm.c | 9 ++- mdadm.h | 25 ++++++- mdmon.c | 22 ++++-- mdopen.c | 17 ++--- platform-intel.c | 21 +++++- platform-intel.h | 1 + sha1.c | 12 +++- super-ddf.c | 2 +- super-intel.c | 75 +++++++++++++++++---- super1.c | 126 +++++++++++++++++------------------ sysfs.c | 2 +- systemd/mdadm-grow-continue@.service | 1 - systemd/mdcheck_continue.service | 2 - systemd/mdcheck_start.service | 2 - systemd/mdmon@.service | 15 +++-- udev-md-raid-arrays.rules | 3 +- util.c | 61 +++++++++++++---- 27 files changed, 335 insertions(+), 232 deletions(-) diff --git a/Create.c b/Create.c index bbe9e13..ea6a474 100644 --- a/Create.c +++ b/Create.c @@ -328,7 +328,7 @@ static int update_metadata(int mdfd, struct shape *s, struct supertype *st, * again returns container info. */ st->ss->getinfo_super(st, &info_new, NULL); - if (st->ss->external && is_container(s->level) && + if (st->ss->external && !is_container(s->level) && !same_uuid(info_new.uuid, info->uuid, 0)) { map_update(map, fd2devnm(mdfd), info_new.text_version, @@ -636,11 +636,6 @@ int Create(struct supertype *st, char *mddev, break; case LEVEL_LINEAR: /* a chunksize of zero 0s perfectly valid (and preferred) since 2.6.16 */ - if (get_linux_version() < 2006016 && s->chunk == 0) { - s->chunk = 64; - if (c->verbose > 0) - pr_err("chunk size defaults to 64K\n"); - } break; case 1: case LEVEL_FAULTY: @@ -1029,10 +1024,9 @@ int Create(struct supertype *st, char *mddev, * it could be in conflict with already existing device * e.g. container, array */ - if (strncmp(chosen_name, "/dev/md/", 8) == 0 && - map_by_name(&map, chosen_name+8) != NULL) { - pr_err("Array name %s is in use already.\n", - chosen_name); + if (strncmp(chosen_name, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0 && + map_by_name(&map, chosen_name + DEV_MD_DIR_LEN)) { + pr_err("Array name %s is in use already.\n", chosen_name); close(mdfd); map_unlock(&map); udev_unblock(); diff --git a/Detail.c b/Detail.c index 4ef2646..206d88e 100644 --- a/Detail.c +++ b/Detail.c @@ -254,10 +254,9 @@ int Detail(char *dev, struct context *c) fname_from_uuid(st, info, nbuf, ':'); printf("MD_UUID=%s\n", nbuf + 5); mp = map_by_uuid(&map, info->uuid); - if (mp && mp->path && - strncmp(mp->path, "/dev/md/", 8) == 0) { + if (mp && mp->path && strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) { printf("MD_DEVNAME="); - print_escape(mp->path + 8); + print_escape(mp->path + DEV_MD_DIR_LEN); putchar('\n'); } @@ -273,9 +272,9 @@ int Detail(char *dev, struct context *c) printf("MD_UUID=%s\n", nbuf+5); } if (mp && mp->path && - strncmp(mp->path, "/dev/md/", 8) == 0) { + strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) { printf("MD_DEVNAME="); - print_escape(mp->path+8); + print_escape(mp->path + DEV_MD_DIR_LEN); putchar('\n'); } map_free(map); diff --git a/Grow.c b/Grow.c index bb5fe45..8fa9787 100644 --- a/Grow.c +++ b/Grow.c @@ -1708,14 +1708,6 @@ char *analyse_change(char *devname, struct mdinfo *info, struct reshape *re) return NULL; } - if (re->after.data_disks == re->before.data_disks && - get_linux_version() < 2006032) - return "in-place reshape is not safe before 2.6.32 - sorry."; - - if (re->after.data_disks < re->before.data_disks && - get_linux_version() < 2006030) - return "reshape to fewer devices is not supported before 2.6.30 - sorry."; - re->backup_blocks = compute_backup_blocks( info->new_chunk, info->array.chunk_size, re->after.data_disks, re->before.data_disks); @@ -1895,14 +1887,6 @@ int Grow_reshape(char *devname, int fd, return 1; } - if (s->raiddisks && s->raiddisks < array.raid_disks && - array.level > 1 && get_linux_version() < 2006032 && - !check_env("MDADM_FORCE_FEWER")) { - pr_err("reducing the number of devices is not safe before Linux 2.6.32\n" - " Please use a newer kernel\n"); - return 1; - } - if (array.level > 1 && s->size > 1 && (unsigned long long) (array.chunk_size / 1024) > s->size) { pr_err("component size must be larger than chunk size.\n"); @@ -3516,7 +3500,7 @@ started: if (!forked) if (continue_via_systemd(container ?: sra->sys_name, - GROW_SERVICE)) { + GROW_SERVICE, NULL)) { free(fdlist); free(offsets); sysfs_free(sra); @@ -3714,7 +3698,7 @@ int reshape_container(char *container, char *devname, ping_monitor(container); if (!forked && !freeze_reshape) - if (continue_via_systemd(container, GROW_SERVICE)) + if (continue_via_systemd(container, GROW_SERVICE, NULL)) return 0; switch (forked ? 0 : fork()) { diff --git a/Incremental.c b/Incremental.c index 09b94b9..f13ce02 100644 --- a/Incremental.c +++ b/Incremental.c @@ -202,8 +202,7 @@ int Incremental(struct mddev_dev *devlist, struct context *c, if (!match && rv == 2) goto out; - if (match && match->devname && - strcasecmp(match->devname, "") == 0) { + if (match && match->devname && is_devname_ignore(match->devname) == true) { if (c->verbose >= 0) pr_err("array containing %s is explicitly ignored by mdadm.conf\n", devname); @@ -460,8 +459,8 @@ int Incremental(struct mddev_dev *devlist, struct context *c, info.array.working_disks ++; } - if (strncmp(chosen_name, "/dev/md/", 8) == 0) - md_devname = chosen_name+8; + if (strncmp(chosen_name, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) + md_devname = chosen_name + DEV_MD_DIR_LEN; else md_devname = chosen_name; if (c->export) { @@ -507,6 +506,9 @@ int Incremental(struct mddev_dev *devlist, struct context *c, GET_OFFSET | GET_SIZE)); active_disks = count_active(st, sra, mdfd, &avail, &info); + if (!avail) + goto out_unlock; + journal_device_missing = (info.journal_device_required) && (info.journal_clean == 0); if (info.consistency_policy == CONSISTENCY_POLICY_PPL) @@ -1564,8 +1566,7 @@ static int Incremental_container(struct supertype *st, char *devname, break; } - if (match && match->devname && - strcasecmp(match->devname, "") == 0) { + if (match && match->devname && is_devname_ignore(match->devname) == true) { if (c->verbose > 0) pr_err("array %s/%s is explicitly ignored by mdadm.conf\n", match->container, match->member); diff --git a/Manage.c b/Manage.c index fde6aba..f54de7c 100644 --- a/Manage.c +++ b/Manage.c @@ -461,17 +461,6 @@ done: goto out; } - if (get_linux_version() < 2006028) { - /* prior to 2.6.28, KOBJ_CHANGE was not sent when an md array - * was stopped, so We'll do it here just to be sure. Drop any - * partitions as well... - */ - if (fd >= 0) - ioctl(fd, BLKRRPART, 0); - if (mdi) - sysfs_uevent(mdi, "change"); - } - if (devnm[0] && use_udev()) { struct map_ent *mp = map_by_devnm(&map, devnm); remove_devices(devnm, mp ? mp->path : NULL); @@ -621,12 +610,6 @@ int attempt_re_add(int fd, int tfd, struct mddev_dev *dv, * though. */ mdu_disk_info_t disc; - /* re-add doesn't work for version-1 superblocks - * before 2.6.18 :-( - */ - if (array->major_version == 1 && - get_linux_version() <= 2006018) - goto skip_re_add; disc.number = mdi.disk.number; if (md_get_disk_info(fd, &disc) != 0 || disc.major != 0 || disc.minor != 0) diff --git a/Monitor.c b/Monitor.c index 4491818..6617596 100644 --- a/Monitor.c +++ b/Monitor.c @@ -36,9 +36,18 @@ #define EVENT_NAME_MAX 32 #define AUTOREBUILD_PID_PATH MDMON_DIR "/autorebuild.pid" +/** + * struct state - external array or container properties. + * @devname: has length of %DEV_MD_DIR + device name + terminating byte + * @devnm: to sync with mdstat info + * @parent_devnm: or subarray, devnm of parent, for others, "" + * @subarray: for a container it is a link to first subarray, for a subarray it is a link to next + * subarray in the same container + * @parent: for a subarray it is a link to its container + */ struct state { - char devname[MD_NAME_MAX + sizeof("/dev/md/")]; /* length of "/dev/md/" + device name + terminating byte*/ - char devnm[MD_NAME_MAX]; /* to sync with mdstat info */ + char devname[MD_NAME_MAX + sizeof(DEV_MD_DIR)]; + char devnm[MD_NAME_MAX]; unsigned int utime; int err; char *spare_group; @@ -49,15 +58,10 @@ struct state { int devstate[MAX_DISKS]; dev_t devid[MAX_DISKS]; int percent; - char parent_devnm[MD_NAME_MAX]; /* For subarray, devnm of parent. - * For others, "" - */ + char parent_devnm[MD_NAME_MAX]; struct supertype *metadata; - struct state *subarray;/* for a container it is a link to first subarray - * for a subarray it is a link to next subarray - * in the same container */ - struct state *parent; /* for a subarray it is a link to its container - */ + struct state *subarray; + struct state *parent; struct state *next; }; @@ -246,14 +250,14 @@ int Monitor(struct mddev_dev *devlist, if (mdlist->devname == NULL) continue; - if (strcasecmp(mdlist->devname, "") == 0) + if (is_devname_ignore(mdlist->devname) == true) continue; if (!is_mddev(mdlist->devname)) continue; st = xcalloc(1, sizeof *st); - snprintf(st->devname, MD_NAME_MAX + sizeof("/dev/md/"), - "/dev/md/%s", basename(mdlist->devname)); + snprintf(st->devname, MD_NAME_MAX + sizeof(DEV_MD_DIR), DEV_MD_DIR "%s", + basename(mdlist->devname)); st->next = statelist; st->devnm[0] = 0; st->percent = RESYNC_UNKNOWN; @@ -274,7 +278,7 @@ int Monitor(struct mddev_dev *devlist, st = xcalloc(1, sizeof *st); mdlist = conf_get_ident(dv->devname); - snprintf(st->devname, MD_NAME_MAX + sizeof("/dev/md/"), "%s", dv->devname); + snprintf(st->devname, MD_NAME_MAX + sizeof(DEV_MD_DIR), "%s", dv->devname); st->next = statelist; st->devnm[0] = 0; st->percent = RESYNC_UNKNOWN; @@ -942,7 +946,7 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist) continue; } - snprintf(st->devname, MD_NAME_MAX + sizeof("/dev/md/"), "%s", name); + snprintf(st->devname, MD_NAME_MAX + sizeof(DEV_MD_DIR), "%s", name); if ((fd = open(st->devname, O_RDONLY)) < 0 || md_get_array_info(fd, &array) < 0) { /* no such array */ diff --git a/config.c b/config.c index eeedd0c..450880e 100644 --- a/config.c +++ b/config.c @@ -119,6 +119,18 @@ int match_keyword(char *word) return -1; } +/** + * is_devname_ignore() - check if &devname is a special "" keyword. + */ +bool is_devname_ignore(char *devname) +{ + static const char keyword[] = ""; + + if (strcasecmp(devname, keyword) == 0) + return true; + return false; +} + /** * ident_init() - Set defaults. * @ident: ident pointer, not NULL. @@ -373,17 +385,6 @@ void devline(char *line) struct mddev_ident *mddevlist = NULL; struct mddev_ident **mddevlp = &mddevlist; -static int is_number(char *w) -{ - /* check if there are 1 or more digits and nothing else */ - int digits = 0; - while (*w && isdigit(*w)) { - digits++; - w++; - } - return (digits && ! *w); -} - void arrayline(char *line) { char *w; @@ -404,13 +405,11 @@ void arrayline(char *line) * * or anything that doesn't start '/' or '<' */ - if (strcasecmp(w, "") == 0 || - strncmp(w, "/dev/md/", 8) == 0 || + if (is_devname_ignore(w) == true || + strncmp(w, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0 || (w[0] != '/' && w[0] != '<') || - (strncmp(w, "/dev/md", 7) == 0 && - is_number(w + 7)) || - (strncmp(w, "/dev/md_d", 9) == 0 && - is_number(w + 9))) { + is_devname_md_numbered(w) == true || + is_devname_md_d_numbered(w) == true) { /* This is acceptable */; if (mis.devname) pr_err("only give one device per ARRAY line: %s and %s\n", @@ -571,7 +570,7 @@ void homehostline(char *line) char *w; for (w = dl_next(line); w != line; w = dl_next(w)) { - if (strcasecmp(w, "") == 0) + if (is_devname_ignore(w) == true) require_homehost = 0; else if (home_host == NULL) { if (strcasecmp(w, "") == 0) @@ -1102,13 +1101,13 @@ int devname_matches(char *name, char *match) * mdNN with NN * then just strcmp */ - if (strncmp(name, "/dev/md/", 8) == 0) - name += 8; + if (strncmp(name, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) + name += DEV_MD_DIR_LEN; else if (strncmp(name, "/dev/", 5) == 0) name += 5; - if (strncmp(match, "/dev/md/", 8) == 0) - match += 8; + if (strncmp(match, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) + match += DEV_MD_DIR_LEN; else if (strncmp(match, "/dev/", 5) == 0) match += 5; diff --git a/lib.c b/lib.c index e395b28..fe5c8d2 100644 --- a/lib.c +++ b/lib.c @@ -313,7 +313,7 @@ char *map_dev_preferred(int major, int minor, int create, for (p = devlist; p; p = p->next) if (p->major == major && p->minor == minor) { - if (strncmp(p->name, "/dev/md/",8) == 0 || + if (strncmp(p->name, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0 || (prefer && strstr(p->name, prefer))) { if (preferred == NULL || strlen(p->name) < strlen(preferred)) @@ -570,7 +570,7 @@ void free_line(char *line) * * Return: 0 on success, 1 otherwise. */ -int parse_num(int *dest, char *num) +int parse_num(int *dest, const char *num) { char *c = NULL; long temp; diff --git a/mapfile.c b/mapfile.c index ac35176..34fea17 100644 --- a/mapfile.c +++ b/mapfile.c @@ -320,9 +320,9 @@ struct map_ent *map_by_name(struct map_ent **map, char *name) for (mp = *map ; mp ; mp = mp->next) { if (!mp->path) continue; - if (strncmp(mp->path, "/dev/md/", 8) != 0) + if (strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) != 0) continue; - if (strcmp(mp->path+8, name) != 0) + if (strcmp(mp->path + DEV_MD_DIR_LEN, name) != 0) continue; if (!mddev_busy(mp->devnm)) { mp->bad = 1; @@ -413,7 +413,7 @@ void RebuildMap(void) devid = devnm2devid(md->devnm); path = map_dev(major(devid), minor(devid), 0); if (path == NULL || - strncmp(path, "/dev/md/", 8) != 0) { + strncmp(path, DEV_MD_DIR, DEV_MD_DIR_LEN) != 0) { /* We would really like a name that provides * an MD_DEVNAME for udev. * The name needs to be unique both in /dev/md/ @@ -434,7 +434,7 @@ void RebuildMap(void) if (match && match->devname && match->devname[0] == '/') { path = match->devname; if (path[0] != '/') { - strcpy(namebuf, "/dev/md/"); + strcpy(namebuf, DEV_MD_DIR); strcat(namebuf, path); path = namebuf; } @@ -478,10 +478,10 @@ void RebuildMap(void) while (conflict) { if (unum >= 0) - sprintf(namebuf, "/dev/md/%s%s%d", + sprintf(namebuf, DEV_MD_DIR "%s%s%d", name, sep, unum); else - sprintf(namebuf, "/dev/md/%s", + sprintf(namebuf, DEV_MD_DIR "%s", name); unum++; if (lstat(namebuf, &stb) != 0 && diff --git a/mdadm.8.in b/mdadm.8.in index 6f0f6c1..b715950 100644 --- a/mdadm.8.in +++ b/mdadm.8.in @@ -3197,6 +3197,11 @@ environment. This can be useful for testing or for disaster recovery. You should be aware that interoperability may be compromised by setting this value. +These change can also be suppressed by adding +.B mdadm.imsm.test=1 +to the kernel command line. This makes it easy to test IMSM +code in a virtual machine that doesn't have IMSM virtual hardware. + .TP .B MDADM_GROW_ALLOW_OLD If an array is stopped while it is performing a reshape and that diff --git a/mdadm.c b/mdadm.c index 4685ad6..076b45e 100644 --- a/mdadm.c +++ b/mdadm.c @@ -107,8 +107,8 @@ int main(int argc, char *argv[]) srandom(time(0) ^ getpid()); - if (get_linux_version() < 2006015) { - pr_err("This version of mdadm does not support kernels older than 2.6.15\n"); + if (get_linux_version() < 2006032) { + pr_err("This version of mdadm does not support kernels older than 2.6.32\n"); exit(1); } @@ -154,7 +154,7 @@ int main(int argc, char *argv[]) continue; case HomeHost: - if (strcasecmp(optarg, "") == 0) + if (is_devname_ignore(optarg) == true) c.require_homehost = 0; else c.homehost = optarg; @@ -1749,8 +1749,7 @@ static int scan_assemble(struct supertype *ss, int r; if (a->assembled) continue; - if (a->devname && - strcasecmp(a->devname, "") == 0) + if (a->devname && is_devname_ignore(a->devname) == true) continue; r = Assemble(ss, a->devname, diff --git a/mdadm.h b/mdadm.h index b9127f9..83f2cf7 100644 --- a/mdadm.h +++ b/mdadm.h @@ -100,6 +100,22 @@ struct dlm_lksb { #define DEFAULT_BITMAP_DELAY 5 #define DEFAULT_MAX_WRITE_BEHIND 256 +/* DEV_NUM_PREF is a subpath to numbered MD devices, e.g. /dev/md1 or directory name. + * DEV_NUM_PREF_LEN is a length with Null byte excluded. + */ +#ifndef DEV_NUM_PREF +#define DEV_NUM_PREF "/dev/md" +#define DEV_NUM_PREF_LEN (sizeof(DEV_NUM_PREF) - 1) +#endif /* DEV_NUM_PREF */ + +/* DEV_MD_DIR points to named MD devices directory. + * DEV_MD_DIR_LEN is a length with Null byte excluded. + */ +#ifndef DEV_MD_DIR +#define DEV_MD_DIR "/dev/md/" +#define DEV_MD_DIR_LEN (sizeof(DEV_MD_DIR) - 1) +#endif /* DEV_MD_DIR */ + /* MAP_DIR should be somewhere that persists across the pivotroot * from early boot to late boot. * /run seems to have emerged as the best standard. @@ -1263,6 +1279,8 @@ extern struct superswitch super0, super1; extern struct superswitch super_imsm, super_ddf; extern struct superswitch mbr, gpt; +void imsm_set_no_platform(int v); + struct metadata_update { int len; char *buf; @@ -1583,7 +1601,7 @@ int default_layout(struct supertype *st, int level, int verbose); extern int is_near_layout_10(int layout); extern int parse_layout_10(char *layout); extern int parse_layout_faulty(char *layout); -extern int parse_num(int *dest, char *num); +extern int parse_num(int *dest, const char *num); extern int parse_cluster_confirm_arg(char *inp, char **devname, int *slot); extern int check_ext2(int fd, char *name); extern int check_reiser(int fd, char *name); @@ -1608,7 +1626,7 @@ extern int same_dev(char *one, char *two); extern int compare_paths (char* path1,char* path2); extern void enable_fds(int devices); extern void manage_fork_fds(int close_all); -extern int continue_via_systemd(char *devnm, char *service_name); +extern int continue_via_systemd(char *devnm, char *service_name, char *prefix); extern void ident_init(struct mddev_ident *ident); @@ -1632,6 +1650,9 @@ extern void print_escape(char *str); extern int use_udev(void); extern unsigned long GCD(unsigned long a, unsigned long b); extern int conf_name_is_free(char *name); +extern bool is_devname_ignore(char *devname); +extern bool is_devname_md_numbered(const char *devname); +extern bool is_devname_md_d_numbered(const char *devname); extern int conf_verify_devnames(struct mddev_ident *array_list); extern int devname_matches(char *name, char *match); extern struct mddev_ident *conf_match(struct supertype *st, diff --git a/mdmon.c b/mdmon.c index 60ba318..cef5bbc 100644 --- a/mdmon.c +++ b/mdmon.c @@ -318,6 +318,12 @@ int main(int argc, char *argv[]) {NULL, 0, NULL, 0} }; + /* + * mdmon should never complain due to lack of a platform, + * that is mdadm's job if at all. + */ + imsm_set_no_platform(1); + while ((opt = getopt_long(argc, argv, "thaF", options, NULL)) != -1) { switch (opt) { case 'a': @@ -352,7 +358,6 @@ int main(int argc, char *argv[]) } } - if (in_initrd()) { /* * set first char of argv[0] to @. This is used by @@ -362,12 +367,15 @@ int main(int argc, char *argv[]) argv[0][0] = '@'; } - if (all == 0 && container_name == NULL) { - if (argv[optind]) { - container_name = get_md_name(argv[optind]); - if (!container_name) - return 1; - } + if (!all && argv[optind]) { + static const char prefix[] = "initrd/"; + container_name = argv[optind]; + if (strncmp(container_name, prefix, + sizeof(prefix) - 1) == 0) + container_name += sizeof(prefix)-1; + container_name = get_md_name(container_name); + if (!container_name) + return 1; } if (container_name == NULL || argc - optind > 1) diff --git a/mdopen.c b/mdopen.c index d18c931..d3022a5 100644 --- a/mdopen.c +++ b/mdopen.c @@ -188,12 +188,12 @@ int create_mddev(char *dev, char *name, int autof, int trustworthy, parts = autof >> 3; autof &= 7; - strcpy(chosen, "/dev/md/"); + strcpy(chosen, DEV_MD_DIR); cname = chosen + strlen(chosen); if (dev) { - if (strncmp(dev, "/dev/md/", 8) == 0) { - strcpy(cname, dev+8); + if (strncmp(dev, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) { + strcpy(cname, dev + DEV_MD_DIR_LEN); } else if (strncmp(dev, "/dev/", 5) == 0) { char *e = dev + strlen(dev); while (e > dev && isdigit(e[-1])) @@ -370,6 +370,7 @@ int create_mddev(char *dev, char *name, int autof, int trustworthy, } if (block_udev) udev_block(devnm); + create_named_array(devnm); } sprintf(devname, "/dev/%s", devnm); @@ -411,11 +412,11 @@ int create_mddev(char *dev, char *name, int autof, int trustworthy, make_parts(devname, parts); if (strcmp(chosen, devname) != 0) { - if (mkdir("/dev/md",0700) == 0) { - if (chown("/dev/md", ci->uid, ci->gid)) - perror("chown /dev/md"); - if (chmod("/dev/md", ci->mode| ((ci->mode>>2) & 0111))) - perror("chmod /dev/md"); + if (mkdir(DEV_NUM_PREF, 0700) == 0) { + if (chown(DEV_NUM_PREF, ci->uid, ci->gid)) + perror("chown " DEV_NUM_PREF); + if (chmod(DEV_NUM_PREF, ci->mode | ((ci->mode >> 2) & 0111))) + perror("chmod " DEV_NUM_PREF); } if (dev && strcmp(chosen, dev) == 0) diff --git a/platform-intel.c b/platform-intel.c index 757f0b1..914164c 100644 --- a/platform-intel.c +++ b/platform-intel.c @@ -64,9 +64,10 @@ struct sys_dev *find_driver_devices(const char *bus, const char *driver) if (strcmp(driver, "isci") == 0) type = SYS_DEV_SAS; - else if (strcmp(driver, "ahci") == 0) + else if (strcmp(driver, "ahci") == 0) { + vmd = find_driver_devices("pci", "vmd"); type = SYS_DEV_SATA; - else if (strcmp(driver, "nvme") == 0) { + } else if (strcmp(driver, "nvme") == 0) { /* if looking for nvme devs, first look for vmd */ vmd = find_driver_devices("pci", "vmd"); type = SYS_DEV_NVME; @@ -115,6 +116,17 @@ struct sys_dev *find_driver_devices(const char *bus, const char *driver) free(rp); } + /* change sata type if under a vmd controller */ + if (type == SYS_DEV_SATA) { + struct sys_dev *dev; + char *rp = realpath(path, NULL); + for (dev = vmd; dev; dev = dev->next) { + if ((strncmp(dev->path, rp, strlen(dev->path)) == 0)) + type = SYS_DEV_SATA_VMD; + } + free(rp); + } + /* if it's not Intel device or mark as VMD connected - skip it. */ if (devpath_to_vendor(path) != 0x8086 || skip == 1) continue; @@ -166,7 +178,8 @@ struct sys_dev *find_driver_devices(const char *bus, const char *driver) } closedir(driver_dir); - if (vmd) { + /* nvme vmd needs a list separate from sata vmd */ + if (vmd && type == SYS_DEV_NVME) { if (list) list->next = vmd; else @@ -273,6 +286,7 @@ struct sys_dev *find_intel_devices(void) free_sys_dev(&intel_devices); isci = find_driver_devices("pci", "isci"); + /* Searching for AHCI will return list of SATA and SATA VMD controllers */ ahci = find_driver_devices("pci", "ahci"); /* Searching for NVMe will return list of NVMe and VMD controllers */ nvme = find_driver_devices("pci", "nvme"); @@ -638,6 +652,7 @@ const struct imsm_orom *find_imsm_efi(struct sys_dev *hba) break; case SYS_DEV_VMD: + case SYS_DEV_SATA_VMD: for (i = 0; i < ARRAY_SIZE(vmd_efivars); i++) { if (!read_efi_variable(&orom, sizeof(orom), vmd_efivars[i], VENDOR_GUID)) diff --git a/platform-intel.h b/platform-intel.h index 6238d23..2c0f4e3 100644 --- a/platform-intel.h +++ b/platform-intel.h @@ -196,6 +196,7 @@ enum sys_dev_type { SYS_DEV_SATA, SYS_DEV_NVME, SYS_DEV_VMD, + SYS_DEV_SATA_VMD, SYS_DEV_MAX }; diff --git a/sha1.c b/sha1.c index 89b32f4..1e4ad5d 100644 --- a/sha1.c +++ b/sha1.c @@ -229,7 +229,17 @@ sha1_process_bytes (const void *buffer, size_t len, struct sha1_ctx *ctx) if (len >= 64) { #if !_STRING_ARCH_unaligned -# define alignof(type) offsetof (struct { char c; type x; }, x) +/* GCC releases before GCC 4.9 had a bug in _Alignof. See GCC bug 52023 + . + clang versions < 8.0.0 have the same bug. */ +# if (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112 \ + || (defined __GNUC__ && __GNUC__ < 4 + (__GNUC_MINOR__ < 9) \ + && !defined __clang__) \ + || (defined __clang__ && __clang_major__ < 8)) +# define alignof(type) offsetof (struct { char c; type x; }, x) +# else +# define alignof(type) _Alignof(type) +# endif # define UNALIGNED_P(p) (((size_t) p) % alignof (sha1_uint32) != 0) if (UNALIGNED_P (buffer)) while (len > 64) diff --git a/super-ddf.c b/super-ddf.c index b86c6ac..7213284 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -1648,7 +1648,7 @@ static void brief_examine_subarrays_ddf(struct supertype *st, int verbose) fname_from_uuid(st, &info, nbuf1, ':'); _ddf_array_name(namebuf, ddf, i); printf("ARRAY%s%s container=%s member=%d UUID=%s\n", - namebuf[0] == '\0' ? "" : " /dev/md/", namebuf, + namebuf[0] == '\0' ? "" : " " DEV_MD_DIR, namebuf, nbuf+5, i, nbuf1+5); } } diff --git a/super-intel.c b/super-intel.c index e155a8a..ae0f4a8 100644 --- a/super-intel.c +++ b/super-intel.c @@ -20,6 +20,7 @@ #define HAVE_STDINT_H 1 #include "mdadm.h" #include "mdmon.h" +#include "dlink.h" #include "sha1.h" #include "platform-intel.h" #include @@ -626,9 +627,48 @@ static const char *_sys_dev_type[] = { [SYS_DEV_SAS] = "SAS", [SYS_DEV_SATA] = "SATA", [SYS_DEV_NVME] = "NVMe", - [SYS_DEV_VMD] = "VMD" + [SYS_DEV_VMD] = "VMD", + [SYS_DEV_SATA_VMD] = "SATA VMD" }; +static int no_platform = -1; + +static int check_no_platform(void) +{ + static const char search[] = "mdadm.imsm.test=1"; + FILE *fp; + + if (no_platform >= 0) + return no_platform; + + if (check_env("IMSM_NO_PLATFORM")) { + no_platform = 1; + return 1; + } + fp = fopen("/proc/cmdline", "r"); + if (fp) { + char *l = conf_line(fp); + char *w = l; + + do { + if (strcmp(w, search) == 0) + no_platform = 1; + w = dl_next(w); + } while (w != l); + free_line(l); + fclose(fp); + if (no_platform >= 0) + return no_platform; + } + no_platform = 0; + return 0; +} + +void imsm_set_no_platform(int v) +{ + no_platform = v; +} + const char *get_sys_dev_type(enum sys_dev_type type) { if (type >= SYS_DEV_MAX) @@ -2270,7 +2310,7 @@ static void brief_examine_subarrays_imsm(struct supertype *st, int verbose) super->current_vol = i; getinfo_super_imsm(st, &info, NULL); fname_from_uuid(st, &info, nbuf1, ':'); - printf("ARRAY /dev/md/%.16s container=%s member=%d UUID=%s\n", + printf("ARRAY " DEV_MD_DIR "%.16s container=%s member=%d UUID=%s\n", dev->volume, nbuf + 5, i, nbuf1 + 5); } } @@ -2559,6 +2599,8 @@ static void print_found_intel_controllers(struct sys_dev *elem) if (elem->type == SYS_DEV_VMD) fprintf(stderr, "VMD domain"); + else if (elem->type == SYS_DEV_SATA_VMD) + fprintf(stderr, "SATA VMD domain"); else fprintf(stderr, "RAID controller"); @@ -2699,7 +2741,7 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle int result=1; if (enumerate_only) { - if (check_env("IMSM_NO_PLATFORM")) + if (check_no_platform()) return 0; list = find_intel_devices(); if (!list) @@ -2729,8 +2771,9 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle if (!find_imsm_capability(hba)) { char buf[PATH_MAX]; pr_err("imsm capabilities not found for controller: %s (type %s)\n", - hba->type == SYS_DEV_VMD ? vmd_domain_to_controller(hba, buf) : hba->path, - get_sys_dev_type(hba->type)); + hba->type == SYS_DEV_VMD || hba->type == SYS_DEV_SATA_VMD ? + vmd_domain_to_controller(hba, buf) : + hba->path, get_sys_dev_type(hba->type)); continue; } result = 0; @@ -2783,11 +2826,12 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle printf(" I/O Controller : %s (%s)\n", hba->path, get_sys_dev_type(hba->type)); - if (hba->type == SYS_DEV_SATA) { + if (hba->type == SYS_DEV_SATA || hba->type == SYS_DEV_SATA_VMD) { host_base = ahci_get_port_count(hba->path, &port_count); if (ahci_enumerate_ports(hba->path, port_count, host_base, verbose)) { if (verbose > 0) - pr_err("failed to enumerate ports on SATA controller at %s.\n", hba->pci_id); + pr_err("failed to enumerate ports on %s controller at %s.\n", + get_sys_dev_type(hba->type), hba->pci_id); result |= 2; } } @@ -2817,7 +2861,8 @@ static int export_detail_platform_imsm(int verbose, char *controller_path) if (!find_imsm_capability(hba) && verbose > 0) { char buf[PATH_MAX]; pr_err("IMSM_DETAIL_PLATFORM_ERROR=NO_IMSM_CAPABLE_DEVICE_UNDER_%s\n", - hba->type == SYS_DEV_VMD ? vmd_domain_to_controller(hba, buf) : hba->path); + hba->type == SYS_DEV_VMD || hba->type == SYS_DEV_SATA_VMD ? + vmd_domain_to_controller(hba, buf) : hba->path); } else result = 0; @@ -2826,7 +2871,7 @@ static int export_detail_platform_imsm(int verbose, char *controller_path) const struct orom_entry *entry; for (entry = orom_entries; entry; entry = entry->next) { - if (entry->type == SYS_DEV_VMD) { + if (entry->type == SYS_DEV_VMD || entry->type == SYS_DEV_SATA_VMD) { for (hba = list; hba; hba = hba->next) print_imsm_capability_export(&entry->orom); continue; @@ -4722,7 +4767,7 @@ static int find_intel_hba_capability(int fd, struct intel_super *super, char *de devname); return 1; } - if (!is_fd_valid(fd) || check_env("IMSM_NO_PLATFORM")) { + if (!is_fd_valid(fd) || check_no_platform()) { super->orom = NULL; super->hba = NULL; return 0; @@ -4743,10 +4788,12 @@ static int find_intel_hba_capability(int fd, struct intel_super *super, char *de " but the container is assigned to Intel(R) %s %s (", devname, get_sys_dev_type(hba_name->type), - hba_name->type == SYS_DEV_VMD ? "domain" : "RAID controller", + hba_name->type == SYS_DEV_VMD || hba_name->type == SYS_DEV_SATA_VMD ? + "domain" : "RAID controller", hba_name->pci_id ? : "Err!", get_sys_dev_type(super->hba->type), - hba->type == SYS_DEV_VMD ? "domain" : "RAID controller"); + hba->type == SYS_DEV_VMD || hba_name->type == SYS_DEV_SATA_VMD ? + "domain" : "RAID controller"); while (hba) { fprintf(stderr, "%s", hba->pci_id ? : "Err!"); @@ -10697,7 +10744,7 @@ static int imsm_get_allowed_degradation(int level, int raid_disks, ******************************************************************************/ int validate_container_imsm(struct mdinfo *info) { - if (check_env("IMSM_NO_PLATFORM")) + if (check_no_platform()) return 0; struct sys_dev *idev; @@ -11235,7 +11282,7 @@ static const char *imsm_get_disk_controller_domain(const char *path) hba = find_disk_attached_hba(-1, path); if (hba && hba->type == SYS_DEV_SAS) drv = "isci"; - else if (hba && hba->type == SYS_DEV_SATA) + else if (hba && (hba->type == SYS_DEV_SATA || hba->type == SYS_DEV_SATA_VMD)) drv = "ahci"; else if (hba && hba->type == SYS_DEV_VMD) drv = "vmd"; diff --git a/super1.c b/super1.c index f702032..856b020 100644 --- a/super1.c +++ b/super1.c @@ -192,7 +192,7 @@ static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb) unsigned int disk_csum, csum; unsigned long long newcsum; int size = sizeof(*sb) + __le32_to_cpu(sb->max_dev)*2; - unsigned int *isuper = (unsigned int*)sb; + unsigned int *isuper = (unsigned int *)sb; /* make sure I can count... */ if (offsetof(struct mdp_superblock_1,data_offset) != 128 || @@ -204,7 +204,7 @@ static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb) disk_csum = sb->sb_csum; sb->sb_csum = 0; newcsum = 0; - for (; size>=4; size -= 4 ) { + for (; size >= 4; size -= 4) { newcsum += __le32_to_cpu(*isuper); isuper++; } @@ -319,7 +319,7 @@ static inline unsigned int choose_ppl_space(int chunk) static void examine_super1(struct supertype *st, char *homehost) { struct mdp_superblock_1 *sb = st->sb; - bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb)+MAX_SB_SIZE); + bitmap_super_t *bms = (bitmap_super_t *)(((char *)sb) + MAX_SB_SIZE); time_t atime; unsigned int d; int role; @@ -343,8 +343,9 @@ static void examine_super1(struct supertype *st, char *homehost) printf(".0\n"); printf(" Feature Map : 0x%x\n", __le32_to_cpu(sb->feature_map)); printf(" Array UUID : "); - for (i=0; i<16; i++) { - if ((i&3)==0 && i != 0) printf(":"); + for (i = 0; i < 16; i++) { + if ((i & 3) == 0 && i != 0) + printf(":"); printf("%02x", sb->set_uuid[i]); } printf("\n"); @@ -416,11 +417,11 @@ static void examine_super1(struct supertype *st, char *homehost) UINT64_MAX - info.space_after); } printf(" State : %s%s\n", - (__le64_to_cpu(sb->resync_offset)+1) ? "active":"clean", + (__le64_to_cpu(sb->resync_offset) + 1) ? "active":"clean", (info.space_after > INT64_MAX) ? " TRUNCATED DEVICE" : ""); printf(" Device UUID : "); - for (i=0; i<16; i++) { - if ((i&3)==0 && i != 0) + for (i = 0; i < 16; i++) { + if ((i & 3)==0 && i != 0) printf(":"); printf("%02x", sb->device_uuid[i]); } @@ -546,7 +547,7 @@ static void examine_super1(struct supertype *st, char *homehost) #if 0 /* This turns out to just be confusing */ printf(" Array Slot : %d (", __le32_to_cpu(sb->dev_number)); - for (i = __le32_to_cpu(sb->max_dev); i> 0 ; i--) + for (i = __le32_to_cpu(sb->max_dev); i > 0 ; i--) if (__le16_to_cpu(sb->dev_roles[i-1]) != MD_DISK_ROLE_SPARE) break; for (d = 0; d < i; d++) { @@ -597,7 +598,7 @@ static void examine_super1(struct supertype *st, char *homehost) #if 0 /* This is confusing too */ faulty = 0; - for (i = 0; i< __le32_to_cpu(sb->max_dev); i++) { + for (i = 0; i < __le32_to_cpu(sb->max_dev); i++) { int role = __le16_to_cpu(sb->dev_roles[i]); if (role == MD_DISK_ROLE_FAULTY) faulty++; @@ -616,10 +617,12 @@ static void examine_super1(struct supertype *st, char *homehost) if (inconsistent) { printf("WARNING Array state is inconsistent - each number should appear only once\n"); for (d = 0; d < __le32_to_cpu(sb->max_dev); d++) - if (__le16_to_cpu(sb->dev_roles[d]) >= MD_DISK_ROLE_FAULTY) + if (__le16_to_cpu(sb->dev_roles[d]) >= + MD_DISK_ROLE_FAULTY) printf(" %d:-", d); else - printf(" %d:%d", d, __le16_to_cpu(sb->dev_roles[d])); + printf(" %d:%d", d, + __le16_to_cpu(sb->dev_roles[d])); printf("\n"); } } @@ -642,8 +645,7 @@ static void brief_examine_super1(struct supertype *st, int verbose) printf("ARRAY "); if (nm) { - printf("/dev/md/"); - print_escape(nm); + printf(DEV_MD_DIR "%s", nm); putchar(' '); } if (verbose && c) @@ -659,7 +661,7 @@ static void brief_examine_super1(struct supertype *st, int verbose) printf("num-devices=%d ", __le32_to_cpu(sb->raid_disks)); printf("UUID="); for (i = 0; i < 16; i++) { - if ((i&3)==0 && i != 0) + if ((i & 3)==0 && i != 0) printf(":"); printf("%02x", sb->set_uuid[i]); } @@ -713,7 +715,7 @@ static void export_examine_super1(struct supertype *st) } printf("MD_UUID="); for (i = 0; i < 16; i++) { - if ((i&3) == 0 && i != 0) + if ((i & 3) == 0 && i != 0) printf(":"); printf("%02x", sb->set_uuid[i]); } @@ -722,7 +724,7 @@ static void export_examine_super1(struct supertype *st) __le64_to_cpu(sb->utime) & 0xFFFFFFFFFFULL); printf("MD_DEV_UUID="); for (i = 0; i < 16; i++) { - if ((i&3) == 0 && i != 0) + if ((i & 3) == 0 && i != 0) printf(":"); printf("%02x", sb->device_uuid[i]); } @@ -812,7 +814,7 @@ static int copy_metadata1(struct supertype *st, int from, int to) /* have the header, can calculate * correct bitmap bytes */ bitmap_super_t *bms; - bms = (void*)buf; + bms = (void *)buf; bytes = calc_bitmap_size(bms, 512); if (n > bytes) n = bytes; @@ -867,7 +869,7 @@ err: static void detail_super1(struct supertype *st, char *homehost, char *subarray) { struct mdp_superblock_1 *sb = st->sb; - bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + MAX_SB_SIZE); + bitmap_super_t *bms = (bitmap_super_t *)(((char *)sb) + MAX_SB_SIZE); int i; int l = homehost ? strlen(homehost) : 0; @@ -880,7 +882,7 @@ static void detail_super1(struct supertype *st, char *homehost, char *subarray) printf("\n Cluster Name : %-64s", bms->cluster_name); printf("\n UUID : "); for (i = 0; i < 16; i++) { - if ((i&3) == 0 && i != 0) + if ((i & 3) == 0 && i != 0) printf(":"); printf("%02x", sb->set_uuid[i]); } @@ -939,7 +941,7 @@ static int examine_badblocks_super1(struct supertype *st, int fd, char *devname) } size = __le16_to_cpu(sb->bblog_size)* 512; - if (posix_memalign((void**)&bbl, 4096, size) != 0) { + if (posix_memalign((void **)&bbl, 4096, size) != 0) { pr_err("could not allocate badblocks list\n"); return 0; } @@ -987,7 +989,7 @@ static int match_home1(struct supertype *st, char *homehost) static void uuid_from_super1(struct supertype *st, int uuid[4]) { struct mdp_superblock_1 *super = st->sb; - char *cuuid = (char*)uuid; + char *cuuid = (char *)uuid; int i; for (i = 0; i < 16; i++) cuuid[i] = super->set_uuid[i]; @@ -996,9 +998,9 @@ static void uuid_from_super1(struct supertype *st, int uuid[4]) static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map) { struct mdp_superblock_1 *sb = st->sb; - struct bitmap_super_s *bsb = (void*)(((char*)sb)+MAX_SB_SIZE); + struct bitmap_super_s *bsb = (void *)(((char *)sb) + MAX_SB_SIZE); struct misc_dev_info *misc = - (void*)(((char*)sb)+MAX_SB_SIZE+BM_SUPER_SIZE); + (void *)(((char *)sb) + MAX_SB_SIZE+BM_SUPER_SIZE); int working = 0; unsigned int i; unsigned int role; @@ -1166,7 +1168,7 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map) info->recovery_blocked = info->reshape_active; if (map) - for (i=0; imax_dev); i++) { role = __le16_to_cpu(sb->dev_roles[i]); @@ -1217,7 +1219,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info, */ int rv = 0; struct mdp_superblock_1 *sb = st->sb; - bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + MAX_SB_SIZE); + bitmap_super_t *bms = (bitmap_super_t *)(((char *)sb) + MAX_SB_SIZE); if (update == UOPT_HOMEHOST && homehost) { /* @@ -1228,9 +1230,10 @@ static int update_super1(struct supertype *st, struct mdinfo *info, update = UOPT_NAME; c = strchr(sb->set_name, ':'); if (c) - snprintf(info->name, sizeof(info->name), "%s", c+1); + snprintf(info->name, sizeof(info->name), "%s", c + 1); else - snprintf(info->name, sizeof(info->name), "%s", sb->set_name); + snprintf(info->name, sizeof(info->name), "%s", + sb->set_name); } switch (update) { @@ -1331,7 +1334,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info, sb->dev_number = __cpu_to_le32(i); if (i == max) - sb->max_dev = __cpu_to_le32(max+1); + sb->max_dev = __cpu_to_le32(max + 1); if (i > max) return -2; @@ -1350,8 +1353,8 @@ static int update_super1(struct supertype *st, struct mdinfo *info, sb->data_size = __cpu_to_le64( ds - __le64_to_cpu(sb->data_offset)); } else { - ds -= 8*2; - ds &= ~(unsigned long long)(4*2-1); + ds -= 8 * 2; + ds &= ~(unsigned long long)(4 * 2 - 1); sb->super_offset = __cpu_to_le64(ds); sb->data_size = __cpu_to_le64( ds - __le64_to_cpu(sb->data_offset)); @@ -1367,7 +1370,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info, if (i > max) return -2; if (i == max) - sb->max_dev = __cpu_to_le32(max+1); + sb->max_dev = __cpu_to_le32(max + 1); sb->raid_disks = __cpu_to_le32(info->array.raid_disks); sb->dev_roles[info->disk.number] = __cpu_to_le16(info->disk.raid_disk); @@ -1645,7 +1648,7 @@ static int init_super1(struct supertype *st, mdu_array_info_t *info, char defname[10]; int sbsize; - if (posix_memalign((void**)&sb, 4096, SUPER1_SIZE) != 0) { + if (posix_memalign((void **)&sb, 4096, SUPER1_SIZE) != 0) { pr_err("could not allocate superblock\n"); return 0; } @@ -1679,8 +1682,8 @@ static int init_super1(struct supertype *st, mdu_array_info_t *info, name = defname; } if (homehost && - strchr(name, ':')== NULL && - strlen(homehost)+1+strlen(name) < 32) { + strchr(name, ':') == NULL && + strlen(homehost) + 1 + strlen(name) < 32) { strcpy(sb->set_name, homehost); strcat(sb->set_name, ":"); strcat(sb->set_name, name); @@ -1759,7 +1762,7 @@ static int add_to_super1(struct supertype *st, mdu_disk_info_t *dk, if (dk->number >= (int)__le32_to_cpu(sb->max_dev) && __le32_to_cpu(sb->max_dev) < MAX_DEVS) - sb->max_dev = __cpu_to_le32(dk->number+1); + sb->max_dev = __cpu_to_le32(dk->number + 1); sb->dev_number = __cpu_to_le32(dk->number); sb->devflags = 0; /* don't copy another disks flags */ @@ -1840,8 +1843,8 @@ static int store_super1(struct supertype *st, int fd) return 4; if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) { - struct bitmap_super_s *bm = (struct bitmap_super_s*) - (((char*)sb)+MAX_SB_SIZE); + struct bitmap_super_s *bm; + bm = (struct bitmap_super_s *)(((char *)sb) + MAX_SB_SIZE); if (__le32_to_cpu(bm->magic) == BITMAP_MAGIC) { locate_bitmap1(st, fd, 0); if (awrite(&afd, bm, sizeof(*bm)) != sizeof(*bm)) @@ -1928,7 +1931,7 @@ static int write_empty_r5l_meta_block(struct supertype *st, int fd) init_afd(&afd, fd); - if (posix_memalign((void**)&mb, 4096, META_BLOCK_SIZE) != 0) { + if (posix_memalign((void **)&mb, 4096, META_BLOCK_SIZE) != 0) { pr_err("Could not allocate memory for the meta block.\n"); return 1; } @@ -2029,11 +2032,6 @@ static int write_init_super1(struct supertype *st) /* same array, so preserve events and * dev_number */ sb->events = refsb->events; - /* bugs in 2.6.17 and earlier mean the - * dev_number chosen in Manage must be preserved - */ - if (get_linux_version() >= 2006018) - sb->dev_number = refsb->dev_number; } free_super1(refst); } @@ -2197,7 +2195,7 @@ static int compare_super1(struct supertype *st, struct supertype *tst, return 1; if (!first) { - if (posix_memalign((void**)&first, 4096, SUPER1_SIZE) != 0) { + if (posix_memalign((void **)&first, 4096, SUPER1_SIZE) != 0) { pr_err("could not allocate superblock\n"); return 1; } @@ -2310,7 +2308,7 @@ static int load_super1(struct supertype *st, int fd, char *devname) return 1; } - if (posix_memalign((void**)&super, 4096, SUPER1_SIZE) != 0) { + if (posix_memalign((void **)&super, 4096, SUPER1_SIZE) != 0) { pr_err("could not allocate superblock\n"); return 1; } @@ -2349,19 +2347,19 @@ static int load_super1(struct supertype *st, int fd, char *devname) return 2; } - bsb = (struct bitmap_super_s *)(((char*)super)+MAX_SB_SIZE); + bsb = (struct bitmap_super_s *)(((char *)super) + MAX_SB_SIZE); misc = (struct misc_dev_info*) - (((char*)super)+MAX_SB_SIZE+BM_SUPER_SIZE); + (((char *)super) + MAX_SB_SIZE+BM_SUPER_SIZE); misc->device_size = dsize; if (st->data_offset == INVALID_SECTORS) st->data_offset = __le64_to_cpu(super->data_offset); if (st->minor_version >= 1 && st->ignore_hw_compat == 0 && - (dsize < (__le64_to_cpu(super->data_offset) + - __le64_to_cpu(super->size)) - || + ((role_from_sb(super) != MD_DISK_ROLE_JOURNAL && + dsize < (__le64_to_cpu(super->data_offset) + + __le64_to_cpu(super->size))) || dsize < (__le64_to_cpu(super->data_offset) + __le64_to_cpu(super->data_size)))) { if (devname) @@ -2390,8 +2388,8 @@ static int load_super1(struct supertype *st, int fd, char *devname) return 0; no_bitmap: - super->feature_map = __cpu_to_le32(__le32_to_cpu(super->feature_map) - & ~MD_FEATURE_BITMAP_OFFSET); + super->feature_map = __cpu_to_le32(__le32_to_cpu(super->feature_map) & + ~MD_FEATURE_BITMAP_OFFSET); return 0; } @@ -2449,7 +2447,7 @@ static __u64 avail_size1(struct supertype *st, __u64 devsize, 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); + bsb = (struct bitmap_super_s *)(((char *)super) + MAX_SB_SIZE); bmspace = calc_bitmap_size(bsb, 4096) >> 9; } else if (md_feature_any_ppl_on(super->feature_map)) { bmspace = __le16_to_cpu(super->ppl.size); @@ -2518,7 +2516,7 @@ add_internal_bitmap1(struct supertype *st, int creating = 0; int len; struct mdp_superblock_1 *sb = st->sb; - bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + MAX_SB_SIZE); + bitmap_super_t *bms = (bitmap_super_t *)(((char *)sb) + MAX_SB_SIZE); int uuid[4]; if (__le64_to_cpu(sb->data_size) == 0) @@ -2606,10 +2604,10 @@ add_internal_bitmap1(struct supertype *st, max_bits = (room * 512 - sizeof(bitmap_super_t)) * 8; min_chunk = 4096; /* sub-page chunks don't work yet.. */ - bits = (size*512)/min_chunk +1; + bits = (size * 512) / min_chunk + 1; while (bits > max_bits) { min_chunk *= 2; - bits = (bits+1)/2; + bits = (bits + 1) / 2; } if (chunk == UnSet) { /* For practical purpose, 64Meg is a good @@ -2627,8 +2625,8 @@ add_internal_bitmap1(struct supertype *st, /* start bitmap on a 4K boundary with enough space for * the bitmap */ - bits = (size*512) / chunk + 1; - room = ((bits+7)/8 + sizeof(bitmap_super_t) +4095)/4096; + bits = (size * 512) / chunk + 1; + room = ((bits + 7) / 8 + sizeof(bitmap_super_t) + 4095) / 4096; room *= 8; /* convert 4K blocks to sectors */ offset = -room - bbl_size; } @@ -2682,7 +2680,7 @@ static int locate_bitmap1(struct supertype *st, int fd, int node_num) offset = __le64_to_cpu(sb->super_offset) + (int32_t)__le32_to_cpu(sb->bitmap_offset); if (node_num) { - bms = (bitmap_super_t*)(((char*)sb)+MAX_SB_SIZE); + bms = (bitmap_super_t *)(((char *)sb) + MAX_SB_SIZE); bm_sectors_per_node = calc_bitmap_size(bms, 4096) >> 9; offset += bm_sectors_per_node * node_num; } @@ -2695,7 +2693,7 @@ static int locate_bitmap1(struct supertype *st, int fd, int node_num) static int write_bitmap1(struct supertype *st, int fd, enum bitmap_update update) { struct mdp_superblock_1 *sb = st->sb; - bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb)+MAX_SB_SIZE); + bitmap_super_t *bms = (bitmap_super_t *)(((char *)sb) + MAX_SB_SIZE); int rv = 0; void *buf; int towrite, n, len; @@ -2969,16 +2967,16 @@ void *super1_make_v0(struct supertype *st, struct mdinfo *info, mdp_super_t *sb0 copy_uuid(sb->set_uuid, info->uuid, super1.swapuuid); sprintf(sb->set_name, "%d", sb0->md_minor); - sb->ctime = __cpu_to_le32(info->array.ctime+1); + sb->ctime = __cpu_to_le32(info->array.ctime + 1); sb->level = __cpu_to_le32(info->array.level); sb->layout = __cpu_to_le32(info->array.layout); sb->size = __cpu_to_le64(info->component_size); - sb->chunksize = __cpu_to_le32(info->array.chunk_size/512); + sb->chunksize = __cpu_to_le32(info->array.chunk_size / 512); sb->raid_disks = __cpu_to_le32(info->array.raid_disks); if (info->array.level > 0) sb->data_size = sb->size; else - sb->data_size = st->ss->avail_size(st, st->devsize/512, 0); + sb->data_size = st->ss->avail_size(st, st->devsize / 512, 0); sb->resync_offset = MaxSector; sb->max_dev = __cpu_to_le32(MD_SB_DISKS); sb->dev_number = __cpu_to_le32(info->disk.number); diff --git a/sysfs.c b/sysfs.c index ca1d888..94d02f5 100644 --- a/sysfs.c +++ b/sysfs.c @@ -1114,7 +1114,7 @@ void sysfsline(char *line) if (strncasecmp(w, "name=", 5) == 0) { char *devname = w + 5; - if (strncmp(devname, "/dev/md/", 8) == 0) { + if (strncmp(devname, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) { if (sr->devname) pr_err("Only give one device per SYSFS line: %s\n", devname); diff --git a/systemd/mdadm-grow-continue@.service b/systemd/mdadm-grow-continue@.service index 9ccadca..64b8254 100644 --- a/systemd/mdadm-grow-continue@.service +++ b/systemd/mdadm-grow-continue@.service @@ -15,4 +15,3 @@ ExecStart=BINDIR/mdadm --grow --continue /dev/%I StandardInput=null StandardOutput=null StandardError=null -KillMode=none diff --git a/systemd/mdcheck_continue.service b/systemd/mdcheck_continue.service index f532490..70892a1 100644 --- a/systemd/mdcheck_continue.service +++ b/systemd/mdcheck_continue.service @@ -13,6 +13,4 @@ Documentation=man:mdadm(8) [Service] Type=oneshot Environment="MDADM_CHECK_DURATION=6 hours" -EnvironmentFile=-/run/sysconfig/mdadm -ExecStartPre=-/usr/lib/mdadm/mdadm_env.sh ExecStart=/usr/share/mdadm/mdcheck --continue --duration ${MDADM_CHECK_DURATION} diff --git a/systemd/mdcheck_start.service b/systemd/mdcheck_start.service index 703a658..fc4fc43 100644 --- a/systemd/mdcheck_start.service +++ b/systemd/mdcheck_start.service @@ -13,6 +13,4 @@ Documentation=man:mdadm(8) [Service] Type=oneshot Environment="MDADM_CHECK_DURATION=6 hours" -EnvironmentFile=-/run/sysconfig/mdadm -ExecStartPre=-/usr/lib/mdadm/mdadm_env.sh ExecStart=/usr/share/mdadm/mdcheck --duration ${MDADM_CHECK_DURATION} diff --git a/systemd/mdmon@.service b/systemd/mdmon@.service index cb6482d..020cc7e 100644 --- a/systemd/mdmon@.service +++ b/systemd/mdmon@.service @@ -6,24 +6,25 @@ # (at your option) any later version. [Unit] -Description=MD Metadata Monitor on /dev/%I +Description=MD Metadata Monitor on %I DefaultDependencies=no Before=initrd-switch-root.target Documentation=man:mdmon(8) +# Allow mdmon to keep running after switchroot, until a new +# instance is started. +IgnoreOnIsolate=true [Service] -# mdmon should never complain due to lack of a platform, -# that is mdadm's job if at all. -Environment=IMSM_NO_PLATFORM=1 # The mdmon starting in the initramfs (with dracut at least) # cannot see sysfs after root is mounted, so we will have to # 'takeover'. As the '--offroot --takeover' don't hurt when # not necessary, are are useful with root-on-md in dracut, # have them always present. -ExecStart=BINDIR/mdmon --offroot --takeover %I -Type=forking +ExecStart=BINDIR/mdmon --foreground --offroot --takeover %I # Don't set the PIDFile. It isn't necessary (systemd can work # it out) and systemd will remove it when transitioning from # initramfs to rootfs. #PIDFile=/run/mdadm/%I.pid -KillMode=none +# The default slice is system-mdmon.slice which Conflicts +# with shutdown, causing mdmon to exit early. So use system.slice. +Slice=system.slice diff --git a/udev-md-raid-arrays.rules b/udev-md-raid-arrays.rules index 2967ace..4e64b24 100644 --- a/udev-md-raid-arrays.rules +++ b/udev-md-raid-arrays.rules @@ -38,7 +38,8 @@ ENV{MD_LEVEL}=="raid[1-9]*", ENV{SYSTEMD_WANTS}+="mdmonitor.service" # Tell systemd to run mdmon for our container, if we need it. ENV{MD_LEVEL}=="raid[1-9]*", ENV{MD_CONTAINER}=="?*", PROGRAM="/usr/bin/readlink $env{MD_CONTAINER}", ENV{MD_MON_THIS}="%c" -ENV{MD_MON_THIS}=="?*", PROGRAM="/usr/bin/basename $env{MD_MON_THIS}", ENV{SYSTEMD_WANTS}+="mdmon@%c.service" +ENV{MD_MON_THIS}=="?*", TEST=="/etc/initrd-release", PROGRAM="/usr/bin/basename $env{MD_MON_THIS}", ENV{SYSTEMD_WANTS}+="mdmon@initrd-%c.service" +ENV{MD_MON_THIS}=="?*", TEST!="/etc/initrd-release", PROGRAM="/usr/bin/basename $env{MD_MON_THIS}", ENV{SYSTEMD_WANTS}+="mdmon@%c.service" ENV{RESHAPE_ACTIVE}=="yes", PROGRAM="/usr/bin/basename $env{MD_MON_THIS}", ENV{SYSTEMD_WANTS}+="mdadm-grow-continue@%c.service" LABEL="md_end" diff --git a/util.c b/util.c index 9f1e1f7..fa378eb 100644 --- a/util.c +++ b/util.c @@ -973,6 +973,50 @@ dev_t devnm2devid(char *devnm) return 0; } +/** + * is_devname_numbered() - helper for numbered devname verification. + * @devname: path or name to check. + * @pref: expected devname prefix. + * @pref_len: prefix len. + */ +static bool is_devname_numbered(const char *devname, const char *pref, const int pref_len) +{ + int val; + + assert(devname && pref); + + if (strncmp(devname, pref, pref_len) != 0) + return false; + + if (parse_num(&val, devname + pref_len) != 0) + return false; + + if (val > 127) + return false; + + return true; +} + +/** + * is_devname_md_numbered() - check if &devname is numbered MD device (md). + * @devname: path or name to check. + */ +bool is_devname_md_numbered(const char *devname) +{ + return is_devname_numbered(devname, DEV_NUM_PREF, DEV_NUM_PREF_LEN); +} + +/** + * is_devname_md_d_numbered() - check if &devname is secondary numbered MD device (md_d). + * @devname: path or name to check. + */ +bool is_devname_md_d_numbered(const char *devname) +{ + static const char d_dev[] = DEV_NUM_PREF "_d"; + + return is_devname_numbered(devname, d_dev, sizeof(d_dev) - 1); +} + /** * get_md_name() - Get main dev node of the md device. * @devnm: Md device name or path. @@ -1916,6 +1960,7 @@ int start_mdmon(char *devnm) int len; pid_t pid; int status; + char *prefix = in_initrd() ? "initrd-" : ""; char pathbuf[1024]; char *paths[4] = { pathbuf, @@ -1926,7 +1971,7 @@ int start_mdmon(char *devnm) if (check_env("MDADM_NO_MDMON")) return 0; - if (continue_via_systemd(devnm, MDMON_SERVICE)) + if (continue_via_systemd(devnm, MDMON_SERVICE, prefix)) return 0; /* That failed, try running mdmon directly */ @@ -2197,7 +2242,7 @@ void manage_fork_fds(int close_all) * 1- if systemd service has been started * 0- otherwise */ -int continue_via_systemd(char *devnm, char *service_name) +int continue_via_systemd(char *devnm, char *service_name, char *prefix) { int pid, status; char pathbuf[1024]; @@ -2209,7 +2254,7 @@ int continue_via_systemd(char *devnm, char *service_name) case 0: manage_fork_fds(1); snprintf(pathbuf, sizeof(pathbuf), - "%s@%s.service", service_name, devnm); + "%s@%s%s.service", service_name, prefix ?: "", devnm); status = execl("/usr/bin/systemctl", "systemctl", "restart", pathbuf, NULL); status = execl("/bin/systemctl", "systemctl", "restart", @@ -2227,15 +2272,7 @@ int continue_via_systemd(char *devnm, char *service_name) int in_initrd(void) { - /* This is based on similar function in systemd. */ - struct statfs s; - /* statfs.f_type is signed long on s390x and MIPS, causing all - sorts of sign extension problems with RAMFS_MAGIC being - defined as 0x858458f6 */ - return statfs("/", &s) >= 0 && - ((unsigned long)s.f_type == TMPFS_MAGIC || - ((unsigned long)s.f_type & 0xFFFFFFFFUL) == - ((unsigned long)RAMFS_MAGIC & 0xFFFFFFFFUL)); + return access("/etc/initrd-release", F_OK) >= 0; } void reopen_mddev(int mdfd) -- cgit v1.2.3