summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/dependabot.yml6
-rw-r--r--.github/tools/.checkpatch.conf10
-rwxr-xr-x.github/tools/install_ubuntu_packages.sh12
-rw-r--r--.github/workflows/review.yml41
-rw-r--r--Assemble.c98
-rw-r--r--Build.c12
-rw-r--r--Create.c50
-rw-r--r--Detail.c2
-rw-r--r--Dump.c11
-rw-r--r--Grow.c169
-rw-r--r--MAINTAINERS.md41
-rw-r--r--Makefile12
-rw-r--r--Manage.c151
-rw-r--r--Monitor.c12
-rw-r--r--Query.c4
-rw-r--r--README.md86
-rw-r--r--clustermd_tests/02r10_Manage_re-add3
-rw-r--r--clustermd_tests/02r1_Manage_re-add1
-rw-r--r--clustermd_tests/03r10_switch-recovery4
-rw-r--r--clustermd_tests/03r1_switch-recovery4
-rw-r--r--clustermd_tests/func.sh60
-rw-r--r--config.c79
-rw-r--r--drive_encryption.c14
-rw-r--r--lib.c4
-rw-r--r--mapfile.c6
-rw-r--r--mdadm.8.in34
-rw-r--r--mdadm.c72
-rw-r--r--mdadm.h44
-rw-r--r--mdstat.c3
-rw-r--r--msg.c2
-rw-r--r--platform-intel.c62
-rw-r--r--platform-intel.h32
-rw-r--r--super-ddf.c180
-rw-r--r--super-intel.c489
-rwxr-xr-xtest36
-rw-r--r--tests/01r5fail6
-rw-r--r--tests/01r5integ.broken7
-rw-r--r--tests/01raid6integ.broken7
-rw-r--r--tests/03assem-incr22
-rw-r--r--tests/03r0assem10
-rw-r--r--tests/03r5assem-failed12
-rw-r--r--tests/03r5assemV117
-rw-r--r--tests/04r5swap.broken7
-rw-r--r--tests/04update-metadata35
-rw-r--r--tests/04update-uuid4
-rw-r--r--tests/05r1-bitmapfile49
-rw-r--r--tests/05r1-grow-external33
-rw-r--r--tests/05r1-grow-internal11
-rw-r--r--tests/05r1-grow-internal-112
-rw-r--r--tests/05r1-internalbitmap22
-rw-r--r--tests/05r1-internalbitmap-v1a22
-rw-r--r--tests/05r1-internalbitmap-v1b23
-rw-r--r--tests/05r1-internalbitmap-v1c22
-rw-r--r--tests/05r1-n3-bitmapfile53
-rw-r--r--tests/05r1-re-add-nosuper2
-rw-r--r--tests/05r5-bitmapfile49
-rw-r--r--tests/05r5-internalbitmap21
-rw-r--r--tests/05r6-bitmapfile49
-rw-r--r--tests/06name12
-rw-r--r--tests/07autoassemble40
-rw-r--r--tests/07autoassemble.broken8
-rw-r--r--tests/07autodetect.broken5
-rw-r--r--tests/07changelevelintr9
-rw-r--r--tests/07changelevelintr.broken9
-rw-r--r--tests/07revert-grow2
-rw-r--r--tests/07revert-inplace2
-rw-r--r--tests/23rdev-lifetime2
-rw-r--r--tests/func.sh98
-rw-r--r--tests/templates/names_template16
-rw-r--r--util.c121
70 files changed, 1462 insertions, 1203 deletions
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..1230149
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,6 @@
+version: 2
+updates:
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "daily"
diff --git a/.github/tools/.checkpatch.conf b/.github/tools/.checkpatch.conf
new file mode 100644
index 0000000..d6e3bc4
--- /dev/null
+++ b/.github/tools/.checkpatch.conf
@@ -0,0 +1,10 @@
+--no-tree
+--show-types
+--exclude .github
+--exclude clustermd_tests
+--exclude documentation
+--exclude misc
+--exclude systemd
+--exclude tests
+--ignore FILE_PATH_CHANGES
+--ignore EMAIL_SUBJECT
diff --git a/.github/tools/install_ubuntu_packages.sh b/.github/tools/install_ubuntu_packages.sh
new file mode 100755
index 0000000..1a31ca4
--- /dev/null
+++ b/.github/tools/install_ubuntu_packages.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/bash
+
+VERSION_CODENAME=$(grep -oP '(?<=^VERSION_CODENAME=).+' /etc/os-release | tr -d '"')
+echo "Detected VERSION_CODENAME: $VERSION_CODENAME"
+
+# Add ubuntu repository
+sudo add-apt-repository -y "deb [arch=amd64] http://archive.ubuntu.com/ubuntu $VERSION_CODENAME \
+ main universe"
+# Install gcc
+sudo apt-get -y update && sudo apt-get -y install gcc-$1
+# Install dependencies
+sudo apt-get -y install make gcc libudev-dev devscripts
diff --git a/.github/workflows/review.yml b/.github/workflows/review.yml
new file mode 100644
index 0000000..3fa29f6
--- /dev/null
+++ b/.github/workflows/review.yml
@@ -0,0 +1,41 @@
+name: review
+on: [pull_request]
+env:
+ cflags: -Werror
+jobs:
+ make:
+ runs-on: ubuntu-latest
+ name: Compilation test with gcc
+ strategy:
+ matrix:
+ gcc-version: [7, 8, 9, 10, 11, 12, 13]
+ steps:
+ - uses: actions/checkout@v4
+ - name: 'Add ubuntu repository and install dependencies'
+ run: .github/tools/install_ubuntu_packages.sh ${{ matrix.gcc-version }}
+ - name: 'Make with DEBUG flag'
+ run: CC=gcc-${{ matrix.gcc-version }} && V=1 make -j$(nproc) -B CXFLAGS=-DEBUG && make clean
+ - name: 'Make with DEBIAN flag'
+ run: CC=gcc-${{ matrix.gcc-version }} && V=1 make -j$(nproc) -B CXGALGS=-DEBIAN && make clean
+ - name: 'Make with USE_PTHREADS flag'
+ run: CC=gcc-${{ matrix.gcc-version }} && V=1 make -j$(nproc) -B CXFLAGS=-USE_PTHREADS && make clean
+ - name: 'Make with DNO_LIBUDEV flag'
+ run: CC=gcc-${{ matrix.gcc-version }} && V=1 make -j$(nproc) -B CXFLAGS=-DNO_LIBUDEV && make clean
+ - name: 'Make'
+ run: CC=gcc-${{ matrix.gcc-version }} && V=1 make -j$(nproc)
+ - name: hardening-check mdadm
+ run: hardening-check mdadm
+ - name: hardening-check mdmon
+ run: hardening-check mdmon
+ checkpatch:
+ runs-on: ubuntu-latest
+ name: checkpatch review
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ ref: ${{ github.event.pull_request.head.sha }}
+ fetch-depth: 0
+ - name: 'Move prepared .checkpatch.conf file to main directory'
+ run: mv .github/tools/.checkpatch.conf .
+ - name: Run checkpatch review
+ uses: webispy/checkpatch-action@v9
diff --git a/Assemble.c b/Assemble.c
index f6c5b99..77f2b50 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -567,6 +567,9 @@ static int select_devices(struct mddev_dev *devlist,
tmpdev->used = 1;
content = *contentp;
+ if (!st)
+ return -1;
+
if (!st->sb) {
/* we need sb from one of the spares */
int dfd = dev_open(tmpdev->devname, O_RDONLY);
@@ -652,7 +655,9 @@ static int load_devices(struct devs *devices, char *devmap,
/* prepare useful information in info structures */
struct stat stb2;
int err;
- fstat(mdfd, &stb2);
+
+ if (fstat(mdfd, &stb2) != 0)
+ goto error;
if (c->update == UOPT_UUID && !ident->uuid_set)
random_uuid((__u8 *)ident->uuid);
@@ -675,13 +680,10 @@ static int load_devices(struct devs *devices, char *devmap,
devname);
if (dfd >= 0)
close(dfd);
- close(mdfd);
- free(devices);
- free(devmap);
tst->ss->free_super(tst);
free(tst);
*stp = st;
- return -1;
+ goto error;
}
tst->ss->getinfo_super(tst, content, devmap + devcnt * content->array.raid_disks);
@@ -715,12 +717,9 @@ static int load_devices(struct devs *devices, char *devmap,
map_num(update_options, c->update), tst->ss->name);
tst->ss->free_super(tst);
free(tst);
- close(mdfd);
close(dfd);
- free(devices);
- free(devmap);
*stp = st;
- return -1;
+ goto error;
}
if (c->update == UOPT_UUID &&
!ident->uuid_set) {
@@ -751,18 +750,23 @@ static int load_devices(struct devs *devices, char *devmap,
devname);
if (dfd >= 0)
close(dfd);
- close(mdfd);
- free(devices);
- free(devmap);
tst->ss->free_super(tst);
free(tst);
*stp = st;
- return -1;
+ goto error;
}
tst->ss->getinfo_super(tst, content, devmap + devcnt * content->array.raid_disks);
}
- fstat(dfd, &stb);
+ if (fstat(dfd, &stb) != 0) {
+ close(dfd);
+ free(devices);
+ free(devmap);
+ tst->ss->free_super(tst);
+ free(tst);
+ *stp = st;
+ return -1;
+ }
close(dfd);
if (c->verbose > 0)
@@ -814,12 +818,12 @@ static int load_devices(struct devs *devices, char *devmap,
if (i >= bestcnt) {
int newbestcnt = i+10;
int *newbest = xmalloc(sizeof(int)*newbestcnt);
- int c;
- for (c=0; c < newbestcnt; c++)
- if (c < bestcnt)
- newbest[c] = best[c];
+ int cc;
+ for (cc = 0; cc < newbestcnt; cc++)
+ if (cc < bestcnt)
+ newbest[cc] = best[cc];
else
- newbest[c] = -1;
+ newbest[cc] = -1;
if (best)free(best);
best = newbest;
bestcnt = newbestcnt;
@@ -842,12 +846,9 @@ static int load_devices(struct devs *devices, char *devmap,
inargv ? "the list" :
"the\n DEVICE list in mdadm.conf"
);
- close(mdfd);
- free(devices);
- free(devmap);
free(best);
*stp = st;
- return -1;
+ goto error;
}
if (best[i] == -1 || (devices[best[i]].i.events
< devices[devcnt].i.events))
@@ -863,6 +864,13 @@ static int load_devices(struct devs *devices, char *devmap,
*bestp = best;
*stp = st;
return devcnt;
+
+error:
+ close(mdfd);
+ free(devices);
+ free(devmap);
+ return -1;
+
}
static int force_array(struct mdinfo *content,
@@ -1197,9 +1205,7 @@ static int start_array(int mdfd,
rv = sysfs_set_str(content, NULL,
"array_state", "readonly");
if (rv == 0)
- rv = Grow_continue(mdfd, st, content,
- c->backup_file, 0,
- c->freeze_reshape);
+ rv = Grow_continue(mdfd, st, content, 0, c);
} else if (c->readonly &&
sysfs_attribute_available(content, NULL,
"array_state")) {
@@ -1211,23 +1217,19 @@ static int start_array(int mdfd,
if (rv == 0) {
sysfs_rules_apply(mddev, content);
if (c->verbose >= 0) {
- pr_err("%s has been started with %d drive%s",
+ pr_info("%s has been started with %d drive%s",
mddev, okcnt, okcnt==1?"":"s");
if (okcnt < (unsigned)content->array.raid_disks)
- fprintf(stderr, " (out of %d)",
- content->array.raid_disks);
+ printf(" (out of %d)", content->array.raid_disks);
if (rebuilding_cnt)
- fprintf(stderr, "%s %d rebuilding",
- sparecnt?",":" and",
+ printf("%s %d rebuilding", sparecnt?",":" and",
rebuilding_cnt);
if (sparecnt)
- fprintf(stderr, " and %d spare%s",
- sparecnt,
+ printf(" and %d spare%s", sparecnt,
sparecnt == 1 ? "" : "s");
if (content->journal_clean)
- fprintf(stderr, " and %d journal",
- journalcnt);
- fprintf(stderr, ".\n");
+ printf(" and %d journal", journalcnt);
+ printf(".\n");
}
if (content->reshape_active &&
is_level456(content->array.level)) {
@@ -1494,8 +1496,11 @@ try_again:
mp = map_by_uuid(&map, content->uuid);
if (mp) {
struct mdinfo *dv;
- /* array already exists. */
pre_exist = sysfs_read(-1, mp->devnm, GET_LEVEL|GET_DEVS);
+ if (!pre_exist)
+ goto out;
+
+ /* array already exists. */
if (pre_exist->array.level != UnSet) {
pr_err("Found some drive for an array that is already active: %s\n",
mp->path);
@@ -1607,6 +1612,7 @@ try_again:
err = assemble_container_content(st, mdfd, content, c,
chosen_name, NULL);
close(mdfd);
+ sysfs_free(pre_exist);
return err;
}
@@ -1746,23 +1752,27 @@ try_again:
: (O_RDONLY|O_EXCL)))< 0) {
pr_err("Cannot open %s: %s\n",
devices[j].devname, strerror(errno));
+ free(avail);
goto out;
}
if (st->ss->load_super(st,fd, NULL)) {
close(fd);
pr_err("RAID superblock has disappeared from %s\n",
devices[j].devname);
+ free(avail);
goto out;
}
close(fd);
}
if (st->sb == NULL) {
pr_err("No suitable drives found for %s\n", mddev);
+ free(avail);
goto out;
}
st->ss->getinfo_super(st, content, NULL);
if (sysfs_init(content, mdfd, NULL)) {
pr_err("Unable to initialize sysfs\n");
+ free(avail);
goto out;
}
@@ -1825,12 +1835,14 @@ try_again:
if (fd < 0) {
pr_err("Could not open %s for write - cannot Assemble array.\n",
devices[chosen_drive].devname);
+ free(avail);
goto out;
}
if (st->ss->store_super(st, fd)) {
close(fd);
pr_err("Could not re-write superblock on %s\n",
devices[chosen_drive].devname);
+ free(avail);
goto out;
}
if (c->verbose >= 0)
@@ -1889,6 +1901,7 @@ try_again:
pr_err("Failed to restore critical section for reshape, sorry.\n");
if (c->backup_file == NULL)
cont_err("Possibly you needed to specify the --backup-file\n");
+ free(avail);
goto out;
}
}
@@ -1917,6 +1930,7 @@ try_again:
if (rv == 1 && !pre_exist)
ioctl(mdfd, STOP_ARRAY, NULL);
free(devices);
+ free(avail);
out:
map_unlock(&map);
if (rv == 0) {
@@ -1952,11 +1966,14 @@ out:
close(mdfd);
free(best);
+ sysfs_free(pre_exist);
+
/* '2' means 'OK, but not started yet' */
if (rv == -1) {
free(devices);
return 1;
}
+ close(mdfd);
return rv == 2 ? 0 : rv;
}
@@ -2175,13 +2192,12 @@ int assemble_container_content(struct supertype *st, int mdfd,
if (!mdmon_running(st->container_devnm))
start_mdmon(st->container_devnm);
ping_monitor(st->container_devnm);
- if (mdmon_running(st->container_devnm) &&
- st->update_tail == NULL)
+ if (wait_for_mdmon(st->container_devnm) == MDADM_STATUS_SUCCESS &&
+ !st->update_tail)
st->update_tail = &st->updates;
}
- err = Grow_continue(mdfd, st, content, c->backup_file,
- 0, c->freeze_reshape);
+ err = Grow_continue(mdfd, st, content, 0, c);
} else switch(content->array.level) {
case LEVEL_LINEAR:
case LEVEL_MULTIPATH:
diff --git a/Build.c b/Build.c
index 1be90e4..052b1bc 100644
--- a/Build.c
+++ b/Build.c
@@ -168,13 +168,13 @@ int Build(struct mddev_ident *ident, struct mddev_dev *devlist, struct shape *s,
goto abort;
}
}
- if (bitmap_fd >= 0) {
- if (ioctl(mdfd, SET_BITMAP_FILE, bitmap_fd) < 0) {
- pr_err("Cannot set bitmap file for %s: %s\n", chosen_name,
- strerror(errno));
- goto abort;
- }
+ if (ioctl(mdfd, SET_BITMAP_FILE, bitmap_fd) < 0) {
+ pr_err("Cannot set bitmap file for %s: %s\n", chosen_name,
+ strerror(errno));
+ close(bitmap_fd);
+ goto abort;
}
+ close(bitmap_fd);
}
if (ioctl(mdfd, RUN_ARRAY, &param)) {
pr_err("RUN_ARRAY failed: %s\n", strerror(errno));
diff --git a/Create.c b/Create.c
index d94253b..7fde1c1 100644
--- a/Create.c
+++ b/Create.c
@@ -178,6 +178,7 @@ static int wait_for_zero_forks(int *zero_pids, int count)
bool interrupted = false;
sigset_t sigset;
ssize_t s;
+ pid_t pid;
for (i = 0; i < count; i++)
if (zero_pids[i])
@@ -196,7 +197,7 @@ static int wait_for_zero_forks(int *zero_pids, int count)
return 1;
}
- while (1) {
+ while (wait_count) {
s = read(sfd, &fdsi, sizeof(fdsi));
if (s != sizeof(fdsi)) {
pr_err("Invalid signalfd read: %s\n", strerror(errno));
@@ -209,23 +210,24 @@ static int wait_for_zero_forks(int *zero_pids, int count)
pr_info("Interrupting zeroing processes, please wait...\n");
interrupted = true;
} else if (fdsi.ssi_signo == SIGCHLD) {
- if (!--wait_count)
- break;
+ for (i = 0; i < count; i++) {
+ if (!zero_pids[i])
+ continue;
+
+ pid = waitpid(zero_pids[i], &wstatus, WNOHANG);
+ if (pid <= 0)
+ continue;
+
+ zero_pids[i] = 0;
+ if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus))
+ ret = 1;
+ wait_count--;
+ }
}
}
close(sfd);
- for (i = 0; i < count; i++) {
- if (!zero_pids[i])
- continue;
-
- waitpid(zero_pids[i], &wstatus, 0);
- zero_pids[i] = 0;
- if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus))
- ret = 1;
- }
-
if (interrupted) {
pr_err("zeroing interrupted!\n");
return 1;
@@ -295,7 +297,7 @@ static int add_disk_to_super(int mdfd, struct shape *s, struct context *c,
if (st->ss->add_to_super(st, &info->disk, fd, dv->devname,
dv->data_offset)) {
ioctl(mdfd, STOP_ARRAY, NULL);
- close(fd);
+ close_fd(&fd);
return 1;
}
st->ss->getinfo_super(st, info, NULL);
@@ -399,6 +401,7 @@ static int add_disks(int mdfd, struct mdinfo *info, struct shape *s,
*/
sigemptyset(&sigset);
sigaddset(&sigset, SIGINT);
+ sigaddset(&sigset, SIGCHLD);
sigprocmask(SIG_BLOCK, &sigset, &orig_sigset);
memset(zero_pids, 0, sizeof(zero_pids));
@@ -965,6 +968,13 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
return 1;
}
+ if (st->ss == &super_imsm && s->level == 10 && s->raiddisks > 4) {
+ /* Print no matter runstop was specifed */
+ pr_err("Warning! VROC UEFI driver does not support RAID10 in requested layout.\n");
+ pr_err("Array won't be suitable as boot device.\n");
+ warn = 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",
@@ -984,7 +994,7 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
if (warn) {
if (c->runstop!= 1) {
- if (!ask("Continue creating array? ")) {
+ if (!ask("Continue creating array")) {
pr_err("create aborted.\n");
return 1;
}
@@ -1334,9 +1344,11 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
if (c->verbose >= 0)
pr_info("array %s started.\n", chosen_name);
if (st->ss->external && st->container_devnm[0]) {
- if (need_mdmon)
+ if (need_mdmon) {
start_mdmon(st->container_devnm);
-
+ if (wait_for_mdmon_control_socket(st->container_devnm) != MDADM_STATUS_SUCCESS)
+ goto abort;
+ }
ping_monitor(st->container_devnm);
close(container_fd);
}
@@ -1358,8 +1370,8 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
map_remove(&map, fd2devnm(mdfd));
map_unlock(&map);
- if (mdfd >= 0)
- close(mdfd);
+ close_fd(&mdfd);
+ close_fd(&container_fd);
dev_policy_free(custom_pols);
return 1;
diff --git a/Detail.c b/Detail.c
index 55a086d..f8b9e84 100644
--- a/Detail.c
+++ b/Detail.c
@@ -274,7 +274,7 @@ int Detail(char *dev, struct context *c)
array.minor_version);
}
- if (info)
+ if (info && memcmp(info->uuid, uuid_zero, sizeof(int[4])) != 0)
mp = map_by_uuid(&map, info->uuid);
if (!mp)
mp = map_by_devnm(&map, fd2devnm(fd));
diff --git a/Dump.c b/Dump.c
index 736bcb6..81b9494 100644
--- a/Dump.c
+++ b/Dump.c
@@ -37,6 +37,7 @@ int Dump_metadata(char *dev, char *dir, struct context *c,
unsigned long long size;
DIR *dirp;
struct dirent *de;
+ int ret = 0;
if (stat(dir, &stb) != 0 ||
(S_IFMT & stb.st_mode) != S_IFDIR) {
@@ -112,9 +113,15 @@ int Dump_metadata(char *dev, char *dir, struct context *c,
}
if (c->verbose >= 0)
printf("%s saved as %s.\n", dev, fname);
- fstat(fd, &dstb);
- close(fd);
+
close(fl);
+ ret = fstat(fd, &dstb);
+ close(fd);
+ if (ret) {
+ unlink(fname);
+ free(fname);
+ return 1;
+ }
if ((dstb.st_mode & S_IFMT) != S_IFBLK) {
/* Not a block device, so cannot create links */
free(fname);
diff --git a/Grow.c b/Grow.c
index 074f199..b135930 100644
--- a/Grow.c
+++ b/Grow.c
@@ -862,10 +862,7 @@ static void wait_reshape(struct mdinfo *sra)
close(fd);
}
-static int reshape_super(struct supertype *st, unsigned long long size,
- int level, int layout, int chunksize, int raid_disks,
- int delta_disks, char *backup_file, char *dev,
- int direction, int verbose)
+static int reshape_super(struct supertype *st, struct shape *shape, struct context *c)
{
/* nothing extra to check in the native case */
if (!st->ss->external)
@@ -876,9 +873,65 @@ static int reshape_super(struct supertype *st, unsigned long long size,
return 1;
}
- return st->ss->reshape_super(st, size, level, layout, chunksize,
- raid_disks, delta_disks, backup_file, dev,
- direction, verbose);
+ return st->ss->reshape_super(st, shape, c);
+}
+
+/**
+ * reshape_super_size() - Reshape array, size only.
+ *
+ * @st: supertype.
+ * @devname: device name.
+ * @size: component size.
+ * @dir metadata changes direction
+ * Returns: 0 on success, 1 otherwise.
+ *
+ * This function is solely used to change size of the volume.
+ * Setting size is not valid for container.
+ * Size is only change that can be rolled back, thus the @dir param.
+ */
+static int reshape_super_size(struct supertype *st, char *devname,
+ unsigned long long size, change_dir_t direction,
+ struct context *c)
+{
+ struct shape shape = {0};
+
+ shape.level = UnSet;
+ shape.layout = UnSet;
+ shape.delta_disks = UnSet;
+ shape.dev = devname;
+ shape.size = size;
+ shape.direction = direction;
+
+ return reshape_super(st, &shape, c);
+}
+
+/**
+ * reshape_super_non_size() - Reshape array, non size changes.
+ *
+ * @st: supertype.
+ * @devname: device name.
+ * @info: superblock info.
+ * Returns: 0 on success, 1 otherwise.
+ *
+ * This function is used for any external array changes but size.
+ * It handles both volumes and containers.
+ * For changes other than size, rollback is not possible.
+ */
+static int reshape_super_non_size(struct supertype *st, char *devname,
+ struct mdinfo *info, struct context *c)
+{
+ struct shape shape = {0};
+ /* Size already set to zero, not updating size */
+ shape.level = info->new_level;
+ shape.layout = info->new_layout;
+ shape.chunk = info->new_chunk;
+ shape.raiddisks = info->array.raid_disks;
+ shape.delta_disks = info->delta_disks;
+ shape.dev = devname;
+ /* Rollback not possible for non size changes */
+ shape.direction = APPLY_METADATA_CHANGES;
+
+ return reshape_super(st, &shape, c);
}
static void sync_metadata(struct supertype *st)
@@ -1170,13 +1223,14 @@ int reshape_open_backup_file(char *backup_file,
* way this will not notice, but it is better than
* nothing.
*/
- fstat(*fdlist, &stb);
+ if (fstat(*fdlist, &stb) != 0)
+ goto error;
dev = stb.st_dev;
- fstat(fd, &stb);
+ if (fstat(fd, &stb) != 0)
+ goto error;
if (stb.st_rdev == dev) {
pr_err("backup file must NOT be on the array being reshaped.\n");
- close(*fdlist);
- return 0;
+ goto error;
}
memset(buf, 0, 512);
@@ -1202,6 +1256,9 @@ int reshape_open_backup_file(char *backup_file,
}
return 1;
+error:
+ close(*fdlist);
+ return 0;
}
unsigned long compute_backup_blocks(int nchunk, int ochunk,
@@ -1764,9 +1821,8 @@ static int reshape_container(char *container, char *devname,
int mdfd,
struct supertype *st,
struct mdinfo *info,
- int force,
- char *backup_file, int verbose,
- int forked, int restart, int freeze_reshape);
+ struct context *c,
+ int forked, int restart);
/**
* prepare_external_reshape() - prepares update on external metadata if supported.
@@ -1982,9 +2038,8 @@ int Grow_reshape(char *devname, int fd,
}
/* ========= set size =============== */
- if (s->size > 0 &&
- (s->size == MAX_SIZE || s->size != (unsigned)array.size)) {
- unsigned long long orig_size = get_component_size(fd)/2;
+ if (s->size > 0 && (s->size == MAX_SIZE || s->size != (unsigned)array.size)) {
+ unsigned long long orig_size = get_component_size(fd) / 2;
unsigned long long min_csize;
struct mdinfo *mdi;
int raid0_takeover = 0;
@@ -2004,9 +2059,7 @@ int Grow_reshape(char *devname, int fd,
goto release;
}
- if (reshape_super(st, s->size, UnSet, UnSet, 0, 0, UnSet, NULL,
- devname, APPLY_METADATA_CHANGES,
- c->verbose > 0)) {
+ if (reshape_super_size(st, devname, s->size, APPLY_METADATA_CHANGES, c)) {
rv = 1;
goto release;
}
@@ -2085,7 +2138,7 @@ int Grow_reshape(char *devname, int fd,
if (!mdmon_running(st->container_devnm))
start_mdmon(st->container_devnm);
ping_monitor(container);
- if (mdmon_running(st->container_devnm) == false) {
+ if (wait_for_mdmon(st->container_devnm) != MDADM_STATUS_SUCCESS) {
pr_err("No mdmon found. Grow cannot continue.\n");
goto release;
}
@@ -2124,10 +2177,8 @@ size_change_error:
int err = errno;
/* restore metadata */
- if (reshape_super(st, orig_size, UnSet, UnSet, 0, 0,
- UnSet, NULL, devname,
- ROLLBACK_METADATA_CHANGES,
- c->verbose) == 0)
+ if (reshape_super_size(st, devname, orig_size,
+ ROLLBACK_METADATA_CHANGES, c) == 0)
sync_metadata(st);
pr_err("Cannot set device size for %s: %s\n",
devname, strerror(err));
@@ -2338,8 +2389,7 @@ size_change_error:
*/
close_fd(&fd);
rv = reshape_container(container, devname, -1, st, &info,
- c->force, c->backup_file, c->verbose,
- 0, 0, 0);
+ c, 0, 0);
frozen = 0;
} else {
/* get spare devices from external metadata
@@ -2356,13 +2406,9 @@ size_change_error:
}
/* Impose these changes on a single array. First
- * check that the metadata is OK with the change. */
-
- if (reshape_super(st, 0, info.new_level,
- info.new_layout, info.new_chunk,
- info.array.raid_disks, info.delta_disks,
- c->backup_file, devname,
- APPLY_METADATA_CHANGES, c->verbose)) {
+ * check that the metadata is OK with the change.
+ */
+ if (reshape_super_non_size(st, devname, &info, c)) {
rv = 1;
goto release;
}
@@ -3176,7 +3222,8 @@ static int reshape_array(char *container, int fd, char *devname,
if (!mdmon_running(container))
start_mdmon(container);
ping_monitor(container);
- if (mdmon_running(container) && st->update_tail == NULL)
+ if (wait_for_mdmon(container) == MDADM_STATUS_SUCCESS &&
+ !st->update_tail)
st->update_tail = &st->updates;
}
}
@@ -3668,23 +3715,15 @@ int reshape_container(char *container, char *devname,
int mdfd,
struct supertype *st,
struct mdinfo *info,
- int force,
- char *backup_file, int verbose,
- int forked, int restart, int freeze_reshape)
+ struct context *c,
+ int forked, int restart)
{
struct mdinfo *cc = NULL;
int rv = restart;
char last_devnm[32] = "";
- /* component_size is not meaningful for a container,
- * so pass '0' meaning 'no change'
- */
- if (!restart &&
- reshape_super(st, 0, info->new_level,
- info->new_layout, info->new_chunk,
- info->array.raid_disks, info->delta_disks,
- backup_file, devname, APPLY_METADATA_CHANGES,
- verbose)) {
+ /* component_size is not meaningful for a container */
+ if (!restart && reshape_super_non_size(st, devname, info, c)) {
unfreeze(st);
return 1;
}
@@ -3695,7 +3734,7 @@ int reshape_container(char *container, char *devname,
*/
ping_monitor(container);
- if (!forked && !freeze_reshape)
+ if (!forked && !c->freeze_reshape)
if (continue_via_systemd(container, GROW_SERVICE, NULL))
return 0;
@@ -3705,7 +3744,7 @@ int reshape_container(char *container, char *devname,
unfreeze(st);
return 1;
default: /* parent */
- if (!freeze_reshape)
+ if (!c->freeze_reshape)
printf("%s: multi-array reshape continues in background\n", Name);
return 0;
case 0: /* child */
@@ -3802,12 +3841,12 @@ int reshape_container(char *container, char *devname,
flush_mdmon(container);
rv = reshape_array(container, fd, adev, st,
- content, force, NULL, INVALID_SECTORS,
- backup_file, verbose, 1, restart,
- freeze_reshape);
+ content, c->force, NULL, INVALID_SECTORS,
+ c->backup_file, c->verbose, 1, restart,
+ c->freeze_reshape);
close(fd);
- if (freeze_reshape) {
+ if (c->freeze_reshape) {
sysfs_free(cc);
exit(0);
}
@@ -4449,7 +4488,6 @@ int child_monitor(int afd, struct mdinfo *sra, struct reshape *reshape,
*/
char *buf;
int degraded = -1;
- unsigned long long speed;
unsigned long long suspend_point, array_size;
unsigned long long backup_point, wait_point;
unsigned long long reshape_completed;
@@ -4505,10 +4543,6 @@ int child_monitor(int afd, struct mdinfo *sra, struct reshape *reshape,
if (posix_memalign((void**)&buf, 4096, disks * chunk))
/* Don't start the 'reshape' */
return 0;
- if (reshape->before.data_disks == reshape->after.data_disks) {
- sysfs_get_ll(sra, NULL, "sync_speed_min", &speed);
- sysfs_set_num(sra, NULL, "sync_speed_min", 200000);
- }
if (increasing) {
array_size = sra->component_size * reshape->after.data_disks;
@@ -4641,8 +4675,6 @@ int child_monitor(int afd, struct mdinfo *sra, struct reshape *reshape,
sysfs_set_num(sra, NULL, "suspend_lo", 0);
sysfs_set_num(sra, NULL, "sync_min", 0);
- if (reshape->before.data_disks == reshape->after.data_disks)
- sysfs_set_num(sra, NULL, "sync_speed_min", speed);
free(buf);
return done;
}
@@ -4970,8 +5002,7 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist,
return 1;
}
-int Grow_continue_command(char *devname, int fd,
- char *backup_file, int verbose)
+int Grow_continue_command(char *devname, int fd, struct context *c)
{
int ret_val = 0;
struct supertype *st = NULL;
@@ -5140,7 +5171,7 @@ int Grow_continue_command(char *devname, int fd,
start_mdmon(container);
ping_monitor(container);
- if (mdmon_running(container) == false) {
+ if (wait_for_mdmon(container) != MDADM_STATUS_SUCCESS) {
pr_err("No mdmon found. Grow cannot continue.\n");
ret_val = 1;
goto Grow_continue_command_exit;
@@ -5157,7 +5188,7 @@ int Grow_continue_command(char *devname, int fd,
/* continue reshape
*/
- ret_val = Grow_continue(fd, st, content, backup_file, 1, 0);
+ ret_val = Grow_continue(fd, st, content, 1, c);
Grow_continue_command_exit:
if (cfd > -1)
@@ -5171,7 +5202,7 @@ Grow_continue_command_exit:
}
int Grow_continue(int mdfd, struct supertype *st, struct mdinfo *info,
- char *backup_file, int forked, int freeze_reshape)
+ int forked, struct context *c)
{
int ret_val = 2;
@@ -5187,14 +5218,12 @@ int Grow_continue(int mdfd, struct supertype *st, struct mdinfo *info,
st->ss->load_container(st, cfd, st->container_devnm);
close(cfd);
ret_val = reshape_container(st->container_devnm, NULL, mdfd,
- st, info, 0, backup_file, 0,
- forked, 1 | info->reshape_active,
- freeze_reshape);
+ st, info, c, forked, 1 | info->reshape_active);
} else
ret_val = reshape_array(NULL, mdfd, "array", st, info, 1,
- NULL, INVALID_SECTORS, backup_file,
+ NULL, INVALID_SECTORS, c->backup_file,
0, forked, 1 | info->reshape_active,
- freeze_reshape);
+ c->freeze_reshape);
return ret_val;
}
diff --git a/MAINTAINERS.md b/MAINTAINERS.md
index 9c79ba8..e5b635f 100644
--- a/MAINTAINERS.md
+++ b/MAINTAINERS.md
@@ -1,44 +1,29 @@
# Maintainer tools
-Useful tools used in daily routines:
+Useful tools for mdadm maintenance:
- [checkpatch](https://docs.kernel.org/dev-tools/checkpatch.html)
- [kup](https://korg.docs.kernel.org/kup.html)
- [Auto-publishing](https://korg.docs.kernel.org/kup.html#auto-publishing-with-git-archive-signer)
- [b4](https://b4.docs.kernel.org/en/latest/)
-# Checklist before applying patch
-
-We don't have CI testing yet, so all those steps must be performed manually:
-- Style check with [checkpatch](https://docs.kernel.org/dev-tools/checkpatch.html):
-
- This is the current code style follows. We are not strict to all rules. It must be run
- by **checkpatch --no-tree**, see README.md.
-
-- [Commit style](https://www.kernel.org/doc/html/v4.10/process/submitting-patches.html):
-
- It doesn't need to be followed as strictly as is in kernel but changes should be logically
- separated. Submitter should care at least to mention "It is used in next patches" if unused
- externs/files are added in patch. We love: *Reported-by:*, *Suggested-by:*, *Fixes:* tags.
-
-- Compilation, ideally on various gcc versions.
-- Mdadm test suite execution.
-- Consider requesting new tests from submitter, especially for new functionalities.
-- Ensure that maintainer *sign-off* is added, before pushing.
-
# Making a release
Assuming that maintainer is certain that release is safe, following steps must be done:
-- Update versions strings in release commit, please refer to previous releases for examples.
+- Make and push release commit:
+ - Update versions strings, refer to previous releases for examples.
+ - Update CHANGELOG.md.
+
+- Create GPG signed tag and push it to both remotes. Use same format as was used previously,
+ prefixed by **mdadm-**, e.g. **mdadm-3.1.2**, **mdadm-4.1**.
-- Create GPG signed tag and push it to repo. Use same format as was used previously, prefixed by
- **mdadm-**, e.g. **mdadm-3.1.2**, **mdadm-4.1**.
+- Run kernel.org
+ [Auto-publishing](https://korg.docs.kernel.org/kup.html#auto-publishing-with-git-archive-signer):
-- [Auto-publishing](https://korg.docs.kernel.org/kup.html#auto-publishing-with-git-archive-signer):
+ Adopt script to our release tag model. When ready, push signed note to kernel.org repository. If
+ it is done correctly, then *(sig)* is added to the package automatically generated by
+ kernel.org automation. There is no need to upload archive manually.
- Adopt script to our release tag model. When ready, push signed note to repository. If it is done
- correctly, then *(sig)* is added to the package automatically generated by kernel.org automation.
- There is no need to upload archive manually.
+- Add release entry on Github.
-- Update CHANGELOG.md.
- Write "ANNOUNCE" mail to linux-raid@kernel.org to notify community.
diff --git a/Makefile b/Makefile
index 7c221a8..3fe0a05 100644
--- a/Makefile
+++ b/Makefile
@@ -56,21 +56,21 @@ CWFLAGS += -Wp -O3
endif
ifeq ($(origin FALLTHROUGH), undefined)
- FALLTHROUGH := $(shell gcc -Q --help=warnings 2>&1 | grep "implicit-fallthrough" | wc -l)
+ FALLTHROUGH := $(shell $(CC) -Q --help=warnings 2>&1 | grep "implicit-fallthrough" | wc -l)
ifneq "$(FALLTHROUGH)" "0"
CWFLAGS += -Wimplicit-fallthrough=0
endif
endif
ifeq ($(origin FORMATOVERFLOW), undefined)
- FORMATOVERFLOW := $(shell gcc -Q --help=warnings 2>&1 | grep "format-overflow" | wc -l)
+ FORMATOVERFLOW := $(shell $(CC) -Q --help=warnings 2>&1 | grep "format-overflow" | wc -l)
ifneq "$(FORMATOVERFLOW)" "0"
CWFLAGS += -Wformat-overflow
endif
endif
ifeq ($(origin STRINGOPOVERFLOW), undefined)
- STRINGOPOVERFLOW := $(shell gcc -Q --help=warnings 2>&1 | grep "stringop-overflow" | wc -l)
+ STRINGOPOVERFLOW := $(shell $(CC) -Q --help=warnings 2>&1 | grep "stringop-overflow" | wc -l)
ifneq "$(STRINGOPOVERFLOW)" "0"
CWFLAGS += -Wstringop-overflow
endif
@@ -132,12 +132,12 @@ CFLAGS += -DUSE_PTHREADS
MON_LDFLAGS += -pthread
endif
-LDFLAGS = -Wl,-z,now,-z,noexecstack
+LDFLAGS ?= -pie -Wl,-z,now,-z,noexecstack
# If you want a static binary, you might uncomment these
# LDFLAGS += -static
# STRIP = -s
-LDLIBS = -ldl -pie
+LDLIBS = -ldl
# To explicitly disable libudev, set -DNO_LIBUDEV in CXFLAGS
ifeq (, $(findstring -DNO_LIBUDEV, $(CXFLAGS)))
@@ -157,7 +157,7 @@ ifndef UDEVDIR
UDEVDIR = /lib/udev
endif
-ifeq (,$(findstring s,$(MAKEFLAGS)))
+ifeq (,$(findstring s,$(firstword -$(MAKEFLAGS))))
ECHO=echo
else
ECHO=:
diff --git a/Manage.c b/Manage.c
index 96e5ee5..f0304e1 100644
--- a/Manage.c
+++ b/Manage.c
@@ -56,7 +56,7 @@ int Manage_ro(char *devname, int fd, int readonly)
vers[9] = '-';
sysfs_set_str(mdi, NULL, "metadata_version", vers);
- close(fd);
+ close_fd(&fd);
rv = sysfs_set_str(mdi, NULL, "array_state", "readonly");
if (rv < 0) {
@@ -165,7 +165,7 @@ int Manage_run(char *devname, int fd, struct context *c)
pr_err("Cannot find %s in sysfs!!\n", devname);
return 1;
}
- strcpy(nm, nmp);
+ snprintf(nm, sizeof(nm), "%s", nmp);
return IncrementalScan(c, nm);
}
@@ -187,7 +187,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry)
if (will_retry && verbose == 0)
verbose = -1;
- strcpy(devnm, fd2devnm(fd));
+ snprintf(devnm, sizeof(devnm), "%s", fd2devnm(fd));
/* Get EXCL access first. If this fails, then attempting
* to stop is probably a bad idea.
*/
@@ -195,7 +195,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry)
if (mdi && is_subarray(mdi->text_version))
sysfs_get_container_devnm(mdi, container);
- close(fd);
+ close_fd(&fd);
count = 5;
while (((fd = ((devname[0] == '/')
?open(devname, O_RDONLY|O_EXCL)
@@ -206,14 +206,12 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry)
* is a container, so we might be racing with mdmon, so
* retry for a bit.
*/
- if (fd >= 0)
- close(fd);
+ close_fd(&fd);
flush_mdmon(container);
count--;
}
if (fd < 0 || strcmp(fd2devnm(fd), devnm) != 0) {
- if (fd >= 0)
- close(fd);
+ close_fd(&fd);
if (verbose >= 0)
pr_err("Cannot get exclusive access to %s:Perhaps a running process, mounted filesystem or active volume group?\n",
devname);
@@ -228,7 +226,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry)
is_subarray(mdi->text_version)) {
int err;
/* This is mdmon managed. */
- close(fd);
+ close_fd(&fd);
/* As we had an O_EXCL open, any use of the device
* which blocks STOP_ARRAY is probably a transient use,
@@ -430,8 +428,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry)
break;
sysfs_wait(scfd, &delay);
}
- if (scfd >= 0)
- close(scfd);
+ close_fd(&scfd);
}
done:
@@ -463,12 +460,13 @@ done:
}
if (verbose >= 0)
- pr_err("stopped %s\n", devname);
+ pr_info("stopped %s\n", devname);
map_lock(&map);
map_remove(&map, devnm);
map_unlock(&map);
out:
sysfs_free(mdi);
+ close_fd(&fd);
return rv;
}
@@ -664,7 +662,7 @@ int attempt_re_add(int fd, int tfd, struct mddev_dev *dv,
devname, verbose, 0, NULL);
if (rv == 0)
rv = dev_st->ss->store_super(dev_st, tfd);
- close(tfd);
+ close_fd(&tfd);
if (rv != 0) {
pr_err("failed to update superblock during re-add\n");
return -1;
@@ -766,15 +764,15 @@ mdadm_status_t manage_add_external(struct supertype *st, int fd, char *disk_name
rv = MDADM_STATUS_SUCCESS;
out:
- close(container_fd);
+ close_fd(&container_fd);
dev_policy_free(pols);
if (sra)
sysfs_free(sra);
- if (rv != MDADM_STATUS_SUCCESS && is_fd_valid(disk_fd))
+ if (rv != MDADM_STATUS_SUCCESS)
/* Metadata handler records this descriptor, so release it only on failure. */
- close(disk_fd);
+ close_fd(&disk_fd);
if (st->sb)
st->ss->free_super(st);
@@ -845,10 +843,10 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
continue;
if (tst->ss->load_super(tst, dfd,
NULL)) {
- close(dfd);
+ close_fd(&dfd);
continue;
}
- close(dfd);
+ close_fd(&dfd);
break;
}
/* FIXME this is a bad test to be using */
@@ -1100,7 +1098,8 @@ int Manage_remove(struct supertype *tst, int fd, struct mddev_dev *dv,
*/
int ret;
char devnm[32];
- strcpy(devnm, fd2devnm(fd));
+
+ snprintf(devnm, sizeof(devnm), "%s", fd2devnm(fd));
lfd = open_dev_excl(devnm);
if (lfd < 0) {
pr_err("Cannot get exclusive access to container - odd\n");
@@ -1134,13 +1133,13 @@ int Manage_remove(struct supertype *tst, int fd, struct mddev_dev *dv,
if (ret == 0) {
pr_err("%s is not a member, cannot remove.\n",
dv->devname);
- close(lfd);
+ close_fd(&lfd);
return -1;
}
if (ret >= 2) {
pr_err("%s is still in use, cannot remove.\n",
dv->devname);
- close(lfd);
+ close_fd(&lfd);
return -1;
}
}
@@ -1157,26 +1156,27 @@ int Manage_remove(struct supertype *tst, int fd, struct mddev_dev *dv,
/* Old kernels rejected this if no personality
* is registered */
struct mdinfo *sra = sysfs_read(fd, NULL, GET_DEVS);
- struct mdinfo *dv = NULL;
- if (sra)
- dv = sra->devs;
- for ( ; dv ; dv=dv->next)
- if (dv->disk.major == (int)major(rdev) &&
- dv->disk.minor == (int)minor(rdev))
- break;
- if (dv)
- err = sysfs_set_str(sra, dv,
- "state", "remove");
- else
+ struct mdinfo *dev = NULL;
+
+ if (!sra) {
err = -1;
- sysfs_free(sra);
+ } else {
+ for (dev = sra->devs; dev ; dev = dev->next)
+ if (dev->disk.major == (int)major(rdev) &&
+ dev->disk.minor == (int)minor(rdev))
+ break;
+
+ if (dev)
+ err = sysfs_set_str(sra, dev,
+ "state", "remove");
+ sysfs_free(sra);
+ }
}
}
if (err) {
pr_err("hot remove failed for %s: %s\n", dv->devname,
strerror(errno));
- if (lfd >= 0)
- close(lfd);
+ close_fd(&lfd);
return -1;
}
if (tst->ss->external) {
@@ -1190,13 +1190,13 @@ int Manage_remove(struct supertype *tst, int fd, struct mddev_dev *dv,
if (!devnm) {
pr_err("unable to get container name\n");
+ close_fd(&lfd);
return -1;
}
ping_manager(devnm);
}
- if (lfd >= 0)
- close(lfd);
+ close_fd(&lfd);
if (verbose >= 0)
pr_err("hot removed %s from %s\n",
dv->devname, devname);
@@ -1218,7 +1218,7 @@ int Manage_replace(struct supertype *tst, int fd, struct mddev_dev *dv,
if (!mdi || !mdi->devs) {
pr_err("Cannot find status of %s to enable replacement - strange\n",
devname);
- return -1;
+ goto abort;
}
for (di = mdi->devs; di; di = di->next)
if (di->disk.major == (int)major(rdev) &&
@@ -1229,16 +1229,14 @@ int Manage_replace(struct supertype *tst, int fd, struct mddev_dev *dv,
if (di->disk.raid_disk < 0) {
pr_err("%s is not active and so cannot be replaced.\n",
dv->devname);
- sysfs_free(mdi);
- return -1;
+ goto abort;
}
rv = sysfs_set_str(mdi, di,
"state", "want_replacement");
if (rv) {
- sysfs_free(mdi);
pr_err("Failed to request replacement for %s\n",
dv->devname);
- return -1;
+ goto abort;
}
if (verbose >= 0)
pr_err("Marked %s (device %d in %s) for replacement\n",
@@ -1252,11 +1250,13 @@ int Manage_replace(struct supertype *tst, int fd, struct mddev_dev *dv,
dv->disposition = 'w';
dv->used = di->disk.raid_disk;
}
+ sysfs_free(mdi);
return 1;
}
- sysfs_free(mdi);
pr_err("%s not found in %s so cannot --replace it\n",
dv->devname, devname);
+abort:
+ sysfs_free(mdi);
return -1;
}
@@ -1269,7 +1269,7 @@ int Manage_with(struct supertype *tst, int fd, struct mddev_dev *dv,
if (!mdi || !mdi->devs) {
pr_err("Cannot find status of %s to enable replacement - strange\n",
devname);
- return -1;
+ goto abort;
}
for (di = mdi->devs; di; di = di->next)
if (di->disk.major == (int)major(rdev) &&
@@ -1280,31 +1280,30 @@ int Manage_with(struct supertype *tst, int fd, struct mddev_dev *dv,
if (di->disk.state & (1<<MD_DISK_FAULTY)) {
pr_err("%s is faulty and cannot be a replacement\n",
dv->devname);
- sysfs_free(mdi);
- return -1;
+ goto abort;
}
if (di->disk.raid_disk >= 0) {
pr_err("%s is active and cannot be a replacement\n",
dv->devname);
- sysfs_free(mdi);
- return -1;
+ goto abort;
}
rv = sysfs_set_num(mdi, di,
"slot", dv->used);
if (rv) {
- sysfs_free(mdi);
pr_err("Failed to set %s as preferred replacement.\n",
dv->devname);
- return -1;
+ goto abort;
}
if (verbose >= 0)
pr_err("Marked %s in %s as replacement for device %d\n",
dv->devname, devname, dv->used);
+ sysfs_free(mdi);
return 1;
}
- sysfs_free(mdi);
pr_err("%s not found in %s so cannot make it preferred replacement\n",
dv->devname, devname);
+abort:
+ sysfs_free(mdi);
return -1;
}
@@ -1324,6 +1323,7 @@ bool is_remove_safe(mdu_array_info_t *array, const int fd, char *devname, const
{
dev_t devid = devnm2devid(devname + 5);
struct mdinfo *mdi = sysfs_read(fd, NULL, GET_DEVS | GET_DISKS | GET_STATE);
+ struct mdinfo *disk;
if (!mdi) {
if (verbose)
@@ -1333,14 +1333,14 @@ bool is_remove_safe(mdu_array_info_t *array, const int fd, char *devname, const
char *avail = xcalloc(array->raid_disks, sizeof(char));
- for (mdi = mdi->devs; mdi; mdi = mdi->next) {
- if (mdi->disk.raid_disk < 0)
+ for (disk = mdi->devs; disk; disk = disk->next) {
+ if (disk->disk.raid_disk < 0)
continue;
- if (!(mdi->disk.state & (1 << MD_DISK_SYNC)))
+ if (!(disk->disk.state & (1 << MD_DISK_SYNC)))
continue;
- if (makedev(mdi->disk.major, mdi->disk.minor) == devid)
+ if (makedev(disk->disk.major, disk->disk.minor) == devid)
continue;
- avail[mdi->disk.raid_disk] = 1;
+ avail[disk->disk.raid_disk] = 1;
}
sysfs_free(mdi);
@@ -1550,7 +1550,7 @@ int Manage_subdevs(char *devname, int fd,
rdev = makedev(mj,mn);
found = 1;
}
- close(sysfd);
+ close_fd(&sysfd);
sysfd = -1;
}
if (!found) {
@@ -1572,7 +1572,7 @@ int Manage_subdevs(char *devname, int fd,
tfd = dev_open(dv->devname, O_RDONLY);
if (tfd >= 0) {
fstat_is_blkdev(tfd, dv->devname, &rdev);
- close(tfd);
+ close_fd(&tfd);
} else {
int open_err = errno;
if (!stat_is_blkdev(dv->devname, &rdev)) {
@@ -1635,7 +1635,7 @@ int Manage_subdevs(char *devname, int fd,
* need non-exclusive access to add it, so
* do that now.
*/
- close(tfd);
+ close_fd(&tfd);
tfd = dev_open(dv->devname, O_RDONLY);
}
if (tfd < 0) {
@@ -1654,8 +1654,7 @@ int Manage_subdevs(char *devname, int fd,
rv = Manage_add(fd, tfd, dv, tst, &array,
force, verbose, devname, update,
rdev, array_size, raid_slot);
- close(tfd);
- tfd = -1;
+ close_fd(&tfd);
if (rv < 0)
goto abort;
if (rv > 0)
@@ -1672,7 +1671,7 @@ int Manage_subdevs(char *devname, int fd,
rdev, verbose, force,
devname);
if (sysfd >= 0)
- close(sysfd);
+ close_fd(&sysfd);
sysfd = -1;
if (rv < 0)
goto abort;
@@ -1684,8 +1683,7 @@ int Manage_subdevs(char *devname, int fd,
if (!is_remove_safe(&array, fd, dv->devname, verbose)) {
pr_err("Cannot remove %s from %s, array will be failed.\n",
dv->devname, devname);
- if (sysfd >= 0)
- close(sysfd);
+ close_fd(&sysfd);
goto abort;
}
case 'I': /* incremental fail */
@@ -1696,13 +1694,10 @@ int Manage_subdevs(char *devname, int fd,
busy = 1;
pr_err("set device faulty failed for %s: %s\n",
dv->devname, strerror(errno));
- if (sysfd >= 0)
- close(sysfd);
+ close_fd(&sysfd);
goto abort;
}
- if (sysfd >= 0)
- close(sysfd);
- sysfd = -1;
+ close_fd(&sysfd);
count++;
if (verbose >= 0)
pr_err("set %s faulty in %s\n",
@@ -1762,7 +1757,7 @@ int autodetect(void)
if (fd >= 0) {
if (ioctl(fd, RAID_AUTORUN, 0) == 0)
rv = 0;
- close(fd);
+ close_fd(&fd);
}
return rv;
}
@@ -1825,7 +1820,7 @@ free_super:
if (info)
free(info);
st->ss->free_super(st);
- close(fd);
+ close_fd(&fd);
return rv;
}
@@ -1843,10 +1838,8 @@ int move_spare(char *from_devname, char *to_devname, dev_t devid)
int fd2 = open(from_devname, O_RDONLY);
if (fd1 < 0 || fd2 < 0) {
- if (fd1 >= 0)
- close(fd1);
- if (fd2 >= 0)
- close(fd2);
+ close_fd(&fd1);
+ close_fd(&fd2);
return 0;
}
@@ -1865,15 +1858,15 @@ int move_spare(char *from_devname, char *to_devname, dev_t devid)
/* make sure manager is aware of changes */
ping_manager(to_devname);
ping_manager(from_devname);
- close(fd1);
- close(fd2);
+ close_fd(&fd1);
+ close_fd(&fd2);
return 1;
}
else
Manage_subdevs(from_devname, fd2, &devlist,
-1, 0, UOPT_UNDEFINED, 0);
}
- close(fd1);
- close(fd2);
+ close_fd(&fd1);
+ close_fd(&fd2);
return 0;
}
diff --git a/Monitor.c b/Monitor.c
index 9b016bc..26c53e1 100644
--- a/Monitor.c
+++ b/Monitor.c
@@ -782,7 +782,9 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
if (!is_container && !md_array_active(fd))
goto disappeared;
- fcntl(fd, F_SETFD, FD_CLOEXEC);
+ if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0)
+ goto out;
+
if (md_get_array_info(fd, &array) < 0)
goto disappeared;
@@ -997,7 +999,8 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist)
snprintf(st->parent_devnm, MD_NAME_MAX,
"%s", mse->metadata_version + 10);
sl = strchr(st->parent_devnm, '/');
- *sl = 0;
+ if (sl)
+ *sl = 0;
} else
st->parent_devnm[0] = 0;
*statelist = st;
@@ -1261,7 +1264,7 @@ int Wait(char *dev)
return 2;
}
- strcpy(devnm, tmp);
+ snprintf(devnm, sizeof(devnm), "%s", tmp);
while(1) {
struct mdstat_ent *ms = mdstat_read(1, 0);
@@ -1332,7 +1335,8 @@ int WaitClean(char *dev, int verbose)
return 1;
}
- strcpy(devnm, fd2devnm(fd));
+ snprintf(devnm, sizeof(devnm), "%s", fd2devnm(fd));
+
mdi = sysfs_read(fd, devnm, GET_VERSION|GET_LEVEL|GET_SAFEMODE);
if (!mdi) {
if (verbose)
diff --git a/Query.c b/Query.c
index adcd231..aedb4ce 100644
--- a/Query.c
+++ b/Query.c
@@ -39,7 +39,7 @@ int Query(char *dev)
struct mdinfo info;
struct mdinfo *sra;
struct supertype *st = NULL;
- unsigned long long larray_size;
+ unsigned long long larray_size = 0;
struct stat stb;
char *mddev;
mdu_disk_info_t disc;
@@ -136,5 +136,7 @@ int Query(char *dev)
if (st->ss == &super0)
put_md_name(mddev);
}
+ free(sra);
+
return 0;
}
diff --git a/README.md b/README.md
index 64f2ece..486c892 100644
--- a/README.md
+++ b/README.md
@@ -20,58 +20,68 @@
**IMPORTANT:** DDF is in **maintenance only** mode. There is no active development around it.
Please do not use it in new solutions.
-# How to Contribute
-
- **mdadm** is hosted on [kernel.org](https://kernel.org/). You can access repository
-[here](https://git.kernel.org/pub/scm/utils/mdadm/mdadm.git).
+# Questions and Support
+
+This Github site is **not** right place to ask if your are looking for:
+- support from Linux Raid Community;
+- support with kernel issues;
+
+This is the place where development of mdadm application is done. Please, do not use for
+looking for support. You should always ask on [Mailing List](https://lore.kernel.org/linux-raid/).
+
+Please use issues if you have confirmation that issue you are experiencing is related to mdadm
+components:
+- mdadm;
+- mdmon;
+- raid6check;
+- swap_super;
+- test_stripe;
+- systemd services ( see systemd/);
+- udev rules;
+- manual pages (including md.man)
+
+For example:
+- mdadm issues (e.g segfaults, memory leaks, crashes, bad communication with MD driver);
+- feature requests for mdadm;
+- suggestions or minor fixes requested (e.g. better error messages);
+
+Generally, if you are not sure it is better to ask on
+[Mailing List](https://lore.kernel.org/linux-raid/) first.
-It is maintained similarly to kernel, using *mailing list*. Patches must be send through email.
-Please familiarize with general kernel
-[submitting patches](https://www.kernel.org/doc/html/v4.17/process/submitting-patches.html)
-documentation. Formatting, tags and commit message guidelines applies to **mdadm**.
+# How to Contribute
-## Sending patches step-by-step
+Effective immediately [Github](https://github.com/md-raid-utilities/mdadm) is the primary
+location for **mdadm**. Use pull request to contribute.
-To maximize change of patches being taken, follow this instruction when submitting:
+It was originally hosted on [kernel.org](https://kernel.org/). You can access the old repository
+[here](https://git.kernel.org/pub/scm/utils/mdadm/mdadm.git).
-1. Create possibly logically separated commits and generate patches:
+Patches sent through Mailing list are accepted but Github is preferred. Sent then to ML only
+if you cannot use Github. Please add "mdadm:" to the subject to allow automation to create Github
+Pull Request and run checks.
- Use ``git format-patch --cover-letter --signoff -v <nr>`` to create patches:
- * ``--cover-letter`` can be skipped if it is only one patch;
- * ``--signoff`` adds sign-off tag;
- * ``-v <nr>`` indicates review revision number, sender should increment it before resending.
+**NOTE:** Maintainers may ask you to send RFC to mailing list if the proposed code requires
+consultation with kernel developers.
-2. Check style of every patch with kernel
- [checkpatch](https://docs.kernel.org/dev-tools/checkpatch.html) script:
+Kernel coding style is used. Please familiarize with general kernel
+[submitting patches](https://www.kernel.org/doc/html/v4.17/process/submitting-patches.html)
+documentation. Formatting, tags and commit message guidelines applies to **mdadm**.
- It is important to keep same coding style that is why in **mdadm**
- [kernel coding style](https://www.kernel.org/doc/html/v4.10/process/coding-style.html)
- is preferred. ``checkpath --no-tree <patch_file>`` can be used to verify patches.
- Following checkpatch issues can be ignored:
- - New typedefs.
- - comparing with *True/False*.
- - kernel *MAINTAINERS* file warning.
- - *extern* keyword in headers.
+[Checkpatch](https://docs.kernel.org/dev-tools/checkpatch.html) script is run on
+every patch in pull request so be sure that your commits are not generating
+issues. There are some excludes, so the best is to follow github checkpatch action result.
-3. Send patches using ``git send-mail --to=linux-raid@vger.kernel.org <cover-letter> <patch1> <patch2> (...)``
+Pull Request are closed by `Rebase and Merge` option, so it requires to keep every commit
+meaningful. Kernel style requires that. The review changes must be pushed with **push --force**
+to the chosen branch, then Pull Request will be automatically updated.
-# Maintainers
+# Maintainers of mdadm repository on kernel.org
-It is good practice to add **mdadm maintainers** to recipients for patches:
+If there are differences between github and kernel.org, please contact kernel.org mdadm maintainers:
- Jes Sorensen <jes@trained-monkey.org>;
- Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>;
-Adding **MD maintainers** could be reasonable, especially if patches may affect MD driver:
-
-- Song Liu <song@kernel.org>;
-- Yu Kuai <yukuai3@huawei.com>;
-
-# Reviewers
-
-**mdadm** utility is not part of kernel tree, so there is no certificated *Reviewers* list. Everyone
-can comment on mailing list, last decision (and merging) belongs to maintainers.
-
# Minimal supported kernel version
We do not support kernel versions below **v3.10**. Please be aware that maintainers may remove
diff --git a/clustermd_tests/02r10_Manage_re-add b/clustermd_tests/02r10_Manage_re-add
index 2288a00..d876466 100644
--- a/clustermd_tests/02r10_Manage_re-add
+++ b/clustermd_tests/02r10_Manage_re-add
@@ -9,7 +9,8 @@ check all state UU
check all dmesg
mdadm --manage $md0 --fail $dev0 --remove $dev0
mdadm --manage $md0 --re-add $dev0
-check $NODE1 recovery
+#non-clustered array also doesn't do sync job
+#check $NODE1 recovery
check all wait
check all state UU
check all dmesg
diff --git a/clustermd_tests/02r1_Manage_re-add b/clustermd_tests/02r1_Manage_re-add
index d0d13e5..811df87 100644
--- a/clustermd_tests/02r1_Manage_re-add
+++ b/clustermd_tests/02r1_Manage_re-add
@@ -9,6 +9,7 @@ check all state UU
check all dmesg
mdadm --manage $md0 --fail $dev0 --remove $dev0
mdadm --manage $md0 --re-add $dev0
+check all wait
check all state UU
check all dmesg
stop_md all $md0
diff --git a/clustermd_tests/03r10_switch-recovery b/clustermd_tests/03r10_switch-recovery
index 867388d..7d0b881 100644
--- a/clustermd_tests/03r10_switch-recovery
+++ b/clustermd_tests/03r10_switch-recovery
@@ -10,9 +10,9 @@ check all state UU
check all dmesg
mdadm --manage $md0 --fail $dev0
sleep 0.2
-check $NODE1 recovery
+check $NODE1 recovery-remote
stop_md $NODE1 $md0
-check $NODE2 recovery
+check $NODE2 recovery-remote
check $NODE2 wait
check $NODE2 state UU
check all dmesg
diff --git a/clustermd_tests/03r1_switch-recovery b/clustermd_tests/03r1_switch-recovery
index a1a7cbe..d8483c4 100644
--- a/clustermd_tests/03r1_switch-recovery
+++ b/clustermd_tests/03r1_switch-recovery
@@ -10,9 +10,9 @@ check all state UU
check all dmesg
mdadm --manage $md0 --fail $dev0
sleep 0.3
-check $NODE1 recovery
+check $NODE1 recovery-remote
stop_md $NODE1 $md0
-check $NODE2 recovery
+check $NODE2 recovery-remote
check $NODE2 wait
check $NODE2 state UU
check all dmesg
diff --git a/clustermd_tests/func.sh b/clustermd_tests/func.sh
index 801d604..e659c0b 100644
--- a/clustermd_tests/func.sh
+++ b/clustermd_tests/func.sh
@@ -1,5 +1,22 @@
#!/bin/bash
+COLOR_FAIL='\033[0;31m' #RED
+COLOR_WARN='\033[1;33m' #YELLOW
+COLOR_SUCCESS='\033[0;32m' #GREEN
+COLOR_NONE='\033[0m'
+
+fail() {
+ printf "${COLOR_FAIL}$1${COLOR_NONE}"
+}
+
+warn() {
+ printf "${COLOR_WARN}$1${COLOR_NONE}"
+}
+
+succeed() {
+ printf "${COLOR_SUCCESS}$1${COLOR_NONE}"
+}
+
check_ssh()
{
NODE1="$(grep '^NODE1' $CLUSTER_CONF | cut -d'=' -f2)"
@@ -151,6 +168,33 @@ stop_md()
fi
}
+record_system_speed_limit() {
+ system_speed_limit_max=`cat /proc/sys/dev/raid/speed_limit_max`
+ system_speed_limit_min=`cat /proc/sys/dev/raid/speed_limit_min`
+}
+
+# To avoid sync action finishes before checking it, it needs to limit
+# the sync speed
+control_system_speed_limit() {
+ echo $test_speed_limit_min > /proc/sys/dev/raid/speed_limit_min
+ echo $test_speed_limit_max > /proc/sys/dev/raid/speed_limit_max
+}
+
+restore_system_speed_limit() {
+ echo $system_speed_limit_min > /proc/sys/dev/raid/speed_limit_max
+ echo $system_speed_limit_max > /proc/sys/dev/raid/speed_limit_max
+}
+
+record_selinux() {
+ # empty
+ return 0
+}
+
+restore_selinux() {
+ # empty
+ return 0
+}
+
# $1/optional, it shows why to save log
save_log()
{
@@ -240,6 +284,22 @@ check()
die "$ip: check '$2' failed."
done
;;
+ recovery-remote )
+ cnt=5
+ for ip in ${NODES[@]}
+ do
+ while ! ssh $ip "grep -sqE 'recovery|REMOTE' /proc/mdstat"
+ do
+ if [ "$cnt" -gt '0' ]
+ then
+ sleep 0.2
+ cnt=$[cnt-1]
+ else
+ die "$ip: no '$2' happening!"
+ fi
+ done
+ done
+ ;;
PENDING | recovery | resync | reshape )
cnt=5
for ip in ${NODES[@]}
diff --git a/config.c b/config.c
index b46d71c..6ea905f 100644
--- a/config.c
+++ b/config.c
@@ -188,8 +188,36 @@ inline void ident_init(struct mddev_ident *ident)
ident->uuid_set = 0;
}
+/** ident_check_name() - helper function to verify name.
+ * @name: name to check.
+ * @prop_name: the name of the property it is validated against, used for logging.
+ * @cmdline: context dependent actions.
+ *
+ * @name must follow name's criteria, be POSIX compatible and does not have leading dot.
+ */
+static mdadm_status_t ident_check_name(const char *name, const char *prop_name, const bool cmdline)
+{
+ if (!is_string_lq(name, MD_NAME_MAX + 1)) {
+ ident_log(prop_name, name, "Too long or empty", cmdline);
+ return MDADM_STATUS_ERROR;
+ }
+
+ if (*name == '.') {
+ /* MD device should not be considered as hidden. */
+ ident_log(prop_name, name, "Leading dot forbidden", cmdline);
+ return MDADM_STATUS_ERROR;
+ }
+
+ if (!is_name_posix_compatible(name)) {
+ ident_log(prop_name, name, "Not POSIX compatible", cmdline);
+ return MDADM_STATUS_ERROR;
+ }
+
+ return MDADM_STATUS_SUCCESS;
+}
+
/**
- * _ident_set_devname()- verify devname and set it in &mddev_ident.
+ * _ident_set_devname() - verify devname and set it in &mddev_ident.
* @ident: pointer to &mddev_ident.
* @devname: devname to be set.
* @cmdline: context dependent actions. If set, ignore keyword is not allowed.
@@ -202,8 +230,7 @@ inline void ident_init(struct mddev_ident *ident)
* /dev/md/{name}
* {name}
*
- * {name} must follow name's criteria and be POSIX compatible.
- * If criteria passed, duplicate memory and set devname in @ident.
+ * If verification passed, duplicate memory and set devname in @ident.
*
* Return: %MDADM_STATUS_SUCCESS or %MDADM_STATUS_ERROR.
*/
@@ -216,6 +243,7 @@ mdadm_status_t _ident_set_devname(struct mddev_ident *ident, const char *devname
static const char named_dev_pref[] = DEV_NUM_PREF "_";
static const int named_dev_pref_size = sizeof(named_dev_pref) - 1;
const char *prop_name = "devname";
+ mdadm_status_t ret;
const char *name;
if (ident->devname) {
@@ -242,53 +270,40 @@ mdadm_status_t _ident_set_devname(struct mddev_ident *ident, const char *devname
else
name = devname;
- if (is_name_posix_compatible(name) == false) {
- ident_log(prop_name, name, "Not POSIX compatible", cmdline);
- return MDADM_STATUS_ERROR;
- }
-
- if (is_string_lq(name, MD_NAME_MAX + 1) == false) {
- ident_log(prop_name, devname, "Invalid length", cmdline);
- return MDADM_STATUS_ERROR;
- }
+ ret = ident_check_name(name, prop_name, cmdline);
+ if (ret)
+ return ret;
pass:
ident->devname = xstrdup(devname);
return MDADM_STATUS_SUCCESS;
}
/**
- * _ident_set_name()- set name in &mddev_ident.
+ * _ident_set_name() - set name in &mddev_ident.
* @ident: pointer to &mddev_ident.
* @name: name to be set.
- * @cmdline: context dependent actions.
*
* If criteria passed, set name in @ident.
* Note: name is not used by config file, it for cmdline only.
*
* Return: %MDADM_STATUS_SUCCESS or %MDADM_STATUS_ERROR.
*/
-static mdadm_status_t _ident_set_name(struct mddev_ident *ident, const char *name,
- const bool cmdline)
+mdadm_status_t ident_set_name(struct mddev_ident *ident, const char *name)
{
assert(name);
assert(ident);
const char *prop_name = "name";
+ mdadm_status_t ret;
if (ident->name[0]) {
- ident_log(prop_name, name, "Already defined", cmdline);
- return MDADM_STATUS_ERROR;
- }
-
- if (is_string_lq(name, MD_NAME_MAX + 1) == false) {
- ident_log(prop_name, name, "Too long or empty", cmdline);
+ ident_log(prop_name, name, "Already defined", true);
return MDADM_STATUS_ERROR;
}
- if (is_name_posix_compatible(name) == false) {
- ident_log(prop_name, name, "Not POSIX compatible", cmdline);
- return MDADM_STATUS_ERROR;
- }
+ ret = ident_check_name(name, prop_name, true);
+ if (ret)
+ return ret;
snprintf(ident->name, MD_NAME_MAX + 1, "%s", name);
return MDADM_STATUS_SUCCESS;
@@ -302,14 +317,6 @@ mdadm_status_t ident_set_devname(struct mddev_ident *ident, const char *name)
return _ident_set_devname(ident, name, true);
}
-/**
- * ident_set_name()- exported, for cmdline.
- */
-mdadm_status_t ident_set_name(struct mddev_ident *ident, const char *name)
-{
- return _ident_set_name(ident, name, true);
-}
-
struct conf_dev {
struct conf_dev *next;
char *name;
@@ -379,6 +386,7 @@ struct mddev_dev *load_containers(void)
map = NULL;
}
free_mdstat(mdstat);
+ map_free(map);
return rv;
}
@@ -949,7 +957,8 @@ void conf_file_or_dir(FILE *f)
struct dirent *dp;
struct fname *list = NULL;
- fstat(fileno(f), &st);
+ if (fstat(fileno(f), &st) != 0)
+ return;
if (S_ISREG(st.st_mode))
conf_file(f);
else if (!S_ISDIR(st.st_mode))
diff --git a/drive_encryption.c b/drive_encryption.c
index 27da962..63bdab1 100644
--- a/drive_encryption.c
+++ b/drive_encryption.c
@@ -65,6 +65,7 @@
#define SENSE_DATA_CURRENT_FIXED (0x70)
#define SENSE_DATA_CURRENT_DESC (0x72)
#define SENSE_CURRENT_RES_DESC_POS (8)
+#define SENSE_RESPONSE_CODE_MASK (0x7f)
#define SG_DRIVER_SENSE (0x08)
typedef enum drive_feature_support_status {
@@ -233,7 +234,7 @@ nvme_security_recv_ioctl(int disk_fd, __u8 sec_protocol, __u16 comm_id, void *re
nvme_cmd.cdw10 = sec_protocol << 24 | comm_id << 8;
nvme_cmd.cdw11 = buf_size;
nvme_cmd.data_len = buf_size;
- nvme_cmd.addr = (__u64)response_buffer;
+ nvme_cmd.addr = (__u64)(uintptr_t)response_buffer;
status = ioctl(disk_fd, NVME_IOCTL_ADMIN_CMD, &nvme_cmd);
if (status != 0) {
@@ -268,7 +269,7 @@ nvme_identify_ioctl(int disk_fd, void *response_buffer, size_t buf_size, const i
nvme_cmd.opcode = NVME_IDENTIFY;
nvme_cmd.cdw10 = NVME_IDENTIFY_CONTROLLER_DATA;
nvme_cmd.data_len = buf_size;
- nvme_cmd.addr = (__u64)response_buffer;
+ nvme_cmd.addr = (__u64)(uintptr_t)response_buffer;
status = ioctl(disk_fd, NVME_IOCTL_ADMIN_CMD, &nvme_cmd);
if (status != 0) {
@@ -473,6 +474,7 @@ ata_pass_through12_ioctl(int disk_fd, __u8 ata_command, __u8 sec_protocol, __u1
{
__u8 cdb[ATA_INQUIRY_LENGTH] = {0};
__u8 sense[SG_SENSE_SIZE] = {0};
+ __u8 sense_response_code;
__u8 *sense_desc = NULL;
sg_io_hdr_t sg = {0};
@@ -517,15 +519,17 @@ ata_pass_through12_ioctl(int disk_fd, __u8 ata_command, __u8 sec_protocol, __u1
return MDADM_STATUS_ERROR;
}
+ sense_response_code = sense[0] & SENSE_RESPONSE_CODE_MASK;
/* verify expected sense response code */
- if (!(sense[0] == SENSE_DATA_CURRENT_DESC || sense[0] == SENSE_DATA_CURRENT_FIXED)) {
+ if (!(sense_response_code == SENSE_DATA_CURRENT_DESC ||
+ sense_response_code == SENSE_DATA_CURRENT_FIXED)) {
pr_vrb("Failed ata passthrough12 ioctl. Device: /dev/%s.\n", fd2kname(disk_fd));
return MDADM_STATUS_ERROR;
}
sense_desc = sense + SENSE_CURRENT_RES_DESC_POS;
/* verify sense data current response with descriptor format */
- if (sense[0] == SENSE_DATA_CURRENT_DESC &&
+ if (sense_response_code == SENSE_DATA_CURRENT_DESC &&
!(sense_desc[0] == ATA_STATUS_RETURN_DESCRIPTOR &&
sense_desc[1] == ATA_INQUIRY_LENGTH)) {
pr_vrb("Failed ata passthrough12 ioctl. Device: /dev/%s. Sense data ASC: %d, ASCQ: %d.\n",
@@ -534,7 +538,7 @@ ata_pass_through12_ioctl(int disk_fd, __u8 ata_command, __u8 sec_protocol, __u1
}
/* verify sense data current response with fixed format */
- if (sense[0] == SENSE_DATA_CURRENT_FIXED &&
+ if (sense_response_code == SENSE_DATA_CURRENT_FIXED &&
!(sense[12] == ATA_PT_INFORMATION_AVAILABLE_ASC &&
sense[13] == ATA_PT_INFORMATION_AVAILABLE_ASCQ)) {
pr_vrb("Failed ata passthrough12 ioctl. Device: /dev/%s. Sense data ASC: %d, ASCQ: %d.\n",
diff --git a/lib.c b/lib.c
index 2b09293..13d4e4f 100644
--- a/lib.c
+++ b/lib.c
@@ -109,7 +109,7 @@ char *devid2kname(dev_t devid)
link[n] = 0;
cp = strrchr(link, '/');
if (cp) {
- strcpy(devnm, cp + 1);
+ snprintf(devnm, sizeof(devnm), "%s", cp + 1);
return devnm;
}
}
@@ -159,7 +159,7 @@ char *devid2devnm(dev_t devid)
ep = strchr(cp, '/');
if (ep)
*ep = 0;
- strcpy(devnm, cp);
+ snprintf(devnm, sizeof(devnm), "%s", cp);
return devnm;
}
}
diff --git a/mapfile.c b/mapfile.c
index f1f3ee2..ea9837a 100644
--- a/mapfile.c
+++ b/mapfile.c
@@ -165,8 +165,8 @@ void map_add(struct map_ent **melp,
{
struct map_ent *me = xmalloc(sizeof(*me));
- strcpy(me->devnm, devnm);
- strcpy(me->metadata, metadata);
+ snprintf(me->devnm, sizeof(me->devnm), "%s", devnm);
+ snprintf(me->metadata, sizeof(me->metadata), "%s", metadata);
memcpy(me->uuid, uuid, 16);
me->path = path ? xstrdup(path) : NULL;
me->next = *melp;
@@ -227,7 +227,7 @@ int map_update(struct map_ent **mpp, char *devnm, char *metadata,
for (mp = map ; mp ; mp=mp->next)
if (strcmp(mp->devnm, devnm) == 0) {
- strcpy(mp->metadata, metadata);
+ snprintf(mp->metadata, sizeof(mp->metadata), "%s", metadata);
memcpy(mp->uuid, uuid, 16);
free(mp->path);
mp->path = path ? xstrdup(path) : NULL;
diff --git a/mdadm.8.in b/mdadm.8.in
index 9ba6682..aa0c540 100644
--- a/mdadm.8.in
+++ b/mdadm.8.in
@@ -727,29 +727,25 @@ same as
.TP
.BR \-b ", " \-\-bitmap=
-Specify a file to store a write-intent bitmap in. The file should not
-exist unless
-.B \-\-force
-is also given. The same file should be provided
-when assembling the array. If the word
-.B "internal"
-is given, then the bitmap is stored with the metadata on the array,
-and so is replicated on all devices. If the word
-.B "none"
-is given with
-.B \-\-grow
-mode, then any bitmap that is present is removed. If the word
-.B "clustered"
-is given, the array is created for a clustered environment. One bitmap
-is created for each node as defined by the
+Specify how to store a write-intent bitmap. Following values are supported:
+
+.B internal
+- the bitmap is stored with the metadata on the array and so is replicated on all devices.
+
+.B clustered
+- the array is created for a clustered environment. One bitmap is created for each node as defined
+by the
.B \-\-nodes
parameter and are stored internally.
-To help catch typing errors, the filename must contain at least one
-slash ('/') if it is a real file (not 'internal' or 'none').
+.B none
+- create array with no bitmap or remove any present bitmap (grow mode).
-Note: external bitmaps are only known to work on ext2 and ext3.
-Storing bitmap files on other filesystems may result in serious problems.
+Setting bitmap for file is deprecated and should not be used. The file should not exist unless
+.B \-\-force
+is also given. The same file should be provided when assembling the array. The file name must
+contain at least one slash ('/'). Bitmap files are only known to work on ext2 and ext3. Storing
+bitmap files on other filesystems may result in serious problems.
When creating an array on devices which are 100G or larger,
.I mdadm
diff --git a/mdadm.c b/mdadm.c
index 3f19128..0b99fad 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -29,6 +29,51 @@
#include "md_p.h"
#include <ctype.h>
+/**
+ * set_bitmap_value() - set bitmap value.
+ * @s: Shape.
+ * @c: Context.
+ * @val: value to set.
+ *
+ * Validate and set bitmap. Context is needed for setting nodes for clustered bitmap.
+ */
+static mdadm_status_t set_bitmap_value(struct shape *s, struct context *c, char *val)
+{
+ if (s->bitmap_file) {
+ pr_err("--bitmap cannot be set twice. Second value: \"%s\".\n", val);
+ return MDADM_STATUS_ERROR;
+ }
+
+ if (strcmp(val, "internal") == 0 || strcmp(optarg, STR_COMMON_NONE) == 0) {
+ s->bitmap_file = val;
+ return MDADM_STATUS_SUCCESS;
+ }
+
+ if (strcmp(val, "clustered") == 0) {
+ s->bitmap_file = val;
+ /* Set the default number of cluster nodes
+ * to 4 if not already set by user
+ */
+ if (c->nodes < 1)
+ c->nodes = 4;
+ return MDADM_STATUS_SUCCESS;
+ }
+
+ if (strchr(val, '/')) {
+ pr_info("Custom write-intent bitmap file option is deprecated.\n");
+ if (ask("Do you want to continue? (y/n)")) {
+ s->bitmap_file = val;
+ return MDADM_STATUS_SUCCESS;
+ }
+
+ return MDADM_STATUS_ERROR;
+ }
+
+ pr_err("--bitmap value must contain a '/' or be 'internal', 'clustered' or 'none'\n");
+ pr_err("Current value is \"%s\"", val);
+ return MDADM_STATUS_ERROR;
+}
+
static int scan_assemble(struct supertype *ss,
struct context *c,
struct mddev_ident *ident);
@@ -1094,30 +1139,9 @@ int main(int argc, char *argv[])
case O(CREATE,Bitmap): /* here we create the bitmap */
case O(GROW,'b'):
case O(GROW,Bitmap):
- if (s.bitmap_file) {
- pr_err("bitmap cannot be set twice. Second value: %s.\n", optarg);
+ if (set_bitmap_value(&s, &c, optarg))
exit(2);
- }
- if (strcmp(optarg, "internal") == 0 ||
- strcmp(optarg, STR_COMMON_NONE) == 0 ||
- strchr(optarg, '/') != NULL) {
- s.bitmap_file = optarg;
- continue;
- }
- if (strcmp(optarg, "clustered") == 0) {
- s.bitmap_file = optarg;
- /* Set the default number of cluster nodes
- * to 4 if not already set by user
- */
- if (c.nodes < 1)
- c.nodes = 4;
- continue;
- }
- /* probable typo */
- pr_err("bitmap file must contain a '/', or be 'internal', or be 'clustered', or 'none'\n"
- " not '%s'\n", optarg);
- exit(2);
-
+ continue;
case O(GROW,BitmapChunk):
case O(BUILD,BitmapChunk):
case O(CREATE,BitmapChunk): /* bitmap chunksize */
@@ -1636,7 +1660,7 @@ int main(int argc, char *argv[])
c.delay = DEFAULT_BITMAP_DELAY;
rv = Grow_addbitmap(ident.devname, mdfd, &c, &s);
} else if (grow_continue)
- rv = Grow_continue_command(ident.devname, mdfd, c.backup_file, c.verbose);
+ rv = Grow_continue_command(ident.devname, mdfd, &c);
else if (s.size > 0 || s.raiddisks || s.layout_str ||
s.chunk != 0 || s.level != UnSet ||
s.data_offset != INVALID_SECTORS) {
diff --git a/mdadm.h b/mdadm.h
index 2640b39..2700915 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -223,6 +223,14 @@ struct dlm_lksb {
struct __una_u16 { __u16 x; } __attribute__ ((packed));
struct __una_u32 { __u32 x; } __attribute__ ((packed));
+/*
+ * Ensure GNU basename behavior on GLIBC less systems.
+ */
+#ifndef __GLIBC__
+#define basename(path) \
+ (strrchr((path), '/') ? strrchr((path),'/') + 1 : (path))
+#endif
+
static inline __u16 __get_unaligned16(const void *p)
{
const struct __una_u16 *ptr = (const struct __una_u16 *)p;
@@ -535,7 +543,8 @@ enum special_options {
};
enum update_opt {
- UOPT_NAME = 1,
+ UOPT_UNDEFINED = 0,
+ UOPT_NAME,
UOPT_PPL,
UOPT_NO_PPL,
UOPT_BITMAP,
@@ -575,7 +584,6 @@ enum update_opt {
UOPT_SPEC_FAILFAST,
UOPT_SPEC_NOFAILFAST,
UOPT_SPEC_REVERT_RESHAPE_NOBACKUP,
- UOPT_UNDEFINED
};
extern void fprint_update_options(FILE *outf, enum update_opt update_mode);
@@ -594,6 +602,11 @@ enum flag_mode {
FlagDefault, FlagSet, FlagClear,
};
+typedef enum {
+ ROLLBACK_METADATA_CHANGES,
+ APPLY_METADATA_CHANGES
+} change_dir_t;
+
/* structures read from config file */
/* List of mddevice names and identifiers
* Identifiers can be:
@@ -667,7 +680,9 @@ struct context {
};
struct shape {
+ char *dev;
int raiddisks;
+ int delta_disks;
int sparedisks;
int journaldisks;
int level;
@@ -682,6 +697,7 @@ struct shape {
unsigned long long size;
unsigned long long data_offset;
int consistency_policy;
+ change_dir_t direction;
};
/* List of device names - wildcards expanded */
@@ -1229,15 +1245,8 @@ extern struct superswitch {
* initialized to indicate if reshape is being performed at the
* container or subarray level
*/
-#define APPLY_METADATA_CHANGES 1
-#define ROLLBACK_METADATA_CHANGES 0
-
- int (*reshape_super)(struct supertype *st,
- unsigned long long size, int level,
- int layout, int chunksize, int raid_disks,
- int delta_disks, char *backup, char *dev,
- int direction,
- int verbose); /* optional */
+
+ int (*reshape_super)(struct supertype *st, struct shape *shape, struct context *c);
int (*manage_reshape)( /* optional */
int afd, struct mdinfo *sra, struct reshape *reshape,
struct supertype *st, unsigned long blocks,
@@ -1541,8 +1550,7 @@ extern int Grow_reshape(char *devname, int fd,
extern int Grow_restart(struct supertype *st, struct mdinfo *info,
int *fdlist, int cnt, char *backup_file, int verbose);
extern int Grow_continue(int mdfd, struct supertype *st,
- struct mdinfo *info, char *backup_file,
- int forked, int freeze_reshape);
+ struct mdinfo *info, int forked, struct context *c);
extern int Grow_consistency_policy(char *devname, int fd,
struct context *c, struct shape *s);
@@ -1552,8 +1560,7 @@ extern int restore_backup(struct supertype *st,
int spares,
char **backup_filep,
int verbose);
-extern int Grow_continue_command(char *devname, int fd,
- char *backup_file, int verbose);
+extern int Grow_continue_command(char *devname, int fd, struct context *c);
extern int Assemble(struct supertype *st, char *mddev,
struct mddev_ident *ident,
@@ -1769,8 +1776,11 @@ extern int is_subarray_active(char *subarray, char *devname);
extern int open_subarray(char *dev, char *subarray, struct supertype *st, int quiet);
extern struct superswitch *version_to_superswitch(char *vers);
-extern int mdmon_running(char *devnm);
-extern int mdmon_pid(char *devnm);
+extern mdadm_status_t wait_for_mdmon_control_socket(const char *container_devnm);
+extern int mdmon_running(const char *devnm);
+extern int mdmon_pid(const char *devnm);
+extern mdadm_status_t wait_for_mdmon(const char *devnm);
+
extern int check_env(char *name);
extern __u32 random32(void);
extern void random_uuid(__u8 *buf);
diff --git a/mdstat.c b/mdstat.c
index 2fd792c..e233f09 100644
--- a/mdstat.c
+++ b/mdstat.c
@@ -348,7 +348,8 @@ void mdstat_wait_fd(int fd, const sigset_t *sigmask)
if (fd >= 0) {
struct stat stb;
- fstat(fd, &stb);
+ if (fstat(fd, &stb) != 0)
+ return;
if ((stb.st_mode & S_IFMT) == S_IFREG)
/* Must be a /proc or /sys fd, so expect
* POLLPRI
diff --git a/msg.c b/msg.c
index ba0e25b..f0772b3 100644
--- a/msg.c
+++ b/msg.c
@@ -170,7 +170,7 @@ int connect_monitor(char *devname)
addr.sun_family = PF_LOCAL;
strcpy(addr.sun_path, path);
- if (connect(sfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
+ if (connect(sfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
close(sfd);
return -1;
}
diff --git a/platform-intel.c b/platform-intel.c
index ac282bc..d6a5353 100644
--- a/platform-intel.c
+++ b/platform-intel.c
@@ -32,6 +32,64 @@
#define NVME_SUBSYS_PATH "/sys/devices/virtual/nvme-subsystem/"
+static bool imsm_orom_has_raid0(const struct imsm_orom *orom)
+{
+ return imsm_rlc_has_bit(orom, IMSM_OROM_RLC_RAID0);
+}
+
+static bool imsm_orom_has_raid1(const struct imsm_orom *orom)
+{
+ return imsm_rlc_has_bit(orom, IMSM_OROM_RLC_RAID1);
+}
+
+static bool imsm_orom_has_raid10(const struct imsm_orom *orom)
+{
+ return imsm_rlc_has_bit(orom, IMSM_OROM_RLC_RAID10);
+}
+
+static bool imsm_orom_has_raid5(const struct imsm_orom *orom)
+{
+ return imsm_rlc_has_bit(orom, IMSM_OROM_RLC_RAID5);
+}
+
+/* IMSM platforms do not define how many disks are allowed for each level,
+ * but there are some global limitations we need to follow.
+ */
+static bool imsm_orom_support_raid_disks_count_raid0(const int raid_disks)
+{
+ return true;
+}
+
+static bool imsm_orom_support_raid_disks_count_raid1(const int raid_disks)
+{
+ if (raid_disks == 2)
+ return true;
+ return false;
+}
+
+static bool imsm_orom_support_raid_disks_count_raid5(const int raid_disks)
+{
+ if (raid_disks > 2)
+ return true;
+ return false;
+}
+
+static bool imsm_orom_support_raid_disks_count_raid10(const int raid_disks)
+{
+ /* raid_disks count must be higher than 4 and even */
+ if (raid_disks >= 4 && (raid_disks & 1) == 0)
+ return true;
+ return false;
+}
+
+struct imsm_level_ops imsm_level_ops[] = {
+ {0, imsm_orom_has_raid0, imsm_orom_support_raid_disks_count_raid0, "raid0"},
+ {1, imsm_orom_has_raid1, imsm_orom_support_raid_disks_count_raid1, "raid1"},
+ {5, imsm_orom_has_raid5, imsm_orom_support_raid_disks_count_raid5, "raid5"},
+ {10, imsm_orom_has_raid10, imsm_orom_support_raid_disks_count_raid10, "raid10"},
+ {-1, NULL, NULL, NULL}
+};
+
static int devpath_to_ll(const char *dev_path, const char *entry,
unsigned long long *val);
@@ -849,14 +907,14 @@ char *get_nvme_multipath_dev_hw_path(const char *dev_path)
return NULL;
for (ent = readdir(dir); ent; ent = readdir(dir)) {
- char buf[strlen(dev_path) + strlen(ent->d_name) + 1];
+ char buf[PATH_MAX];
/* Check if dir is a controller, ignore namespaces*/
if (!(strncmp(ent->d_name, "nvme", 4) == 0) ||
(strrchr(ent->d_name, 'n') != &ent->d_name[0]))
continue;
- sprintf(buf, "%s/%s", dev_path, ent->d_name);
+ snprintf(buf, PATH_MAX, "%s/%s", dev_path, ent->d_name);
rp = realpath(buf, NULL);
break;
}
diff --git a/platform-intel.h b/platform-intel.h
index 3c2bc59..dcc5aaa 100644
--- a/platform-intel.h
+++ b/platform-intel.h
@@ -109,25 +109,21 @@ struct imsm_orom {
#define IMSM_OROM_CAPABILITIES_TPV (1 << 10)
} __attribute__((packed));
-static inline int imsm_orom_has_raid0(const struct imsm_orom *orom)
-{
- return !!(orom->rlc & IMSM_OROM_RLC_RAID0);
-}
-static inline int imsm_orom_has_raid1(const struct imsm_orom *orom)
-{
- return !!(orom->rlc & IMSM_OROM_RLC_RAID1);
-}
-static inline int imsm_orom_has_raid1e(const struct imsm_orom *orom)
-{
- return !!(orom->rlc & IMSM_OROM_RLC_RAID1E);
-}
-static inline int imsm_orom_has_raid10(const struct imsm_orom *orom)
-{
- return !!(orom->rlc & IMSM_OROM_RLC_RAID10);
-}
-static inline int imsm_orom_has_raid5(const struct imsm_orom *orom)
+/* IMSM metadata requirements for each level */
+struct imsm_level_ops {
+ int level;
+ bool (*is_level_supported)(const struct imsm_orom *);
+ bool (*is_raiddisks_count_supported)(const int);
+ char *name;
+};
+
+extern struct imsm_level_ops imsm_level_ops[];
+
+static inline bool imsm_rlc_has_bit(const struct imsm_orom *orom, const unsigned short bit)
{
- return !!(orom->rlc & IMSM_OROM_RLC_RAID5);
+ if (orom->rlc & bit)
+ return true;
+ return false;
}
/**
diff --git a/super-ddf.c b/super-ddf.c
index 21426c7..d870102 100644
--- a/super-ddf.c
+++ b/super-ddf.c
@@ -809,7 +809,7 @@ static int load_ddf_header(int fd, unsigned long long lba,
if (lba >= size-1)
return 0;
- if (lseek64(fd, lba<<9, 0) < 0)
+ if (lseek64(fd, lba << 9, 0) == -1L)
return 0;
if (read(fd, hdr, 512) != 512)
@@ -828,8 +828,7 @@ static int load_ddf_header(int fd, unsigned long long lba,
!be64_eq(anchor->primary_lba, hdr->primary_lba) ||
!be64_eq(anchor->secondary_lba, hdr->secondary_lba) ||
hdr->type != type ||
- memcmp(anchor->pad2, hdr->pad2, 512 -
- offsetof(struct ddf_header, pad2)) != 0) {
+ memcmp(anchor->pad2, hdr->pad2, sizeof(anchor->pad2)) != 0) {
pr_err("header mismatch\n");
return 0;
}
@@ -863,7 +862,7 @@ static void *load_section(int fd, struct ddf_super *super, void *buf,
else
offset += be64_to_cpu(super->active->secondary_lba);
- if ((unsigned long long)lseek64(fd, offset<<9, 0) != (offset<<9)) {
+ if ((unsigned long long)lseek64(fd, offset << 9, 0) != (offset << 9)) {
if (dofree)
free(buf);
return NULL;
@@ -882,7 +881,7 @@ static int load_ddf_headers(int fd, struct ddf_super *super, char *devname)
get_dev_size(fd, NULL, &dsize);
- if (lseek64(fd, dsize-512, 0) < 0) {
+ if (lseek64(fd, dsize - 512, 0) == -1L) {
if (devname)
pr_err("Cannot seek to anchor block on %s: %s\n",
devname, strerror(errno));
@@ -909,8 +908,7 @@ static int load_ddf_headers(int fd, struct ddf_super *super, char *devname)
if (memcmp(super->anchor.revision, DDF_REVISION_0, 8) != 0 &&
memcmp(super->anchor.revision, DDF_REVISION_2, 8) != 0) {
if (devname)
- pr_err("can only support super revision %.8s and earlier, not %.8s on %s\n",
- DDF_REVISION_2, super->anchor.revision,devname);
+ pr_err("The DDF revision on %s\n is not supported", devname);
return 2;
}
super->active = NULL;
@@ -1053,7 +1051,10 @@ static int load_ddf_local(int fd, struct ddf_super *super,
0);
dl->devname = devname ? xstrdup(devname) : NULL;
- fstat(fd, &stb);
+ if (fstat(fd, &stb) != 0) {
+ free(dl);
+ return 1;
+ }
dl->major = major(stb.st_rdev);
dl->minor = minor(stb.st_rdev);
dl->next = super->dlist;
@@ -1607,6 +1608,7 @@ static unsigned int get_vd_num_of_subarray(struct supertype *st)
return DDF_NOTFOUND;
}
+ sysfs_free(sra);
return vcnum;
}
@@ -1614,11 +1616,11 @@ static void brief_examine_super_ddf(struct supertype *st, int verbose)
{
/* We just write a generic DDF ARRAY entry
*/
- struct mdinfo info;
+ struct mdinfo info = {0};
char nbuf[64];
+
getinfo_super_ddf(st, &info, NULL);
fname_from_uuid(&info, nbuf);
-
printf("ARRAY metadata=ddf UUID=%s\n", nbuf + 5);
}
@@ -1628,9 +1630,10 @@ static void brief_examine_subarrays_ddf(struct supertype *st, int verbose)
* by uuid and member by unit number and uuid.
*/
struct ddf_super *ddf = st->sb;
- struct mdinfo info;
+ struct mdinfo info = {0};
unsigned int i;
char nbuf[64];
+
getinfo_super_ddf(st, &info, NULL);
fname_from_uuid(&info, nbuf);
@@ -1655,8 +1658,9 @@ static void brief_examine_subarrays_ddf(struct supertype *st, int verbose)
static void export_examine_super_ddf(struct supertype *st)
{
- struct mdinfo info;
+ struct mdinfo info = {0};
char nbuf[64];
+
getinfo_super_ddf(st, &info, NULL);
fname_from_uuid(&info, nbuf);
printf("MD_METADATA=ddf\n");
@@ -1689,10 +1693,12 @@ static int copy_metadata_ddf(struct supertype *st, int from, int to)
if (!get_dev_size(from, NULL, &dsize))
goto err;
- if (lseek64(from, dsize-512, 0) < 0)
+ if (lseek64(from, dsize - 512, 0) == -1L)
goto err;
+
if (read(from, buf, 512) != 512)
goto err;
+
ddf = buf;
if (!be32_eq(ddf->magic, DDF_HEADER_MAGIC) ||
!be32_eq(calc_crc(ddf, 512), ddf->crc) ||
@@ -1708,9 +1714,9 @@ static int copy_metadata_ddf(struct supertype *st, int from, int to)
bytes = dsize - offset;
- if (lseek64(from, offset, 0) < 0 ||
- lseek64(to, offset, 0) < 0)
+ if (lseek64(from, offset, 0) == -1L || lseek64(to, offset, 0) == -1L)
goto err;
+
while (written < bytes) {
int n = bytes - written;
if (n > 4096)
@@ -1792,6 +1798,7 @@ static void brief_detail_super_ddf(struct supertype *st, char *subarray)
char nbuf[64];
struct ddf_super *ddf = st->sb;
unsigned int vcnum = get_vd_num_of_subarray(st);
+
if (vcnum == DDF_CONTAINER)
uuid_from_super_ddf(st, info.uuid);
else if (vcnum == DDF_NOTFOUND)
@@ -2786,7 +2793,8 @@ static int add_to_super_ddf(struct supertype *st,
/* This is device numbered dk->number. We need to create
* a phys_disk entry and a more detailed disk_data entry.
*/
- fstat(fd, &stb);
+ if (fstat(fd, &stb) != 0)
+ return 1;
n = find_unused_pde(ddf);
if (n == DDF_NOTFOUND) {
pr_err("No free slot in array, cannot add disk\n");
@@ -2967,7 +2975,9 @@ static int __write_ddf_structure(struct dl *d, struct ddf_super *ddf, __u8 type)
header->openflag = 1;
header->crc = calc_crc(header, 512);
- lseek64(fd, sector<<9, 0);
+ if (lseek64(fd, sector << 9, 0) == -1L)
+ goto out;
+
if (write(fd, header, 512) < 0)
goto out;
@@ -2978,6 +2988,7 @@ static int __write_ddf_structure(struct dl *d, struct ddf_super *ddf, __u8 type)
ddf->phys->crc = calc_crc(ddf->phys, ddf->pdsize);
if (write(fd, ddf->phys, ddf->pdsize) < 0)
goto out;
+
ddf->virt->crc = calc_crc(ddf->virt, ddf->vdsize);
if (write(fd, ddf->virt, ddf->vdsize) < 0)
goto out;
@@ -3031,7 +3042,9 @@ out:
header->openflag = 0;
header->crc = calc_crc(header, 512);
- lseek64(fd, sector<<9, 0);
+ if (lseek64(fd, sector << 9, 0) == -1L)
+ return 0;
+
if (write(fd, header, 512) < 0)
ret = 0;
@@ -3084,7 +3097,9 @@ static int _write_super_to_disk(struct ddf_super *ddf, struct dl *d)
if (!__write_ddf_structure(d, ddf, DDF_HEADER_SECONDARY))
return 0;
- lseek64(fd, (size-1)*512, SEEK_SET);
+ if (lseek64(fd, (size - 1) * 512, SEEK_SET) == -1L)
+ return 0;
+
if (write(fd, &ddf->anchor, 512) < 0)
return 0;
@@ -3295,9 +3310,10 @@ static int validate_geometry_ddf(struct supertype *st,
char *dev, unsigned long long *freesize,
int consistency_policy, int verbose)
{
- int fd;
- struct mdinfo *sra;
+ struct mdinfo *sra = NULL;
+ int ret = 1;
int cfd;
+ int fd;
/* ddf potentially supports lots of things, but it depends on
* what devices are offered (and maybe kernel version?)
@@ -3365,7 +3381,7 @@ static int validate_geometry_ddf(struct supertype *st,
* Later we should check for a BVD and make an SVD.
*/
fd = open(dev, O_RDONLY|O_EXCL, 0);
- if (fd >= 0) {
+ if (is_fd_valid(fd)) {
close(fd);
/* Just a bare device, no good to us */
if (verbose)
@@ -3373,44 +3389,58 @@ static int validate_geometry_ddf(struct supertype *st,
dev);
return 0;
}
+
if (errno != EBUSY || (fd = open(dev, O_RDONLY, 0)) < 0) {
if (verbose)
pr_err("ddf: Cannot open %s: %s\n",
dev, strerror(errno));
return 0;
}
+
/* Well, it is in use by someone, maybe a 'ddf' container. */
cfd = open_container(fd);
- if (cfd < 0) {
- close(fd);
+ close(fd);
+
+ if (!is_fd_valid(cfd)) {
if (verbose)
- pr_err("ddf: Cannot use %s: %s\n",
- dev, strerror(EBUSY));
+ pr_err("ddf: Cannot use %s\n", dev);
return 0;
}
+
sra = sysfs_read(cfd, NULL, GET_VERSION);
- close(fd);
- if (sra && sra->array.major_version == -1 &&
- strcmp(sra->text_version, "ddf") == 0) {
+ if (!sra) {
+ pr_err("Cannot read sysfs for /dev/%s\n", fd2kname(cfd));
+ goto error;
+ }
+
+ if (sra->array.major_version == -1 && strcmp(sra->text_version, "ddf") == 0) {
/* This is a member of a ddf container. Load the container
* and try to create a bvd
*/
- struct ddf_super *ddf;
+ struct ddf_super *ddf = NULL;
+
if (load_super_ddf_all(st, cfd, (void **)&ddf, NULL) == 0) {
st->sb = ddf;
- strcpy(st->container_devnm, fd2devnm(cfd));
+ snprintf(st->container_devnm, sizeof(st->container_devnm),
+ "%s", fd2kname(cfd));
close(cfd);
- return validate_geometry_ddf_bvd(st, level, layout,
- raiddisks, chunk, size,
- data_offset,
- dev, freesize,
- verbose);
+ free(sra);
+
+ return validate_geometry_ddf_bvd(st, level, layout, raiddisks,
+ chunk, size, data_offset, dev,
+ freesize, verbose);
}
- close(cfd);
- } else /* device may belong to a different container */
- return 0;
+ free(ddf);
+ }
- return 1;
+ /* device may belong to a different container */
+ ret = 0;
+
+error:
+ free(sra);
+ close(cfd);
+
+ return ret;
}
static int validate_geometry_ddf_bvd(struct supertype *st,
@@ -3479,35 +3509,42 @@ static int validate_geometry_ddf_bvd(struct supertype *st,
static int load_super_ddf_all(struct supertype *st, int fd,
void **sbp, char *devname)
{
- struct mdinfo *sra;
- struct ddf_super *super;
struct mdinfo *sd, *best = NULL;
+ struct ddf_super *super = NULL;
+ struct mdinfo *sra;
int bestseq = 0;
- int seq;
+ int ret = 1;
char nm[20];
+ int seq;
int dfd;
sra = sysfs_read(fd, NULL, GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE);
if (!sra)
return 1;
- if (sra->array.major_version != -1 ||
- sra->array.minor_version != -2 ||
+ if (sra->array.major_version != -1 || sra->array.minor_version != -2 ||
strcmp(sra->text_version, "ddf") != 0)
- return 1;
+ goto out;
if (posix_memalign((void**)&super, 512, sizeof(*super)) != 0)
- return 1;
+ goto out;
+
memset(super, 0, sizeof(*super));
/* first, try each device, and choose the best ddf */
for (sd = sra->devs ; sd ; sd = sd->next) {
int rv;
+
sprintf(nm, "%d:%d", sd->disk.major, sd->disk.minor);
+
dfd = dev_open(nm, O_RDONLY);
- if (dfd < 0)
- return 2;
+ if (!is_fd_valid(dfd)) {
+ ret = 2;
+ goto out;
+ }
+
rv = load_ddf_headers(dfd, super, NULL);
close(dfd);
+
if (rv == 0) {
seq = be32_to_cpu(super->active->seq);
if (super->active->openflag)
@@ -3519,28 +3556,39 @@ static int load_super_ddf_all(struct supertype *st, int fd,
}
}
if (!best)
- return 1;
+ goto out;
+
/* OK, load this ddf */
sprintf(nm, "%d:%d", best->disk.major, best->disk.minor);
+
dfd = dev_open(nm, O_RDONLY);
if (dfd < 0)
- return 1;
+ goto out;
+
load_ddf_headers(dfd, super, NULL);
load_ddf_global(dfd, super, NULL);
close(dfd);
+
/* Now we need the device-local bits */
for (sd = sra->devs ; sd ; sd = sd->next) {
int rv;
sprintf(nm, "%d:%d", sd->disk.major, sd->disk.minor);
+
dfd = dev_open(nm, O_RDWR);
- if (dfd < 0)
- return 2;
+ if (dfd < 0) {
+ ret = 2;
+ goto out;
+ }
+
rv = load_ddf_headers(dfd, super, NULL);
if (rv == 0)
rv = load_ddf_local(dfd, super, NULL, 1);
- if (rv)
- return 1;
+
+ if (rv) {
+ close(dfd);
+ goto out;
+ }
}
*sbp = super;
@@ -3549,8 +3597,16 @@ static int load_super_ddf_all(struct supertype *st, int fd,
st->minor_version = 0;
st->max_devs = 512;
}
- strcpy(st->container_devnm, fd2devnm(fd));
- return 0;
+
+ snprintf(st->container_devnm, sizeof(st->container_devnm), "%s", fd2devnm(fd));
+ ret = 0;
+
+out:
+ if (sra)
+ free(sra);
+ if (super && ret != 0)
+ free(super);
+ return ret;
}
static int load_container_ddf(struct supertype *st, int fd,
@@ -3787,7 +3843,7 @@ static struct mdinfo *container_content_ddf(struct supertype *st, char *subarray
be64_to_cpu(LBA_OFFSET(ddf, bvd)[iphys]);
dev->component_size = be64_to_cpu(bvd->blocks);
if (d->devname)
- strcpy(dev->name, d->devname);
+ snprintf(dev->name, sizeof(dev->name), "%s", d->devname);
}
}
return rest;
@@ -3836,11 +3892,15 @@ static int store_super_ddf(struct supertype *st, int fd)
return 1;
memset(buf, 0, 512);
- lseek64(fd, dsize-512, 0);
+ if (lseek64(fd, dsize - 512, 0) == -1L) {
+ free(buf);
+ return 1;
+ }
rc = write(fd, buf, 512);
free(buf);
if (rc < 0)
return 1;
+
return 0;
}
@@ -3955,6 +4015,7 @@ static int compare_super_ddf(struct supertype *st, struct supertype *tst,
if (posix_memalign((void **)&dl1->spare, 512,
first->conf_rec_len*512) != 0) {
pr_err("could not allocate spare info buf\n");
+ free(dl1);
return 3;
}
memcpy(dl1->spare, dl2->spare, first->conf_rec_len*512);
@@ -4176,6 +4237,7 @@ static int get_bvd_state(const struct ddf_super *ddf,
state = DDF_state_part_optimal;
break;
}
+ free(avail);
return state;
}
diff --git a/super-intel.c b/super-intel.c
index 1faab60..713bfcc 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -32,14 +32,19 @@
/* MPB == Metadata Parameter Block */
#define MPB_SIGNATURE "Intel Raid ISM Cfg Sig. "
#define MPB_SIG_LEN (strlen(MPB_SIGNATURE))
-#define MPB_VERSION_RAID0 "1.0.00"
-#define MPB_VERSION_RAID1 "1.1.00"
-#define MPB_VERSION_MANY_VOLUMES_PER_ARRAY "1.2.00"
-#define MPB_VERSION_3OR4_DISK_ARRAY "1.2.01"
-#define MPB_VERSION_RAID5 "1.2.02"
-#define MPB_VERSION_5OR6_DISK_ARRAY "1.2.04"
-#define MPB_VERSION_CNG "1.2.06"
+
+/* Legacy IMSM versions:
+ * MPB_VERSION_RAID0 1.0.00
+ * MPB_VERSION_RAID1 1.1.00
+ * MPB_VERSION_MANY_VOLUMES_PER_ARRAY 1.2.00
+ * MPB_VERSION_3OR4_DISK_ARRAY 1.2.01
+ * MPB_VERSION_RAID5 1.2.02
+ * MPB_VERSION_5OR6_DISK_ARRAY 1.2.04
+ * MPB_VERSION_CNG 1.2.06
+ */
+
#define MPB_VERSION_ATTRIBS "1.3.00"
+#define MPB_VERSION_ATTRIBS_JD "2.0.00"
#define MAX_SIGNATURE_LENGTH 32
#define MAX_RAID_SERIAL_LEN 16
@@ -57,6 +62,8 @@
#define MPB_ATTRIB_RAIDCNG __cpu_to_le32(0x00000020)
/* supports expanded stripe sizes of 256K, 512K and 1MB */
#define MPB_ATTRIB_EXP_STRIPE_SIZE __cpu_to_le32(0x00000040)
+/* supports RAID10 with more than 4 drives */
+#define MPB_ATTRIB_RAID10_EXT __cpu_to_le32(0x00000080)
/* The OROM Support RST Caching of Volumes */
#define MPB_ATTRIB_NVM __cpu_to_le32(0x02000000)
@@ -84,6 +91,7 @@
MPB_ATTRIB_RAID10 | \
MPB_ATTRIB_RAID5 | \
MPB_ATTRIB_EXP_STRIPE_SIZE | \
+ MPB_ATTRIB_RAID10_EXT | \
MPB_ATTRIB_BBM)
/* Define attributes that are unused but not harmful */
@@ -166,7 +174,8 @@ struct imsm_map {
__u8 raid_level;
#define IMSM_T_RAID0 0
#define IMSM_T_RAID1 1
-#define IMSM_T_RAID5 5 /* since metadata version 1.2.02 ? */
+#define IMSM_T_RAID5 5
+#define IMSM_T_RAID10 10
__u8 num_members; /* number of member disks */
__u8 num_domains; /* number of parity domains */
__u8 failed_disk_num; /* valid only when state is degraded */
@@ -514,6 +523,7 @@ enum imsm_reshape_type {
CH_TAKEOVER,
CH_MIGRATION,
CH_ARRAY_SIZE,
+ CH_ABORT
};
/* definition of messages passed to imsm_process_update */
@@ -1259,14 +1269,42 @@ static int get_imsm_disk_slot(struct imsm_map *map, const unsigned int idx)
return IMSM_STATUS_ERROR;
}
+/**
+ * update_imsm_raid_level() - update raid level appropriately in &imsm_map.
+ * @map: &imsm_map pointer.
+ * @new_level: MD style level.
+ *
+ * For backward compatibility reasons we need to differentiate RAID10.
+ * In the past IMSM RAID10 was presented as RAID1.
+ * Keep compatibility unless it is not explicitly updated by UEFI driver.
+ *
+ * Routine needs num_members to be set and (optionally) raid_level.
+ */
+static void update_imsm_raid_level(struct imsm_map *map, int new_level)
+{
+ if (new_level != IMSM_T_RAID10) {
+ map->raid_level = new_level;
+ return;
+ }
+
+ if (map->num_members == 4) {
+ if (map->raid_level == IMSM_T_RAID10 || map->raid_level == IMSM_T_RAID1)
+ return;
+
+ map->raid_level = IMSM_T_RAID1;
+ return;
+ }
+
+ map->raid_level = IMSM_T_RAID10;
+}
static int get_imsm_raid_level(struct imsm_map *map)
{
- if (map->raid_level == 1) {
+ if (map->raid_level == IMSM_T_RAID1) {
if (map->num_members == 2)
- return 1;
+ return IMSM_T_RAID1;
else
- return 10;
+ return IMSM_T_RAID10;
}
return map->raid_level;
@@ -2098,91 +2136,18 @@ void convert_from_4k(struct intel_super *super)
mpb->check_sum = __gen_imsm_checksum(mpb);
}
-/*******************************************************************************
- * function: imsm_check_attributes
- * Description: Function checks if features represented by attributes flags
- * are supported by mdadm.
- * Parameters:
- * attributes - Attributes read from metadata
- * Returns:
- * 0 - passed attributes contains unsupported features flags
- * 1 - all features are supported
- ******************************************************************************/
-static int imsm_check_attributes(__u32 attributes)
+/**
+ * imsm_check_attributes() - Check if features represented by attributes flags are supported.
+ *
+ * @attributes: attributes read from metadata.
+ * Returns: true if all features are supported, false otherwise.
+ */
+static bool imsm_check_attributes(__u32 attributes)
{
- int ret_val = 1;
- __u32 not_supported = MPB_ATTRIB_SUPPORTED^0xffffffff;
-
- not_supported &= ~MPB_ATTRIB_IGNORED;
-
- not_supported &= attributes;
- if (not_supported) {
- pr_err("(IMSM): Unsupported attributes : %x\n",
- (unsigned)__le32_to_cpu(not_supported));
- if (not_supported & MPB_ATTRIB_CHECKSUM_VERIFY) {
- dprintf("\t\tMPB_ATTRIB_CHECKSUM_VERIFY \n");
- not_supported ^= MPB_ATTRIB_CHECKSUM_VERIFY;
- }
- if (not_supported & MPB_ATTRIB_2TB) {
- dprintf("\t\tMPB_ATTRIB_2TB\n");
- not_supported ^= MPB_ATTRIB_2TB;
- }
- if (not_supported & MPB_ATTRIB_RAID0) {
- dprintf("\t\tMPB_ATTRIB_RAID0\n");
- not_supported ^= MPB_ATTRIB_RAID0;
- }
- if (not_supported & MPB_ATTRIB_RAID1) {
- dprintf("\t\tMPB_ATTRIB_RAID1\n");
- not_supported ^= MPB_ATTRIB_RAID1;
- }
- if (not_supported & MPB_ATTRIB_RAID10) {
- dprintf("\t\tMPB_ATTRIB_RAID10\n");
- not_supported ^= MPB_ATTRIB_RAID10;
- }
- if (not_supported & MPB_ATTRIB_RAID1E) {
- dprintf("\t\tMPB_ATTRIB_RAID1E\n");
- not_supported ^= MPB_ATTRIB_RAID1E;
- }
- if (not_supported & MPB_ATTRIB_RAID5) {
- dprintf("\t\tMPB_ATTRIB_RAID5\n");
- not_supported ^= MPB_ATTRIB_RAID5;
- }
- if (not_supported & MPB_ATTRIB_RAIDCNG) {
- dprintf("\t\tMPB_ATTRIB_RAIDCNG\n");
- not_supported ^= MPB_ATTRIB_RAIDCNG;
- }
- if (not_supported & MPB_ATTRIB_BBM) {
- dprintf("\t\tMPB_ATTRIB_BBM\n");
- not_supported ^= MPB_ATTRIB_BBM;
- }
- if (not_supported & MPB_ATTRIB_CHECKSUM_VERIFY) {
- dprintf("\t\tMPB_ATTRIB_CHECKSUM_VERIFY (== MPB_ATTRIB_LEGACY)\n");
- not_supported ^= MPB_ATTRIB_CHECKSUM_VERIFY;
- }
- if (not_supported & MPB_ATTRIB_EXP_STRIPE_SIZE) {
- dprintf("\t\tMPB_ATTRIB_EXP_STRIP_SIZE\n");
- not_supported ^= MPB_ATTRIB_EXP_STRIPE_SIZE;
- }
- if (not_supported & MPB_ATTRIB_2TB_DISK) {
- dprintf("\t\tMPB_ATTRIB_2TB_DISK\n");
- not_supported ^= MPB_ATTRIB_2TB_DISK;
- }
- if (not_supported & MPB_ATTRIB_NEVER_USE2) {
- dprintf("\t\tMPB_ATTRIB_NEVER_USE2\n");
- not_supported ^= MPB_ATTRIB_NEVER_USE2;
- }
- if (not_supported & MPB_ATTRIB_NEVER_USE) {
- dprintf("\t\tMPB_ATTRIB_NEVER_USE\n");
- not_supported ^= MPB_ATTRIB_NEVER_USE;
- }
-
- if (not_supported)
- dprintf("(IMSM): Unknown attributes : %x\n", not_supported);
-
- ret_val = 0;
- }
+ if ((attributes & (MPB_ATTRIB_SUPPORTED | MPB_ATTRIB_IGNORED)) == attributes)
+ return true;
- return ret_val;
+ return false;
}
static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *map);
@@ -2210,11 +2175,10 @@ static void examine_super_imsm(struct supertype *st, char *homehost)
creation_time = __le64_to_cpu(mpb->creation_time);
printf(" Creation Time : %.24s\n",
creation_time ? ctime(&creation_time) : "Unknown");
- printf(" Attributes : ");
- if (imsm_check_attributes(mpb->attributes))
- printf("All supported\n");
- else
- printf("not supported\n");
+
+ printf(" Attributes : %08x (%s)\n", mpb->attributes,
+ imsm_check_attributes(mpb->attributes) ? "supported" : "not supported");
+
getinfo_super_imsm(st, &info, NULL);
fname_from_uuid(&info, nbuf);
printf(" UUID : %s\n", nbuf + 5);
@@ -2354,7 +2318,7 @@ void print_encryption_information(int disk_fd, enum sys_dev_type hba_type)
{
struct encryption_information information = {0};
mdadm_status_t status = MDADM_STATUS_SUCCESS;
- const char *indent = " ";
+ const char *indent = " ";
switch (hba_type) {
case SYS_DEV_VMD:
@@ -2379,7 +2343,8 @@ void print_encryption_information(int disk_fd, enum sys_dev_type hba_type)
get_encryption_status_string(information.status));
}
-static int ahci_enumerate_ports(struct sys_dev *hba, int port_count, int host_base, int verbose)
+static int ahci_enumerate_ports(struct sys_dev *hba, unsigned long port_count, int host_base,
+ int verbose)
{
/* dump an unsorted list of devices attached to AHCI Intel storage
* controller, as well as non-connected ports
@@ -2393,7 +2358,7 @@ static int ahci_enumerate_ports(struct sys_dev *hba, int port_count, int host_ba
if (port_count > (int)sizeof(port_mask) * 8) {
if (verbose > 0)
- pr_err("port_count %d out of range\n", port_count);
+ pr_err("port_count %ld out of range\n", port_count);
return 2;
}
@@ -2535,11 +2500,11 @@ static int ahci_enumerate_ports(struct sys_dev *hba, int port_count, int host_ba
if (dir)
closedir(dir);
if (err == 0) {
- int i;
+ unsigned long i;
for (i = 0; i < port_count; i++)
- if (port_mask & (1 << i))
- printf(" Port%d : - no device attached -\n", i);
+ if (port_mask & (1L << i))
+ printf(" Port%ld : - no device attached -\n", i);
}
return err;
@@ -2652,6 +2617,15 @@ static int ahci_get_port_count(const char *hba_path, int *port_count)
return host_base;
}
+static void print_imsm_level_capability(const struct imsm_orom *orom)
+{
+ int idx;
+
+ for (idx = 0; imsm_level_ops[idx].name; idx++)
+ if (imsm_level_ops[idx].is_level_supported(orom))
+ printf("%s ", imsm_level_ops[idx].name);
+}
+
static void print_imsm_capability(const struct imsm_orom *orom)
{
printf(" Platform : Intel(R) ");
@@ -2670,12 +2644,11 @@ static void print_imsm_capability(const struct imsm_orom *orom)
printf(" Version : %d.%d.%d.%d\n", orom->major_ver,
orom->minor_ver, orom->hotfix_ver, orom->build);
}
- printf(" RAID Levels :%s%s%s%s%s\n",
- imsm_orom_has_raid0(orom) ? " raid0" : "",
- imsm_orom_has_raid1(orom) ? " raid1" : "",
- imsm_orom_has_raid1e(orom) ? " raid1e" : "",
- imsm_orom_has_raid10(orom) ? " raid10" : "",
- imsm_orom_has_raid5(orom) ? " raid5" : "");
+
+ printf(" RAID Levels : ");
+ print_imsm_level_capability(orom);
+ printf("\n");
+
printf(" Chunk Sizes :%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
imsm_orom_has_chunk(orom, 2) ? " 2k" : "",
imsm_orom_has_chunk(orom, 4) ? " 4k" : "",
@@ -2710,12 +2683,11 @@ static void print_imsm_capability_export(const struct imsm_orom *orom)
if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build)
printf("IMSM_VERSION=%d.%d.%d.%d\n", orom->major_ver, orom->minor_ver,
orom->hotfix_ver, orom->build);
- printf("IMSM_SUPPORTED_RAID_LEVELS=%s%s%s%s%s\n",
- imsm_orom_has_raid0(orom) ? "raid0 " : "",
- imsm_orom_has_raid1(orom) ? "raid1 " : "",
- imsm_orom_has_raid1e(orom) ? "raid1e " : "",
- imsm_orom_has_raid5(orom) ? "raid10 " : "",
- imsm_orom_has_raid10(orom) ? "raid5 " : "");
+
+ printf("IMSM_SUPPORTED_RAID_LEVELS=");
+ print_imsm_level_capability(orom);
+ printf("\n");
+
printf("IMSM_SUPPORTED_CHUNK_SIZES=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
imsm_orom_has_chunk(orom, 2) ? "2k " : "",
imsm_orom_has_chunk(orom, 4) ? "4k " : "",
@@ -4268,7 +4240,10 @@ load_imsm_disk(int fd, struct intel_super *super, char *devname, int keep_fd)
dl = xcalloc(1, sizeof(*dl));
- fstat(fd, &stb);
+ if (fstat(fd, &stb) != 0) {
+ free(dl);
+ return 1;
+ }
dl->major = major(stb.st_rdev);
dl->minor = minor(stb.st_rdev);
dl->next = super->disks;
@@ -5476,51 +5451,48 @@ static unsigned long long info_to_blocks_per_member(mdu_array_info_t *info,
return (size * 2) & ~(info_to_blocks_per_strip(info) - 1);
}
+static void imsm_write_signature(struct imsm_super *mpb)
+{
+ /* It is safer to eventually truncate version rather than left it not NULL ended */
+ snprintf((char *) mpb->sig, MAX_SIGNATURE_LENGTH, MPB_SIGNATURE MPB_VERSION_ATTRIBS);
+}
+
static void imsm_update_version_info(struct intel_super *super)
{
/* update the version and attributes */
struct imsm_super *mpb = super->anchor;
- char *version;
struct imsm_dev *dev;
struct imsm_map *map;
int i;
+ mpb->attributes |= MPB_ATTRIB_CHECKSUM_VERIFY;
+
for (i = 0; i < mpb->num_raid_devs; i++) {
dev = get_imsm_dev(super, i);
map = get_imsm_map(dev, MAP_0);
+
if (__le32_to_cpu(dev->size_high) > 0)
mpb->attributes |= MPB_ATTRIB_2TB;
- /* FIXME detect when an array spans a port multiplier */
- #if 0
- mpb->attributes |= MPB_ATTRIB_PM;
- #endif
-
- if (mpb->num_raid_devs > 1 ||
- mpb->attributes != MPB_ATTRIB_CHECKSUM_VERIFY) {
- version = MPB_VERSION_ATTRIBS;
- switch (get_imsm_raid_level(map)) {
- case 0: mpb->attributes |= MPB_ATTRIB_RAID0; break;
- case 1: mpb->attributes |= MPB_ATTRIB_RAID1; break;
- case 10: mpb->attributes |= MPB_ATTRIB_RAID10; break;
- case 5: mpb->attributes |= MPB_ATTRIB_RAID5; break;
- }
- } else {
- if (map->num_members >= 5)
- version = MPB_VERSION_5OR6_DISK_ARRAY;
- else if (dev->status == DEV_CLONE_N_GO)
- version = MPB_VERSION_CNG;
- else if (get_imsm_raid_level(map) == 5)
- version = MPB_VERSION_RAID5;
- else if (map->num_members >= 3)
- version = MPB_VERSION_3OR4_DISK_ARRAY;
- else if (get_imsm_raid_level(map) == 1)
- version = MPB_VERSION_RAID1;
- else
- version = MPB_VERSION_RAID0;
+ switch (get_imsm_raid_level(map)) {
+ case IMSM_T_RAID0:
+ mpb->attributes |= MPB_ATTRIB_RAID0;
+ break;
+ case IMSM_T_RAID1:
+ mpb->attributes |= MPB_ATTRIB_RAID1;
+ break;
+ case IMSM_T_RAID5:
+ mpb->attributes |= MPB_ATTRIB_RAID5;
+ break;
+ case IMSM_T_RAID10:
+ mpb->attributes |= MPB_ATTRIB_RAID10;
+ if (map->num_members > 4)
+ mpb->attributes |= MPB_ATTRIB_RAID10_EXT;
+ break;
}
- strcpy(((char *) mpb->sig) + strlen(MPB_SIGNATURE), version);
}
+
+ imsm_write_signature(mpb);
}
/**
@@ -5678,7 +5650,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
set_pba_of_lba0(map, super->create_offset);
map->blocks_per_strip = __cpu_to_le16(info_to_blocks_per_strip(info));
map->failed_disk_num = ~0;
- if (info->level > 0)
+ if (info->level > IMSM_T_RAID0)
map->map_state = (info->state ? IMSM_T_STATE_NORMAL
: IMSM_T_STATE_UNINITIALIZED);
else
@@ -5686,16 +5658,15 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
IMSM_T_STATE_NORMAL;
map->ddf = 1;
- if (info->level == 1 && info->raid_disks > 2) {
+ if (info->level == IMSM_T_RAID1 && info->raid_disks > 2) {
free(dev);
free(dv);
- pr_err("imsm does not support more than 2 disksin a raid1 volume\n");
+ pr_err("imsm does not support more than 2 disks in a raid1 volume\n");
return 0;
}
+ map->num_members = info->raid_disks;
- map->raid_level = info->level;
- if (info->level == 10)
- map->raid_level = 1;
+ update_imsm_raid_level(map, info->level);
set_num_domains(map);
size_per_member += NUM_BLOCKS_DIRTY_STRIPE_REGION;
@@ -5703,7 +5674,6 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
size_per_member /
BLOCKS_PER_KB));
- map->num_members = info->raid_disks;
update_num_data_stripes(map, array_blocks);
for (i = 0; i < map->num_members; i++) {
/* initialized in add_to_super */
@@ -5751,7 +5721,6 @@ static int init_super_imsm(struct supertype *st, mdu_array_info_t *info,
struct intel_super *super;
struct imsm_super *mpb;
size_t mpb_size;
- char *version;
if (data_offset != INVALID_SECTORS) {
pr_err("data-offset not supported by imsm\n");
@@ -5794,13 +5763,7 @@ static int init_super_imsm(struct supertype *st, mdu_array_info_t *info,
return 0;
}
- mpb->attributes = MPB_ATTRIB_CHECKSUM_VERIFY;
-
- version = (char *) mpb->sig;
- strcpy(version, MPB_SIGNATURE);
- version += strlen(MPB_SIGNATURE);
- strcpy(version, MPB_VERSION_RAID0);
-
+ imsm_update_version_info(super);
return 1;
}
@@ -6022,7 +5985,8 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
if (super->current_vol >= 0)
return add_to_super_imsm_volume(st, dk, fd, devname);
- fstat(fd, &stb);
+ if (fstat(fd, &stb) != 0)
+ return 1;
dd = xcalloc(sizeof(*dd), 1);
dd->major = major(stb.st_rdev);
dd->minor = minor(stb.st_rdev);
@@ -6174,7 +6138,6 @@ static union {
static int write_super_imsm_spare(struct intel_super *super, struct dl *d)
{
- struct imsm_super *mpb = super->anchor;
struct imsm_super *spare = &spare_record.anchor;
__u32 sum;
@@ -6183,14 +6146,11 @@ static int write_super_imsm_spare(struct intel_super *super, struct dl *d)
spare->mpb_size = __cpu_to_le32(sizeof(struct imsm_super));
spare->generation_num = __cpu_to_le32(1UL);
- spare->attributes = MPB_ATTRIB_CHECKSUM_VERIFY;
spare->num_disks = 1;
spare->num_raid_devs = 0;
- spare->cache_size = mpb->cache_size;
spare->pwr_cycle_count = __cpu_to_le32(1);
- snprintf((char *) spare->sig, MAX_SIGNATURE_LENGTH,
- MPB_SIGNATURE MPB_VERSION_RAID0);
+ imsm_write_signature(spare);
spare->disk[0] = d->disk;
if (__le32_to_cpu(d->disk.total_blocks_hi) > 0)
@@ -6965,26 +6925,41 @@ static unsigned long long merge_extents(struct intel_super *super, const bool ex
return free_size - reservation_size;
}
-static int is_raid_level_supported(const struct imsm_orom *orom, int level, int raiddisks)
+/**
+ * is_raid_level_supported() - check if this count of drives and level is supported by platform.
+ * @orom: hardware properties, could be NULL.
+ * @level: requested raid level.
+ * @raiddisks: requested disk count.
+ *
+ * IMSM UEFI/OROM does not provide information about supported count of raid disks
+ * for particular level. That is why it is hardcoded.
+ * It is recommended to not allow of usage other levels than supported,
+ * IMSM code is not tested against different level implementations.
+ *
+ * Return: true if supported, false otherwise.
+ */
+static bool is_raid_level_supported(const struct imsm_orom *orom, int level, int raiddisks)
{
- if (level < 0 || level == 6 || level == 4)
- return 0;
+ int idx;
- /* if we have an orom prevent invalid raid levels */
- if (orom)
- switch (level) {
- case 0: return imsm_orom_has_raid0(orom);
- case 1:
- if (raiddisks > 2)
- return imsm_orom_has_raid1e(orom);
- return imsm_orom_has_raid1(orom) && raiddisks == 2;
- case 10: return imsm_orom_has_raid10(orom) && raiddisks == 4;
- case 5: return imsm_orom_has_raid5(orom) && raiddisks > 2;
- }
- else
- return 1; /* not on an Intel RAID platform so anything goes */
+ for (idx = 0; imsm_level_ops[idx].name; idx++) {
+ if (imsm_level_ops[idx].level == level)
+ break;
+ }
- return 0;
+ if (!imsm_level_ops[idx].name)
+ return false;
+
+ if (!imsm_level_ops[idx].is_raiddisks_count_supported(raiddisks))
+ return false;
+
+ if (!orom)
+ return true;
+
+ if (imsm_level_ops[idx].is_level_supported(orom))
+ return true;
+
+ return false;
}
static int
@@ -7072,7 +7047,6 @@ get_devices(const char *hba_path)
struct md_list *dv;
struct dirent *ent;
DIR *dir;
- int err = 0;
#if DEBUG_LOOP
devlist = get_loop_devices();
@@ -7114,14 +7088,6 @@ get_devices(const char *hba_path)
dv->next = devlist;
devlist = dv;
}
- if (err) {
- while(devlist) {
- dv = devlist;
- devlist = devlist->next;
- free(dv->devname);
- free(dv);
- }
- }
closedir(dir);
return devlist;
}
@@ -7740,9 +7706,11 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
char *dev, unsigned long long *freesize,
int consistency_policy, int verbose)
{
- int fd, cfd;
+ struct intel_super *super = st->sb;
struct mdinfo *sra;
int is_member = 0;
+ imsm_status_t rv;
+ int fd, cfd;
/* load capability
* if given unused devices create a container
@@ -7767,11 +7735,10 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
}
if (!dev) {
- struct intel_super *super = st->sb;
-
/*
* Autolayout mode, st->sb must be set.
*/
+
if (!super) {
pr_vrb("superblock must be set for autolayout, aborting\n");
return 0;
@@ -7782,21 +7749,22 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
verbose))
return 0;
- if (super->orom && freesize) {
- imsm_status_t rv;
- int count = count_volumes(super->hba, super->orom->dpa,
- verbose);
+ if (super->orom) {
+ int count = count_volumes(super->hba, super->orom->dpa, verbose);
+
if (super->orom->vphba <= count) {
pr_vrb("platform does not support more than %d raid volumes.\n",
super->orom->vphba);
return 0;
}
+ }
- rv = autolayout_imsm(super, raiddisks, size, *chunk,
- freesize);
- if (rv != IMSM_STATUS_OK)
- return 0;
+ if (freesize) {
+ rv = autolayout_imsm(super, raiddisks, size, *chunk, freesize);
+ if (rv != IMSM_STATUS_OK)
+ return 0;
}
+
return 1;
}
if (st->sb) {
@@ -8139,9 +8107,9 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
int current_vol = super->current_vol;
/* do not assemble arrays when not all attributes are supported */
- if (imsm_check_attributes(mpb->attributes) == 0) {
+ if (imsm_check_attributes(mpb->attributes) == false) {
sb_errors = 1;
- pr_err("Unsupported attributes in IMSM metadata.Arrays activation is blocked.\n");
+ pr_err("Unsupported attributes in IMSM metadata. Arrays activation is blocked.\n");
}
/* count spare devices, not used in maps
@@ -8275,7 +8243,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
info_d->data_offset = pba_of_lba0(map);
info_d->component_size = calc_component_size(map, dev);
- if (map->raid_level == 5) {
+ if (map->raid_level == IMSM_T_RAID5) {
info_d->ppl_sector = this->ppl_sector;
info_d->ppl_size = this->ppl_size;
if (this->consistency_policy == CONSISTENCY_POLICY_PPL &&
@@ -9533,7 +9501,7 @@ static int apply_reshape_migration_update(struct imsm_update_reshape_migration *
}
to_state = map->map_state;
- if ((u->new_level == 5) && (map->raid_level == 0)) {
+ if ((u->new_level == IMSM_T_RAID5) && (map->raid_level == IMSM_T_RAID0)) {
map->num_members++;
/* this should not happen */
if (u->new_disks[0] < 0) {
@@ -9544,11 +9512,13 @@ static int apply_reshape_migration_update(struct imsm_update_reshape_migration *
to_state = IMSM_T_STATE_NORMAL;
}
migrate(new_dev, super, to_state, MIGR_GEN_MIGR);
+
if (u->new_level > -1)
- map->raid_level = u->new_level;
+ update_imsm_raid_level(map, u->new_level);
+
migr_map = get_imsm_map(new_dev, MAP_1);
- if ((u->new_level == 5) &&
- (migr_map->raid_level == 0)) {
+ if ((u->new_level == IMSM_T_RAID5) &&
+ (migr_map->raid_level == IMSM_T_RAID0)) {
int ord = map->num_members - 1;
migr_map->num_members--;
if (u->new_disks[0] < 0)
@@ -9584,7 +9554,7 @@ static int apply_reshape_migration_update(struct imsm_update_reshape_migration *
/* add disk
*/
- if (u->new_level != 5 || migr_map->raid_level != 0 ||
+ if (u->new_level != IMSM_T_RAID5 || migr_map->raid_level != IMSM_T_RAID0 ||
migr_map->raid_level == map->raid_level)
goto skip_disk_add;
@@ -9963,7 +9933,7 @@ static int apply_takeover_update(struct imsm_update_takeover *u,
/* update map */
map->num_members /= map->num_domains;
map->map_state = IMSM_T_STATE_NORMAL;
- map->raid_level = 0;
+ update_imsm_raid_level(map, IMSM_T_RAID0);
set_num_domains(map);
update_num_data_stripes(map, imsm_dev_size(dev));
map->failed_disk_num = -1;
@@ -10007,7 +9977,7 @@ static int apply_takeover_update(struct imsm_update_takeover *u,
map = get_imsm_map(dev_new, MAP_0);
map->map_state = IMSM_T_STATE_DEGRADED;
- map->raid_level = 1;
+ update_imsm_raid_level(map, IMSM_T_RAID10);
set_num_domains(map);
map->num_members = map->num_members * map->num_domains;
update_num_data_stripes(map, imsm_dev_size(dev));
@@ -11352,7 +11322,7 @@ check_policy:
return MDADM_STATUS_SUCCESS;
fd2devname(disk_fd, devname);
- pr_vrb("Encryption status \"%s\" detected for disk %s, but \"%s\" status was detected eariler.\n",
+ pr_vrb("Encryption status \"%s\" detected for disk %s, but \"%s\" status was detected earlier.\n",
encryption_state, devname, expected_policy->value);
pr_vrb("Disks with different encryption status cannot be used.\n");
return MDADM_STATUS_ERROR;
@@ -11927,24 +11897,23 @@ success:
****************************************************************************/
enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
struct geo_params *geo,
- int direction)
+ int direction, struct context *c)
{
struct mdinfo info;
int change = -1;
int check_devs = 0;
int chunk;
- /* number of added/removed disks in operation result */
- int devNumChange = 0;
/* imsm compatible layout value for array geometry verification */
int imsm_layout = -1;
+ int raid_disks = geo->raid_disks;
imsm_status_t rv;
getinfo_super_imsm_volume(st, &info, NULL);
- if (geo->level != info.array.level && geo->level >= 0 &&
+ if (geo->level != info.array.level && geo->level >= IMSM_T_RAID0 &&
geo->level != UnSet) {
switch (info.array.level) {
- case 0:
- if (geo->level == 5) {
+ case IMSM_T_RAID0:
+ if (geo->level == IMSM_T_RAID5) {
change = CH_MIGRATION;
if (geo->layout != ALGORITHM_LEFT_ASYMMETRIC) {
pr_err("Error. Requested Layout not supported (left-asymmetric layout is supported only)!\n");
@@ -11953,20 +11922,28 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
}
imsm_layout = geo->layout;
check_devs = 1;
- devNumChange = 1; /* parity disk added */
- } else if (geo->level == 10) {
+ raid_disks += 1; /* parity disk added */
+ } else if (geo->level == IMSM_T_RAID10) {
+ if (geo->level == IMSM_T_RAID10 && geo->raid_disks > 2 &&
+ !c->force) {
+ pr_err("Warning! VROC UEFI driver does not support RAID10 in requested layout.\n");
+ pr_err("Array won't be suitable as boot device.\n");
+ pr_err("Note: You can omit this check with \"--force\"\n");
+ if (ask("Do you want to continue") < 1)
+ return CH_ABORT;
+ }
change = CH_TAKEOVER;
check_devs = 1;
- devNumChange = 2; /* two mirrors added */
+ raid_disks *= 2; /* mirrors added */
imsm_layout = 0x102; /* imsm supported layout */
}
break;
- case 1:
- case 10:
+ case IMSM_T_RAID1:
+ case IMSM_T_RAID10:
if (geo->level == 0) {
change = CH_TAKEOVER;
check_devs = 1;
- devNumChange = -(geo->raid_disks/2);
+ raid_disks /= 2;
imsm_layout = 0; /* imsm raid0 layout */
}
break;
@@ -11982,10 +11959,10 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
if (geo->layout != info.array.layout &&
(geo->layout != UnSet && geo->layout != -1)) {
change = CH_MIGRATION;
- if (info.array.layout == 0 && info.array.level == 5 &&
+ if (info.array.layout == 0 && info.array.level == IMSM_T_RAID5 &&
geo->layout == 5) {
/* reshape 5 -> 4 */
- } else if (info.array.layout == 5 && info.array.level == 5 &&
+ } else if (info.array.layout == 5 && info.array.level == IMSM_T_RAID5 &&
geo->layout == 0) {
/* reshape 4 -> 5 */
geo->layout = 0;
@@ -12004,7 +11981,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
if (geo->chunksize > 0 && geo->chunksize != UnSet &&
geo->chunksize != info.array.chunk_size) {
- if (info.array.level == 10) {
+ if (info.array.level == IMSM_T_RAID10) {
pr_err("Error. Chunk size change for RAID 10 is not supported.\n");
change = -1;
goto analyse_change_exit;
@@ -12029,14 +12006,16 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
rv = imsm_analyze_expand(st, geo, &info, direction);
if (rv != IMSM_STATUS_OK)
goto analyse_change_exit;
+ raid_disks = geo->raid_disks;
change = CH_ARRAY_SIZE;
}
chunk = geo->chunksize / 1024;
+
if (!validate_geometry_imsm(st,
geo->level,
imsm_layout,
- geo->raid_disks + devNumChange,
+ raid_disks,
&chunk,
geo->size, INVALID_SECTORS,
0, 0, info.consistency_policy, 1))
@@ -12152,28 +12131,37 @@ exit:
return ret_val;
}
-static int imsm_reshape_super(struct supertype *st, unsigned long long size,
- int level,
- int layout, int chunksize, int raid_disks,
- int delta_disks, char *backup, char *dev,
- int direction, int verbose)
+/**
+ * shape_to_geo() - fill geo_params from shape.
+ *
+ * @shape: array details.
+ * @geo: new geometry params.
+ * Returns: 0 on success, 1 otherwise.
+ */
+static void shape_to_geo(struct shape *shape, struct geo_params *geo)
+{
+ assert(shape);
+ assert(geo);
+
+ geo->dev_name = shape->dev;
+ geo->size = shape->size;
+ geo->level = shape->level;
+ geo->layout = shape->layout;
+ geo->chunksize = shape->chunk;
+ geo->raid_disks = shape->raiddisks;
+}
+
+static int imsm_reshape_super(struct supertype *st, struct shape *shape, struct context *c)
{
int ret_val = 1;
- struct geo_params geo;
+ struct geo_params geo = {0};
dprintf("(enter)\n");
- memset(&geo, 0, sizeof(struct geo_params));
-
- geo.dev_name = dev;
+ shape_to_geo(shape, &geo);
strcpy(geo.devnm, st->devnm);
- geo.size = size;
- geo.level = level;
- geo.layout = layout;
- geo.chunksize = chunksize;
- geo.raid_disks = raid_disks;
- if (delta_disks != UnSet)
- geo.raid_disks += delta_disks;
+ if (shape->delta_disks != UnSet)
+ geo.raid_disks += shape->delta_disks;
dprintf("for level : %i\n", geo.level);
dprintf("for raid_disks : %i\n", geo.raid_disks);
@@ -12184,7 +12172,7 @@ static int imsm_reshape_super(struct supertype *st, unsigned long long size,
int old_raid_disks = 0;
if (imsm_reshape_is_allowed_on_container(
- st, &geo, &old_raid_disks, direction)) {
+ st, &geo, &old_raid_disks, shape->direction)) {
struct imsm_update_reshape *u = NULL;
int len;
@@ -12238,7 +12226,7 @@ static int imsm_reshape_super(struct supertype *st, unsigned long long size,
goto exit_imsm_reshape_super;
}
super->current_vol = dev->index;
- change = imsm_analyze_change(st, &geo, direction);
+ change = imsm_analyze_change(st, &geo, shape->direction, c);
switch (change) {
case CH_TAKEOVER:
ret_val = imsm_takeover(st, &geo);
@@ -12281,6 +12269,7 @@ static int imsm_reshape_super(struct supertype *st, unsigned long long size,
free(u);
}
break;
+ case CH_ABORT:
default:
ret_val = 1;
}
diff --git a/test b/test
index 338c2db..3a05bc9 100755
--- a/test
+++ b/test
@@ -6,8 +6,21 @@ targetdir="/var/tmp"
logdir="$targetdir"
config=/tmp/mdadm.conf
testdir=$PWD/tests
-system_speed_limit=`cat /proc/sys/dev/raid/speed_limit_max`
+system_speed_limit_max=0
+system_speed_limit_min=0
+test_speed_limit_min=100
+test_speed_limit_max=500
devlist=
+# If super1 metadata name doesn't have the same hostname with machine,
+# it's treated as foreign.
+# For example, /dev/md0 is created, stops it, then assemble it, the
+# device node will be /dev/md127 (127 is choosed by mdadm autumatically)
+is_foreign="no"
+#disable selinux
+sys_selinux="Permissive"
+
+skipping_linear="no"
+skipping_multipath="no"
savelogs=0
exitonerror=1
@@ -25,6 +38,11 @@ LVM_VOLGROUP=mdtest
md0=/dev/md0
md1=/dev/md1
md2=/dev/md2
+# if user doesn't specify minor number, mdadm chooses minor number
+# automatically from 127.
+md127=/dev/md127
+md126=/dev/md126
+md125=/dev/md125
mdp0=/dev/md_d0
mdp1=/dev/md_d1
@@ -39,10 +57,6 @@ ctrl_c() {
ctrl_c_error=1
}
-restore_system_speed_limit() {
- echo $system_speed_limit > /proc/sys/dev/raid/speed_limit_max
-}
-
mdadm() {
rm -f $targetdir/stderr
case $* in
@@ -103,16 +117,17 @@ do_test() {
do_clean
# source script in a subshell, so it has access to our
# namespace, but cannot change it.
+ control_system_speed_limit
echo -ne "$_script... "
if ( set -ex ; . $_script ) &> $targetdir/log
then
if [ -f "${_script}.inject_error" ]; then
echo "dmesg checking is skipped because test inject error"
else
- dmesg | grep -iq "error\|call trace\|segfault" &&
+ dmesg | grep -iq "error\|call trace\|segfault" | grep -v "systemd" &&
die "dmesg prints errors when testing $_basename!"
fi
- echo "succeeded"
+ succeed "succeeded\n"
_fail=0
else
save_log fail
@@ -300,10 +315,8 @@ parse_args() {
}
print_warning() {
- cat <<-EOF
- Warning! Tests are performed on system level mdadm!
- If you want to test local build, you need to install it first!
- EOF
+ warn "Warning! Tests are performed on system level mdadm!\n"
+ echo "If you want to test local build, you need to install it first!"
}
main() {
@@ -338,6 +351,7 @@ main() {
fi
done
+ restore_selinux
exit 0
}
diff --git a/tests/01r5fail b/tests/01r5fail
index 873dba5..c210d6e 100644
--- a/tests/01r5fail
+++ b/tests/01r5fail
@@ -17,11 +17,7 @@ check wait
mdadm $md0 --fail $dev0
mdadm $md0 --remove $dev3 $dev0
check recovery
-check state _UUU
-
-mdadm $md0 -a $dev3
-check recovery
check wait
check state UUUU
-mdadm -S $md0 \ No newline at end of file
+mdadm -S $md0
diff --git a/tests/01r5integ.broken b/tests/01r5integ.broken
deleted file mode 100644
index 2073763..0000000
--- a/tests/01r5integ.broken
+++ /dev/null
@@ -1,7 +0,0 @@
-fails rarely
-
-Fails about 1 in every 30 runs with a sha mismatch error:
-
- c49ab26e1b01def7874af9b8a6d6d0c29fdfafe6 /dev/md0 does not match
- 15dc2f73262f811ada53c65e505ceec9cf025cb9 /dev/md0 with /dev/loop3
- missing
diff --git a/tests/01raid6integ.broken b/tests/01raid6integ.broken
deleted file mode 100644
index 1df735f..0000000
--- a/tests/01raid6integ.broken
+++ /dev/null
@@ -1,7 +0,0 @@
-fails infrequently
-
-Fails about 1 in 5 with a sha mismatch:
-
- 8286c2bc045ae2cfe9f8b7ae3a898fa25db6926f /dev/md0 does not match
- a083a0738b58caab37fd568b91b177035ded37df /dev/md0 with /dev/loop2 and
- /dev/loop3 missing
diff --git a/tests/03assem-incr b/tests/03assem-incr
index 38880a7..56afbf2 100644
--- a/tests/03assem-incr
+++ b/tests/03assem-incr
@@ -9,15 +9,23 @@ set -x -e
levels=(raid0 raid1 raid5)
if [ "$LINEAR" == "yes" ]; then
- levels+=( linear )
+ levels+=( linear )
fi
+is_raid_foreign $md0
+
for l in ${levels[@]}
do
- mdadm -CR $md0 -l $l -n5 $dev0 $dev1 $dev2 $dev3 $dev4 --assume-clean
- mdadm -S md0
- mdadm -I $dev1
- mdadm -I $dev3
- mdadm -A /dev/md0 $dev0 $dev1 $dev2 $dev3 $dev4
- mdadm -S /dev/md0
+ mdadm -CR $md0 -l $l -n5 $dev0 $dev1 $dev2 $dev3 $dev4 --assume-clean
+ mdadm -S $md0
+ mdadm -I $dev1
+ mdadm -I $dev3
+ mdadm -A $md0 $dev0 $dev1 $dev2 $dev3 $dev4
+ # If one array is foreign (metadata name doesn't have the machine's
+ # hostname), mdadm chooses a minor number automatically from 127
+ if [ $is_foreign == "no" ]; then
+ mdadm -S $md0
+ else
+ mdadm -S $md127
+ fi
done
diff --git a/tests/03r0assem b/tests/03r0assem
index f7c29e8..4bf8b9e 100644
--- a/tests/03r0assem
+++ b/tests/03r0assem
@@ -35,16 +35,6 @@ mdadm -S $md2
{
echo DEVICE $devlist
- echo array $md2 name=2
-} > $conf
-
-mdadm -As -c $conf $md2
-$tst
-mdadm -S $md2
-
-
-{
- echo DEVICE $devlist
echo array $md2 devices=$dev0,$dev1,$dev2
} > $conf
diff --git a/tests/03r5assem-failed b/tests/03r5assem-failed
deleted file mode 100644
index d38241d..0000000
--- a/tests/03r5assem-failed
+++ /dev/null
@@ -1,12 +0,0 @@
-
-# Create an array, fail one device while array is active, stop array,
-# then re-assemble listing the failed device first.
-
-mdadm -CR $md1 -l5 -n4 $dev0 $dev1 $dev2 $dev3
-check wait
-
-echo 2000 > /sys/block/md1/md/safe_mode_delay
-mkfs $md1
-mdadm $md1 -f $dev0
-mdadm -S $md1
-mdadm -A $md1 $dev0 $dev1 $dev2 $dev3 || exit 1
diff --git a/tests/03r5assemV1 b/tests/03r5assemV1
index bca0c58..6026011 100644
--- a/tests/03r5assemV1
+++ b/tests/03r5assemV1
@@ -33,14 +33,6 @@ eval $tst
{
echo DEVICE $devlist
- echo array $md1 name=one
-} > $conf
-
-mdadm -As -c $conf
-eval $tst
-
-{
- echo DEVICE $devlist
echo array $md1 devices=$dev0,$dev1,$dev2,$dev3,$dev4
} > $conf
@@ -90,15 +82,6 @@ eval $tst
{
echo DEVICE $devlist
- echo array $md1 name=one
-} > $conf
-
-mdadm -As -c $conf
-check state U_U
-eval $tst
-
-{
- echo DEVICE $devlist
echo array $md1 devices=$dev0,$dev1,$dev2
} > $conf
diff --git a/tests/04r5swap.broken b/tests/04r5swap.broken
deleted file mode 100644
index e38987d..0000000
--- a/tests/04r5swap.broken
+++ /dev/null
@@ -1,7 +0,0 @@
-always fails
-
-Fails with errors:
-
- mdadm: /dev/loop0 has no superblock - assembly aborted
-
- ERROR: no recovery happening
diff --git a/tests/04update-metadata b/tests/04update-metadata
index 2b72a30..c748770 100644
--- a/tests/04update-metadata
+++ b/tests/04update-metadata
@@ -8,24 +8,29 @@ set -xe
dlist="$dev0 $dev1 $dev2 $dev3"
-for ls in linear/4 raid1/1 raid5/3 raid6/2
+if [ $skipping_linear == "yes" ]; then
+ level_list="raid1/1 raid5/3 raid6/2"
+else
+ level_list="linear/4 raid1/1 raid5/3 raid6/2"
+fi
+for ls in $level_list
do
- s=${ls#*/} l=${ls%/*}
- if [[ $l == 'raid1' ]]; then
- mdadm -CR --assume-clean -e 0.90 $md0 --level $l -n 4 $dlist
- else
- mdadm -CR --assume-clean -e 0.90 $md0 --level $l -n 4 -c 64 $dlist
- fi
- testdev $md0 $s 19904 64
- mdadm -S $md0
- mdadm -A $md0 --update=metadata $dlist
- testdev $md0 $s 19904 64 check
- mdadm -S $md0
+ s=${ls#*/} l=${ls%/*}
+ if [[ $l == 'raid1' ]]; then
+ mdadm -CR --assume-clean -e 0.90 $md0 --level $l -n 4 $dlist
+ else
+ mdadm -CR --assume-clean -e 0.90 $md0 --level $l -n 4 -c 64 $dlist
+ fi
+ testdev $md0 $s 19904 64
+ mdadm -S $md0
+ mdadm -A $md0 --update=metadata $dlist
+ testdev $md0 $s 19904 64 check
+ mdadm -S $md0
done
if mdadm -A $md0 --update=metadata $dlist
then echo >&2 should fail with v1.0 metadata
- exit 1
+ exit 1
fi
mdadm -CR -e 0.90 $md0 --level=6 -n4 -c32 $dlist
@@ -33,7 +38,7 @@ mdadm -S $md0
if mdadm -A $md0 --update=metadata $dlist
then echo >&2 should fail during resync
- exit 1
+ exit 1
fi
mdadm -A $md0 $dlist
mdadm --wait $md0 || true
@@ -48,5 +53,5 @@ mdadm -S $md0
if mdadm -A $md0 --update=metadata $dlist
then echo >&2 should fail when bitmap present
- exit 1
+ exit 1
fi
diff --git a/tests/04update-uuid b/tests/04update-uuid
index a4409e7..25314ab 100644
--- a/tests/04update-uuid
+++ b/tests/04update-uuid
@@ -25,7 +25,7 @@ mdadm -S /dev/md0
# now if we have a bitmap, that needs updating too.
rm -f $targetdir/bitmap
-mdadm -CR --assume-clean -b $targetdir/bitmap $md0 -l5 -n3 $dev0 $dev1 $dev2
+yes | mdadm -CR --assume-clean -b $targetdir/bitmap $md0 -l5 -n3 $dev0 $dev1 $dev2
mdadm -S /dev/md0
mdadm -A /dev/md0 -b $targetdir/bitmap --update=uuid --uuid=0123456789abcdef:fedcba9876543210 $dev0 $dev1 $dev2
no_errors
@@ -41,7 +41,7 @@ mdadm -S /dev/md0
# and bitmap for version1
rm -f $targetdir/bitmap
-mdadm -CR --assume-clean -e1.1 -b $targetdir/bitmap $md0 -l5 -n3 $dev0 $dev1 $dev2
+yes | mdadm -CR --assume-clean -e1.1 -b $targetdir/bitmap $md0 -l5 -n3 $dev0 $dev1 $dev2
mdadm -S /dev/md0
mdadm -A /dev/md0 -b $targetdir/bitmap --update=uuid --uuid=0123456789abcdef:fedcba9876543210 $dev0 $dev1 $dev2
no_errors
diff --git a/tests/05r1-bitmapfile b/tests/05r1-bitmapfile
deleted file mode 100644
index f384f0e..0000000
--- a/tests/05r1-bitmapfile
+++ /dev/null
@@ -1,49 +0,0 @@
-
-#
-# create a raid1 with a bitmap file
-#
-bmf=$targetdir/bitmap
-rm -f $bmf
-mdadm --create --run $md0 --level=1 -n2 --delay=1 --bitmap $bmf $dev1 $dev2
-check wait
-testdev $md0 1 $mdsize1a 64
-mdadm -S $md0
-
-mdadm --assemble $md0 --bitmap=$bmf $dev1 $dev2
-testdev $md0 1 $mdsize1a 64
-dirty1=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-sleep 4
-dirty2=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-
-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ]
-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2"
- exit 1
-fi
-mdadm $md0 -f $dev1
-testdev $md0 1 $mdsize1a 64
-sleep 4
-dirty3=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty3 -lt 400 ]
-then
- echo >&2 "ERROR dirty count $dirty3 is too small"
- exit 2
-fi
-
-mdadm -S $md0
-
-mdadm --assemble -R $md0 --bitmap=$bmf $dev2
-dirty4=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-mdadm --zero $dev1 # force --add, not --re-add
-mdadm $md0 --add $dev1
-#it is too fast# check recovery
-
-check wait
-sleep 4
-dirty5=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-
-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ]
-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5"
- exit 1
-fi
-
-mdadm -S $md0
diff --git a/tests/05r1-grow-external b/tests/05r1-grow-external
deleted file mode 100644
index 69da3e9..0000000
--- a/tests/05r1-grow-external
+++ /dev/null
@@ -1,33 +0,0 @@
-
-#
-# create a raid1 array, add an external bitmap
-#
-mdadm --create --run $md0 -l 1 -n 2 $dev1 $dev2
-check wait
-testdev $md0 1 $mdsize1a 64
-
-bmf=$targetdir/bm
-rm -f $bmf
-#mdadm -E $dev1
-mdadm --grow $md0 --bitmap=$bmf --delay=1 || { mdadm -X $bmf ; exit 1; }
-dirty1=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-sleep 4
-dirty2=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-
-testdev $md0 1 $mdsize1a 64
-dirty3=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-sleep 4
-dirty4=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-
-#echo $dirty1 $dirty2 $dirty3 $dirty4
-if [ $dirty2 -ne 0 -o $dirty4 -ne 0 -o $dirty3 -lt 400 ]
-then
- echo bad dirty counts
- exit 1
-fi
-
-# now to remove the bitmap
-check bitmap
-mdadm --grow $md0 --bitmap=none
-check nobitmap
-mdadm -S $md0
diff --git a/tests/05r1-grow-internal b/tests/05r1-grow-internal
index 24b3aec..f7fff98 100644
--- a/tests/05r1-grow-internal
+++ b/tests/05r1-grow-internal
@@ -8,18 +8,15 @@ testdev $md0 1 $mdsize1a 64
#mdadm -E $dev1
mdadm --grow $md0 --bitmap=internal --bitmap-chunk=4 --delay=1 || { mdadm -X $dev2 ; exit 1; }
-dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
sleep 4
-dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
testdev $md0 1 $mdsize1a 64
-dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
sleep 4
-dirty4=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-#echo $dirty1 $dirty2 $dirty3 $dirty4
-if [ $dirty2 -ne 0 -o $dirty4 -ne 0 -o $dirty3 -lt 400 ]
-then
+if [ $dirty1 -ne 0 -o $dirty2 -ne 0 ]
+then echo >&2 "ERROR bad 'dirty' counts: dirty1 $dirty1, dirty2 $dirty2"
echo bad dirty counts
exit 1
fi
diff --git a/tests/05r1-grow-internal-1 b/tests/05r1-grow-internal-1
index 2f0d823..f0f8349 100644
--- a/tests/05r1-grow-internal-1
+++ b/tests/05r1-grow-internal-1
@@ -8,19 +8,15 @@ testdev $md0 1 $mdsize1b 64
#mdadm -E $dev1
mdadm --grow $md0 --bitmap=internal --bitmap-chunk=4 --delay=1
-dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
sleep 4
-dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
testdev $md0 1 $mdsize1b 64
-dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
sleep 4
-dirty4=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-#echo $dirty1 $dirty2 $dirty3 $dirty4
-if [ $dirty2 -ne 0 -o $dirty4 -ne 0 -o $dirty3 -lt 400 ]
-then
- echo bad dirty counts
+if [ $dirty1 -ne 0 -o $dirty2 -ne 0 ]
+then echo >&2 "ERROR bad 'dirty' counts: dirty1 $dirty1, dirty2 $dirty2"
exit 1
fi
diff --git a/tests/05r1-internalbitmap b/tests/05r1-internalbitmap
index dd7232a..f1a2843 100644
--- a/tests/05r1-internalbitmap
+++ b/tests/05r1-internalbitmap
@@ -9,21 +9,20 @@ mdadm -S $md0
mdadm --assemble $md0 $dev1 $dev2
testdev $md0 1 $mdsize0 64
-dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
sleep 4
-dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ]
-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2"
+if [ $dirty1 -ne 0 ]
+then echo >&2 "ERROR bad 'dirty' counts: $dirty1"
exit 1
fi
mdadm $md0 -f $dev1
testdev $md0 1 $mdsize0 64
sleep 4
-dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty3 -lt 400 ]
-then
- echo >&2 "ERROR dirty count $dirty3 is too small"
+total=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) bits.*/\1/p'`
+dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+if [ $dirty2 -ne $total ]
+then echo >&2 "ERROR bad 'dirty' counts: total $total, dirty2 $dirty2"
exit 2
fi
@@ -34,13 +33,12 @@ mdadm --zero-superblock $dev1
mdadm $md0 --add $dev1
check recovery
-dirty4=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
check wait
sleep 4
-dirty5=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ]
-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5"
+if [ $dirty3 -ne 0 ]
+then echo >&2 "ERROR bad 'dirty' counts: $dirty3"
exit 1
fi
diff --git a/tests/05r1-internalbitmap-v1a b/tests/05r1-internalbitmap-v1a
index 3ddc082..cf3f397 100644
--- a/tests/05r1-internalbitmap-v1a
+++ b/tests/05r1-internalbitmap-v1a
@@ -10,21 +10,20 @@ mdadm -S $md0
mdadm --assemble $md0 $dev1 $dev2
testdev $md0 1 $mdsize1b 64
-dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
sleep 4
-dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ]
-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2"
+if [ $dirty1 -ne 0 ]
+then echo >&2 "ERROR bad 'dirty' counts: $dirty1"
exit 1
fi
mdadm $md0 -f $dev1
testdev $md0 1 $mdsize1b 64
sleep 4
-dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty3 -lt 400 ]
-then
- echo >&2 "ERROR dirty count $dirty3 is too small"
+total=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) bits.*/\1/p'`
+dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+if [ $dirty2 -ne $total ]
+then echo >&2 "ERROR bad 'dirty' counts: total $total, dirty2 $dirty2"
exit 2
fi
@@ -35,13 +34,12 @@ mdadm --assemble -R $md0 $dev2
mdadm $md0 --add $dev1
check recovery
-dirty4=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
check wait
sleep 4
-dirty5=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ]
-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5"
+if [ $dirty3 -ne 0 ]
+then echo >&2 "ERROR bad 'dirty' counts: $dirty3"
exit 1
fi
diff --git a/tests/05r1-internalbitmap-v1b b/tests/05r1-internalbitmap-v1b
index 40f7abe..4952887 100644
--- a/tests/05r1-internalbitmap-v1b
+++ b/tests/05r1-internalbitmap-v1b
@@ -11,21 +11,20 @@ mdadm -S $md0
mdadm --assemble $md0 $dev1 $dev2
check bitmap
testdev $md0 1 $mdsize11 64
-dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
sleep 4
-dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ]
-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2"
+if [ $dirty1 -ne 0 ]
+then echo >&2 "ERROR bad 'dirty' counts: $dirty1"
exit 1
fi
mdadm $md0 -f $dev1
testdev $md0 1 $mdsize11 64
sleep 4
-dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty3 -lt 400 ]
-then
- echo >&2 "ERROR dirty count $dirty3 is too small"
+total=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) bits.*/\1/p'`
+dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+if [ $dirty2 -ne $total ]
+then echo >&2 "ERROR bad 'dirty' counts: total $total, dirty2 $dirty2"
exit 2
fi
@@ -35,14 +34,12 @@ mdadm --zero-superblock $dev1
mdadm --assemble -R $md0 $dev2
mdadm $md0 --add $dev1
check recovery
-
-dirty4=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
check wait
sleep 4
-dirty5=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ]
-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5"
+if [ $dirty3 -ne 0 ]
+then echo >&2 "ERROR bad 'dirty' counts: $dirty3"
exit 1
fi
diff --git a/tests/05r1-internalbitmap-v1c b/tests/05r1-internalbitmap-v1c
index 2eaea59..e1e4472 100644
--- a/tests/05r1-internalbitmap-v1c
+++ b/tests/05r1-internalbitmap-v1c
@@ -10,21 +10,20 @@ mdadm -S $md0
mdadm --assemble $md0 $dev1 $dev2
testdev $md0 1 $mdsize12 64
-dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
sleep 4
-dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ]
-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2"
+if [ $dirty1 -ne 0 ]
+then echo >&2 "ERROR bad 'dirty' counts: $dirty1"
exit 1
fi
mdadm $md0 -f $dev1
testdev $md0 1 $mdsize12 64
sleep 4
-dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty3 -lt 400 ]
-then
- echo >&2 "ERROR dirty count $dirty3 is too small"
+total=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) bits.*/\1/p'`
+dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+if [ $dirty2 -ne $total ]
+then echo >&2 "ERROR bad 'dirty' counts: total $total, dirty2 $dirty2"
exit 2
fi
@@ -35,13 +34,12 @@ mdadm --assemble -R $md0 $dev2
mdadm $md0 --add $dev1
check recovery
-dirty4=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
check wait
sleep 4
-dirty5=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ]
-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5"
+if [ $dirty3 -ne 0 ]
+then echo >&2 "ERROR bad 'dirty' counts: $dirty3"
exit 1
fi
diff --git a/tests/05r1-n3-bitmapfile b/tests/05r1-n3-bitmapfile
deleted file mode 100644
index f1c3f1e..0000000
--- a/tests/05r1-n3-bitmapfile
+++ /dev/null
@@ -1,53 +0,0 @@
-
-#
-# create a raid1 with 3 devices and a bitmap file
-# make sure resync does right thing.
-#
-#
-bmf=$targetdir/bitmap
-rm -f $bmf
-mdadm --create -e0.90 --run $md0 --level=1 -n3 --delay=1 --bitmap $bmf $dev1 $dev2 $dev3
-check wait
-testdev $md0 1 $mdsize0 64
-mdadm -S $md0
-
-mdadm --assemble $md0 --bitmap=$bmf $dev1 $dev2 $dev3
-testdev $md0 1 $mdsize0 64
-dirty1=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-sleep 4
-dirty2=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-
-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ]
-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2"
- exit 1
-fi
-mdadm $md0 -f $dev2
-testdev $md0 1 $mdsize0 64
-sleep 4
-dirty3=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty3 -lt 400 ]
-then
- echo >&2 "ERROR dirty count $dirty3 is too small"
- exit 2
-fi
-
-mdadm -S $md0
-
-mdadm --assemble -R $md0 --bitmap=$bmf $dev1 $dev3
-check nosync
-mdadm --zero-superblock $dev2
-mdadm $md0 --add $dev2
-check recovery
-
-dirty4=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-check wait
-sleep 4
-dirty5=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-
-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ]
-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5"
- exit 1
-fi
-
-mdadm -S $md0
-exit 0
diff --git a/tests/05r1-re-add-nosuper b/tests/05r1-re-add-nosuper
index 058d602..7d41fd7 100644
--- a/tests/05r1-re-add-nosuper
+++ b/tests/05r1-re-add-nosuper
@@ -6,7 +6,7 @@
#
bmf=$targetdir/bitmap2
rm -f $bmf
-mdadm -B $md0 -l1 -n2 -b$bmf -d1 $dev1 $dev2
+yes | mdadm -B $md0 -l1 -n2 -b$bmf -d1 $dev1 $dev2
check resync
check wait
testdev $md0 1 $size 1
diff --git a/tests/05r5-bitmapfile b/tests/05r5-bitmapfile
deleted file mode 100644
index 6d173d8..0000000
--- a/tests/05r5-bitmapfile
+++ /dev/null
@@ -1,49 +0,0 @@
-
-#
-# create a raid1 with a bitmap file
-#
-bmf=$targetdir/bitmap
-rm -f $bmf
-mdadm --create --run $md0 --level=5 -n3 --delay=1 --bitmap $bmf $dev1 $dev2 $dev3
-check wait
-testdev $md0 2 $mdsize1 512
-mdadm -S $md0
-
-mdadm --assemble $md0 --bitmap=$bmf $dev1 $dev2 $dev3
-testdev $md0 2 $mdsize1 512
-dirty1=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-sleep 4
-dirty2=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-
-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ]
-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2"
- exit 1
-fi
-mdadm $md0 -f $dev1
-testdev $md0 2 $mdsize1 512
-sleep 4
-dirty3=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty3 -lt 400 ]
-then
- echo >&2 "ERROR dirty count $dirty3 is too small"
- exit 2
-fi
-
-mdadm -S $md0
-
-mdadm --assemble -R $md0 --bitmap=$bmf $dev2 $dev3
-mdadm --zero $dev1 # force add, not re-add
-mdadm $md0 --add $dev1
-check recovery
-
-dirty4=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-check wait
-sleep 4
-dirty5=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-
-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ]
-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5"
- exit 1
-fi
-
-mdadm -S $md0
diff --git a/tests/05r5-internalbitmap b/tests/05r5-internalbitmap
index 13dc592..1a64482 100644
--- a/tests/05r5-internalbitmap
+++ b/tests/05r5-internalbitmap
@@ -9,21 +9,20 @@ mdadm -S $md0
mdadm --assemble $md0 $dev1 $dev2 $dev3
testdev $md0 2 $mdsize1 512
-dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
sleep 4
-dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ]
-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2"
+if [ $dirty1 -ne 0 ]
+then echo >&2 "ERROR bad 'dirty' counts: $dirty1"
exit 1
fi
mdadm $md0 -f $dev1
testdev $md0 2 $mdsize1 512
sleep 4
-dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty3 -lt 400 ]
+dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+if [ $dirty2 -lt 400 ]
then
- echo >&2 "ERROR dirty count $dirty3 is too small"
+ echo >&2 "ERROR dirty count $dirty2 is too small"
exit 2
fi
@@ -33,14 +32,12 @@ mdadm --assemble -R $md0 $dev2 $dev3
mdadm --zero $dev1 # force --add, not --re-add
mdadm $md0 --add $dev1
check recovery
-
-dirty4=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
check wait
sleep 4
-dirty5=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ]
-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5"
+if [ $dirty3 -ne 0 ]
+then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty3"
exit 1
fi
diff --git a/tests/05r6-bitmapfile b/tests/05r6-bitmapfile
deleted file mode 100644
index d11896d..0000000
--- a/tests/05r6-bitmapfile
+++ /dev/null
@@ -1,49 +0,0 @@
-
-#
-# create a raid1 with a bitmap file
-#
-bmf=$targetdir/bitmap
-rm -f $bmf
-mdadm --create --run $md0 --level=6 -n4 --delay=1 --bitmap $bmf $dev1 $dev2 $dev3 $dev4
-check wait
-testdev $md0 2 $mdsize1 512
-mdadm -S $md0
-
-mdadm --assemble $md0 --bitmap=$bmf $dev1 $dev2 $dev3 $dev4
-testdev $md0 2 $mdsize1 512
-dirty1=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-sleep 4
-dirty2=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-
-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ]
-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2"
- exit 1
-fi
-mdadm $md0 -f $dev3
-testdev $md0 2 $mdsize1 512
-sleep 4
-dirty3=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty3 -lt 400 ]
-then
- echo >&2 "ERROR dirty count $dirty3 is too small"
- exit 2
-fi
-
-mdadm -S $md0
-
-mdadm --assemble -R $md0 --bitmap=$bmf $dev1 $dev2 $dev4
-mdadm --zero $dev3 # force --add, not --re-add
-mdadm $md0 --add $dev3
-check recovery
-
-dirty4=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-check wait
-sleep 4
-dirty5=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-
-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ]
-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5"
- exit 1
-fi
-
-mdadm -S $md0
diff --git a/tests/06name b/tests/06name
index 86eaab6..9ec3437 100644
--- a/tests/06name
+++ b/tests/06name
@@ -2,9 +2,17 @@ set -x
# create an array with a name
+is_raid_foreign $md0
+
mdadm -CR $md0 -l0 -n2 --metadata=1 --name="Fred" $dev0 $dev1
-mdadm -E $dev0 | grep 'Name : Fred' > /dev/null || exit 1
-mdadm -D $md0 | grep 'Name : Fred' > /dev/null || exit 1
+
+if [ $is_foreign == "no" ]; then
+ mdadm -E $dev0 | grep "Name : $(hostname):Fred" > /dev/null || exit 1
+ mdadm -D $md0 | grep "Name : $(hostname):Fred" > /dev/null || exit 1
+else
+ mdadm -E $dev0 | grep "Name : Fred" > /dev/null || exit 1
+ mdadm -D $md0 | grep "Name : Fred" > /dev/null || exit 1
+fi
mdadm -S $md0
mdadm -A $md0 --name="Fred" $devlist
diff --git a/tests/07autoassemble b/tests/07autoassemble
index e689be7..b6630e1 100644
--- a/tests/07autoassemble
+++ b/tests/07autoassemble
@@ -2,6 +2,9 @@
# create two raid1s, build a raid0 on top, then
# tear it down and get auto-assemble to rebuild it.
+#the length of md0/md1/md2 is same. So use md0 here.
+is_raid_foreign $md0
+
mdadm -CR $md1 -l1 -n2 $dev0 $dev1 --homehost=testing
mdadm -CR $md2 -l1 -n2 $dev2 $dev3 --homehost=testing
mdadm -CR $md0 -l0 -n2 $md1 $md2 --homehost=testing
@@ -10,7 +13,14 @@ mdadm -Ss
mdadm -As -c /dev/null --homehost=testing -vvv
testdev $md1 1 $mdsize1a 64
testdev $md2 1 $mdsize1a 64
-testdev $md0 2 $mdsize11a 512
+# md1 and md2 will be incremental assemble by udev rule. And
+# the testing machines' hostname is not testing. The md0 will
+# be considered as a foreign array. It can use 0 as metadata
+# name. md127 will be used
+testdev $md127 2 $mdsize11a 512
+mdadm --stop $md127
+mdadm --zero-superblock $md1
+mdadm --zero-superblock $md2
mdadm -Ss
mdadm --zero-superblock $dev0 $dev1 $dev2 $dev3
@@ -20,5 +30,31 @@ mdadm -CR $md0 -l0 -n2 $md1 $dev2 --homehost=testing
mdadm -Ss
mdadm -As -c /dev/null --homehost=testing -vvv
testdev $md1 1 $mdsize1a 64
-testdev $md0 1 $[mdsize1a+mdsize11a] 512
+testdev $md127 1 $[mdsize1a+mdsize11a] 512
+mdadm --stop $md127
+mdadm --zero-superblock $md1
+mdadm -Ss
+
+# Don't specify homehost when creating raid and use the test
+# machine's homehost. For super1.2, if homehost name's length
+# is > 32, it doesn't use homehost name in metadata name and
+# the array will be treated as foreign array
+mdadm --zero-superblock $dev0 $dev1 $dev2 $dev3
+mdadm -CR $md1 -l1 -n2 $dev0 $dev1
+mdadm -CR $md2 -l1 -n2 $dev2 $dev3
+mdadm -CR $md0 -l0 -n2 $md1 $md2
+mdadm -Ss
+mdadm -As -c /dev/null
+if [ $is_foreign == "yes" ]; then
+ # md127 is md1
+ testdev $md127 1 $mdsize1a 64
+ # md126 is md0, udev rule incremental assemble it
+ testdev $md126 2 $mdsize11a 512
+ # md125 is md2
+ testdev $md125 1 $mdsize1a 64
+else
+ testdev $md1 1 $mdsize1a 64
+ testdev $md2 1 $mdsize1a 64
+ testdev $md0 2 $mdsize11a 512
+fi
mdadm -Ss
diff --git a/tests/07autoassemble.broken b/tests/07autoassemble.broken
deleted file mode 100644
index 8be0940..0000000
--- a/tests/07autoassemble.broken
+++ /dev/null
@@ -1,8 +0,0 @@
-always fails
-
-Prints lots of messages, but the array doesn't assemble. Error
-possibly related to:
-
- mdadm: /dev/md/1 is busy - skipping
- mdadm: no recogniseable superblock on /dev/md/testing:0
- mdadm: /dev/md/2 is busy - skipping
diff --git a/tests/07autodetect.broken b/tests/07autodetect.broken
deleted file mode 100644
index 294954a..0000000
--- a/tests/07autodetect.broken
+++ /dev/null
@@ -1,5 +0,0 @@
-always fails
-
-Fails with error:
-
- ERROR: no resync happening
diff --git a/tests/07changelevelintr b/tests/07changelevelintr
index 18c6309..d921f2b 100644
--- a/tests/07changelevelintr
+++ b/tests/07changelevelintr
@@ -27,11 +27,9 @@ checkgeo() {
}
restart() {
- sleep 0.5
check reshape
mdadm -S $md0
mdadm -A $md0 $devs --backup-file=$bu
- sleep 0.5
check reshape
}
@@ -49,13 +47,16 @@ mdadm -G $md0 --layout rs --backup-file=$bu
restart
checkgeo md0 raid5 5 $[128*1024] 3
-mdadm -G $md0 --array-size 58368
+# It needs to shrink array size first. Choose a value that
+# is power of 2 for array size. If not, it can't change
+# chunk size.
+mdadm -G $md0 --array-size 51200
mdadm -G $md0 --raid-disks 4 -c 64 --backup-file=$bu
restart
checkgeo md0 raid5 4 $[64*1024] 3
devs="$dev0 $dev1 $dev2 $dev3"
-mdadm -G $md0 --array-size 19456
+mdadm -G $md0 --array-size 18432
mdadm -G $md0 -n 2 -c 256 --backup-file=$bu
restart
checkgeo md0 raid5 2 $[256*1024] 3
diff --git a/tests/07changelevelintr.broken b/tests/07changelevelintr.broken
deleted file mode 100644
index 284b490..0000000
--- a/tests/07changelevelintr.broken
+++ /dev/null
@@ -1,9 +0,0 @@
-always fails
-
-Fails with errors:
-
- mdadm: this change will reduce the size of the array.
- use --grow --array-size first to truncate array.
- e.g. mdadm --grow /dev/md0 --array-size 56832
-
- ERROR: no reshape happening
diff --git a/tests/07revert-grow b/tests/07revert-grow
index c8c4e85..333483d 100644
--- a/tests/07revert-grow
+++ b/tests/07revert-grow
@@ -43,7 +43,7 @@ testdev $md0 2 $mdsize1 512
mdadm -G $md0 -n 5
sleep 3
mdadm -S $md0
-strace -o /tmp/str ./mdadm -A $md0 --update=revert-reshape $devlist4
+mdadm -A $md0 --update=revert-reshape $devlist4
check wait
check raid10
testdev $md0 2 $mdsize1 512
diff --git a/tests/07revert-inplace b/tests/07revert-inplace
index a73eb97..776324a 100644
--- a/tests/07revert-inplace
+++ b/tests/07revert-inplace
@@ -37,7 +37,7 @@ testdev $md0 3 $mdsize1 64
mdadm -G $md0 -c 32
sleep 2
mdadm -S $md0
-strace -o /tmp/str ./mdadm -A $md0 --update=revert-reshape $devlist5
+mdadm -A $md0 --update=revert-reshape $devlist5
check wait
check raid10
testdev $md0 3 $mdsize1 64
diff --git a/tests/23rdev-lifetime b/tests/23rdev-lifetime
index 1750b0d..03b61de 100644
--- a/tests/23rdev-lifetime
+++ b/tests/23rdev-lifetime
@@ -4,7 +4,7 @@ pid=""
runtime=2
clean_up_test() {
- pill -9 $pid
+ kill -9 $pid
echo clear > /sys/block/md0/md/array_state
}
diff --git a/tests/func.sh b/tests/func.sh
index b474442..e7ccc4f 100644
--- a/tests/func.sh
+++ b/tests/func.sh
@@ -23,6 +23,28 @@ mdsize12=19988
# ddf needs bigger devices as 32Meg is reserved!
ddfsize=65536
+# Systemd flags
+devname_as_serial_flag="IMSM_DEVNAME_AS_SERIAL=1"
+no_platform_flag="IMSM_NO_PLATFORM=1"
+
+# Common colors
+COLOR_FAIL='\033[0;31m' #RED
+COLOR_WARN='\033[1;33m' #YELLOW
+COLOR_SUCCESS='\033[0;32m' #GREEN
+COLOR_NONE='\033[0m'
+
+fail() {
+ printf "${COLOR_FAIL}$1${COLOR_NONE}"
+}
+
+warn() {
+ printf "${COLOR_WARN}$1${COLOR_NONE}"
+}
+
+succeed() {
+ printf "${COLOR_SUCCESS}$1${COLOR_NONE}"
+}
+
# $1 is optional parameter, it shows why to save log
save_log() {
status=$1
@@ -36,7 +58,8 @@ save_log() {
cat /proc/mdstat >> $logdir/$logfile
array=($(mdadm -Ds | cut -d' ' -f2))
[ "$1" == "fail" ] &&
- echo "FAILED - see $logdir/$_basename.log and $logdir/$logfile for details"
+ fail "FAILED"
+ echo " - see $logdir/$_basename.log and $logdir/$logfile for details\n"
if [ $DEVTYPE == 'lvm' ]
then
# not supported lvm type yet
@@ -86,6 +109,7 @@ cleanup() {
$mdadm --zero ${disks[@]} &> /dev/null
;;
esac
+ clean_systemd_env
}
do_clean()
@@ -125,6 +149,7 @@ check_env() {
MULTIPATH="yes"
if [ "$MULTIPATH" != "yes" ]; then
echo "test: skipping tests for multipath, which is removed in upstream 6.8+ kernels"
+ skipping_multipath="yes"
fi
# Check whether to run linear tests
@@ -133,14 +158,75 @@ check_env() {
LINEAR="yes"
if [ "$LINEAR" != "yes" ]; then
echo "test: skipping tests for linear, which is removed in upstream 6.8+ kernels"
+ skipping_linear="yes"
+ fi
+}
+
+record_system_speed_limit() {
+ system_speed_limit_max=`cat /proc/sys/dev/raid/speed_limit_max`
+ system_speed_limit_min=`cat /proc/sys/dev/raid/speed_limit_min`
+}
+
+# To avoid sync action finishes before checking it, it needs to limit
+# the sync speed
+control_system_speed_limit() {
+ echo $test_speed_limit_min > /proc/sys/dev/raid/speed_limit_min
+ echo $test_speed_limit_max > /proc/sys/dev/raid/speed_limit_max
+}
+
+restore_system_speed_limit() {
+ echo $system_speed_limit_min > /proc/sys/dev/raid/speed_limit_max
+ echo $system_speed_limit_max > /proc/sys/dev/raid/speed_limit_max
+}
+
+is_raid_foreign() {
+
+ name=$1
+ # super1 uses this formula strlen(homehost)+1+strlen(name) < 32
+ # to decide if an array is foreign or local. It adds homehost if
+ # one array is local
+ hostname=$(hostname)
+ if [ `expr length "$(hostname)$name"` -lt 31 ]; then
+ is_foreign="no"
+ else
+ is_foreign="yes"
fi
}
+record_selinux() {
+ sys_selinux=`getenforce`
+ setenforce Permissive
+}
+
+restore_selinux() {
+ setenforce $sys_selinux
+}
+
+setup_systemd_env() {
+ warn "Warning! Test suite will set up systemd environment!\n"
+ echo "Use \"systemctl show-environment\" to show systemd environment variables"
+ for env_var in $devname_as_serial_flag $no_platform_flag
+ do
+ systemctl set-environment $env_var
+ echo "Added $env_var" to systemd environment, use \
+ \"systemctl unset-environment $env_var\" to remove it.
+ done
+}
+
+clean_systemd_env() {
+ for env_var in $devname_as_serial_flag $no_platform_flag
+ do
+ systemctl unset-environment $env_var
+ echo "Removed $env_var from systemd environment."
+ done
+}
+
do_setup() {
trap cleanup 0 1 3 15
trap ctrl_c 2
check_env
+ setup_systemd_env
[ -d $logdir ] || mkdir -p $logdir
devlist=
@@ -214,6 +300,8 @@ do_setup() {
ulimit -c unlimited
[ -f /proc/mdstat ] || modprobe md_mod
echo 0 > /sys/module/md_mod/parameters/start_ro
+ record_system_speed_limit
+ record_selinux
}
# check various things
@@ -265,15 +353,17 @@ check() {
fi
;;
wait )
- p=`cat /proc/sys/dev/raid/speed_limit_max`
- echo 2000000 > /proc/sys/dev/raid/speed_limit_max
+ min=`cat /proc/sys/dev/raid/speed_limit_min`
+ max=`cat /proc/sys/dev/raid/speed_limit_max`
+ echo 200000 > /proc/sys/dev/raid/speed_limit_max
sleep 0.1
while grep -Eq '(resync|recovery|reshape|check|repair) *=' /proc/mdstat ||
grep -v idle > /dev/null /sys/block/md*/md/sync_action
do
sleep 0.5
done
- echo $p > /proc/sys/dev/raid/speed_limit_max
+ echo $min > /proc/sys/dev/raid/speed_limit_min
+ echo $max > /proc/sys/dev/raid/speed_limit_max
;;
state )
grep -sq "blocks.*\[$2\]\$" /proc/mdstat ||
diff --git a/tests/templates/names_template b/tests/templates/names_template
index 1b6cd14..c94245e 100644
--- a/tests/templates/names_template
+++ b/tests/templates/names_template
@@ -4,6 +4,8 @@ function names_create() {
local NAME=$2
local NEG_TEST=$3
+ is_raid_foreign $DEVNAME
+
if [[ -z "$NAME" ]]; then
mdadm -CR "$DEVNAME" -l0 -n 1 $dev0 --force
else
@@ -30,6 +32,7 @@ function names_verify() {
local DEVNODE_NAME="$1"
local WANTED_LINK="$2"
local WANTED_NAME="$3"
+ local EXPECTED=""
local RES="$(mdadm -D --export $DEVNODE_NAME | grep MD_DEVNAME)"
if [[ "$?" != "0" ]]; then
@@ -38,7 +41,12 @@ function names_verify() {
fi
if [[ "$WANTED_LINK" != "empty" ]]; then
- local EXPECTED="MD_DEVNAME=$WANTED_LINK"
+ EXPECTED="MD_DEVNAME=$WANTED_LINK"
+
+ if [ ! -b /dev/md/$WANTED_LINK ]; then
+ echo "/dev/md/$WANTED_LINK doesn't exit"
+ exit 1
+ fi
fi
if [[ "$RES" != "$EXPECTED" ]]; then
@@ -52,7 +60,11 @@ function names_verify() {
exit 1
fi
- local EXPECTED="MD_NAME=$(hostname):$WANTED_NAME"
+ if [ $is_foreign == "no" ]; then
+ EXPECTED="MD_NAME=$(hostname):$WANTED_NAME"
+ else
+ EXPECTED="MD_NAME=$WANTED_NAME"
+ fi
if [[ "$RES" != "$EXPECTED" ]]; then
echo "$RES doesn't match $EXPECTED."
exit 1
diff --git a/util.c b/util.c
index 9e83704..908f843 100644
--- a/util.c
+++ b/util.c
@@ -633,9 +633,9 @@ int check_ext2(int fd, char *name)
bsize = sb[24]|(sb[25]|(sb[26]|sb[27]<<8)<<8)<<8;
size = sb[4]|(sb[5]|(sb[6]|sb[7]<<8)<<8)<<8;
size <<= bsize;
- pr_err("%s appears to contain an ext2fs file system\n",
+ pr_info("%s appears to contain an ext2fs file system\n",
name);
- cont_err("size=%lluK mtime=%s", size, ctime(&mtime));
+ pr_info("size=%lluK mtime=%s", size, ctime(&mtime));
return 1;
}
@@ -725,23 +725,33 @@ int stat_is_blkdev(char *devname, dev_t *rdev)
return 1;
}
+/**
+ * ask() - prompt user for "yes/no" dialog.
+ * @mesg: message to be printed, without '?' sign.
+ * Returns: 1 if 'Y/y', 0 otherwise.
+ *
+ * The default value is 'N/n', thus the caps on "N" on prompt.
+ */
int ask(char *mesg)
{
- char *add = "";
- int i;
- for (i = 0; i < 5; i++) {
- char buf[100];
- fprintf(stderr, "%s%s", mesg, add);
- fflush(stderr);
- if (fgets(buf, 100, stdin)==NULL)
- return 0;
- if (buf[0]=='y' || buf[0]=='Y')
- return 1;
- if (buf[0]=='n' || buf[0]=='N')
- return 0;
- add = "(y/n) ";
+ char buf[3] = {0};
+
+ fprintf(stderr, "%s [y/N]? ", mesg);
+ fflush(stderr);
+ if (fgets(buf, 3, stdin) == NULL)
+ return 0;
+ if (strlen(buf) == 1) {
+ pr_err("assuming no.\n");
+ return 0;
}
- pr_err("assuming 'no'\n");
+ if (buf[1] != '\n')
+ goto bad_option;
+ if (toupper(buf[0]) == 'Y')
+ return 1;
+ if (toupper(buf[0]) == 'N')
+ return 0;
+bad_option:
+ pr_err("bad option.\n");
return 0;
}
@@ -1868,6 +1878,7 @@ int set_array_info(int mdfd, struct supertype *st, struct mdinfo *info)
if (st->ss->external)
return sysfs_set_array(info);
+
memset(&inf, 0, sizeof(inf));
inf.major_version = info->array.major_version;
inf.minor_version = info->array.minor_version;
@@ -1891,7 +1902,7 @@ unsigned long long min_recovery_start(struct mdinfo *array)
return recovery_start;
}
-int mdmon_pid(char *devnm)
+int mdmon_pid(const char *devnm)
{
char path[100];
char pid[10];
@@ -1911,7 +1922,7 @@ int mdmon_pid(char *devnm)
return atoi(pid);
}
-int mdmon_running(char *devnm)
+int mdmon_running(const char *devnm)
{
int pid = mdmon_pid(devnm);
if (pid <= 0)
@@ -1921,6 +1932,80 @@ int mdmon_running(char *devnm)
return 0;
}
+/*
+ * wait_for_mdmon_control_socket() - Waits for mdmon control socket
+ * to be created within specified time.
+ * @container_devnm: Device for which mdmon control socket should start.
+ *
+ * In foreground mode, when mdadm is trying to connect to control
+ * socket it is possible that the mdmon has not created it yet.
+ * Give some time to mdmon to create socket. Timeout set to 2 sec.
+ *
+ * Return: MDADM_STATUS_SUCCESS if connect succeed, otherwise return
+ * error code.
+ */
+mdadm_status_t wait_for_mdmon_control_socket(const char *container_devnm)
+{
+ enum mdadm_status status = MDADM_STATUS_SUCCESS;
+ int sfd, rv, retry_count = 0;
+ struct sockaddr_un addr;
+ char path[PATH_MAX];
+
+ snprintf(path, PATH_MAX, "%s/%s.sock", MDMON_DIR, container_devnm);
+ sfd = socket(PF_LOCAL, SOCK_STREAM, 0);
+ if (!is_fd_valid(sfd))
+ return MDADM_STATUS_ERROR;
+
+ addr.sun_family = PF_LOCAL;
+ strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
+ addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
+
+ for (retry_count = 0; retry_count < 10; retry_count++) {
+ rv = connect(sfd, (struct sockaddr*)&addr, sizeof(addr));
+ if (rv < 0) {
+ sleep_for(0, MSEC_TO_NSEC(200), true);
+ continue;
+ }
+ break;
+ }
+
+ if (rv < 0) {
+ pr_err("Failed to connect to control socket.\n");
+ status = MDADM_STATUS_ERROR;
+ }
+ close(sfd);
+ return status;
+}
+
+/*
+ * wait_for_mdmon() - Waits for mdmon within specified time.
+ * @devnm: Device for which mdmon should start.
+ *
+ * Function waits for mdmon to start. It may need few seconds
+ * to start, we set timeout to 5, it should be sufficient.
+ * Do not wait if mdmon has been started.
+ *
+ * Return: MDADM_STATUS_SUCCESS if mdmon is running, error code otherwise.
+ */
+mdadm_status_t wait_for_mdmon(const char *devnm)
+{
+ const time_t mdmon_timeout = 5;
+ time_t start_time = time(0);
+
+ if (mdmon_running(devnm))
+ return MDADM_STATUS_SUCCESS;
+
+ pr_info("Waiting for mdmon to start\n");
+ while (time(0) - start_time < mdmon_timeout) {
+ sleep_for(0, MSEC_TO_NSEC(200), true);
+ if (mdmon_running(devnm))
+ return MDADM_STATUS_SUCCESS;
+ };
+
+ pr_err("Timeout waiting for mdmon\n");
+ return MDADM_STATUS_ERROR;
+}
+
int start_mdmon(char *devnm)
{
int i;