Merging upstream version 4.3+20240723.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
9d4f96bc70
commit
aa881a3626
70 changed files with 1465 additions and 1206 deletions
6
.github/dependabot.yml
vendored
Normal file
6
.github/dependabot.yml
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
10
.github/tools/.checkpatch.conf
vendored
Normal file
10
.github/tools/.checkpatch.conf
vendored
Normal file
|
@ -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
|
12
.github/tools/install_ubuntu_packages.sh
vendored
Executable file
12
.github/tools/install_ubuntu_packages.sh
vendored
Executable file
|
@ -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
|
41
.github/workflows/review.yml
vendored
Normal file
41
.github/workflows/review.yml
vendored
Normal file
|
@ -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
|
98
Assemble.c
98
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:
|
||||
|
|
12
Build.c
12
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, ¶m)) {
|
||||
pr_err("RUN_ARRAY failed: %s\n", strerror(errno));
|
||||
|
|
50
Create.c
50
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;
|
||||
|
|
2
Detail.c
2
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));
|
||||
|
|
11
Dump.c
11
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);
|
||||
|
|
169
Grow.c
169
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;
|
||||
}
|
||||
|
|
|
@ -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 repo. 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 both remotes. Use same format as was used previously,
|
||||
prefixed by **mdadm-**, e.g. **mdadm-3.1.2**, **mdadm-4.1**.
|
||||
|
||||
- [Auto-publishing](https://korg.docs.kernel.org/kup.html#auto-publishing-with-git-archive-signer):
|
||||
- Run kernel.org
|
||||
[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 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 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.
|
||||
|
||||
- Add release entry on Github.
|
||||
|
||||
- Update CHANGELOG.md.
|
||||
- Write "ANNOUNCE" mail to linux-raid@kernel.org to notify community.
|
||||
|
|
12
Makefile
12
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=:
|
||||
|
|
151
Manage.c
151
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;
|
||||
}
|
||||
|
|
12
Monitor.c
12
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)
|
||||
|
|
4
Query.c
4
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;
|
||||
}
|
||||
|
|
86
README.md
86
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.
|
||||
|
||||
# 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.
|
||||
|
||||
# How to Contribute
|
||||
|
||||
**mdadm** is hosted on [kernel.org](https://kernel.org/). You can access repository
|
||||
Effective immediately [Github](https://github.com/md-raid-utilities/mdadm) is the primary
|
||||
location for **mdadm**. Use pull request to contribute.
|
||||
|
||||
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).
|
||||
|
||||
It is maintained similarly to kernel, using *mailing list*. Patches must be send through email.
|
||||
Please familiarize with general kernel
|
||||
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.
|
||||
|
||||
**NOTE:** Maintainers may ask you to send RFC to mailing list if the proposed code requires
|
||||
consultation with kernel developers.
|
||||
|
||||
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**.
|
||||
|
||||
## Sending patches step-by-step
|
||||
[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.
|
||||
|
||||
To maximize change of patches being taken, follow this instruction when submitting:
|
||||
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.
|
||||
|
||||
1. Create possibly logically separated commits and generate patches:
|
||||
# Maintainers of mdadm repository on kernel.org
|
||||
|
||||
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.
|
||||
|
||||
2. Check style of every patch with kernel
|
||||
[checkpatch](https://docs.kernel.org/dev-tools/checkpatch.html) script:
|
||||
|
||||
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.
|
||||
|
||||
3. Send patches using ``git send-mail --to=linux-raid@vger.kernel.org <cover-letter> <patch1> <patch2> (...)``
|
||||
|
||||
# Maintainers
|
||||
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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[@]}
|
||||
|
|
79
config.c
79
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);
|
||||
ident_log(prop_name, name, "Already defined", true);
|
||||
return MDADM_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if (is_string_lq(name, MD_NAME_MAX + 1) == false) {
|
||||
ident_log(prop_name, name, "Too long or empty", cmdline);
|
||||
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))
|
||||
|
|
|
@ -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",
|
||||
|
|
4
lib.c
4
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
34
mdadm.8.in
34
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
|
||||
|
|
72
mdadm.c
72
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) {
|
||||
|
|
42
mdadm.h
42
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);
|
||||
|
|
3
mdstat.c
3
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
|
||||
|
|
2
msg.c
2
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
/* 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_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)
|
||||
{
|
||||
return !!(orom->rlc & IMSM_OROM_RLC_RAID5);
|
||||
if (orom->rlc & bit)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
182
super-ddf.c
182
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);
|
||||
}
|
||||
close(cfd);
|
||||
} else /* device may belong to a different container */
|
||||
return 0;
|
||||
free(sra);
|
||||
|
||||
return 1;
|
||||
return validate_geometry_ddf_bvd(st, level, layout, raiddisks,
|
||||
chunk, size, data_offset, dev,
|
||||
freesize, verbose);
|
||||
}
|
||||
free(ddf);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
|
491
super-intel.c
491
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;
|
||||
if ((attributes & (MPB_ATTRIB_SUPPORTED | MPB_ATTRIB_IGNORED)) == attributes)
|
||||
return true;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
36
test
36
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
|
||||
}
|
||||
|
||||
|
|
|
@ -17,10 +17,6 @@ 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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -33,16 +33,6 @@ mdadm -As -c $conf $md2
|
|||
$tst
|
||||
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
|
||||
|
|
|
@ -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
|
|
@ -31,14 +31,6 @@ conf=$targetdir/mdadm.conf
|
|||
mdadm -As -c $conf $md1
|
||||
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
|
||||
|
@ -88,15 +80,6 @@ mdadm -As -c $conf $md1
|
|||
check state U_U
|
||||
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
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
always fails
|
||||
|
||||
Fails with errors:
|
||||
|
||||
mdadm: /dev/loop0 has no superblock - assembly aborted
|
||||
|
||||
ERROR: no recovery happening
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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; }
|
||||
sleep 4
|
||||
dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
|
||||
|
||||
testdev $md0 1 $mdsize1a 64
|
||||
sleep 4
|
||||
dirty2=`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'`
|
||||
|
||||
#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
|
||||
|
|
|
@ -8,19 +8,15 @@ testdev $md0 1 $mdsize1b 64
|
|||
|
||||
#mdadm -E $dev1
|
||||
mdadm --grow $md0 --bitmap=internal --bitmap-chunk=4 --delay=1
|
||||
sleep 4
|
||||
dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
|
||||
|
||||
testdev $md0 1 $mdsize1b 64
|
||||
sleep 4
|
||||
dirty2=`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'`
|
||||
|
||||
#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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
12
tests/06name
12
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -1,5 +0,0 @@
|
|||
always fails
|
||||
|
||||
Fails with error:
|
||||
|
||||
ERROR: no resync happening
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -4,7 +4,7 @@ pid=""
|
|||
runtime=2
|
||||
|
||||
clean_up_test() {
|
||||
pill -9 $pid
|
||||
kill -9 $pid
|
||||
echo clear > /sys/block/md0/md/array_state
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ||
|
||||
|
|
|
@ -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
|
||||
|
|
121
util.c
121
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;
|
||||
|
|
Loading…
Add table
Reference in a new issue