1
0
Fork 0

Merging upstream version 4.3+20240723.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-14 06:34:47 +01:00
parent 9d4f96bc70
commit aa881a3626
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
70 changed files with 1465 additions and 1206 deletions

6
.github/dependabot.yml vendored Normal file
View file

@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"

10
.github/tools/.checkpatch.conf vendored Normal file
View 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
View 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
View 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

View file

@ -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
View file

@ -168,13 +168,13 @@ int Build(struct mddev_ident *ident, struct mddev_dev *devlist, struct shape *s,
goto abort;
}
}
if (bitmap_fd >= 0) {
if (ioctl(mdfd, SET_BITMAP_FILE, bitmap_fd) < 0) {
pr_err("Cannot set bitmap file for %s: %s\n", chosen_name,
strerror(errno));
goto abort;
}
if (ioctl(mdfd, SET_BITMAP_FILE, bitmap_fd) < 0) {
pr_err("Cannot set bitmap file for %s: %s\n", chosen_name,
strerror(errno));
close(bitmap_fd);
goto abort;
}
close(bitmap_fd);
}
if (ioctl(mdfd, RUN_ARRAY, &param)) {
pr_err("RUN_ARRAY failed: %s\n", strerror(errno));

View file

@ -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;

View file

@ -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
View file

@ -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
View file

@ -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;
}

View file

@ -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.

View file

@ -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
View file

@ -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;
}

View file

@ -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)

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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[@]}

View file

@ -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))

View file

@ -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
View file

@ -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;
}
}

View file

@ -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;

View file

@ -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
View file

@ -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
View file

@ -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);

View file

@ -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
View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}
/**

View file

@ -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;
}

View file

@ -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
View file

@ -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
}

View file

@ -17,11 +17,7 @@ check wait
mdadm $md0 --fail $dev0
mdadm $md0 --remove $dev3 $dev0
check recovery
check state _UUU
mdadm $md0 -a $dev3
check recovery
check wait
check state UUUU
mdadm -S $md0
mdadm -S $md0

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1,7 +0,0 @@
always fails
Fails with errors:
mdadm: /dev/loop0 has no superblock - assembly aborted
ERROR: no recovery happening

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1,5 +0,0 @@
always fails
Fails with error:
ERROR: no resync happening

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -4,7 +4,7 @@ pid=""
runtime=2
clean_up_test() {
pill -9 $pid
kill -9 $pid
echo clear > /sys/block/md0/md/array_state
}

View file

@ -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 ||

View file

@ -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
View file

@ -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;