Merging upstream version 4.2+20230223.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
866376462c
commit
30ed170f74
76 changed files with 2282 additions and 1386 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -3,6 +3,7 @@
|
|||
/*-stamp
|
||||
/mdadm
|
||||
/mdadm.8
|
||||
/mdadm.conf.5
|
||||
/mdadm.udeb
|
||||
/mdassemble
|
||||
/mdmon
|
||||
|
|
82
Assemble.c
82
Assemble.c
|
@ -63,7 +63,7 @@ static void set_array_assembly_status(struct context *c,
|
|||
struct assembly_array_info *arr)
|
||||
{
|
||||
int raid_disks = arr->preexist_cnt + arr->new_cnt;
|
||||
char *status_msg = map_num(assemble_statuses, status);
|
||||
char *status_msg = map_num_s(assemble_statuses, status);
|
||||
|
||||
if (c->export && result)
|
||||
*result |= status;
|
||||
|
@ -77,9 +77,7 @@ static void set_array_assembly_status(struct context *c,
|
|||
fprintf(stderr, " (%d new)", arr->new_cnt);
|
||||
if (arr->exp_cnt)
|
||||
fprintf(stderr, " ( + %d for expansion)", arr->exp_cnt);
|
||||
if (status_msg)
|
||||
fprintf(stderr, " %s", status_msg);
|
||||
fprintf(stderr, ".\n");
|
||||
fprintf(stderr, " %s.\n", status_msg);
|
||||
}
|
||||
|
||||
static int name_matches(char *found, char *required, char *homehost, int require_homehost)
|
||||
|
@ -137,17 +135,17 @@ static int ident_matches(struct mddev_ident *ident,
|
|||
struct mdinfo *content,
|
||||
struct supertype *tst,
|
||||
char *homehost, int require_homehost,
|
||||
char *update, char *devname)
|
||||
enum update_opt update, char *devname)
|
||||
{
|
||||
|
||||
if (ident->uuid_set && (!update || strcmp(update, "uuid")!= 0) &&
|
||||
if (ident->uuid_set && update != UOPT_UUID &&
|
||||
same_uuid(content->uuid, ident->uuid, tst->ss->swapuuid)==0 &&
|
||||
memcmp(content->uuid, uuid_zero, sizeof(int[4])) != 0) {
|
||||
if (devname)
|
||||
pr_err("%s has wrong uuid.\n", devname);
|
||||
return 0;
|
||||
}
|
||||
if (ident->name[0] && (!update || strcmp(update, "name")!= 0) &&
|
||||
if (ident->name[0] && update != UOPT_NAME &&
|
||||
name_matches(content->name, ident->name, homehost, require_homehost)==0) {
|
||||
if (devname)
|
||||
pr_err("%s has wrong name.\n", devname);
|
||||
|
@ -650,11 +648,10 @@ static int load_devices(struct devs *devices, char *devmap,
|
|||
int err;
|
||||
fstat(mdfd, &stb2);
|
||||
|
||||
if (strcmp(c->update, "uuid") == 0 && !ident->uuid_set)
|
||||
if (c->update == UOPT_UUID && !ident->uuid_set)
|
||||
random_uuid((__u8 *)ident->uuid);
|
||||
|
||||
if (strcmp(c->update, "ppl") == 0 &&
|
||||
ident->bitmap_fd >= 0) {
|
||||
if (c->update == UOPT_PPL && ident->bitmap_fd >= 0) {
|
||||
pr_err("PPL is not compatible with bitmap\n");
|
||||
close(mdfd);
|
||||
free(devices);
|
||||
|
@ -686,30 +683,30 @@ static int load_devices(struct devs *devices, char *devmap,
|
|||
strcpy(content->name, ident->name);
|
||||
content->array.md_minor = minor(stb2.st_rdev);
|
||||
|
||||
if (strcmp(c->update, "byteorder") == 0)
|
||||
if (c->update == UOPT_BYTEORDER)
|
||||
err = 0;
|
||||
else if (strcmp(c->update, "home-cluster") == 0) {
|
||||
else if (c->update == UOPT_HOME_CLUSTER) {
|
||||
tst->cluster_name = c->homecluster;
|
||||
err = tst->ss->write_bitmap(tst, dfd, NameUpdate);
|
||||
} else if (strcmp(c->update, "nodes") == 0) {
|
||||
} else if (c->update == UOPT_NODES) {
|
||||
tst->nodes = c->nodes;
|
||||
err = tst->ss->write_bitmap(tst, dfd, NodeNumUpdate);
|
||||
} else if (strcmp(c->update, "revert-reshape") == 0 &&
|
||||
c->invalid_backup)
|
||||
} else if (c->update == UOPT_REVERT_RESHAPE && c->invalid_backup)
|
||||
err = tst->ss->update_super(tst, content,
|
||||
"revert-reshape-nobackup",
|
||||
UOPT_SPEC_REVERT_RESHAPE_NOBACKUP,
|
||||
devname, c->verbose,
|
||||
ident->uuid_set,
|
||||
c->homehost);
|
||||
else
|
||||
err = tst->ss->update_super(tst, content, c->update,
|
||||
err = tst->ss->update_super(tst, content,
|
||||
c->update,
|
||||
devname, c->verbose,
|
||||
ident->uuid_set,
|
||||
c->homehost);
|
||||
if (err < 0) {
|
||||
if (err == -1)
|
||||
pr_err("--update=%s not understood for %s metadata\n",
|
||||
c->update, tst->ss->name);
|
||||
map_num(update_options, c->update), tst->ss->name);
|
||||
tst->ss->free_super(tst);
|
||||
free(tst);
|
||||
close(mdfd);
|
||||
|
@ -719,7 +716,7 @@ static int load_devices(struct devs *devices, char *devmap,
|
|||
*stp = st;
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(c->update, "uuid")==0 &&
|
||||
if (c->update == UOPT_UUID &&
|
||||
!ident->uuid_set) {
|
||||
ident->uuid_set = 1;
|
||||
memcpy(ident->uuid, content->uuid, 16);
|
||||
|
@ -728,7 +725,7 @@ static int load_devices(struct devs *devices, char *devmap,
|
|||
pr_err("Could not re-write superblock on %s.\n",
|
||||
devname);
|
||||
|
||||
if (strcmp(c->update, "uuid")==0 &&
|
||||
if (c->update == UOPT_UUID &&
|
||||
ident->bitmap_fd >= 0 && !bitmap_done) {
|
||||
if (bitmap_update_uuid(ident->bitmap_fd,
|
||||
content->uuid,
|
||||
|
@ -908,8 +905,7 @@ static int force_array(struct mdinfo *content,
|
|||
* devices in RAID4 or last devices in RAID4/5/6.
|
||||
*/
|
||||
delta = devices[j].i.delta_disks;
|
||||
if (devices[j].i.array.level >= 4 &&
|
||||
devices[j].i.array.level <= 6 &&
|
||||
if (is_level456(devices[j].i.array.level) &&
|
||||
i/2 >= content->array.raid_disks - delta)
|
||||
/* OK */;
|
||||
else if (devices[j].i.array.level == 4 &&
|
||||
|
@ -963,7 +959,7 @@ static int force_array(struct mdinfo *content,
|
|||
continue;
|
||||
}
|
||||
content->events = devices[most_recent].i.events;
|
||||
tst->ss->update_super(tst, content, "force-one",
|
||||
tst->ss->update_super(tst, content, UOPT_SPEC_FORCE_ONE,
|
||||
devices[chosen_drive].devname, c->verbose,
|
||||
0, NULL);
|
||||
|
||||
|
@ -1123,7 +1119,7 @@ static int start_array(int mdfd,
|
|||
i/2, mddev);
|
||||
}
|
||||
|
||||
if (content->array.level == LEVEL_CONTAINER) {
|
||||
if (is_container(content->array.level)) {
|
||||
sysfs_rules_apply(mddev, content);
|
||||
if (c->verbose >= 0) {
|
||||
pr_err("Container %s has been assembled with %d drive%s",
|
||||
|
@ -1187,8 +1183,7 @@ static int start_array(int mdfd,
|
|||
pr_err("%s: Need a backup file to complete reshape of this array.\n",
|
||||
mddev);
|
||||
pr_err("Please provided one with \"--backup-file=...\"\n");
|
||||
if (c->update &&
|
||||
strcmp(c->update, "revert-reshape") == 0)
|
||||
if (c->update == UOPT_REVERT_RESHAPE)
|
||||
pr_err("(Don't specify --update=revert-reshape again, that part succeeded.)\n");
|
||||
return 1;
|
||||
}
|
||||
|
@ -1228,8 +1223,7 @@ static int start_array(int mdfd,
|
|||
fprintf(stderr, ".\n");
|
||||
}
|
||||
if (content->reshape_active &&
|
||||
content->array.level >= 4 &&
|
||||
content->array.level <= 6) {
|
||||
is_level456(content->array.level)) {
|
||||
/* might need to increase the size
|
||||
* of the stripe cache - default is 256
|
||||
*/
|
||||
|
@ -1487,7 +1481,7 @@ try_again:
|
|||
*/
|
||||
if (map_lock(&map))
|
||||
pr_err("failed to get exclusive lock on mapfile - continue anyway...\n");
|
||||
if (c->update && strcmp(c->update,"uuid") == 0)
|
||||
if (c->update == UOPT_UUID)
|
||||
mp = NULL;
|
||||
else
|
||||
mp = map_by_uuid(&map, content->uuid);
|
||||
|
@ -1553,8 +1547,7 @@ try_again:
|
|||
*/
|
||||
trustworthy = LOCAL;
|
||||
|
||||
if (name[0] == 0 &&
|
||||
content->array.level == LEVEL_CONTAINER) {
|
||||
if (!name[0] && is_container(content->array.level)) {
|
||||
name = content->text_version;
|
||||
trustworthy = METADATA;
|
||||
}
|
||||
|
@ -1635,7 +1628,7 @@ try_again:
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (c->update && strcmp(c->update, "byteorder")==0)
|
||||
if (c->update == UOPT_BYTEORDER)
|
||||
st->minor_version = 90;
|
||||
|
||||
st->ss->getinfo_super(st, content, NULL);
|
||||
|
@ -1793,7 +1786,7 @@ try_again:
|
|||
if (!(devices[j].i.array.state & 1))
|
||||
clean = 0;
|
||||
|
||||
if (st->ss->update_super(st, &devices[j].i, "assemble", NULL,
|
||||
if (st->ss->update_super(st, &devices[j].i, UOPT_SPEC_ASSEMBLE, NULL,
|
||||
c->verbose, 0, NULL)) {
|
||||
if (c->force) {
|
||||
if (c->verbose >= 0)
|
||||
|
@ -1813,11 +1806,10 @@ try_again:
|
|||
}
|
||||
#endif
|
||||
}
|
||||
if (c->force && !clean &&
|
||||
if (c->force && !clean && !is_container(content->array.level) &&
|
||||
!enough(content->array.level, content->array.raid_disks,
|
||||
content->array.layout, clean,
|
||||
avail)) {
|
||||
change += st->ss->update_super(st, content, "force-array",
|
||||
content->array.layout, clean, avail)) {
|
||||
change += st->ss->update_super(st, content, UOPT_SPEC_FORCE_ARRAY,
|
||||
devices[chosen_drive].devname, c->verbose,
|
||||
0, NULL);
|
||||
was_forced = 1;
|
||||
|
@ -1904,7 +1896,7 @@ try_again:
|
|||
/* First, fill in the map, so that udev can find our name
|
||||
* as soon as we become active.
|
||||
*/
|
||||
if (c->update && strcmp(c->update, "metadata")==0) {
|
||||
if (c->update == UOPT_METADATA) {
|
||||
content->array.major_version = 1;
|
||||
content->array.minor_version = 0;
|
||||
strcpy(content->text_version, "1.0");
|
||||
|
@ -1951,7 +1943,7 @@ out:
|
|||
break;
|
||||
close(mdfd);
|
||||
}
|
||||
usleep(usecs);
|
||||
sleep_for(0, USEC_TO_NSEC(usecs), true);
|
||||
usecs <<= 1;
|
||||
}
|
||||
}
|
||||
|
@ -1976,7 +1968,8 @@ int assemble_container_content(struct supertype *st, int mdfd,
|
|||
int start_reshape;
|
||||
char *avail;
|
||||
int err;
|
||||
int is_raid456, is_clean, all_disks;
|
||||
int is_clean, all_disks;
|
||||
bool is_raid456;
|
||||
|
||||
if (sysfs_init(content, mdfd, NULL)) {
|
||||
pr_err("Unable to initialize sysfs\n");
|
||||
|
@ -1984,7 +1977,12 @@ int assemble_container_content(struct supertype *st, int mdfd,
|
|||
}
|
||||
|
||||
sra = sysfs_read(mdfd, NULL, GET_VERSION|GET_DEVS);
|
||||
if (sra == NULL || strcmp(sra->text_version, content->text_version) != 0) {
|
||||
if (sra == NULL) {
|
||||
pr_err("Failed to read sysfs parameters\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(sra->text_version, content->text_version) != 0) {
|
||||
if (content->array.major_version == -1 &&
|
||||
content->array.minor_version == -2 &&
|
||||
c->readonly &&
|
||||
|
@ -2104,7 +2102,7 @@ int assemble_container_content(struct supertype *st, int mdfd,
|
|||
content->array.state |= 1;
|
||||
}
|
||||
|
||||
is_raid456 = (content->array.level >= 4 && content->array.level <= 6);
|
||||
is_raid456 = is_level456(content->array.level);
|
||||
is_clean = content->array.state & 1;
|
||||
|
||||
if (enough(content->array.level, content->array.raid_disks,
|
||||
|
|
23
Build.c
23
Build.c
|
@ -71,28 +71,7 @@ int Build(char *mddev, struct mddev_dev *devlist,
|
|||
}
|
||||
|
||||
if (s->layout == UnSet)
|
||||
switch(s->level) {
|
||||
default: /* no layout */
|
||||
s->layout = 0;
|
||||
break;
|
||||
case 10:
|
||||
s->layout = 0x102; /* near=2, far=1 */
|
||||
if (c->verbose > 0)
|
||||
pr_err("layout defaults to n1\n");
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
s->layout = map_name(r5layout, "default");
|
||||
if (c->verbose > 0)
|
||||
pr_err("layout defaults to %s\n", map_num(r5layout, s->layout));
|
||||
break;
|
||||
case LEVEL_FAULTY:
|
||||
s->layout = map_name(faultylayout, "default");
|
||||
|
||||
if (c->verbose > 0)
|
||||
pr_err("layout defaults to %s\n", map_num(faultylayout, s->layout));
|
||||
break;
|
||||
}
|
||||
s->layout = default_layout(NULL, s->level, c->verbose);
|
||||
|
||||
/* We need to create the device. It can have no name. */
|
||||
map_lock(&map);
|
||||
|
|
89
Create.c
89
Create.c
|
@ -39,39 +39,54 @@ static int round_size_and_verify(unsigned long long *size, int chunk)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int default_layout(struct supertype *st, int level, int verbose)
|
||||
/**
|
||||
* default_layout() - Get default layout for level.
|
||||
* @st: metadata requested, could be NULL.
|
||||
* @level: raid level requested.
|
||||
* @verbose: verbose level.
|
||||
*
|
||||
* Try to ask metadata handler first, otherwise use global defaults.
|
||||
*
|
||||
* Return: Layout or &UnSet, return value meaning depends of level used.
|
||||
*/
|
||||
int default_layout(struct supertype *st, int level, int verbose)
|
||||
{
|
||||
int layout = UnSet;
|
||||
mapping_t *layout_map = NULL;
|
||||
char *layout_name = NULL;
|
||||
|
||||
if (st && st->ss->default_geometry)
|
||||
st->ss->default_geometry(st, &level, &layout, NULL);
|
||||
|
||||
if (layout == UnSet)
|
||||
switch(level) {
|
||||
default: /* no layout */
|
||||
layout = 0;
|
||||
break;
|
||||
case 0:
|
||||
layout = RAID0_ORIG_LAYOUT;
|
||||
break;
|
||||
case 10:
|
||||
layout = 0x102; /* near=2, far=1 */
|
||||
if (verbose > 0)
|
||||
pr_err("layout defaults to n2\n");
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
layout = map_name(r5layout, "default");
|
||||
if (verbose > 0)
|
||||
pr_err("layout defaults to %s\n", map_num(r5layout, layout));
|
||||
break;
|
||||
case LEVEL_FAULTY:
|
||||
layout = map_name(faultylayout, "default");
|
||||
if (layout != UnSet)
|
||||
return layout;
|
||||
|
||||
if (verbose > 0)
|
||||
pr_err("layout defaults to %s\n", map_num(faultylayout, layout));
|
||||
break;
|
||||
}
|
||||
switch (level) {
|
||||
default: /* no layout */
|
||||
layout = 0;
|
||||
break;
|
||||
case 0:
|
||||
layout = RAID0_ORIG_LAYOUT;
|
||||
break;
|
||||
case 10:
|
||||
layout = 0x102; /* near=2, far=1 */
|
||||
layout_name = "n2";
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
layout_map = r5layout;
|
||||
break;
|
||||
case LEVEL_FAULTY:
|
||||
layout_map = faultylayout;
|
||||
break;
|
||||
}
|
||||
|
||||
if (layout_map) {
|
||||
layout = map_name(layout_map, "default");
|
||||
layout_name = map_num_s(layout_map, layout);
|
||||
}
|
||||
if (layout_name && verbose > 0)
|
||||
pr_err("layout defaults to %s\n", layout_name);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
@ -80,7 +95,7 @@ int Create(struct supertype *st, char *mddev,
|
|||
char *name, int *uuid,
|
||||
int subdevs, struct mddev_dev *devlist,
|
||||
struct shape *s,
|
||||
struct context *c, unsigned long long data_offset)
|
||||
struct context *c)
|
||||
{
|
||||
/*
|
||||
* Create a new raid array.
|
||||
|
@ -273,7 +288,7 @@ int Create(struct supertype *st, char *mddev,
|
|||
newsize = s->size * 2;
|
||||
if (st && ! st->ss->validate_geometry(st, s->level, s->layout, s->raiddisks,
|
||||
&s->chunk, s->size*2,
|
||||
data_offset, NULL,
|
||||
s->data_offset, NULL,
|
||||
&newsize, s->consistency_policy,
|
||||
c->verbose >= 0))
|
||||
return 1;
|
||||
|
@ -308,10 +323,10 @@ int Create(struct supertype *st, char *mddev,
|
|||
info.array.working_disks = 0;
|
||||
dnum = 0;
|
||||
for (dv = devlist; dv; dv = dv->next)
|
||||
if (data_offset == VARIABLE_OFFSET)
|
||||
if (s->data_offset == VARIABLE_OFFSET)
|
||||
dv->data_offset = INVALID_SECTORS;
|
||||
else
|
||||
dv->data_offset = data_offset;
|
||||
dv->data_offset = s->data_offset;
|
||||
|
||||
for (dv=devlist; dv && !have_container; dv=dv->next, dnum++) {
|
||||
char *dname = dv->devname;
|
||||
|
@ -327,7 +342,7 @@ int Create(struct supertype *st, char *mddev,
|
|||
missing_disks ++;
|
||||
continue;
|
||||
}
|
||||
if (data_offset == VARIABLE_OFFSET) {
|
||||
if (s->data_offset == VARIABLE_OFFSET) {
|
||||
doff = strchr(dname, ':');
|
||||
if (doff) {
|
||||
*doff++ = 0;
|
||||
|
@ -335,7 +350,7 @@ int Create(struct supertype *st, char *mddev,
|
|||
} else
|
||||
dv->data_offset = INVALID_SECTORS;
|
||||
} else
|
||||
dv->data_offset = data_offset;
|
||||
dv->data_offset = s->data_offset;
|
||||
|
||||
dfd = open(dname, O_RDONLY);
|
||||
if (dfd < 0) {
|
||||
|
@ -472,7 +487,7 @@ int Create(struct supertype *st, char *mddev,
|
|||
st->minor_version >= 1)
|
||||
/* metadata at front */
|
||||
warn |= check_partitions(fd, dname, 0, 0);
|
||||
else if (s->level == 1 || s->level == LEVEL_CONTAINER ||
|
||||
else if (s->level == 1 || is_container(s->level) ||
|
||||
(s->level == 0 && s->raiddisks == 1))
|
||||
/* partitions could be meaningful */
|
||||
warn |= check_partitions(fd, dname, freesize*2, s->size*2);
|
||||
|
@ -520,7 +535,7 @@ int Create(struct supertype *st, char *mddev,
|
|||
if (!st->ss->validate_geometry(st, s->level, s->layout,
|
||||
s->raiddisks,
|
||||
&s->chunk, minsize*2,
|
||||
data_offset,
|
||||
s->data_offset,
|
||||
NULL, NULL,
|
||||
s->consistency_policy, 0)) {
|
||||
pr_err("devices too large for RAID level %d\n", s->level);
|
||||
|
@ -739,7 +754,7 @@ int Create(struct supertype *st, char *mddev,
|
|||
}
|
||||
}
|
||||
if (!st->ss->init_super(st, &info.array, s, name, c->homehost, uuid,
|
||||
data_offset))
|
||||
s->data_offset))
|
||||
goto abort_locked;
|
||||
|
||||
total_slots = info.array.nr_disks;
|
||||
|
@ -982,7 +997,7 @@ int Create(struct supertype *st, char *mddev,
|
|||
* again returns container info.
|
||||
*/
|
||||
st->ss->getinfo_super(st, &info_new, NULL);
|
||||
if (st->ss->external && s->level != LEVEL_CONTAINER &&
|
||||
if (st->ss->external && !is_container(s->level) &&
|
||||
!same_uuid(info_new.uuid, info.uuid, 0)) {
|
||||
map_update(&map, fd2devnm(mdfd),
|
||||
info_new.text_version,
|
||||
|
@ -1025,7 +1040,7 @@ int Create(struct supertype *st, char *mddev,
|
|||
map_unlock(&map);
|
||||
free(infos);
|
||||
|
||||
if (s->level == LEVEL_CONTAINER) {
|
||||
if (is_container(s->level)) {
|
||||
/* No need to start. But we should signal udev to
|
||||
* create links */
|
||||
sysfs_uevent(&info, "change");
|
||||
|
|
4
Detail.c
4
Detail.c
|
@ -495,8 +495,8 @@ int Detail(char *dev, struct context *c)
|
|||
if (array.state & (1 << MD_SB_CLEAN)) {
|
||||
if ((array.level == 0) ||
|
||||
(array.level == LEVEL_LINEAR))
|
||||
arrayst = map_num(sysfs_array_states,
|
||||
sra->array_state);
|
||||
arrayst = map_num_s(sysfs_array_states,
|
||||
sra->array_state);
|
||||
else
|
||||
arrayst = "clean";
|
||||
} else {
|
||||
|
|
|
@ -117,7 +117,7 @@ int Examine(struct mddev_dev *devlist,
|
|||
}
|
||||
|
||||
if (c->SparcAdjust)
|
||||
st->ss->update_super(st, NULL, "sparc2.2",
|
||||
st->ss->update_super(st, NULL, UOPT_SPARC22,
|
||||
devlist->devname, 0, 0, NULL);
|
||||
/* Ok, its good enough to try, though the checksum could be wrong */
|
||||
|
||||
|
|
204
Grow.c
204
Grow.c
|
@ -26,7 +26,6 @@
|
|||
#include <sys/mman.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#if ! defined(__BIG_ENDIAN) && ! defined(__LITTLE_ENDIAN)
|
||||
|
@ -197,7 +196,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
|
|||
info.disk.minor = minor(rdev);
|
||||
info.disk.raid_disk = d;
|
||||
info.disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
|
||||
if (st->ss->update_super(st, &info, "linear-grow-new", newdev,
|
||||
if (st->ss->update_super(st, &info, UOPT_SPEC_LINEAR_GROW_NEW, newdev,
|
||||
0, 0, NULL) != 0) {
|
||||
pr_err("Preparing new metadata failed on %s\n", newdev);
|
||||
close(nfd);
|
||||
|
@ -255,7 +254,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
|
|||
info.array.active_disks = nd+1;
|
||||
info.array.working_disks = nd+1;
|
||||
|
||||
if (st->ss->update_super(st, &info, "linear-grow-update", dv,
|
||||
if (st->ss->update_super(st, &info, UOPT_SPEC_LINEAR_GROW_UPDATE, dv,
|
||||
0, 0, NULL) != 0) {
|
||||
pr_err("Updating metadata failed on %s\n", dv);
|
||||
close(fd2);
|
||||
|
@ -430,9 +429,10 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s)
|
|||
dv = map_dev(disk.major, disk.minor, 1);
|
||||
if (!dv)
|
||||
continue;
|
||||
if (((disk.state & (1 << MD_DISK_WRITEMOSTLY)) == 0) &&
|
||||
if ((disk.state & (1 << MD_DISK_WRITEMOSTLY)) &&
|
||||
(strcmp(s->bitmap_file, "clustered") == 0)) {
|
||||
pr_err("%s disks marked write-mostly are not supported with clustered bitmap\n",devname);
|
||||
free(mdi);
|
||||
return 1;
|
||||
}
|
||||
fd2 = dev_open(dv, O_RDWR);
|
||||
|
@ -454,8 +454,10 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s)
|
|||
pr_err("failed to load super-block.\n");
|
||||
}
|
||||
close(fd2);
|
||||
if (rv)
|
||||
if (rv) {
|
||||
free(mdi);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (offset_setable) {
|
||||
st->ss->getinfo_super(st, mdi, NULL);
|
||||
|
@ -548,7 +550,7 @@ int Grow_consistency_policy(char *devname, int fd, struct context *c, struct sha
|
|||
if (s->consistency_policy != CONSISTENCY_POLICY_RESYNC &&
|
||||
s->consistency_policy != CONSISTENCY_POLICY_PPL) {
|
||||
pr_err("Operation not supported for consistency policy %s\n",
|
||||
map_num(consistency_policies, s->consistency_policy));
|
||||
map_num_s(consistency_policies, s->consistency_policy));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -579,14 +581,14 @@ int Grow_consistency_policy(char *devname, int fd, struct context *c, struct sha
|
|||
|
||||
if (sra->consistency_policy == (unsigned)s->consistency_policy) {
|
||||
pr_err("Consistency policy is already %s\n",
|
||||
map_num(consistency_policies, s->consistency_policy));
|
||||
map_num_s(consistency_policies, s->consistency_policy));
|
||||
ret = 1;
|
||||
goto free_info;
|
||||
} else if (sra->consistency_policy != CONSISTENCY_POLICY_RESYNC &&
|
||||
sra->consistency_policy != CONSISTENCY_POLICY_PPL) {
|
||||
pr_err("Current consistency policy is %s, cannot change to %s\n",
|
||||
map_num(consistency_policies, sra->consistency_policy),
|
||||
map_num(consistency_policies, s->consistency_policy));
|
||||
map_num_s(consistency_policies, sra->consistency_policy),
|
||||
map_num_s(consistency_policies, s->consistency_policy));
|
||||
ret = 1;
|
||||
goto free_info;
|
||||
}
|
||||
|
@ -603,12 +605,12 @@ int Grow_consistency_policy(char *devname, int fd, struct context *c, struct sha
|
|||
}
|
||||
|
||||
if (subarray) {
|
||||
char *update;
|
||||
enum update_opt update;
|
||||
|
||||
if (s->consistency_policy == CONSISTENCY_POLICY_PPL)
|
||||
update = "ppl";
|
||||
update = UOPT_PPL;
|
||||
else
|
||||
update = "no-ppl";
|
||||
update = UOPT_NO_PPL;
|
||||
|
||||
sprintf(container_dev, "/dev/%s", st->container_devnm);
|
||||
|
||||
|
@ -666,7 +668,7 @@ int Grow_consistency_policy(char *devname, int fd, struct context *c, struct sha
|
|||
goto free_info;
|
||||
}
|
||||
|
||||
ret = st->ss->update_super(st, sra, "ppl",
|
||||
ret = st->ss->update_super(st, sra, UOPT_PPL,
|
||||
devname,
|
||||
c->verbose, 0, NULL);
|
||||
if (ret) {
|
||||
|
@ -705,8 +707,8 @@ int Grow_consistency_policy(char *devname, int fd, struct context *c, struct sha
|
|||
}
|
||||
|
||||
ret = sysfs_set_str(sra, NULL, "consistency_policy",
|
||||
map_num(consistency_policies,
|
||||
s->consistency_policy));
|
||||
map_num_s(consistency_policies,
|
||||
s->consistency_policy));
|
||||
if (ret)
|
||||
pr_err("Failed to change array consistency policy\n");
|
||||
|
||||
|
@ -955,7 +957,7 @@ int start_reshape(struct mdinfo *sra, int already_running,
|
|||
err = sysfs_set_str(sra, NULL, "sync_action",
|
||||
"reshape");
|
||||
if (err)
|
||||
sleep(1);
|
||||
sleep_for(1, 0, true);
|
||||
} while (err && errno == EBUSY && cnt-- > 0);
|
||||
}
|
||||
return err;
|
||||
|
@ -1001,8 +1003,8 @@ int remove_disks_for_takeover(struct supertype *st,
|
|||
rv = 1;
|
||||
sysfs_free(arrays);
|
||||
if (rv) {
|
||||
pr_err("Error. Cannot perform operation on /dev/%s\n", st->devnm);
|
||||
pr_err("For this operation it MUST be single array in container\n");
|
||||
pr_err("Error. Cannot perform operation on %s- for this operation "
|
||||
"it MUST be single array in container\n", st->devnm);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
@ -1774,9 +1776,67 @@ static int reshape_container(char *container, char *devname,
|
|||
char *backup_file, int verbose,
|
||||
int forked, int restart, int freeze_reshape);
|
||||
|
||||
/**
|
||||
* prepare_external_reshape() - prepares update on external metadata if supported.
|
||||
* @devname: Device name.
|
||||
* @subarray: Subarray.
|
||||
* @st: Supertype.
|
||||
* @container: Container.
|
||||
* @cfd: Container file descriptor.
|
||||
*
|
||||
* Function checks that the requested reshape is supported on external metadata,
|
||||
* and performs an initial check that the container holds the pre-requisite
|
||||
* spare devices (mdmon owns final validation).
|
||||
*
|
||||
* Return: 0 on success, else 1
|
||||
*/
|
||||
static int prepare_external_reshape(char *devname, char *subarray,
|
||||
struct supertype *st, char *container,
|
||||
const int cfd)
|
||||
{
|
||||
struct mdinfo *cc = NULL;
|
||||
struct mdinfo *content = NULL;
|
||||
|
||||
if (st->ss->load_container(st, cfd, NULL)) {
|
||||
pr_err("Cannot read superblock for %s\n", devname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!st->ss->container_content)
|
||||
return 1;
|
||||
|
||||
cc = st->ss->container_content(st, subarray);
|
||||
for (content = cc; content ; content = content->next) {
|
||||
/*
|
||||
* check if reshape is allowed based on metadata
|
||||
* indications stored in content.array.status
|
||||
*/
|
||||
if (is_bit_set(&content->array.state, MD_SB_BLOCK_VOLUME) ||
|
||||
is_bit_set(&content->array.state, MD_SB_BLOCK_CONTAINER_RESHAPE)) {
|
||||
pr_err("Cannot reshape arrays in container with unsupported metadata: %s(%s)\n",
|
||||
devname, container);
|
||||
goto error;
|
||||
}
|
||||
if (content->consistency_policy == CONSISTENCY_POLICY_PPL) {
|
||||
pr_err("Operation not supported when ppl consistency policy is enabled\n");
|
||||
goto error;
|
||||
}
|
||||
if (content->consistency_policy == CONSISTENCY_POLICY_BITMAP) {
|
||||
pr_err("Operation not supported when write-intent bitmap consistency policy is enabled\n");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
sysfs_free(cc);
|
||||
if (mdmon_running(container))
|
||||
st->update_tail = &st->updates;
|
||||
return 0;
|
||||
error:
|
||||
sysfs_free(cc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Grow_reshape(char *devname, int fd,
|
||||
struct mddev_dev *devlist,
|
||||
unsigned long long data_offset,
|
||||
struct context *c, struct shape *s)
|
||||
{
|
||||
/* Make some changes in the shape of an array.
|
||||
|
@ -1801,7 +1861,7 @@ int Grow_reshape(char *devname, int fd,
|
|||
struct supertype *st;
|
||||
char *subarray = NULL;
|
||||
|
||||
int frozen;
|
||||
int frozen = 0;
|
||||
int changed = 0;
|
||||
char *container = NULL;
|
||||
int cfd = -1;
|
||||
|
@ -1810,7 +1870,7 @@ int Grow_reshape(char *devname, int fd,
|
|||
int added_disks;
|
||||
|
||||
struct mdinfo info;
|
||||
struct mdinfo *sra;
|
||||
struct mdinfo *sra = NULL;
|
||||
|
||||
if (md_get_array_info(fd, &array) < 0) {
|
||||
pr_err("%s is not an active md array - aborting\n",
|
||||
|
@ -1822,7 +1882,7 @@ int Grow_reshape(char *devname, int fd,
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (data_offset != INVALID_SECTORS && array.level != 10 &&
|
||||
if (s->data_offset != INVALID_SECTORS && array.level != 10 &&
|
||||
(array.level < 4 || array.level > 6)) {
|
||||
pr_err("--grow --data-offset not yet supported\n");
|
||||
return 1;
|
||||
|
@ -1867,13 +1927,7 @@ int Grow_reshape(char *devname, int fd,
|
|||
}
|
||||
}
|
||||
|
||||
/* in the external case we need to check that the requested reshape is
|
||||
* supported, and perform an initial check that the container holds the
|
||||
* pre-requisite spare devices (mdmon owns final validation)
|
||||
*/
|
||||
if (st->ss->external) {
|
||||
int retval;
|
||||
|
||||
if (subarray) {
|
||||
container = st->container_devnm;
|
||||
cfd = open_dev_excl(st->container_devnm);
|
||||
|
@ -1889,58 +1943,20 @@ int Grow_reshape(char *devname, int fd,
|
|||
return 1;
|
||||
}
|
||||
|
||||
retval = st->ss->load_container(st, cfd, NULL);
|
||||
rv = prepare_external_reshape(devname, subarray, st,
|
||||
container, cfd);
|
||||
if (rv > 0) {
|
||||
free(subarray);
|
||||
close(cfd);
|
||||
goto release;
|
||||
}
|
||||
|
||||
if (retval) {
|
||||
pr_err("Cannot read superblock for %s\n", devname);
|
||||
if (s->raiddisks && subarray) {
|
||||
pr_err("--raid-devices operation can be performed on a container only\n");
|
||||
close(cfd);
|
||||
free(subarray);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* check if operation is supported for metadata handler */
|
||||
if (st->ss->container_content) {
|
||||
struct mdinfo *cc = NULL;
|
||||
struct mdinfo *content = NULL;
|
||||
|
||||
cc = st->ss->container_content(st, subarray);
|
||||
for (content = cc; content ; content = content->next) {
|
||||
int allow_reshape = 1;
|
||||
|
||||
/* check if reshape is allowed based on metadata
|
||||
* indications stored in content.array.status
|
||||
*/
|
||||
if (content->array.state &
|
||||
(1 << MD_SB_BLOCK_VOLUME))
|
||||
allow_reshape = 0;
|
||||
if (content->array.state &
|
||||
(1 << MD_SB_BLOCK_CONTAINER_RESHAPE))
|
||||
allow_reshape = 0;
|
||||
if (!allow_reshape) {
|
||||
pr_err("cannot reshape arrays in container with unsupported metadata: %s(%s)\n",
|
||||
devname, container);
|
||||
sysfs_free(cc);
|
||||
free(subarray);
|
||||
return 1;
|
||||
}
|
||||
if (content->consistency_policy ==
|
||||
CONSISTENCY_POLICY_PPL) {
|
||||
pr_err("Operation not supported when ppl consistency policy is enabled\n");
|
||||
sysfs_free(cc);
|
||||
free(subarray);
|
||||
return 1;
|
||||
}
|
||||
if (content->consistency_policy ==
|
||||
CONSISTENCY_POLICY_BITMAP) {
|
||||
pr_err("Operation not supported when write-intent bitmap is enabled\n");
|
||||
sysfs_free(cc);
|
||||
free(subarray);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
sysfs_free(cc);
|
||||
}
|
||||
if (mdmon_running(container))
|
||||
st->update_tail = &st->updates;
|
||||
}
|
||||
|
||||
added_disks = 0;
|
||||
|
@ -1998,6 +2014,12 @@ int Grow_reshape(char *devname, int fd,
|
|||
goto release;
|
||||
}
|
||||
|
||||
if (array.level == 0) {
|
||||
pr_err("Component size change is not supported for RAID0\n");
|
||||
rv = 1;
|
||||
goto release;
|
||||
}
|
||||
|
||||
if (reshape_super(st, s->size, UnSet, UnSet, 0, 0, UnSet, NULL,
|
||||
devname, APPLY_METADATA_CHANGES,
|
||||
c->verbose > 0)) {
|
||||
|
@ -2156,7 +2178,7 @@ size_change_error:
|
|||
devname, s->size);
|
||||
}
|
||||
changed = 1;
|
||||
} else if (array.level != LEVEL_CONTAINER) {
|
||||
} else if (!is_container(array.level)) {
|
||||
s->size = get_component_size(fd)/2;
|
||||
if (s->size == 0)
|
||||
s->size = array.size;
|
||||
|
@ -2166,7 +2188,7 @@ size_change_error:
|
|||
if ((s->level == UnSet || s->level == array.level) &&
|
||||
(s->layout_str == NULL) &&
|
||||
(s->chunk == 0 || s->chunk == array.chunk_size) &&
|
||||
data_offset == INVALID_SECTORS &&
|
||||
s->data_offset == INVALID_SECTORS &&
|
||||
(s->raiddisks == 0 || s->raiddisks == array.raid_disks)) {
|
||||
/* Nothing more to do */
|
||||
if (!changed && c->verbose >= 0)
|
||||
|
@ -2212,7 +2234,7 @@ size_change_error:
|
|||
info.component_size = s->size*2;
|
||||
info.new_level = s->level;
|
||||
info.new_chunk = s->chunk * 1024;
|
||||
if (info.array.level == LEVEL_CONTAINER) {
|
||||
if (is_container(info.array.level)) {
|
||||
info.delta_disks = UnSet;
|
||||
info.array.raid_disks = s->raiddisks;
|
||||
} else if (s->raiddisks)
|
||||
|
@ -2236,7 +2258,7 @@ size_change_error:
|
|||
info.new_layout = UnSet;
|
||||
if (info.array.level == 6 && info.new_level == UnSet) {
|
||||
char l[40], *h;
|
||||
strcpy(l, map_num(r6layout, info.array.layout));
|
||||
strcpy(l, map_num_s(r6layout, info.array.layout));
|
||||
h = strrchr(l, '-');
|
||||
if (h && strcmp(h, "-6") == 0) {
|
||||
*h = 0;
|
||||
|
@ -2261,7 +2283,7 @@ size_change_error:
|
|||
info.new_layout = info.array.layout;
|
||||
else if (info.array.level == 5 && info.new_level == 6) {
|
||||
char l[40];
|
||||
strcpy(l, map_num(r5layout, info.array.layout));
|
||||
strcpy(l, map_num_s(r5layout, info.array.layout));
|
||||
strcat(l, "-6");
|
||||
info.new_layout = map_name(r6layout, l);
|
||||
} else {
|
||||
|
@ -2325,7 +2347,7 @@ size_change_error:
|
|||
printf("layout for %s set to %d\n",
|
||||
devname, array.layout);
|
||||
}
|
||||
} else if (array.level == LEVEL_CONTAINER) {
|
||||
} else if (is_container(array.level)) {
|
||||
/* This change is to be applied to every array in the
|
||||
* container. This is only needed when the metadata imposes
|
||||
* restraints of the various arrays in the container.
|
||||
|
@ -2366,7 +2388,7 @@ size_change_error:
|
|||
}
|
||||
sync_metadata(st);
|
||||
rv = reshape_array(container, fd, devname, st, &info, c->force,
|
||||
devlist, data_offset, c->backup_file,
|
||||
devlist, s->data_offset, c->backup_file,
|
||||
c->verbose, 0, 0, 0);
|
||||
frozen = 0;
|
||||
}
|
||||
|
@ -2931,7 +2953,7 @@ static int impose_level(int fd, int level, char *devname, int verbose)
|
|||
}
|
||||
|
||||
md_get_array_info(fd, &array);
|
||||
if (level == 0 && (array.level >= 4 && array.level <= 6)) {
|
||||
if (level == 0 && is_level456(array.level)) {
|
||||
/* To convert to RAID0 we need to fail and
|
||||
* remove any non-data devices. */
|
||||
int found = 0;
|
||||
|
@ -3221,7 +3243,7 @@ static int reshape_array(char *container, int fd, char *devname,
|
|||
* level and frozen, we can safely add them.
|
||||
*/
|
||||
if (devlist) {
|
||||
if (Manage_subdevs(devname, fd, devlist, verbose, 0, NULL, 0))
|
||||
if (Manage_subdevs(devname, fd, devlist, verbose, 0, UOPT_UNDEFINED, 0))
|
||||
goto release;
|
||||
}
|
||||
|
||||
|
@ -3501,7 +3523,6 @@ started:
|
|||
return 0;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
/* Now we just need to kick off the reshape and watch, while
|
||||
* handling backups of the data...
|
||||
* This is all done by a forked background process.
|
||||
|
@ -3522,6 +3543,9 @@ started:
|
|||
break;
|
||||
}
|
||||
|
||||
/* Close unused file descriptor in the forked process */
|
||||
close_fd(&fd);
|
||||
|
||||
/* If another array on the same devices is busy, the
|
||||
* reshape will wait for them. This would mean that
|
||||
* the first section that we suspend will stay suspended
|
||||
|
@ -3560,7 +3584,8 @@ started:
|
|||
fd = -1;
|
||||
mlockall(MCL_FUTURE);
|
||||
|
||||
signal(SIGTERM, catch_term);
|
||||
if (signal_s(SIGTERM, catch_term) == SIG_ERR)
|
||||
goto release;
|
||||
|
||||
if (st->ss->external) {
|
||||
/* metadata handler takes it from here */
|
||||
|
@ -4925,7 +4950,8 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist,
|
|||
continue;
|
||||
st->ss->getinfo_super(st, &dinfo, NULL);
|
||||
dinfo.reshape_progress = info->reshape_progress;
|
||||
st->ss->update_super(st, &dinfo, "_reshape_progress",
|
||||
st->ss->update_super(st, &dinfo,
|
||||
UOPT_SPEC__RESHAPE_PROGRESS,
|
||||
NULL,0, 0, NULL);
|
||||
st->ss->store_super(st, fdlist[j]);
|
||||
st->ss->free_super(st);
|
||||
|
@ -5042,7 +5068,7 @@ int Grow_continue_command(char *devname, int fd,
|
|||
}
|
||||
st->ss->getinfo_super(st, content, NULL);
|
||||
if (!content->reshape_active)
|
||||
sleep(3);
|
||||
sleep_for(3, 0, true);
|
||||
else
|
||||
break;
|
||||
} while (cnt-- > 0);
|
||||
|
|
|
@ -244,7 +244,7 @@ int Incremental(struct mddev_dev *devlist, struct context *c,
|
|||
c->autof = ci->autof;
|
||||
|
||||
name_to_use = info.name;
|
||||
if (name_to_use[0] == 0 && info.array.level == LEVEL_CONTAINER) {
|
||||
if (name_to_use[0] == 0 && is_container(info.array.level)) {
|
||||
name_to_use = info.text_version;
|
||||
trustworthy = METADATA;
|
||||
}
|
||||
|
@ -472,7 +472,7 @@ int Incremental(struct mddev_dev *devlist, struct context *c,
|
|||
|
||||
/* 7/ Is there enough devices to possibly start the array? */
|
||||
/* 7a/ if not, finish with success. */
|
||||
if (info.array.level == LEVEL_CONTAINER) {
|
||||
if (is_container(info.array.level)) {
|
||||
char devnm[32];
|
||||
/* Try to assemble within the container */
|
||||
sysfs_uevent(sra, "change");
|
||||
|
@ -1025,7 +1025,7 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
|
|||
close(dfd);
|
||||
*dfdp = -1;
|
||||
rv = Manage_subdevs(chosen->sys_name, mdfd, &devlist,
|
||||
-1, 0, NULL, 0);
|
||||
-1, 0, UOPT_UNDEFINED, 0);
|
||||
close(mdfd);
|
||||
}
|
||||
if (verbose > 0) {
|
||||
|
@ -1499,7 +1499,7 @@ static int Incremental_container(struct supertype *st, char *devname,
|
|||
return 0;
|
||||
}
|
||||
for (ra = list ; ra ; ra = ra->next) {
|
||||
int mdfd;
|
||||
int mdfd = -1;
|
||||
char chosen_name[1024];
|
||||
struct map_ent *mp;
|
||||
struct mddev_ident *match = NULL;
|
||||
|
@ -1514,6 +1514,12 @@ static int Incremental_container(struct supertype *st, char *devname,
|
|||
|
||||
if (mp) {
|
||||
mdfd = open_dev(mp->devnm);
|
||||
if (!is_fd_valid(mdfd)) {
|
||||
pr_err("failed to open %s: %s.\n",
|
||||
mp->devnm, strerror(errno));
|
||||
rv = 2;
|
||||
goto release;
|
||||
}
|
||||
if (mp->path)
|
||||
strcpy(chosen_name, mp->path);
|
||||
else
|
||||
|
@ -1573,21 +1579,25 @@ static int Incremental_container(struct supertype *st, char *devname,
|
|||
c->autof,
|
||||
trustworthy,
|
||||
chosen_name, 0);
|
||||
}
|
||||
if (only && (!mp || strcmp(mp->devnm, only) != 0))
|
||||
continue;
|
||||
|
||||
if (mdfd < 0) {
|
||||
pr_err("failed to open %s: %s.\n",
|
||||
chosen_name, strerror(errno));
|
||||
return 2;
|
||||
if (!is_fd_valid(mdfd)) {
|
||||
pr_err("create_mddev failed with chosen name %s: %s.\n",
|
||||
chosen_name, strerror(errno));
|
||||
rv = 2;
|
||||
goto release;
|
||||
}
|
||||
}
|
||||
|
||||
if (only && (!mp || strcmp(mp->devnm, only) != 0)) {
|
||||
close_fd(&mdfd);
|
||||
continue;
|
||||
}
|
||||
|
||||
assemble_container_content(st, mdfd, ra, c,
|
||||
chosen_name, &result);
|
||||
map_free(map);
|
||||
map = NULL;
|
||||
close(mdfd);
|
||||
close_fd(&mdfd);
|
||||
}
|
||||
if (c->export && result) {
|
||||
char sep = '=';
|
||||
|
@ -1610,7 +1620,11 @@ static int Incremental_container(struct supertype *st, char *devname,
|
|||
}
|
||||
printf("\n");
|
||||
}
|
||||
return 0;
|
||||
|
||||
release:
|
||||
map_free(map);
|
||||
sysfs_free(list);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void run_udisks(char *arg1, char *arg2)
|
||||
|
@ -1652,7 +1666,7 @@ static void remove_from_member_array(struct mdstat_ent *memb,
|
|||
|
||||
if (subfd >= 0) {
|
||||
rv = Manage_subdevs(memb->devnm, subfd, devlist, verbose,
|
||||
0, NULL, 0);
|
||||
0, UOPT_UNDEFINED, 0);
|
||||
if (rv & 2) {
|
||||
if (sysfs_init(&mmdi, -1, memb->devnm))
|
||||
pr_err("unable to initialize sysfs for: %s\n",
|
||||
|
@ -1730,7 +1744,7 @@ int IncrementalRemove(char *devname, char *id_path, int verbose)
|
|||
|
||||
memset(&devlist, 0, sizeof(devlist));
|
||||
devlist.devname = devname;
|
||||
devlist.disposition = 'f';
|
||||
devlist.disposition = 'I';
|
||||
/* for a container, we must fail each member array */
|
||||
if (ent->metadata_version &&
|
||||
strncmp(ent->metadata_version, "external:", 9) == 0) {
|
||||
|
@ -1744,7 +1758,7 @@ int IncrementalRemove(char *devname, char *id_path, int verbose)
|
|||
free_mdstat(mdstat);
|
||||
} else {
|
||||
rv |= Manage_subdevs(ent->devnm, mdfd, &devlist,
|
||||
verbose, 0, NULL, 0);
|
||||
verbose, 0, UOPT_UNDEFINED, 0);
|
||||
if (rv & 2) {
|
||||
/* Failed due to EBUSY, try to stop the array.
|
||||
* Give udisks a chance to unmount it first.
|
||||
|
@ -1756,7 +1770,7 @@ int IncrementalRemove(char *devname, char *id_path, int verbose)
|
|||
|
||||
devlist.disposition = 'r';
|
||||
rv = Manage_subdevs(ent->devnm, mdfd, &devlist,
|
||||
verbose, 0, NULL, 0);
|
||||
verbose, 0, UOPT_UNDEFINED, 0);
|
||||
end:
|
||||
close(mdfd);
|
||||
free_mdstat(ent);
|
||||
|
|
13
Makefile
13
Makefile
|
@ -160,7 +160,7 @@ SRCS = $(patsubst %.o,%.c,$(OBJS))
|
|||
|
||||
INCL = mdadm.h part.h bitmap.h
|
||||
|
||||
MON_OBJS = mdmon.o monitor.o managemon.o uuid.o util.o maps.o mdstat.o sysfs.o \
|
||||
MON_OBJS = mdmon.o monitor.o managemon.o uuid.o util.o maps.o mdstat.o sysfs.o config.o mapfile.o mdopen.o\
|
||||
policy.o lib.o \
|
||||
Kill.o sg_io.o dlink.o ReadMe.o super-intel.o \
|
||||
super-mbr.o super-gpt.o \
|
||||
|
@ -182,9 +182,9 @@ check_rundir:
|
|||
echo "***** or set CHECK_RUN_DIR=0"; exit 1; \
|
||||
fi
|
||||
|
||||
everything: all mdadm.static swap_super test_stripe raid6check \
|
||||
everything: all swap_super test_stripe raid6check \
|
||||
mdadm.Os mdadm.O2 man
|
||||
everything-test: all mdadm.static swap_super test_stripe \
|
||||
everything-test: all swap_super test_stripe \
|
||||
mdadm.Os mdadm.O2 man
|
||||
# mdadm.uclibc doesn't work on x86-64
|
||||
# mdadm.tcc doesn't work..
|
||||
|
@ -227,7 +227,12 @@ raid6check : raid6check.o mdadm.h $(CHECK_OBJS)
|
|||
|
||||
mdadm.8 : mdadm.8.in
|
||||
sed -e 's/{DEFAULT_METADATA}/$(DEFAULT_METADATA)/g' \
|
||||
-e 's,{MAP_PATH},$(MAP_PATH),g' mdadm.8.in > mdadm.8
|
||||
-e 's,{MAP_PATH},$(MAP_PATH),g' -e 's,{CONFFILE},$(CONFFILE),g' \
|
||||
-e 's,{CONFFILE2},$(CONFFILE2),g' mdadm.8.in > mdadm.8
|
||||
|
||||
mdadm.conf.5 : mdadm.conf.5.in
|
||||
sed -e 's,{CONFFILE},$(CONFFILE),g' \
|
||||
-e 's,{CONFFILE2},$(CONFFILE2),g' mdadm.conf.5.in > mdadm.conf.5
|
||||
|
||||
mdadm.man : mdadm.8
|
||||
man -l mdadm.8 > mdadm.man
|
||||
|
|
193
Manage.c
193
Manage.c
|
@ -244,7 +244,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry)
|
|||
"array_state",
|
||||
"inactive")) < 0 &&
|
||||
errno == EBUSY) {
|
||||
usleep(200000);
|
||||
sleep_for(0, MSEC_TO_NSEC(200), true);
|
||||
count--;
|
||||
}
|
||||
if (err) {
|
||||
|
@ -307,7 +307,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry)
|
|||
* - unfreeze reshape
|
||||
* - wait on 'sync_completed' for that point to be reached.
|
||||
*/
|
||||
if (mdi && (mdi->array.level >= 4 && mdi->array.level <= 6) &&
|
||||
if (mdi && is_level456(mdi->array.level) &&
|
||||
sysfs_attribute_available(mdi, NULL, "sync_action") &&
|
||||
sysfs_attribute_available(mdi, NULL, "reshape_direction") &&
|
||||
sysfs_get_str(mdi, NULL, "sync_action", buf, 20) > 0 &&
|
||||
|
@ -328,7 +328,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry)
|
|||
sysfs_get_ll(mdi, NULL, "sync_max", &old_sync_max) == 0) {
|
||||
/* must be in the critical section - wait a bit */
|
||||
delay -= 1;
|
||||
usleep(100000);
|
||||
sleep_for(0, MSEC_TO_NSEC(100), true);
|
||||
}
|
||||
|
||||
if (sysfs_set_str(mdi, NULL, "sync_action", "frozen") != 0)
|
||||
|
@ -405,7 +405,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry)
|
|||
* quite started yet. Wait a bit and
|
||||
* check 'sync_action' to see.
|
||||
*/
|
||||
usleep(10000);
|
||||
sleep_for(0, MSEC_TO_NSEC(10), true);
|
||||
sysfs_get_str(mdi, NULL, "sync_action", buf, sizeof(buf));
|
||||
if (strncmp(buf, "reshape", 7) != 0)
|
||||
break;
|
||||
|
@ -447,7 +447,7 @@ done:
|
|||
count = 25; err = 0;
|
||||
while (count && fd >= 0 &&
|
||||
(err = ioctl(fd, STOP_ARRAY, NULL)) < 0 && errno == EBUSY) {
|
||||
usleep(200000);
|
||||
sleep_for(0, MSEC_TO_NSEC(200), true);
|
||||
count --;
|
||||
}
|
||||
if (fd >= 0 && err) {
|
||||
|
@ -598,9 +598,8 @@ static void add_set(struct mddev_dev *dv, int fd, char set_char)
|
|||
|
||||
int attempt_re_add(int fd, int tfd, struct mddev_dev *dv,
|
||||
struct supertype *dev_st, struct supertype *tst,
|
||||
unsigned long rdev,
|
||||
char *update, char *devname, int verbose,
|
||||
mdu_array_info_t *array)
|
||||
unsigned long rdev, enum update_opt update,
|
||||
char *devname, int verbose, mdu_array_info_t *array)
|
||||
{
|
||||
struct mdinfo mdi;
|
||||
int duuid[4];
|
||||
|
@ -666,19 +665,19 @@ int attempt_re_add(int fd, int tfd, struct mddev_dev *dv,
|
|||
|
||||
if (dv->writemostly == FlagSet)
|
||||
rv = dev_st->ss->update_super(
|
||||
dev_st, NULL, "writemostly",
|
||||
dev_st, NULL, UOPT_SPEC_WRITEMOSTLY,
|
||||
devname, verbose, 0, NULL);
|
||||
if (dv->writemostly == FlagClear)
|
||||
rv = dev_st->ss->update_super(
|
||||
dev_st, NULL, "readwrite",
|
||||
dev_st, NULL, UOPT_SPEC_READWRITE,
|
||||
devname, verbose, 0, NULL);
|
||||
if (dv->failfast == FlagSet)
|
||||
rv = dev_st->ss->update_super(
|
||||
dev_st, NULL, "failfast",
|
||||
dev_st, NULL, UOPT_SPEC_FAILFAST,
|
||||
devname, verbose, 0, NULL);
|
||||
if (dv->failfast == FlagClear)
|
||||
rv = dev_st->ss->update_super(
|
||||
dev_st, NULL, "nofailfast",
|
||||
dev_st, NULL, UOPT_SPEC_NOFAILFAST,
|
||||
devname, verbose, 0, NULL);
|
||||
if (update)
|
||||
rv = dev_st->ss->update_super(
|
||||
|
@ -714,8 +713,8 @@ skip_re_add:
|
|||
int Manage_add(int fd, int tfd, struct mddev_dev *dv,
|
||||
struct supertype *tst, mdu_array_info_t *array,
|
||||
int force, int verbose, char *devname,
|
||||
char *update, unsigned long rdev, unsigned long long array_size,
|
||||
int raid_slot)
|
||||
enum update_opt update, unsigned long rdev,
|
||||
unsigned long long array_size, int raid_slot)
|
||||
{
|
||||
unsigned long long ldsize;
|
||||
struct supertype *dev_st;
|
||||
|
@ -1105,7 +1104,7 @@ int Manage_remove(struct supertype *tst, int fd, struct mddev_dev *dv,
|
|||
ret = sysfs_unique_holder(devnm, rdev);
|
||||
if (ret < 2)
|
||||
break;
|
||||
usleep(100 * 1000); /* 100ms */
|
||||
sleep_for(0, MSEC_TO_NSEC(100), true);
|
||||
} while (--count > 0);
|
||||
|
||||
if (ret == 0) {
|
||||
|
@ -1285,38 +1284,97 @@ int Manage_with(struct supertype *tst, int fd, struct mddev_dev *dv,
|
|||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* is_remove_safe() - Check if remove is safe.
|
||||
* @array: Array info.
|
||||
* @fd: Array file descriptor.
|
||||
* @devname: Name of device to remove.
|
||||
* @verbose: Verbose.
|
||||
*
|
||||
* The function determines if array will be operational
|
||||
* after removing &devname.
|
||||
*
|
||||
* Return: True if array will be operational, false otherwise.
|
||||
*/
|
||||
bool is_remove_safe(mdu_array_info_t *array, const int fd, char *devname, const int verbose)
|
||||
{
|
||||
dev_t devid = devnm2devid(devname + 5);
|
||||
struct mdinfo *mdi = sysfs_read(fd, NULL, GET_DEVS | GET_DISKS | GET_STATE);
|
||||
|
||||
if (!mdi) {
|
||||
if (verbose)
|
||||
pr_err("Failed to read sysfs attributes for %s\n", devname);
|
||||
return false;
|
||||
}
|
||||
|
||||
char *avail = xcalloc(array->raid_disks, sizeof(char));
|
||||
|
||||
for (mdi = mdi->devs; mdi; mdi = mdi->next) {
|
||||
if (mdi->disk.raid_disk < 0)
|
||||
continue;
|
||||
if (!(mdi->disk.state & (1 << MD_DISK_SYNC)))
|
||||
continue;
|
||||
if (makedev(mdi->disk.major, mdi->disk.minor) == devid)
|
||||
continue;
|
||||
avail[mdi->disk.raid_disk] = 1;
|
||||
}
|
||||
sysfs_free(mdi);
|
||||
|
||||
bool is_enough = enough(array->level, array->raid_disks,
|
||||
array->layout, 1, avail);
|
||||
|
||||
free(avail);
|
||||
return is_enough;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage_subdevs() - Execute operation depending on devmode.
|
||||
*
|
||||
* @devname: name of the device.
|
||||
* @fd: file descriptor.
|
||||
* @devlist: list of sub-devices to manage.
|
||||
* @verbose: verbose level.
|
||||
* @test: test flag.
|
||||
* @update: type of update.
|
||||
* @force: force flag.
|
||||
*
|
||||
* This function executes operation defined by devmode
|
||||
* for each dev from devlist.
|
||||
* Devmode can be:
|
||||
* 'a' - add the device
|
||||
* 'S' - add the device as a spare - don't try re-add
|
||||
* 'j' - add the device as a journal device
|
||||
* 'A' - re-add the device
|
||||
* 'r' - remove the device: HOT_REMOVE_DISK
|
||||
* device can be 'faulty' or 'detached' in which case all
|
||||
* matching devices are removed.
|
||||
* 'f' - set the device faulty SET_DISK_FAULTY
|
||||
* device can be 'detached' in which case any device that
|
||||
* is inaccessible will be marked faulty.
|
||||
* 'I' - remove device by using incremental fail
|
||||
* which is executed when device is removed surprisingly.
|
||||
* 'R' - mark this device as wanting replacement.
|
||||
* 'W' - this device is added if necessary and activated as
|
||||
* a replacement for a previous 'R' device.
|
||||
* -----
|
||||
* 'w' - 'W' will be changed to 'w' when it is paired with
|
||||
* a 'R' device. If a 'W' is found while walking the list
|
||||
* it must be unpaired, and is an error.
|
||||
* 'M' - this is created by a 'missing' target. It is a slight
|
||||
* variant on 'A'
|
||||
* 'F' - Another variant of 'A', where the device was faulty
|
||||
* so must be removed from the array first.
|
||||
* 'c' - confirm the device as found (for clustered environments)
|
||||
*
|
||||
* For 'f' and 'r', the device can also be a kernel-internal
|
||||
* name such as 'sdb'.
|
||||
*
|
||||
* Return: 0 on success, otherwise 1 or 2.
|
||||
*/
|
||||
int Manage_subdevs(char *devname, int fd,
|
||||
struct mddev_dev *devlist, int verbose, int test,
|
||||
char *update, int force)
|
||||
enum update_opt update, int force)
|
||||
{
|
||||
/* Do something to each dev.
|
||||
* devmode can be
|
||||
* 'a' - add the device
|
||||
* 'S' - add the device as a spare - don't try re-add
|
||||
* 'j' - add the device as a journal device
|
||||
* 'A' - re-add the device
|
||||
* 'r' - remove the device: HOT_REMOVE_DISK
|
||||
* device can be 'faulty' or 'detached' in which case all
|
||||
* matching devices are removed.
|
||||
* 'f' - set the device faulty SET_DISK_FAULTY
|
||||
* device can be 'detached' in which case any device that
|
||||
* is inaccessible will be marked faulty.
|
||||
* 'R' - mark this device as wanting replacement.
|
||||
* 'W' - this device is added if necessary and activated as
|
||||
* a replacement for a previous 'R' device.
|
||||
* -----
|
||||
* 'w' - 'W' will be changed to 'w' when it is paired with
|
||||
* a 'R' device. If a 'W' is found while walking the list
|
||||
* it must be unpaired, and is an error.
|
||||
* 'M' - this is created by a 'missing' target. It is a slight
|
||||
* variant on 'A'
|
||||
* 'F' - Another variant of 'A', where the device was faulty
|
||||
* so must be removed from the array first.
|
||||
* 'c' - confirm the device as found (for clustered environments)
|
||||
*
|
||||
* For 'f' and 'r', the device can also be a kernel-internal
|
||||
* name such as 'sdb'.
|
||||
*/
|
||||
mdu_array_info_t array;
|
||||
unsigned long long array_size;
|
||||
struct mddev_dev *dv;
|
||||
|
@ -1452,8 +1510,9 @@ int Manage_subdevs(char *devname, int fd,
|
|||
/* Assume this is a kernel-internal name like 'sda1' */
|
||||
int found = 0;
|
||||
char dname[55];
|
||||
if (dv->disposition != 'r' && dv->disposition != 'f') {
|
||||
pr_err("%s only meaningful with -r or -f, not -%c\n",
|
||||
if (dv->disposition != 'r' && dv->disposition != 'f' &&
|
||||
dv->disposition != 'I') {
|
||||
pr_err("%s only meaningful with -r, -f or -I, not -%c\n",
|
||||
dv->devname, dv->disposition);
|
||||
goto abort;
|
||||
}
|
||||
|
@ -1598,7 +1657,14 @@ int Manage_subdevs(char *devname, int fd,
|
|||
break;
|
||||
|
||||
case 'f': /* set faulty */
|
||||
/* FIXME check current member */
|
||||
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);
|
||||
goto abort;
|
||||
}
|
||||
case 'I': /* incremental fail */
|
||||
if ((sysfd >= 0 && write(sysfd, "faulty", 6) != 6) ||
|
||||
(sysfd < 0 && ioctl(fd, SET_DISK_FAULTY,
|
||||
rdev))) {
|
||||
|
@ -1675,10 +1741,13 @@ int autodetect(void)
|
|||
return rv;
|
||||
}
|
||||
|
||||
int Update_subarray(char *dev, char *subarray, char *update, struct mddev_ident *ident, int verbose)
|
||||
int Update_subarray(char *dev, char *subarray, enum update_opt update,
|
||||
struct mddev_ident *ident, int verbose)
|
||||
{
|
||||
struct supertype supertype, *st = &supertype;
|
||||
int fd, rv = 2;
|
||||
struct mdinfo *info = NULL;
|
||||
char *update_verb = map_num(update_options, update);
|
||||
|
||||
memset(st, 0, sizeof(*st));
|
||||
|
||||
|
@ -1693,25 +1762,41 @@ int Update_subarray(char *dev, char *subarray, char *update, struct mddev_ident
|
|||
goto free_super;
|
||||
}
|
||||
|
||||
if (is_subarray_active(subarray, st->devnm)) {
|
||||
if (verbose >= 0)
|
||||
pr_err("Subarray %s in %s is active, cannot update %s\n",
|
||||
subarray, dev, update_verb);
|
||||
goto free_super;
|
||||
}
|
||||
|
||||
if (mdmon_running(st->devnm))
|
||||
st->update_tail = &st->updates;
|
||||
|
||||
info = st->ss->container_content(st, subarray);
|
||||
|
||||
if (update == UOPT_PPL && !is_level456(info->array.level)) {
|
||||
pr_err("RWH policy ppl is supported only for raid4, raid5 and raid6.\n");
|
||||
goto free_super;
|
||||
}
|
||||
|
||||
rv = st->ss->update_subarray(st, subarray, update, ident);
|
||||
|
||||
if (rv) {
|
||||
if (verbose >= 0)
|
||||
pr_err("Failed to update %s of subarray-%s in %s\n",
|
||||
update, subarray, dev);
|
||||
update_verb, subarray, dev);
|
||||
} else if (st->update_tail)
|
||||
flush_metadata_updates(st);
|
||||
else
|
||||
st->ss->sync_metadata(st);
|
||||
|
||||
if (rv == 0 && strcmp(update, "name") == 0 && verbose >= 0)
|
||||
if (rv == 0 && update == UOPT_NAME && verbose >= 0)
|
||||
pr_err("Updated subarray-%s name from %s, UUIDs may have changed\n",
|
||||
subarray, dev);
|
||||
|
||||
free_super:
|
||||
free_super:
|
||||
if (info)
|
||||
free(info);
|
||||
st->ss->free_super(st);
|
||||
close(fd);
|
||||
|
||||
|
@ -1746,10 +1831,10 @@ int move_spare(char *from_devname, char *to_devname, dev_t devid)
|
|||
sprintf(devname, "%d:%d", major(devid), minor(devid));
|
||||
|
||||
devlist.disposition = 'r';
|
||||
if (Manage_subdevs(from_devname, fd2, &devlist, -1, 0, NULL, 0) == 0) {
|
||||
if (Manage_subdevs(from_devname, fd2, &devlist, -1, 0, UOPT_UNDEFINED, 0) == 0) {
|
||||
devlist.disposition = 'a';
|
||||
if (Manage_subdevs(to_devname, fd1, &devlist, -1, 0,
|
||||
NULL, 0) == 0) {
|
||||
UOPT_UNDEFINED, 0) == 0) {
|
||||
/* make sure manager is aware of changes */
|
||||
ping_manager(to_devname);
|
||||
ping_manager(from_devname);
|
||||
|
@ -1759,7 +1844,7 @@ int move_spare(char *from_devname, char *to_devname, dev_t devid)
|
|||
}
|
||||
else
|
||||
Manage_subdevs(from_devname, fd2, &devlist,
|
||||
-1, 0, NULL, 0);
|
||||
-1, 0, UOPT_UNDEFINED, 0);
|
||||
}
|
||||
close(fd1);
|
||||
close(fd2);
|
||||
|
|
292
Monitor.c
292
Monitor.c
|
@ -26,7 +26,6 @@
|
|||
#include "md_p.h"
|
||||
#include "md_u.h"
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
#include <limits.h>
|
||||
#include <syslog.h>
|
||||
#ifndef NO_LIBUDEV
|
||||
|
@ -34,8 +33,8 @@
|
|||
#endif
|
||||
|
||||
struct state {
|
||||
char *devname;
|
||||
char devnm[32]; /* to sync with mdstat info */
|
||||
char devname[MD_NAME_MAX + sizeof("/dev/md/")]; /* length of "/dev/md/" + device name + terminating byte*/
|
||||
char devnm[MD_NAME_MAX]; /* to sync with mdstat info */
|
||||
unsigned int utime;
|
||||
int err;
|
||||
char *spare_group;
|
||||
|
@ -46,9 +45,9 @@ struct state {
|
|||
int devstate[MAX_DISKS];
|
||||
dev_t devid[MAX_DISKS];
|
||||
int percent;
|
||||
char parent_devnm[32]; /* For subarray, devnm of parent.
|
||||
* For others, ""
|
||||
*/
|
||||
char parent_devnm[MD_NAME_MAX]; /* For subarray, devnm of parent.
|
||||
* For others, ""
|
||||
*/
|
||||
struct supertype *metadata;
|
||||
struct state *subarray;/* for a container it is a link to first subarray
|
||||
* for a subarray it is a link to next subarray
|
||||
|
@ -67,7 +66,7 @@ struct alert_info {
|
|||
static int make_daemon(char *pidfile);
|
||||
static int check_one_sharer(int scan);
|
||||
static void write_autorebuild_pid(void);
|
||||
static void alert(char *event, char *dev, char *disc, struct alert_info *info);
|
||||
static void alert(const char *event, const char *dev, const char *disc, struct alert_info *info);
|
||||
static int check_array(struct state *st, struct mdstat_ent *mdstat,
|
||||
int test, struct alert_info *info,
|
||||
int increments, char *prefer);
|
||||
|
@ -75,6 +74,7 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist,
|
|||
int test, struct alert_info *info);
|
||||
static void try_spare_migration(struct state *statelist, struct alert_info *info);
|
||||
static void link_containers_with_subarrays(struct state *list);
|
||||
static void free_statelist(struct state *statelist);
|
||||
#ifndef NO_LIBUDEV
|
||||
static int check_udev_activity(void);
|
||||
#endif
|
||||
|
@ -123,13 +123,12 @@ int Monitor(struct mddev_dev *devlist,
|
|||
* and if we can get_disk_info and find a name
|
||||
* Then we hot-remove and hot-add to the other array
|
||||
*
|
||||
* If devlist is NULL, then we can monitor everything because --scan
|
||||
* If devlist is NULL, then we can monitor everything if --scan
|
||||
* was given. We get an initial list from config file and add anything
|
||||
* that appears in /proc/mdstat
|
||||
*/
|
||||
|
||||
struct state *statelist = NULL;
|
||||
struct state *st2;
|
||||
int finished = 0;
|
||||
struct mdstat_ent *mdstat = NULL;
|
||||
char *mailfrom;
|
||||
|
@ -137,24 +136,32 @@ int Monitor(struct mddev_dev *devlist,
|
|||
struct mddev_ident *mdlist;
|
||||
int delay_for_event = c->delay;
|
||||
|
||||
if (!mailaddr) {
|
||||
mailaddr = conf_get_mailaddr();
|
||||
if (mailaddr && ! c->scan)
|
||||
pr_err("Monitor using email address \"%s\" from config file\n",
|
||||
mailaddr);
|
||||
if (devlist && c->scan) {
|
||||
pr_err("Devices list and --scan option cannot be combined - not monitoring.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!mailaddr)
|
||||
mailaddr = conf_get_mailaddr();
|
||||
|
||||
if (!alert_cmd)
|
||||
alert_cmd = conf_get_program();
|
||||
|
||||
mailfrom = conf_get_mailfrom();
|
||||
|
||||
if (!alert_cmd) {
|
||||
alert_cmd = conf_get_program();
|
||||
if (alert_cmd && !c->scan)
|
||||
pr_err("Monitor using program \"%s\" from config file\n",
|
||||
alert_cmd);
|
||||
}
|
||||
if (c->scan && !mailaddr && !alert_cmd && !dosyslog) {
|
||||
pr_err("No mail address or alert command - not monitoring.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (c->verbose) {
|
||||
pr_err("Monitor is started with delay %ds\n", c->delay);
|
||||
if (mailaddr)
|
||||
pr_err("Monitor using email address %s\n", mailaddr);
|
||||
if (alert_cmd)
|
||||
pr_err("Monitor using program %s\n", alert_cmd);
|
||||
}
|
||||
|
||||
info.alert_cmd = alert_cmd;
|
||||
info.mailaddr = mailaddr;
|
||||
info.mailfrom = mailfrom;
|
||||
|
@ -183,14 +190,12 @@ int Monitor(struct mddev_dev *devlist,
|
|||
continue;
|
||||
if (strcasecmp(mdlist->devname, "<ignore>") == 0)
|
||||
continue;
|
||||
if (!is_mddev(mdlist->devname))
|
||||
continue;
|
||||
|
||||
st = xcalloc(1, sizeof *st);
|
||||
if (mdlist->devname[0] == '/')
|
||||
st->devname = xstrdup(mdlist->devname);
|
||||
else {
|
||||
st->devname = xmalloc(8+strlen(mdlist->devname)+1);
|
||||
strcpy(strcpy(st->devname, "/dev/md/"),
|
||||
mdlist->devname);
|
||||
}
|
||||
snprintf(st->devname, MD_NAME_MAX + sizeof("/dev/md/"),
|
||||
"/dev/md/%s", basename(mdlist->devname));
|
||||
st->next = statelist;
|
||||
st->devnm[0] = 0;
|
||||
st->percent = RESYNC_UNKNOWN;
|
||||
|
@ -204,9 +209,14 @@ int Monitor(struct mddev_dev *devlist,
|
|||
struct mddev_dev *dv;
|
||||
|
||||
for (dv = devlist; dv; dv = dv->next) {
|
||||
struct state *st = xcalloc(1, sizeof *st);
|
||||
struct state *st;
|
||||
|
||||
if (!is_mddev(dv->devname))
|
||||
continue;
|
||||
|
||||
st = xcalloc(1, sizeof *st);
|
||||
mdlist = conf_get_ident(dv->devname);
|
||||
st->devname = xstrdup(dv->devname);
|
||||
snprintf(st->devname, MD_NAME_MAX + sizeof("/dev/md/"), "%s", dv->devname);
|
||||
st->next = statelist;
|
||||
st->devnm[0] = 0;
|
||||
st->percent = RESYNC_UNKNOWN;
|
||||
|
@ -289,17 +299,16 @@ int Monitor(struct mddev_dev *devlist,
|
|||
for (stp = &statelist; (st = *stp) != NULL; ) {
|
||||
if (st->from_auto && st->err > 5) {
|
||||
*stp = st->next;
|
||||
free(st->devname);
|
||||
free(st->spare_group);
|
||||
if (st->spare_group)
|
||||
free(st->spare_group);
|
||||
|
||||
free(st);
|
||||
} else
|
||||
stp = &st->next;
|
||||
}
|
||||
}
|
||||
for (st2 = statelist; st2; st2 = statelist) {
|
||||
statelist = st2->next;
|
||||
free(st2);
|
||||
}
|
||||
|
||||
free_statelist(statelist);
|
||||
|
||||
if (pidfile)
|
||||
unlink(pidfile);
|
||||
|
@ -403,109 +412,115 @@ static void write_autorebuild_pid()
|
|||
}
|
||||
}
|
||||
|
||||
static void alert(char *event, char *dev, char *disc, struct alert_info *info)
|
||||
static void execute_alert_cmd(const char *event, const char *dev, const char *disc, struct alert_info *info)
|
||||
{
|
||||
int pid = fork();
|
||||
|
||||
switch (pid) {
|
||||
default:
|
||||
waitpid(pid, NULL, 0);
|
||||
break;
|
||||
case -1:
|
||||
pr_err("Cannot fork to execute alert command");
|
||||
break;
|
||||
case 0:
|
||||
execl(info->alert_cmd, info->alert_cmd, event, dev, disc, NULL);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
static void send_event_email(const char *event, const char *dev, const char *disc, struct alert_info *info)
|
||||
{
|
||||
FILE *mp, *mdstat;
|
||||
char hname[256];
|
||||
char buf[BUFSIZ];
|
||||
int n;
|
||||
|
||||
mp = popen(Sendmail, "w");
|
||||
if (!mp) {
|
||||
pr_err("Cannot open pipe stream for sendmail.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
gethostname(hname, sizeof(hname));
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
if (info->mailfrom)
|
||||
fprintf(mp, "From: %s\n", info->mailfrom);
|
||||
else
|
||||
fprintf(mp, "From: %s monitoring <root>\n", Name);
|
||||
fprintf(mp, "To: %s\n", info->mailaddr);
|
||||
fprintf(mp, "Subject: %s event on %s:%s\n\n", event, dev, hname);
|
||||
fprintf(mp, "This is an automatically generated mail message. \n");
|
||||
fprintf(mp, "A %s event had been detected on md device %s.\n\n", event, dev);
|
||||
|
||||
if (disc && disc[0] != ' ')
|
||||
fprintf(mp,
|
||||
"It could be related to component device %s.\n\n", disc);
|
||||
if (disc && disc[0] == ' ')
|
||||
fprintf(mp, "Extra information:%s.\n\n", disc);
|
||||
|
||||
mdstat = fopen("/proc/mdstat", "r");
|
||||
if (!mdstat) {
|
||||
pr_err("Cannot open /proc/mdstat\n");
|
||||
pclose(mp);
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(mp, "The /proc/mdstat file currently contains the following:\n\n");
|
||||
while ((n = fread(buf, 1, sizeof(buf), mdstat)) > 0)
|
||||
n = fwrite(buf, 1, n, mp);
|
||||
fclose(mdstat);
|
||||
pclose(mp);
|
||||
}
|
||||
|
||||
static void log_event_to_syslog(const char *event, const char *dev, const char *disc)
|
||||
{
|
||||
int priority;
|
||||
/* Log at a different severity depending on the event.
|
||||
*
|
||||
* These are the critical events: */
|
||||
if (strncmp(event, "Fail", 4) == 0 ||
|
||||
strncmp(event, "Degrade", 7) == 0 ||
|
||||
strncmp(event, "DeviceDisappeared", 17) == 0)
|
||||
priority = LOG_CRIT;
|
||||
/* Good to know about, but are not failures: */
|
||||
else if (strncmp(event, "Rebuild", 7) == 0 ||
|
||||
strncmp(event, "MoveSpare", 9) == 0 ||
|
||||
strncmp(event, "Spares", 6) != 0)
|
||||
priority = LOG_WARNING;
|
||||
/* Everything else: */
|
||||
else
|
||||
priority = LOG_INFO;
|
||||
|
||||
if (disc && disc[0] != ' ')
|
||||
syslog(priority,
|
||||
"%s event detected on md device %s, component device %s", event, dev, disc);
|
||||
else if (disc)
|
||||
syslog(priority, "%s event detected on md device %s: %s", event, dev, disc);
|
||||
else
|
||||
syslog(priority, "%s event detected on md device %s", event, dev);
|
||||
}
|
||||
|
||||
static void alert(const char *event, const char *dev, const char *disc, struct alert_info *info)
|
||||
{
|
||||
if (!info->alert_cmd && !info->mailaddr && !info->dosyslog) {
|
||||
time_t now = time(0);
|
||||
|
||||
printf("%1.15s: %s on %s %s\n", ctime(&now) + 4,
|
||||
event, dev, disc?disc:"unknown device");
|
||||
}
|
||||
if (info->alert_cmd) {
|
||||
int pid = fork();
|
||||
switch(pid) {
|
||||
default:
|
||||
waitpid(pid, NULL, 0);
|
||||
break;
|
||||
case -1:
|
||||
break;
|
||||
case 0:
|
||||
execl(info->alert_cmd, info->alert_cmd,
|
||||
event, dev, disc, NULL);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
if (info->alert_cmd)
|
||||
execute_alert_cmd(event, dev, disc, info);
|
||||
|
||||
if (info->mailaddr && (strncmp(event, "Fail", 4) == 0 ||
|
||||
strncmp(event, "Test", 4) == 0 ||
|
||||
strncmp(event, "Spares", 6) == 0 ||
|
||||
strncmp(event, "Degrade", 7) == 0)) {
|
||||
FILE *mp = popen(Sendmail, "w");
|
||||
if (mp) {
|
||||
FILE *mdstat;
|
||||
char hname[256];
|
||||
gethostname(hname, sizeof(hname));
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
if (info->mailfrom)
|
||||
fprintf(mp, "From: %s\n", info->mailfrom);
|
||||
else
|
||||
fprintf(mp, "From: %s monitoring <root>\n",
|
||||
Name);
|
||||
fprintf(mp, "To: %s\n", info->mailaddr);
|
||||
fprintf(mp, "Subject: %s event on %s:%s\n\n",
|
||||
event, dev, hname);
|
||||
|
||||
fprintf(mp,
|
||||
"This is an automatically generated mail message from %s\n", Name);
|
||||
fprintf(mp, "running on %s\n\n", hname);
|
||||
|
||||
fprintf(mp,
|
||||
"A %s event had been detected on md device %s.\n\n", event, dev);
|
||||
|
||||
if (disc && disc[0] != ' ')
|
||||
fprintf(mp,
|
||||
"It could be related to component device %s.\n\n", disc);
|
||||
if (disc && disc[0] == ' ')
|
||||
fprintf(mp, "Extra information:%s.\n\n", disc);
|
||||
|
||||
fprintf(mp, "Faithfully yours, etc.\n");
|
||||
|
||||
mdstat = fopen("/proc/mdstat", "r");
|
||||
if (mdstat) {
|
||||
char buf[8192];
|
||||
int n;
|
||||
fprintf(mp,
|
||||
"\nP.S. The /proc/mdstat file currently contains the following:\n\n");
|
||||
while ((n = fread(buf, 1, sizeof(buf),
|
||||
mdstat)) > 0)
|
||||
n = fwrite(buf, 1, n, mp);
|
||||
fclose(mdstat);
|
||||
}
|
||||
pclose(mp);
|
||||
}
|
||||
send_event_email(event, dev, disc, info);
|
||||
}
|
||||
|
||||
/* log the event to syslog maybe */
|
||||
if (info->dosyslog) {
|
||||
/* Log at a different severity depending on the event.
|
||||
*
|
||||
* These are the critical events: */
|
||||
if (strncmp(event, "Fail", 4) == 0 ||
|
||||
strncmp(event, "Degrade", 7) == 0 ||
|
||||
strncmp(event, "DeviceDisappeared", 17) == 0)
|
||||
priority = LOG_CRIT;
|
||||
/* Good to know about, but are not failures: */
|
||||
else if (strncmp(event, "Rebuild", 7) == 0 ||
|
||||
strncmp(event, "MoveSpare", 9) == 0 ||
|
||||
strncmp(event, "Spares", 6) != 0)
|
||||
priority = LOG_WARNING;
|
||||
/* Everything else: */
|
||||
else
|
||||
priority = LOG_INFO;
|
||||
|
||||
if (disc && disc[0] != ' ')
|
||||
syslog(priority,
|
||||
"%s event detected on md device %s, component device %s", event, dev, disc);
|
||||
else if (disc)
|
||||
syslog(priority,
|
||||
"%s event detected on md device %s: %s",
|
||||
event, dev, disc);
|
||||
else
|
||||
syslog(priority,
|
||||
"%s event detected on md device %s",
|
||||
event, dev);
|
||||
}
|
||||
if (info->dosyslog)
|
||||
log_event_to_syslog(event, dev, disc);
|
||||
}
|
||||
|
||||
static int check_array(struct state *st, struct mdstat_ent *mdstat,
|
||||
|
@ -540,7 +555,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
|
|||
goto disappeared;
|
||||
|
||||
if (st->devnm[0] == 0)
|
||||
strcpy(st->devnm, fd2devnm(fd));
|
||||
snprintf(st->devnm, MD_NAME_MAX, "%s", fd2devnm(fd));
|
||||
|
||||
for (mse2 = mdstat; mse2; mse2 = mse2->next)
|
||||
if (strcmp(mse2->devnm, st->devnm) == 0) {
|
||||
|
@ -670,7 +685,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
|
|||
strncmp(mse->metadata_version, "external:", 9) == 0 &&
|
||||
is_subarray(mse->metadata_version+9)) {
|
||||
char *sl;
|
||||
strcpy(st->parent_devnm, mse->metadata_version + 10);
|
||||
snprintf(st->parent_devnm, MD_NAME_MAX, "%s", mse->metadata_version + 10);
|
||||
sl = strchr(st->parent_devnm, '/');
|
||||
if (sl)
|
||||
*sl = 0;
|
||||
|
@ -758,14 +773,13 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist,
|
|||
continue;
|
||||
}
|
||||
|
||||
st->devname = xstrdup(name);
|
||||
snprintf(st->devname, MD_NAME_MAX + sizeof("/dev/md/"), "%s", name);
|
||||
if ((fd = open(st->devname, O_RDONLY)) < 0 ||
|
||||
md_get_array_info(fd, &array) < 0) {
|
||||
/* no such array */
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
put_md_name(st->devname);
|
||||
free(st->devname);
|
||||
if (st->metadata) {
|
||||
st->metadata->ss->free_super(st->metadata);
|
||||
free(st->metadata);
|
||||
|
@ -777,7 +791,7 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist,
|
|||
st->next = *statelist;
|
||||
st->err = 1;
|
||||
st->from_auto = 1;
|
||||
strcpy(st->devnm, mse->devnm);
|
||||
snprintf(st->devnm, MD_NAME_MAX, "%s", mse->devnm);
|
||||
st->percent = RESYNC_UNKNOWN;
|
||||
st->expected_spares = -1;
|
||||
if (mse->metadata_version &&
|
||||
|
@ -785,8 +799,8 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist,
|
|||
"external:", 9) == 0 &&
|
||||
is_subarray(mse->metadata_version+9)) {
|
||||
char *sl;
|
||||
strcpy(st->parent_devnm,
|
||||
mse->metadata_version+10);
|
||||
snprintf(st->parent_devnm, MD_NAME_MAX,
|
||||
"%s", mse->metadata_version + 10);
|
||||
sl = strchr(st->parent_devnm, '/');
|
||||
*sl = 0;
|
||||
} else
|
||||
|
@ -1051,6 +1065,24 @@ static void link_containers_with_subarrays(struct state *list)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* free_statelist() - Frees statelist.
|
||||
* @statelist: statelist to free
|
||||
*/
|
||||
static void free_statelist(struct state *statelist)
|
||||
{
|
||||
struct state *tmp = NULL;
|
||||
|
||||
while (statelist) {
|
||||
if (statelist->spare_group)
|
||||
free(statelist->spare_group);
|
||||
|
||||
tmp = statelist;
|
||||
statelist = statelist->next;
|
||||
free(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NO_LIBUDEV
|
||||
/* function: check_udev_activity
|
||||
* Description: Function waits for udev to finish
|
||||
|
|
4
Query.c
4
Query.c
|
@ -93,7 +93,7 @@ int Query(char *dev)
|
|||
else {
|
||||
printf("%s: %s %s %d devices, %d spare%s. Use mdadm --detail for more detail.\n",
|
||||
dev, human_size_brief(larray_size,IEC),
|
||||
map_num(pers, level), raid_disks,
|
||||
map_num_s(pers, level), raid_disks,
|
||||
spare_disks, spare_disks == 1 ? "" : "s");
|
||||
}
|
||||
st = guess_super(fd);
|
||||
|
@ -131,7 +131,7 @@ int Query(char *dev)
|
|||
dev,
|
||||
info.disk.number, info.array.raid_disks,
|
||||
activity,
|
||||
map_num(pers, info.array.level),
|
||||
map_num_s(pers, info.array.level),
|
||||
mddev);
|
||||
if (st->ss == &super0)
|
||||
put_md_name(mddev);
|
||||
|
|
52
ReadMe.c
52
ReadMe.c
|
@ -81,11 +81,12 @@ char Version[] = "mdadm - v" VERSION " - " VERS_DATE EXTRAVERSION "\n";
|
|||
* found, it is started.
|
||||
*/
|
||||
|
||||
char short_options[]="-ABCDEFGIQhVXYWZ:vqbc:i:l:p:m:r:n:x:u:c:d:z:U:N:safRSow1tye:k";
|
||||
char short_options[]="-ABCDEFGIQhVXYWZ:vqbc:i:l:p:m:n:x:u:c:d:z:U:N:sarfRSow1tye:k:";
|
||||
char short_monitor_options[]="-ABCDEFGIQhVXYWZ:vqbc:i:l:p:m:r:n:x:u:c:d:z:U:N:safRSow1tye:k:";
|
||||
char short_bitmap_options[]=
|
||||
"-ABCDEFGIQhVXYWZ:vqb:c:i:l:p:m:r:n:x:u:c:d:z:U:N:sarfRSow1tye:k:";
|
||||
"-ABCDEFGIQhVXYWZ:vqb:c:i:l:p:m:n:x:u:c:d:z:U:N:sarfRSow1tye:k:";
|
||||
char short_bitmap_auto_options[]=
|
||||
"-ABCDEFGIQhVXYWZ:vqb:c:i:l:p:m:r:n:x:u:c:d:z:U:N:sa:rfRSow1tye:k:";
|
||||
"-ABCDEFGIQhVXYWZ:vqb:c:i:l:p:m:n:x:u:c:d:z:U:N:sa:rfRSow1tye:k:";
|
||||
|
||||
struct option long_options[] = {
|
||||
{"manage", 0, 0, ManageOpt},
|
||||
|
@ -146,7 +147,6 @@ struct option long_options[] = {
|
|||
{"nofailfast",0, 0, NoFailFast},
|
||||
{"re-add", 0, 0, ReAdd},
|
||||
{"homehost", 1, 0, HomeHost},
|
||||
{"symlinks", 1, 0, Symlinks},
|
||||
{"data-offset",1, 0, DataOffset},
|
||||
{"nodes",1, 0, Nodes}, /* also for --assemble */
|
||||
{"home-cluster",1, 0, ClusterName},
|
||||
|
@ -477,7 +477,7 @@ char Help_assemble[] =
|
|||
;
|
||||
|
||||
char Help_manage[] =
|
||||
"Usage: mdadm arraydevice options component devices...\n"
|
||||
"Usage: mdadm [mode] arraydevice [options] <component devices...>\n"
|
||||
"\n"
|
||||
"This usage is for managing the component devices within an array.\n"
|
||||
"The --manage option is not needed and is assumed if the first argument\n"
|
||||
|
@ -613,7 +613,6 @@ char Help_incr[] =
|
|||
;
|
||||
|
||||
char Help_config[] =
|
||||
"The /etc/mdadm.conf config file:\n\n"
|
||||
" The config file contains, apart from blank lines and comment lines that\n"
|
||||
" start with a hash(#), array lines, device lines, and various\n"
|
||||
" configuration lines.\n"
|
||||
|
@ -636,10 +635,12 @@ char Help_config[] =
|
|||
" than a device must match all of them to be considered.\n"
|
||||
"\n"
|
||||
" Other configuration lines include:\n"
|
||||
" mailaddr, mailfrom, program used for --monitor mode\n"
|
||||
" create, auto used when creating device names in /dev\n"
|
||||
" homehost, policy, part-policy used to guide policy in various\n"
|
||||
" situations\n"
|
||||
" mailaddr, mailfrom, program, monitordelay used for --monitor mode\n"
|
||||
" create, auto used when creating device names in /dev\n"
|
||||
" homehost, homecluster, policy, part-policy used to guide policy in various\n"
|
||||
" situations\n"
|
||||
"\n"
|
||||
"For more details see mdadm.conf(5).\n"
|
||||
"\n"
|
||||
;
|
||||
|
||||
|
@ -654,3 +655,34 @@ char *mode_help[mode_count] = {
|
|||
[GROW] = Help_grow,
|
||||
[INCREMENTAL] = Help_incr,
|
||||
};
|
||||
|
||||
/**
|
||||
* fprint_update_options() - Print valid update options depending on the mode.
|
||||
* @outf: File (output stream)
|
||||
* @update_mode: Used to distinguish update and update_subarray
|
||||
*/
|
||||
void fprint_update_options(FILE *outf, enum update_opt update_mode)
|
||||
{
|
||||
int counter = UOPT_NAME, breakpoint = UOPT_HELP;
|
||||
mapping_t *map = update_options;
|
||||
|
||||
if (!outf)
|
||||
return;
|
||||
if (update_mode == UOPT_SUBARRAY_ONLY) {
|
||||
breakpoint = UOPT_SUBARRAY_ONLY;
|
||||
fprintf(outf, "Valid --update options for update-subarray are:\n\t");
|
||||
} else
|
||||
fprintf(outf, "Valid --update options are:\n\t");
|
||||
while (map->num) {
|
||||
if (map->num >= breakpoint)
|
||||
break;
|
||||
fprintf(outf, "'%s', ", map->name);
|
||||
if (counter % 5 == 0)
|
||||
fprintf(outf, "\n\t");
|
||||
counter++;
|
||||
map++;
|
||||
}
|
||||
if ((counter - 1) % 5)
|
||||
fprintf(outf, "\n");
|
||||
fprintf(outf, "\r");
|
||||
}
|
||||
|
|
52
config.c
52
config.c
|
@ -119,6 +119,34 @@ int match_keyword(char *word)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* ident_init() - Set defaults.
|
||||
* @ident: ident pointer, not NULL.
|
||||
*/
|
||||
inline void ident_init(struct mddev_ident *ident)
|
||||
{
|
||||
assert(ident);
|
||||
|
||||
ident->assembled = false;
|
||||
ident->autof = 0;
|
||||
ident->bitmap_fd = -1;
|
||||
ident->bitmap_file = NULL;
|
||||
ident->container = NULL;
|
||||
ident->devices = NULL;
|
||||
ident->devname = NULL;
|
||||
ident->level = UnSet;
|
||||
ident->member = NULL;
|
||||
ident->name[0] = 0;
|
||||
ident->next = NULL;
|
||||
ident->raid_disks = UnSet;
|
||||
ident->spare_group = NULL;
|
||||
ident->spare_disks = 0;
|
||||
ident->st = NULL;
|
||||
ident->super_minor = UnSet;
|
||||
ident->uuid[0] = 0;
|
||||
ident->uuid_set = 0;
|
||||
}
|
||||
|
||||
struct conf_dev {
|
||||
struct conf_dev *next;
|
||||
char *name;
|
||||
|
@ -194,7 +222,6 @@ struct mddev_dev *load_containers(void)
|
|||
|
||||
struct createinfo createinfo = {
|
||||
.autof = 2, /* by default, create devices with standard names */
|
||||
.symlinks = 1,
|
||||
.names = 0, /* By default, stick with numbered md devices. */
|
||||
.bblist = 1, /* Use a bad block list by default */
|
||||
#ifdef DEBIAN
|
||||
|
@ -310,11 +337,7 @@ static void createline(char *line)
|
|||
if (!createinfo.supertype)
|
||||
pr_err("metadata format %s unknown, ignoring\n",
|
||||
w+9);
|
||||
} else if (strncasecmp(w, "symlinks=yes", 12) == 0)
|
||||
createinfo.symlinks = 1;
|
||||
else if (strncasecmp(w, "symlinks=no", 11) == 0)
|
||||
createinfo.symlinks = 0;
|
||||
else if (strncasecmp(w, "names=yes", 12) == 0)
|
||||
} else if (strncasecmp(w, "names=yes", 12) == 0)
|
||||
createinfo.names = 1;
|
||||
else if (strncasecmp(w, "names=no", 11) == 0)
|
||||
createinfo.names = 0;
|
||||
|
@ -368,22 +391,7 @@ void arrayline(char *line)
|
|||
struct mddev_ident mis;
|
||||
struct mddev_ident *mi;
|
||||
|
||||
mis.uuid_set = 0;
|
||||
mis.super_minor = UnSet;
|
||||
mis.level = UnSet;
|
||||
mis.raid_disks = UnSet;
|
||||
mis.spare_disks = 0;
|
||||
mis.devices = NULL;
|
||||
mis.devname = NULL;
|
||||
mis.spare_group = NULL;
|
||||
mis.autof = 0;
|
||||
mis.next = NULL;
|
||||
mis.st = NULL;
|
||||
mis.bitmap_fd = -1;
|
||||
mis.bitmap_file = NULL;
|
||||
mis.name[0] = 0;
|
||||
mis.container = NULL;
|
||||
mis.member = NULL;
|
||||
ident_init(&mis);
|
||||
|
||||
for (w = dl_next(line); w != line; w = dl_next(w)) {
|
||||
if (w[0] == '/' || strchr(w, '=') == NULL) {
|
||||
|
|
12
lib.c
12
lib.c
|
@ -164,6 +164,18 @@ char *stat2devnm(struct stat *st)
|
|||
return devid2devnm(st->st_rdev);
|
||||
}
|
||||
|
||||
bool stat_is_md_dev(struct stat *st)
|
||||
{
|
||||
if ((S_IFMT & st->st_mode) != S_IFBLK)
|
||||
return false;
|
||||
if (major(st->st_rdev) == MD_MAJOR)
|
||||
return true;
|
||||
if (major(st->st_rdev) == (unsigned)get_mdp_major())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
char *fd2devnm(int fd)
|
||||
{
|
||||
struct stat stb;
|
||||
|
|
|
@ -106,7 +106,6 @@
|
|||
#include "mdmon.h"
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/socket.h>
|
||||
#include <signal.h>
|
||||
|
||||
static void close_aa(struct active_array *aa)
|
||||
{
|
||||
|
@ -208,7 +207,7 @@ static void replace_array(struct supertype *container,
|
|||
remove_old();
|
||||
while (pending_discard) {
|
||||
while (discard_this == NULL)
|
||||
sleep(1);
|
||||
sleep_for(1, 0, true);
|
||||
remove_old();
|
||||
}
|
||||
pending_discard = old;
|
||||
|
@ -569,7 +568,7 @@ static void manage_member(struct mdstat_ent *mdstat,
|
|||
updates = NULL;
|
||||
while (update_queue_pending || update_queue) {
|
||||
check_update_queue(container);
|
||||
usleep(15*1000);
|
||||
sleep_for(0, MSEC_TO_NSEC(15), true);
|
||||
}
|
||||
replace_array(container, a, newa);
|
||||
if (sysfs_set_str(&a->info, NULL,
|
||||
|
@ -823,7 +822,7 @@ static void handle_message(struct supertype *container, struct metadata_update *
|
|||
if (msg->len <= 0)
|
||||
while (update_queue_pending || update_queue) {
|
||||
check_update_queue(container);
|
||||
usleep(15*1000);
|
||||
sleep_for(0, MSEC_TO_NSEC(15), true);
|
||||
}
|
||||
|
||||
if (msg->len == 0) { /* ping_monitor */
|
||||
|
@ -837,7 +836,7 @@ static void handle_message(struct supertype *container, struct metadata_update *
|
|||
wakeup_monitor();
|
||||
|
||||
while (monitor_loop_cnt - cnt < 0)
|
||||
usleep(10 * 1000);
|
||||
sleep_for(0, MSEC_TO_NSEC(10), true);
|
||||
} else if (msg->len == -1) { /* ping_manager */
|
||||
struct mdstat_ent *mdstat = mdstat_read(1, 0);
|
||||
|
||||
|
|
55
maps.c
55
maps.c
|
@ -165,7 +165,62 @@ mapping_t sysfs_array_states[] = {
|
|||
{ "broken", ARRAY_BROKEN },
|
||||
{ NULL, ARRAY_UNKNOWN_STATE }
|
||||
};
|
||||
/**
|
||||
* mapping_t update_options - stores supported update options.
|
||||
*/
|
||||
mapping_t update_options[] = {
|
||||
{ "name", UOPT_NAME },
|
||||
{ "ppl", UOPT_PPL },
|
||||
{ "no-ppl", UOPT_NO_PPL },
|
||||
{ "bitmap", UOPT_BITMAP },
|
||||
{ "no-bitmap", UOPT_NO_BITMAP },
|
||||
{ "sparc2.2", UOPT_SPARC22 },
|
||||
{ "super-minor", UOPT_SUPER_MINOR },
|
||||
{ "summaries", UOPT_SUMMARIES },
|
||||
{ "resync", UOPT_RESYNC },
|
||||
{ "uuid", UOPT_UUID },
|
||||
{ "homehost", UOPT_HOMEHOST },
|
||||
{ "home-cluster", UOPT_HOME_CLUSTER },
|
||||
{ "nodes", UOPT_NODES },
|
||||
{ "devicesize", UOPT_DEVICESIZE },
|
||||
{ "bbl", UOPT_BBL },
|
||||
{ "no-bbl", UOPT_NO_BBL },
|
||||
{ "force-no-bbl", UOPT_FORCE_NO_BBL },
|
||||
{ "metadata", UOPT_METADATA },
|
||||
{ "revert-reshape", UOPT_REVERT_RESHAPE },
|
||||
{ "layout-original", UOPT_LAYOUT_ORIGINAL },
|
||||
{ "layout-alternate", UOPT_LAYOUT_ALTERNATE },
|
||||
{ "layout-unspecified", UOPT_LAYOUT_UNSPECIFIED },
|
||||
{ "byteorder", UOPT_BYTEORDER },
|
||||
{ "help", UOPT_HELP },
|
||||
{ "?", UOPT_HELP },
|
||||
{ NULL, UOPT_UNDEFINED}
|
||||
};
|
||||
|
||||
/**
|
||||
* map_num_s() - Safer alternative of map_num() function.
|
||||
* @map: map to search.
|
||||
* @num: key to match.
|
||||
*
|
||||
* Shall be used only if key existence is quaranted.
|
||||
*
|
||||
* Return: Pointer to name of the element.
|
||||
*/
|
||||
char *map_num_s(mapping_t *map, int num)
|
||||
{
|
||||
char *ret = map_num(map, num);
|
||||
|
||||
assert(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* map_num() - get element name by key.
|
||||
* @map: map to search.
|
||||
* @num: key to match.
|
||||
*
|
||||
* Return: Pointer to name of the element or NULL.
|
||||
*/
|
||||
char *map_num(mapping_t *map, int num)
|
||||
{
|
||||
while (map->name) {
|
||||
|
|
301
mdadm.8.in
301
mdadm.8.in
|
@ -158,7 +158,7 @@ adding new spares and removing faulty devices.
|
|||
.B Misc
|
||||
This is an 'everything else' mode that supports operations on active
|
||||
arrays, operations on component devices such as erasing old superblocks, and
|
||||
information gathering operations.
|
||||
information-gathering operations.
|
||||
.\"This mode allows operations on independent devices such as examine MD
|
||||
.\"superblocks, erasing old superblocks and stopping active arrays.
|
||||
|
||||
|
@ -231,12 +231,12 @@ mode to be assumed.
|
|||
|
||||
.TP
|
||||
.BR \-h ", " \-\-help
|
||||
Display general help message or, after one of the above options, a
|
||||
Display a general help message or, after one of the above options, a
|
||||
mode-specific help message.
|
||||
|
||||
.TP
|
||||
.B \-\-help\-options
|
||||
Display more detailed help about command line parsing and some commonly
|
||||
Display more detailed help about command-line parsing and some commonly
|
||||
used options.
|
||||
|
||||
.TP
|
||||
|
@ -266,14 +266,11 @@ the exact meaning of this option in different contexts.
|
|||
|
||||
.TP
|
||||
.BR \-c ", " \-\-config=
|
||||
Specify the config file or directory. Default is to use
|
||||
.B /etc/mdadm.conf
|
||||
and
|
||||
.BR /etc/mdadm.conf.d ,
|
||||
or if those are missing then
|
||||
.B /etc/mdadm/mdadm.conf
|
||||
and
|
||||
.BR /etc/mdadm/mdadm.conf.d .
|
||||
Specify the config file or directory. If not specified, the default config file
|
||||
and default conf.d directory will be used. See
|
||||
.BR mdadm.conf (5)
|
||||
for more details.
|
||||
|
||||
If the config file given is
|
||||
.B "partitions"
|
||||
then nothing will be read, but
|
||||
|
@ -382,7 +379,7 @@ When creating an array, the
|
|||
.B homehost
|
||||
will be recorded in the metadata. For version-1 superblocks, it will
|
||||
be prefixed to the array name. For version-0.90 superblocks, part of
|
||||
the SHA1 hash of the hostname will be stored in the later half of the
|
||||
the SHA1 hash of the hostname will be stored in the latter half of the
|
||||
UUID.
|
||||
|
||||
When reporting information about an array, any array which is tagged
|
||||
|
@ -391,7 +388,7 @@ for the given homehost will be reported as such.
|
|||
When using Auto-Assemble, only arrays tagged for the given homehost
|
||||
will be allowed to use 'local' names (i.e. not ending in '_' followed
|
||||
by a digit string). See below under
|
||||
.BR "Auto Assembly" .
|
||||
.BR "Auto-Assembly" .
|
||||
|
||||
The special name "\fBany\fP" can be used as a wild card. If an array
|
||||
is created with
|
||||
|
@ -406,7 +403,7 @@ When
|
|||
.I mdadm
|
||||
needs to print the name for a device it normally finds the name in
|
||||
.B /dev
|
||||
which refers to the device and is shortest. When a path component is
|
||||
which refers to the device and is the shortest. When a path component is
|
||||
given with
|
||||
.B \-\-prefer
|
||||
.I mdadm
|
||||
|
@ -459,7 +456,8 @@ number of spare devices.
|
|||
|
||||
.TP
|
||||
.BR \-z ", " \-\-size=
|
||||
Amount (in Kilobytes) of space to use from each drive in RAID levels 1/4/5/6.
|
||||
Amount (in Kilobytes) of space to use from each drive in RAID levels 1/4/5/6/10
|
||||
and for RAID 0 on external metadata.
|
||||
This must be a multiple of the chunk size, and must leave about 128Kb
|
||||
of space at the end of the drive for the RAID superblock.
|
||||
If this is not specified
|
||||
|
@ -478,10 +476,19 @@ To guard against this it can be useful to set the initial size
|
|||
slightly smaller than the smaller device with the aim that it will
|
||||
still be larger than any replacement.
|
||||
|
||||
This option can be used with
|
||||
.B \-\-create
|
||||
for determining the initial size of an array. For external metadata,
|
||||
it can be used on a volume, but not on a container itself.
|
||||
Setting the initial size of
|
||||
.B RAID 0
|
||||
array is only valid for external metadata.
|
||||
|
||||
This value can be set with
|
||||
.B \-\-grow
|
||||
for RAID level 1/4/5/6 though
|
||||
for RAID level 1/4/5/6/10 though
|
||||
DDF arrays may not be able to support this.
|
||||
RAID 0 array size cannot be changed.
|
||||
If the array was created with a size smaller than the currently
|
||||
active drives, the extra space can be accessed using
|
||||
.BR \-\-grow .
|
||||
|
@ -501,11 +508,6 @@ problems the array can be made bigger again with no loss with another
|
|||
.B "\-\-grow \-\-size="
|
||||
command.
|
||||
|
||||
This value cannot be used when creating a
|
||||
.B CONTAINER
|
||||
such as with DDF and IMSM metadata, though it perfectly valid when
|
||||
creating an array inside a container.
|
||||
|
||||
.TP
|
||||
.BR \-Z ", " \-\-array\-size=
|
||||
This is only meaningful with
|
||||
|
@ -543,20 +545,20 @@ Clustered arrays do not support this parameter yet.
|
|||
|
||||
.TP
|
||||
.BR \-c ", " \-\-chunk=
|
||||
Specify chunk size of kilobytes. The default when creating an
|
||||
Specify chunk size in kilobytes. The default when creating an
|
||||
array is 512KB. To ensure compatibility with earlier versions, the
|
||||
default when building an array with no persistent metadata is 64KB.
|
||||
This is only meaningful for RAID0, RAID4, RAID5, RAID6, and RAID10.
|
||||
|
||||
RAID4, RAID5, RAID6, and RAID10 require the chunk size to be a power
|
||||
of 2. In any case it must be a multiple of 4KB.
|
||||
of 2, with minimal chunk size being 4KB.
|
||||
|
||||
A suffix of 'K', 'M', 'G' or 'T' can be given to indicate Kilobytes,
|
||||
Megabytes, Gigabytes or Terabytes respectively.
|
||||
|
||||
.TP
|
||||
.BR \-\-rounding=
|
||||
Specify rounding factor for a Linear array. The size of each
|
||||
Specify the rounding factor for a Linear array. The size of each
|
||||
component will be rounded down to a multiple of this size.
|
||||
This is a synonym for
|
||||
.B \-\-chunk
|
||||
|
@ -653,7 +655,8 @@ option to set subsequent failure modes.
|
|||
and "flush" will clear any persistent faults.
|
||||
|
||||
The layout options for RAID10 are one of 'n', 'o' or 'f' followed
|
||||
by a small number. The default is 'n2'. The supported options are:
|
||||
by a small number signifying the number of copies of each datablock.
|
||||
The default is 'n2'. The supported options are:
|
||||
|
||||
.I 'n'
|
||||
signals 'near' copies. Multiple copies of one data block are at
|
||||
|
@ -671,7 +674,7 @@ signals 'far' copies
|
|||
(multiple copies have very different offsets).
|
||||
See md(4) for more detail about 'near', 'offset', and 'far'.
|
||||
|
||||
The number is the number of copies of each datablock. 2 is normal, 3
|
||||
As for the number of copies of each data block, 2 is normal, 3
|
||||
can be useful. This number can be at most equal to the number of
|
||||
devices in the array. It does not need to divide evenly into that
|
||||
number (e.g. it is perfectly legal to have an 'n2' layout for an array
|
||||
|
@ -682,7 +685,7 @@ A bug introduced in Linux 3.14 means that RAID0 arrays
|
|||
started using a different layout. This could lead to
|
||||
data corruption. Since Linux 5.4 (and various stable releases that received
|
||||
backports), the kernel will not accept such an array unless
|
||||
a layout is explictly set. It can be set to
|
||||
a layout is explicitly set. It can be set to
|
||||
.RB ' original '
|
||||
or
|
||||
.RB ' alternate '.
|
||||
|
@ -758,13 +761,13 @@ or by selecting a different consistency policy with
|
|||
|
||||
.TP
|
||||
.BR \-\-bitmap\-chunk=
|
||||
Set the chunksize of the bitmap. Each bit corresponds to that many
|
||||
Set the chunk size of the bitmap. Each bit corresponds to that many
|
||||
Kilobytes of storage.
|
||||
When using a file based bitmap, the default is to use the smallest
|
||||
size that is at-least 4 and requires no more than 2^21 chunks.
|
||||
When using a file-based bitmap, the default is to use the smallest
|
||||
size that is at least 4 and requires no more than 2^21 chunks.
|
||||
When using an
|
||||
.B internal
|
||||
bitmap, the chunksize defaults to 64Meg, or larger if necessary to
|
||||
bitmap, the chunk size defaults to 64Meg, or larger if necessary to
|
||||
fit the bitmap into the available space.
|
||||
|
||||
A suffix of 'K', 'M', 'G' or 'T' can be given to indicate Kilobytes,
|
||||
|
@ -838,7 +841,7 @@ can be used with that command to avoid the automatic resync.
|
|||
.BR \-\-backup\-file=
|
||||
This is needed when
|
||||
.B \-\-grow
|
||||
is used to increase the number of raid-devices in a RAID5 or RAID6 if
|
||||
is used to increase the number of raid devices in a RAID5 or RAID6 if
|
||||
there are no spare devices available, or to shrink, change RAID level
|
||||
or layout. See the GROW MODE section below on RAID\-DEVICES CHANGES.
|
||||
The file must be stored on a separate device, not on the RAID array
|
||||
|
@ -877,7 +880,7 @@ When creating an array,
|
|||
.B \-\-data\-offset
|
||||
can be specified as
|
||||
.BR variable .
|
||||
In the case each member device is expected to have a offset appended
|
||||
In the case each member device is expected to have an offset appended
|
||||
to the name, separated by a colon. This makes it possible to recreate
|
||||
exactly an array which has varying data offsets (as can happen when
|
||||
different versions of
|
||||
|
@ -941,7 +944,7 @@ Insist that
|
|||
.I mdadm
|
||||
accept the geometry and layout specified without question. Normally
|
||||
.I mdadm
|
||||
will not allow creation of an array with only one device, and will try
|
||||
will not allow the creation of an array with only one device, and will try
|
||||
to create a RAID5 array with one missing drive (as this makes the
|
||||
initial resync work faster). With
|
||||
.BR \-\-force ,
|
||||
|
@ -1002,7 +1005,7 @@ number added, e.g.
|
|||
If the md device name is in a 'standard' format as described in DEVICE
|
||||
NAMES, then it will be created, if necessary, with the appropriate
|
||||
device number based on that name. If the device name is not in one of these
|
||||
formats, then a unused device number will be allocated. The device
|
||||
formats, then an unused device number will be allocated. The device
|
||||
number will be considered unused if there is no active array for that
|
||||
number, and there is no entry in /dev for that number and with a
|
||||
non-standard name. Names that are not in 'standard' format are only
|
||||
|
@ -1030,30 +1033,25 @@ then
|
|||
.B \-\-add
|
||||
can be used to add some extra devices to be included in the array.
|
||||
In most cases this is not needed as the extra devices can be added as
|
||||
spares first, and then the number of raid-disks can be changed.
|
||||
However for RAID0, it is not possible to add spares. So to increase
|
||||
spares first, and then the number of raid disks can be changed.
|
||||
However, for RAID0 it is not possible to add spares. So to increase
|
||||
the number of devices in a RAID0, it is necessary to set the new
|
||||
number of devices, and to add the new devices, in the same command.
|
||||
|
||||
.TP
|
||||
.BR \-\-nodes
|
||||
Only works when the array is for clustered environment. It specifies
|
||||
Only works when the array is created for a clustered environment. It specifies
|
||||
the maximum number of nodes in the cluster that will use this device
|
||||
simultaneously. If not specified, this defaults to 4.
|
||||
|
||||
.TP
|
||||
.BR \-\-write-journal
|
||||
Specify journal device for the RAID-4/5/6 array. The journal device
|
||||
should be a SSD with reasonable lifetime.
|
||||
|
||||
.TP
|
||||
.BR \-\-symlinks
|
||||
Auto creation of symlinks in /dev to /dev/md, option --symlinks must
|
||||
be 'no' or 'yes' and work with --create and --build.
|
||||
should be an SSD with a reasonable lifetime.
|
||||
|
||||
.TP
|
||||
.BR \-k ", " \-\-consistency\-policy=
|
||||
Specify how the array maintains consistency in case of unexpected shutdown.
|
||||
Specify how the array maintains consistency in the case of an unexpected shutdown.
|
||||
Only relevant for RAID levels with redundancy.
|
||||
Currently supported options are:
|
||||
.RS
|
||||
|
@ -1061,7 +1059,7 @@ Currently supported options are:
|
|||
.TP
|
||||
.B resync
|
||||
Full resync is performed and all redundancy is regenerated when the array is
|
||||
started after unclean shutdown.
|
||||
started after an unclean shutdown.
|
||||
|
||||
.TP
|
||||
.B bitmap
|
||||
|
@ -1070,8 +1068,8 @@ Resync assisted by a write-intent bitmap. Implicitly selected when using
|
|||
|
||||
.TP
|
||||
.B journal
|
||||
For RAID levels 4/5/6, journal device is used to log transactions and replay
|
||||
after unclean shutdown. Implicitly selected when using
|
||||
For RAID levels 4/5/6, the journal device is used to log transactions and replay
|
||||
after an unclean shutdown. Implicitly selected when using
|
||||
.BR \-\-write\-journal .
|
||||
|
||||
.TP
|
||||
|
@ -1240,7 +1238,7 @@ This can be useful if
|
|||
reports a different "Preferred Minor" to
|
||||
.BR \-\-detail .
|
||||
In some cases this update will be performed automatically
|
||||
by the kernel driver. In particular the update happens automatically
|
||||
by the kernel driver. In particular, the update happens automatically
|
||||
at the first write to an array with redundancy (RAID level 1 or
|
||||
greater) on a 2.6 (or later) kernel.
|
||||
|
||||
|
@ -1280,7 +1278,7 @@ For version-1 superblocks, this involves updating the name.
|
|||
The
|
||||
.B home\-cluster
|
||||
option will change the cluster name as recorded in the superblock and
|
||||
bitmap. This option only works for clustered environment.
|
||||
bitmap. This option only works for a clustered environment.
|
||||
|
||||
The
|
||||
.B resync
|
||||
|
@ -1393,20 +1391,16 @@ This option should be used with great caution.
|
|||
|
||||
.TP
|
||||
.BR \-\-freeze\-reshape
|
||||
Option is intended to be used in start-up scripts during initrd boot phase.
|
||||
When array under reshape is assembled during initrd phase, this option
|
||||
stops reshape after reshape critical section is being restored. This happens
|
||||
before file system pivot operation and avoids loss of file system context.
|
||||
This option is intended to be used in start-up scripts during the initrd boot phase.
|
||||
When the array under reshape is assembled during the initrd phase, this option
|
||||
stops the reshape after the reshape-critical section has been restored. This happens
|
||||
before the file system pivot operation and avoids loss of filesystem context.
|
||||
Losing file system context would cause reshape to be broken.
|
||||
|
||||
Reshape can be continued later using the
|
||||
.B \-\-continue
|
||||
option for the grow command.
|
||||
|
||||
.TP
|
||||
.BR \-\-symlinks
|
||||
See this option under Create and Build options.
|
||||
|
||||
.SH For Manage mode:
|
||||
|
||||
.TP
|
||||
|
@ -1444,9 +1438,9 @@ re\-add a device that was previously removed from an array.
|
|||
If the metadata on the device reports that it is a member of the
|
||||
array, and the slot that it used is still vacant, then the device will
|
||||
be added back to the array in the same position. This will normally
|
||||
cause the data for that device to be recovered. However based on the
|
||||
cause the data for that device to be recovered. However, based on the
|
||||
event count on the device, the recovery may only require sections that
|
||||
are flagged a write-intent bitmap to be recovered or may not require
|
||||
are flagged by a write-intent bitmap to be recovered or may not require
|
||||
any recovery at all.
|
||||
|
||||
When used on an array that has no metadata (i.e. it was built with
|
||||
|
@ -1454,13 +1448,12 @@ When used on an array that has no metadata (i.e. it was built with
|
|||
it will be assumed that bitmap-based recovery is enough to make the
|
||||
device fully consistent with the array.
|
||||
|
||||
When used with v1.x metadata,
|
||||
.B \-\-re\-add
|
||||
can be accompanied by
|
||||
can also be accompanied by
|
||||
.BR \-\-update=devicesize ,
|
||||
.BR \-\-update=bbl ", or"
|
||||
.BR \-\-update=no\-bbl .
|
||||
See the description of these option when used in Assemble mode for an
|
||||
See descriptions of these options when used in Assemble mode for an
|
||||
explanation of their use.
|
||||
|
||||
If the device name given is
|
||||
|
@ -1487,7 +1480,7 @@ Add a device as a spare. This is similar to
|
|||
except that it does not attempt
|
||||
.B \-\-re\-add
|
||||
first. The device will be added as a spare even if it looks like it
|
||||
could be an recent member of the array.
|
||||
could be a recent member of the array.
|
||||
|
||||
.TP
|
||||
.BR \-r ", " \-\-remove
|
||||
|
@ -1504,12 +1497,12 @@ and names like
|
|||
.B set-A
|
||||
can be given to
|
||||
.BR \-\-remove .
|
||||
The first causes all failed device to be removed. The second causes
|
||||
The first causes all failed devices to be removed. The second causes
|
||||
any device which is no longer connected to the system (i.e an 'open'
|
||||
returns
|
||||
.BR ENXIO )
|
||||
to be removed.
|
||||
The third will remove a set as describe below under
|
||||
The third will remove a set as described below under
|
||||
.BR \-\-fail .
|
||||
|
||||
.TP
|
||||
|
@ -1526,7 +1519,7 @@ For RAID10 arrays where the number of copies evenly divides the number
|
|||
of devices, the devices can be conceptually divided into sets where
|
||||
each set contains a single complete copy of the data on the array.
|
||||
Sometimes a RAID10 array will be configured so that these sets are on
|
||||
separate controllers. In this case all the devices in one set can be
|
||||
separate controllers. In this case, all the devices in one set can be
|
||||
failed by giving a name like
|
||||
.B set\-A
|
||||
or
|
||||
|
@ -1556,9 +1549,9 @@ This can follow a list of
|
|||
.B \-\-replace
|
||||
devices. The devices listed after
|
||||
.B \-\-with
|
||||
will be preferentially used to replace the devices listed after
|
||||
will preferentially be used to replace the devices listed after
|
||||
.BR \-\-replace .
|
||||
These device must already be spare devices in the array.
|
||||
These devices must already be spare devices in the array.
|
||||
|
||||
.TP
|
||||
.BR \-\-write\-mostly
|
||||
|
@ -1581,8 +1574,8 @@ the device is found or <slot>:missing in case the device is not found.
|
|||
|
||||
.TP
|
||||
.BR \-\-add-journal
|
||||
Add journal to an existing array, or recreate journal for RAID-4/5/6 array
|
||||
that lost a journal device. To avoid interrupting on-going write opertions,
|
||||
Add a journal to an existing array, or recreate journal for a RAID-4/5/6 array
|
||||
that lost a journal device. To avoid interrupting ongoing write operations,
|
||||
.B \-\-add-journal
|
||||
only works for array in Read-Only state.
|
||||
|
||||
|
@ -1638,9 +1631,9 @@ Print details of one or more md devices.
|
|||
.TP
|
||||
.BR \-\-detail\-platform
|
||||
Print details of the platform's RAID capabilities (firmware / hardware
|
||||
topology) for a given metadata format. If used without argument, mdadm
|
||||
topology) for a given metadata format. If used without an argument, mdadm
|
||||
will scan all controllers looking for their capabilities. Otherwise, mdadm
|
||||
will only look at the controller specified by the argument in form of an
|
||||
will only look at the controller specified by the argument in the form of an
|
||||
absolute filepath or a link, e.g.
|
||||
.IR /sys/devices/pci0000:00/0000:00:1f.2 .
|
||||
|
||||
|
@ -1749,8 +1742,8 @@ the block where the superblock would be is overwritten even if it
|
|||
doesn't appear to be valid.
|
||||
|
||||
.B Note:
|
||||
Be careful to call \-\-zero\-superblock with clustered raid, make sure
|
||||
array isn't used or assembled in other cluster node before execute it.
|
||||
Be careful when calling \-\-zero\-superblock with clustered raid. Make sure
|
||||
the array isn't used or assembled in another cluster node before executing it.
|
||||
|
||||
.TP
|
||||
.B \-\-kill\-subarray=
|
||||
|
@ -1797,7 +1790,7 @@ For each md device given, or each device in /proc/mdstat if
|
|||
is given, arrange for the array to be marked clean as soon as possible.
|
||||
.I mdadm
|
||||
will return with success if the array uses external metadata and we
|
||||
successfully waited. For native arrays this returns immediately as the
|
||||
successfully waited. For native arrays, this returns immediately as the
|
||||
kernel handles dirty-clean transitions at shutdown. No action is taken
|
||||
if safe-mode handling is disabled.
|
||||
|
||||
|
@ -1837,7 +1830,7 @@ uses to help track which arrays are currently being assembled.
|
|||
|
||||
.TP
|
||||
.BR \-\-run ", " \-R
|
||||
Run any array assembled as soon as a minimal number of devices are
|
||||
Run any array assembled as soon as a minimal number of devices is
|
||||
available, rather than waiting until all expected devices are present.
|
||||
|
||||
.TP
|
||||
|
@ -1867,7 +1860,7 @@ Only used with \-\-fail. The 'path' given will be recorded so that if
|
|||
a new device appears at the same location it can be automatically
|
||||
added to the same array. This allows the failed device to be
|
||||
automatically replaced by a new device without metadata if it appears
|
||||
at specified path. This option is normally only set by a
|
||||
at specified path. This option is normally only set by an
|
||||
.I udev
|
||||
script.
|
||||
|
||||
|
@ -1968,7 +1961,7 @@ Usage:
|
|||
.PP
|
||||
This usage assembles one or more RAID arrays from pre-existing components.
|
||||
For each array, mdadm needs to know the md device, the identity of the
|
||||
array, and a number of component-devices. These can be found in a number of ways.
|
||||
array, and the number of component devices. These can be found in a number of ways.
|
||||
|
||||
In the first usage example (without the
|
||||
.BR \-\-scan )
|
||||
|
@ -2008,11 +2001,9 @@ The config file is only used if explicitly named with
|
|||
.B \-\-config
|
||||
or requested with (a possibly implicit)
|
||||
.BR \-\-scan .
|
||||
In the later case,
|
||||
.B /etc/mdadm.conf
|
||||
or
|
||||
.B /etc/mdadm/mdadm.conf
|
||||
is used.
|
||||
In the latter case, the default config file is used. See
|
||||
.BR mdadm.conf (5)
|
||||
for more details.
|
||||
|
||||
If
|
||||
.B \-\-scan
|
||||
|
@ -2048,14 +2039,14 @@ detects that udev is not configured, it will create the devices in
|
|||
.B /dev
|
||||
itself.
|
||||
|
||||
In Linux kernels prior to version 2.6.28 there were two distinctly
|
||||
different types of md devices that could be created: one that could be
|
||||
In Linux kernels prior to version 2.6.28 there were two distinct
|
||||
types of md devices that could be created: one that could be
|
||||
partitioned using standard partitioning tools and one that could not.
|
||||
Since 2.6.28 that distinction is no longer relevant as both type of
|
||||
Since 2.6.28 that distinction is no longer relevant as both types of
|
||||
devices can be partitioned.
|
||||
.I mdadm
|
||||
will normally create the type that originally could not be partitioned
|
||||
as it has a well defined major number (9).
|
||||
as it has a well-defined major number (9).
|
||||
|
||||
Prior to 2.6.28, it is important that mdadm chooses the correct type
|
||||
of array device to use. This can be controlled with the
|
||||
|
@ -2075,7 +2066,7 @@ can also be given in the configuration file as a word starting
|
|||
.B auto=
|
||||
on the ARRAY line for the relevant array.
|
||||
|
||||
.SS Auto Assembly
|
||||
.SS Auto-Assembly
|
||||
When
|
||||
.B \-\-assemble
|
||||
is used with
|
||||
|
@ -2131,11 +2122,11 @@ See
|
|||
.IR mdadm.conf (5)
|
||||
for further details.
|
||||
|
||||
Note: Auto assembly cannot be used for assembling and activating some
|
||||
Note: Auto-assembly cannot be used for assembling and activating some
|
||||
arrays which are undergoing reshape. In particular as the
|
||||
.B backup\-file
|
||||
cannot be given, any reshape which requires a backup-file to continue
|
||||
cannot be started by auto assembly. An array which is growing to more
|
||||
cannot be given, any reshape which requires a backup file to continue
|
||||
cannot be started by auto-assembly. An array which is growing to more
|
||||
devices and has passed the critical section can be assembled using
|
||||
auto-assembly.
|
||||
|
||||
|
@ -2242,7 +2233,7 @@ When creating a partition based array, using
|
|||
.I mdadm
|
||||
with version-1.x metadata, the partition type should be set to
|
||||
.B 0xDA
|
||||
(non fs-data). This type selection allows for greater precision since
|
||||
(non fs-data). This type of selection allows for greater precision since
|
||||
using any other [RAID auto-detect (0xFD) or a GNU/Linux partition (0x83)],
|
||||
might create problems in the event of array recovery through a live cdrom.
|
||||
|
||||
|
@ -2258,7 +2249,7 @@ when creating a v0.90 array will silently override any
|
|||
setting.
|
||||
.\"If the
|
||||
.\".B \-\-size
|
||||
.\"option is given, it is not necessary to list any component-devices in this command.
|
||||
.\"option is given, it is not necessary to list any component devices in this command.
|
||||
.\"They can be added later, before a
|
||||
.\".B \-\-run.
|
||||
.\"If no
|
||||
|
@ -2272,7 +2263,7 @@ requested with the
|
|||
.B \-\-bitmap
|
||||
option or a different consistency policy is selected with the
|
||||
.B \-\-consistency\-policy
|
||||
option. In any case space for a bitmap will be reserved so that one
|
||||
option. In any case, space for a bitmap will be reserved so that one
|
||||
can be added later with
|
||||
.BR "\-\-grow \-\-bitmap=internal" .
|
||||
|
||||
|
@ -2322,7 +2313,7 @@ will firstly mark
|
|||
as faulty in
|
||||
.B /dev/md0
|
||||
and will then remove it from the array and finally add it back
|
||||
in as a spare. However only one md array can be affected by a single
|
||||
in as a spare. However, only one md array can be affected by a single
|
||||
command.
|
||||
|
||||
When a device is added to an active array, mdadm checks to see if it
|
||||
|
@ -2467,14 +2458,14 @@ config file to be examined.
|
|||
If the device contains RAID metadata, a file will be created in the
|
||||
.I directory
|
||||
and the metadata will be written to it. The file will be the same
|
||||
size as the device and have the metadata written in the file at the
|
||||
same locate that it exists in the device. However the file will be "sparse" so
|
||||
size as the device and will have the metadata written at the
|
||||
same location as it exists in the device. However, the file will be "sparse" so
|
||||
that only those blocks containing metadata will be allocated. The
|
||||
total space used will be small.
|
||||
|
||||
The file name used in the
|
||||
The filename used in the
|
||||
.I directory
|
||||
will be the base name of the device. Further if any links appear in
|
||||
will be the base name of the device. Further, if any links appear in
|
||||
.I /dev/disk/by-id
|
||||
which point to the device, then hard links to the file will be created
|
||||
in
|
||||
|
@ -2557,13 +2548,33 @@ Usage:
|
|||
.I options... devices...
|
||||
|
||||
.PP
|
||||
This usage causes
|
||||
Monitor option can work in two modes:
|
||||
.IP \(bu 4
|
||||
system wide mode, follow all md devices based on
|
||||
.B /proc/mdstat,
|
||||
.IP \(bu 4
|
||||
follow only specified MD devices in command line.
|
||||
.PP
|
||||
|
||||
.B \-\-scan -
|
||||
indicates system wide mode. Option causes the
|
||||
.I monitor
|
||||
to track all md devices that appear in
|
||||
.B /proc/mdstat.
|
||||
If it is not set, then at least one
|
||||
.B device
|
||||
must be specified.
|
||||
|
||||
Monitor usage causes
|
||||
.I mdadm
|
||||
to periodically poll a number of md arrays and to report on any events
|
||||
noticed.
|
||||
.I mdadm
|
||||
will never exit once it decides that there are arrays to be checked,
|
||||
so it should normally be run in the background.
|
||||
|
||||
In both modes,
|
||||
.I monitor
|
||||
will work as long as there is an active array with redundancy and it is defined to follow (for
|
||||
.B \-\-scan
|
||||
every array is followed).
|
||||
|
||||
As well as reporting events,
|
||||
.I mdadm
|
||||
|
@ -2574,15 +2585,6 @@ or
|
|||
.B domain
|
||||
and if the destination array has a failed drive but no spares.
|
||||
|
||||
If any devices are listed on the command line,
|
||||
.I mdadm
|
||||
will only monitor those devices. Otherwise all arrays listed in the
|
||||
configuration file will be monitored. Further, if
|
||||
.B \-\-scan
|
||||
is given, then any other md devices that appear in
|
||||
.B /proc/mdstat
|
||||
will also be monitored.
|
||||
|
||||
The result of monitoring the arrays is the generation of events.
|
||||
These events are passed to a separate program (if specified) and may
|
||||
be mailed to a given E-mail address.
|
||||
|
@ -2595,16 +2597,34 @@ device if relevant (such as a component device that has failed).
|
|||
|
||||
If
|
||||
.B \-\-scan
|
||||
is given, then a program or an E-mail address must be specified on the
|
||||
command line or in the config file. If neither are available, then
|
||||
is given, then a
|
||||
.B program
|
||||
or an
|
||||
.B e-mail
|
||||
address must be specified on the
|
||||
command line or in the config file. If neither are available, then
|
||||
.I mdadm
|
||||
will not monitor anything.
|
||||
Without
|
||||
.B \-\-scan,
|
||||
.I mdadm
|
||||
will continue monitoring as long as something was found to monitor. If
|
||||
no program or email is given, then each event is reported to
|
||||
.BR stdout .
|
||||
For devices given directly in command line, without
|
||||
.B program
|
||||
or
|
||||
.B email
|
||||
specified, each event is reported to
|
||||
.BR stdout.
|
||||
|
||||
Note: For systems where
|
||||
.If mdadm monitor
|
||||
is configured via systemd,
|
||||
.B mdmonitor(mdmonitor.service)
|
||||
should be configured. The service is designed to be primary solution for array monitoring,
|
||||
it is configured to work in system wide mode.
|
||||
It is automatically started and stopped according to current state and types of MD arrays in system.
|
||||
The service may require additional configuration, like
|
||||
.B e-mail
|
||||
or
|
||||
.B delay.
|
||||
That should be done in
|
||||
.B mdadm.conf.
|
||||
|
||||
The different events are:
|
||||
|
||||
|
@ -2633,10 +2653,10 @@ check, repair). (syslog priority: Warning)
|
|||
.BI Rebuild NN
|
||||
Where
|
||||
.I NN
|
||||
is a two-digit number (ie. 05, 48). This indicates that rebuild
|
||||
has passed that many percent of the total. The events are generated
|
||||
with fixed increment since 0. Increment size may be specified with
|
||||
a commandline option (default is 20). (syslog priority: Warning)
|
||||
is a two-digit number (eg. 05, 48). This indicates that the rebuild
|
||||
has reached that percentage of the total. The events are generated
|
||||
at a fixed increment from 0. The increment size may be specified with
|
||||
a command-line option (the default is 20). (syslog priority: Warning)
|
||||
|
||||
.TP
|
||||
.B RebuildFinished
|
||||
|
@ -2744,8 +2764,8 @@ When
|
|||
detects that an array in a spare group has fewer active
|
||||
devices than necessary for the complete array, and has no spare
|
||||
devices, it will look for another array in the same spare group that
|
||||
has a full complement of working drive and a spare. It will then
|
||||
attempt to remove the spare from the second drive and add it to the
|
||||
has a full complement of working drives and a spare. It will then
|
||||
attempt to remove the spare from the second array and add it to the
|
||||
first.
|
||||
If the removal succeeds but the adding fails, then it is added back to
|
||||
the original array.
|
||||
|
@ -2759,10 +2779,8 @@ and then follow similar steps as above if a matching spare is found.
|
|||
.SH GROW MODE
|
||||
The GROW mode is used for changing the size or shape of an active
|
||||
array.
|
||||
For this to work, the kernel must support the necessary change.
|
||||
Various types of growth are being added during 2.6 development.
|
||||
|
||||
Currently the supported changes include
|
||||
During the kernel 2.6 era the following changes were added:
|
||||
.IP \(bu 4
|
||||
change the "size" attribute for RAID1, RAID4, RAID5 and RAID6.
|
||||
.IP \(bu 4
|
||||
|
@ -2805,8 +2823,8 @@ use more than half of a spare device for backup space.
|
|||
|
||||
.SS SIZE CHANGES
|
||||
Normally when an array is built the "size" is taken from the smallest
|
||||
of the drives. If all the small drives in an arrays are, one at a
|
||||
time, removed and replaced with larger drives, then you could have an
|
||||
of the drives. If all the small drives in an arrays are, over time,
|
||||
removed and replaced with larger drives, then you could have an
|
||||
array of large drives with only a small amount used. In this
|
||||
situation, changing the "size" with "GROW" mode will allow the extra
|
||||
space to start being used. If the size is increased in this way, a
|
||||
|
@ -2821,7 +2839,7 @@ after growing, or to reduce its size
|
|||
.B prior
|
||||
to shrinking the array.
|
||||
|
||||
Also the size of an array cannot be changed while it has an active
|
||||
Also, the size of an array cannot be changed while it has an active
|
||||
bitmap. If an array has a bitmap, it must be removed before the size
|
||||
can be changed. Once the change is complete a new bitmap can be created.
|
||||
|
||||
|
@ -2901,7 +2919,7 @@ long time. A
|
|||
is required. If the array is not simultaneously being grown or
|
||||
shrunk, so that the array size will remain the same - for example,
|
||||
reshaping a 3-drive RAID5 into a 4-drive RAID6 - the backup file will
|
||||
be used not just for a "cricital section" but throughout the reshape
|
||||
be used not just for a "critical section" but throughout the reshape
|
||||
operation, as described below under LAYOUT CHANGES.
|
||||
|
||||
.SS CHUNK-SIZE AND LAYOUT CHANGES
|
||||
|
@ -2919,7 +2937,7 @@ slowly.
|
|||
If the reshape is interrupted for any reason, this backup file must be
|
||||
made available to
|
||||
.B "mdadm --assemble"
|
||||
so the array can be reassembled. Consequently the file cannot be
|
||||
so the array can be reassembled. Consequently, the file cannot be
|
||||
stored on the device being reshaped.
|
||||
|
||||
|
||||
|
@ -3339,18 +3357,17 @@ uses this to find arrays when
|
|||
is given in Misc mode, and to monitor array reconstruction
|
||||
on Monitor mode.
|
||||
|
||||
.SS /etc/mdadm.conf
|
||||
.SS {CONFFILE} (or {CONFFILE2})
|
||||
|
||||
The config file lists which devices may be scanned to see if
|
||||
they contain MD super block, and gives identifying information
|
||||
(e.g. UUID) about known MD arrays. See
|
||||
Default config file. See
|
||||
.BR mdadm.conf (5)
|
||||
for more details.
|
||||
|
||||
.SS /etc/mdadm.conf.d
|
||||
.SS {CONFFILE}.d (or {CONFFILE2}.d)
|
||||
|
||||
A directory containing configuration files which are read in lexical
|
||||
order.
|
||||
Default directory containing configuration files. See
|
||||
.BR mdadm.conf (5)
|
||||
for more details.
|
||||
|
||||
.SS {MAP_PATH}
|
||||
When
|
||||
|
|
251
mdadm.c
251
mdadm.c
|
@ -49,7 +49,6 @@ int main(int argc, char *argv[])
|
|||
int i;
|
||||
|
||||
unsigned long long array_size = 0;
|
||||
unsigned long long data_offset = INVALID_SECTORS;
|
||||
struct mddev_ident ident;
|
||||
char *configfile = NULL;
|
||||
int devmode = 0;
|
||||
|
@ -59,7 +58,6 @@ int main(int argc, char *argv[])
|
|||
struct mddev_dev *dv;
|
||||
mdu_array_info_t array;
|
||||
int devs_found = 0;
|
||||
char *symlinks = NULL;
|
||||
int grow_continue = 0;
|
||||
/* autof indicates whether and how to create device node.
|
||||
* bottom 3 bits are style. Rest (when shifted) are number of parts
|
||||
|
@ -80,6 +78,7 @@ int main(int argc, char *argv[])
|
|||
.layout = UnSet,
|
||||
.bitmap_chunk = UnSet,
|
||||
.consistency_policy = CONSISTENCY_POLICY_UNKNOWN,
|
||||
.data_offset = INVALID_SECTORS,
|
||||
};
|
||||
|
||||
char sys_hostname[256];
|
||||
|
@ -101,32 +100,20 @@ int main(int argc, char *argv[])
|
|||
char *dump_directory = NULL;
|
||||
|
||||
int print_help = 0;
|
||||
FILE *outf;
|
||||
FILE *outf = NULL;
|
||||
|
||||
int mdfd = -1;
|
||||
int locked = 0;
|
||||
|
||||
srandom(time(0) ^ getpid());
|
||||
|
||||
ident.uuid_set = 0;
|
||||
ident.level = UnSet;
|
||||
ident.raid_disks = UnSet;
|
||||
ident.super_minor = UnSet;
|
||||
ident.devices = 0;
|
||||
ident.spare_group = NULL;
|
||||
ident.autof = 0;
|
||||
ident.st = NULL;
|
||||
ident.bitmap_fd = -1;
|
||||
ident.bitmap_file = NULL;
|
||||
ident.name[0] = 0;
|
||||
ident.container = NULL;
|
||||
ident.member = NULL;
|
||||
|
||||
if (get_linux_version() < 2006015) {
|
||||
pr_err("This version of mdadm does not support kernels older than 2.6.15\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ident_init(&ident);
|
||||
|
||||
while ((option_index = -1),
|
||||
(opt = getopt_long(argc, argv, shortopt, long_options,
|
||||
&option_index)) != -1) {
|
||||
|
@ -227,6 +214,7 @@ int main(int argc, char *argv[])
|
|||
shortopt = short_bitmap_auto_options;
|
||||
break;
|
||||
case 'F': newmode = MONITOR;
|
||||
shortopt = short_monitor_options;
|
||||
break;
|
||||
case 'G': newmode = GROW;
|
||||
shortopt = short_bitmap_options;
|
||||
|
@ -280,8 +268,8 @@ int main(int argc, char *argv[])
|
|||
else
|
||||
fprintf(stderr, "-%c", opt);
|
||||
fprintf(stderr, " would set mdadm mode to \"%s\", but it is already set to \"%s\".\n",
|
||||
map_num(modes, newmode),
|
||||
map_num(modes, mode));
|
||||
map_num_s(modes, newmode),
|
||||
map_num_s(modes, mode));
|
||||
exit(2);
|
||||
} else if (!mode && newmode) {
|
||||
mode = newmode;
|
||||
|
@ -479,15 +467,15 @@ int main(int argc, char *argv[])
|
|||
|
||||
case O(CREATE,DataOffset):
|
||||
case O(GROW,DataOffset):
|
||||
if (data_offset != INVALID_SECTORS) {
|
||||
if (s.data_offset != INVALID_SECTORS) {
|
||||
pr_err("data-offset may only be specified one. Second value is %s.\n", optarg);
|
||||
exit(2);
|
||||
}
|
||||
if (mode == CREATE && strcmp(optarg, "variable") == 0)
|
||||
data_offset = VARIABLE_OFFSET;
|
||||
s.data_offset = VARIABLE_OFFSET;
|
||||
else
|
||||
data_offset = parse_size(optarg);
|
||||
if (data_offset == INVALID_SECTORS) {
|
||||
s.data_offset = parse_size(optarg);
|
||||
if (s.data_offset == INVALID_SECTORS) {
|
||||
pr_err("invalid data-offset: %s\n",
|
||||
optarg);
|
||||
exit(2);
|
||||
|
@ -544,7 +532,7 @@ int main(int argc, char *argv[])
|
|||
switch(s.level) {
|
||||
default:
|
||||
pr_err("layout not meaningful for %s arrays.\n",
|
||||
map_num(pers, s.level));
|
||||
map_num_s(pers, s.level));
|
||||
exit(2);
|
||||
case UnSet:
|
||||
pr_err("raid level must be given before layout.\n");
|
||||
|
@ -662,13 +650,6 @@ int main(int argc, char *argv[])
|
|||
case O(ASSEMBLE,Auto): /* auto-creation of device node */
|
||||
c.autof = parse_auto(optarg, "--auto flag", 0);
|
||||
continue;
|
||||
|
||||
case O(CREATE,Symlinks):
|
||||
case O(BUILD,Symlinks):
|
||||
case O(ASSEMBLE,Symlinks): /* auto creation of symlinks in /dev to /dev/md */
|
||||
symlinks = optarg;
|
||||
continue;
|
||||
|
||||
case O(BUILD,'f'): /* force honouring '-n 1' */
|
||||
case O(BUILD,Force): /* force honouring '-n 1' */
|
||||
case O(GROW,'f'): /* ditto */
|
||||
|
@ -742,93 +723,50 @@ int main(int argc, char *argv[])
|
|||
continue;
|
||||
|
||||
case O(ASSEMBLE,'U'): /* update the superblock */
|
||||
case O(MISC,'U'):
|
||||
case O(MISC,'U'): {
|
||||
enum update_opt print_mode = UOPT_HELP;
|
||||
const char *error_addon = "update option";
|
||||
|
||||
if (c.update) {
|
||||
pr_err("Can only update one aspect of superblock, both %s and %s given.\n",
|
||||
c.update, optarg);
|
||||
map_num(update_options, c.update), optarg);
|
||||
exit(2);
|
||||
}
|
||||
if (mode == MISC && !c.subarray) {
|
||||
pr_err("Only subarrays can be updated in misc mode\n");
|
||||
exit(2);
|
||||
}
|
||||
c.update = optarg;
|
||||
if (strcmp(c.update, "sparc2.2") == 0)
|
||||
continue;
|
||||
if (strcmp(c.update, "super-minor") == 0)
|
||||
continue;
|
||||
if (strcmp(c.update, "summaries") == 0)
|
||||
continue;
|
||||
if (strcmp(c.update, "resync") == 0)
|
||||
continue;
|
||||
if (strcmp(c.update, "uuid") == 0)
|
||||
continue;
|
||||
if (strcmp(c.update, "name") == 0)
|
||||
continue;
|
||||
if (strcmp(c.update, "homehost") == 0)
|
||||
continue;
|
||||
if (strcmp(c.update, "home-cluster") == 0)
|
||||
continue;
|
||||
if (strcmp(c.update, "nodes") == 0)
|
||||
continue;
|
||||
if (strcmp(c.update, "devicesize") == 0)
|
||||
continue;
|
||||
if (strcmp(c.update, "bitmap") == 0)
|
||||
continue;
|
||||
if (strcmp(c.update, "no-bitmap") == 0)
|
||||
continue;
|
||||
if (strcmp(c.update, "bbl") == 0)
|
||||
continue;
|
||||
if (strcmp(c.update, "no-bbl") == 0)
|
||||
continue;
|
||||
if (strcmp(c.update, "force-no-bbl") == 0)
|
||||
continue;
|
||||
if (strcmp(c.update, "ppl") == 0)
|
||||
continue;
|
||||
if (strcmp(c.update, "no-ppl") == 0)
|
||||
continue;
|
||||
if (strcmp(c.update, "metadata") == 0)
|
||||
continue;
|
||||
if (strcmp(c.update, "revert-reshape") == 0)
|
||||
continue;
|
||||
if (strcmp(c.update, "layout-original") == 0 ||
|
||||
strcmp(c.update, "layout-alternate") == 0 ||
|
||||
strcmp(c.update, "layout-unspecified") == 0)
|
||||
continue;
|
||||
if (strcmp(c.update, "byteorder") == 0) {
|
||||
|
||||
c.update = map_name(update_options, optarg);
|
||||
|
||||
if (devmode == UpdateSubarray) {
|
||||
print_mode = UOPT_SUBARRAY_ONLY;
|
||||
error_addon = "update-subarray option";
|
||||
|
||||
if (c.update > UOPT_SUBARRAY_ONLY && c.update < UOPT_HELP)
|
||||
c.update = UOPT_UNDEFINED;
|
||||
}
|
||||
|
||||
switch (c.update) {
|
||||
case UOPT_UNDEFINED:
|
||||
pr_err("'--update=%s' is invalid %s. ",
|
||||
optarg, error_addon);
|
||||
outf = stderr;
|
||||
case UOPT_HELP:
|
||||
if (!outf)
|
||||
outf = stdout;
|
||||
fprint_update_options(outf, print_mode);
|
||||
exit(outf == stdout ? 0 : 2);
|
||||
case UOPT_BYTEORDER:
|
||||
if (ss) {
|
||||
pr_err("must not set metadata type with --update=byteorder.\n");
|
||||
exit(2);
|
||||
}
|
||||
for(i = 0; !ss && superlist[i]; i++)
|
||||
ss = superlist[i]->match_metadata_desc(
|
||||
"0.swap");
|
||||
if (!ss) {
|
||||
pr_err("INTERNAL ERROR cannot find 0.swap\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (strcmp(c.update,"?") == 0 ||
|
||||
strcmp(c.update, "help") == 0) {
|
||||
outf = stdout;
|
||||
fprintf(outf, "%s: ", Name);
|
||||
} else {
|
||||
outf = stderr;
|
||||
fprintf(outf,
|
||||
"%s: '--update=%s' is invalid. ",
|
||||
Name, c.update);
|
||||
}
|
||||
fprintf(outf, "Valid --update options are:\n"
|
||||
" 'sparc2.2', 'super-minor', 'uuid', 'name', 'nodes', 'resync',\n"
|
||||
" 'summaries', 'homehost', 'home-cluster', 'byteorder', 'devicesize',\n"
|
||||
" 'bitmap', 'no-bitmap', 'metadata', 'revert-reshape'\n"
|
||||
" 'bbl', 'no-bbl', 'force-no-bbl', 'ppl', 'no-ppl'\n"
|
||||
" 'layout-original', 'layout-alternate', 'layout-unspecified'\n"
|
||||
);
|
||||
exit(outf == stdout ? 0 : 2);
|
||||
|
||||
continue;
|
||||
}
|
||||
case O(MANAGE,'U'):
|
||||
/* update=devicesize is allowed with --re-add */
|
||||
if (devmode != 'A') {
|
||||
|
@ -837,14 +775,14 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
if (c.update) {
|
||||
pr_err("Can only update one aspect of superblock, both %s and %s given.\n",
|
||||
c.update, optarg);
|
||||
map_num(update_options, c.update), optarg);
|
||||
exit(2);
|
||||
}
|
||||
c.update = optarg;
|
||||
if (strcmp(c.update, "devicesize") != 0 &&
|
||||
strcmp(c.update, "bbl") != 0 &&
|
||||
strcmp(c.update, "force-no-bbl") != 0 &&
|
||||
strcmp(c.update, "no-bbl") != 0) {
|
||||
c.update = map_name(update_options, optarg);
|
||||
if (c.update != UOPT_DEVICESIZE &&
|
||||
c.update != UOPT_BBL &&
|
||||
c.update != UOPT_NO_BBL &&
|
||||
c.update != UOPT_FORCE_NO_BBL) {
|
||||
pr_err("only 'devicesize', 'bbl', 'no-bbl', and 'force-no-bbl' can be updated with --re-add\n");
|
||||
exit(2);
|
||||
}
|
||||
|
@ -1200,8 +1138,9 @@ int main(int argc, char *argv[])
|
|||
case O(BUILD, WriteBehind):
|
||||
case O(CREATE, WriteBehind):
|
||||
s.write_behind = DEFAULT_MAX_WRITE_BEHIND;
|
||||
if (parse_num(&s.write_behind, optarg) != 0 ||
|
||||
s.write_behind < 0 || s.write_behind > 16383) {
|
||||
if (optarg &&
|
||||
(parse_num(&s.write_behind, optarg) != 0 ||
|
||||
s.write_behind < 0 || s.write_behind > 16383)) {
|
||||
pr_err("Invalid value for maximum outstanding write-behind writes: %s.\n\tMust be between 0 and 16383.\n",
|
||||
optarg);
|
||||
exit(2);
|
||||
|
@ -1248,10 +1187,10 @@ int main(int argc, char *argv[])
|
|||
if (option_index > 0)
|
||||
pr_err(":option --%s not valid in %s mode\n",
|
||||
long_options[option_index].name,
|
||||
map_num(modes, mode));
|
||||
map_num_s(modes, mode));
|
||||
else
|
||||
pr_err("option -%c not valid in %s mode\n",
|
||||
opt, map_num(modes, mode));
|
||||
opt, map_num_s(modes, mode));
|
||||
exit(2);
|
||||
|
||||
}
|
||||
|
@ -1276,7 +1215,7 @@ int main(int argc, char *argv[])
|
|||
if (s.consistency_policy != CONSISTENCY_POLICY_UNKNOWN &&
|
||||
s.consistency_policy != CONSISTENCY_POLICY_JOURNAL) {
|
||||
pr_err("--write-journal is not supported with consistency policy: %s\n",
|
||||
map_num(consistency_policies, s.consistency_policy));
|
||||
map_num_s(consistency_policies, s.consistency_policy));
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
@ -1285,12 +1224,12 @@ int main(int argc, char *argv[])
|
|||
s.consistency_policy != CONSISTENCY_POLICY_UNKNOWN) {
|
||||
if (s.level <= 0) {
|
||||
pr_err("--consistency-policy not meaningful with level %s.\n",
|
||||
map_num(pers, s.level));
|
||||
map_num_s(pers, s.level));
|
||||
exit(2);
|
||||
} else if (s.consistency_policy == CONSISTENCY_POLICY_JOURNAL &&
|
||||
!s.journaldisks) {
|
||||
pr_err("--write-journal is required for consistency policy: %s\n",
|
||||
map_num(consistency_policies, s.consistency_policy));
|
||||
map_num_s(consistency_policies, s.consistency_policy));
|
||||
exit(2);
|
||||
} else if (s.consistency_policy == CONSISTENCY_POLICY_PPL &&
|
||||
s.level != 5) {
|
||||
|
@ -1300,14 +1239,14 @@ int main(int argc, char *argv[])
|
|||
(!s.bitmap_file ||
|
||||
strcmp(s.bitmap_file, "none") == 0)) {
|
||||
pr_err("--bitmap is required for consistency policy: %s\n",
|
||||
map_num(consistency_policies, s.consistency_policy));
|
||||
map_num_s(consistency_policies, s.consistency_policy));
|
||||
exit(2);
|
||||
} else if (s.bitmap_file &&
|
||||
strcmp(s.bitmap_file, "none") != 0 &&
|
||||
s.consistency_policy != CONSISTENCY_POLICY_BITMAP &&
|
||||
s.consistency_policy != CONSISTENCY_POLICY_JOURNAL) {
|
||||
pr_err("--bitmap is not compatible with consistency policy: %s\n",
|
||||
map_num(consistency_policies, s.consistency_policy));
|
||||
map_num_s(consistency_policies, s.consistency_policy));
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
@ -1323,18 +1262,6 @@ int main(int argc, char *argv[])
|
|||
exit(2);
|
||||
}
|
||||
|
||||
if (symlinks) {
|
||||
struct createinfo *ci = conf_get_create_info();
|
||||
|
||||
if (strcasecmp(symlinks, "yes") == 0)
|
||||
ci->symlinks = 1;
|
||||
else if (strcasecmp(symlinks, "no") == 0)
|
||||
ci->symlinks = 0;
|
||||
else {
|
||||
pr_err("option --symlinks must be 'no' or 'yes'\n");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
/* Ok, got the option parsing out of the way
|
||||
* hopefully it's mostly right but there might be some stuff
|
||||
* missing
|
||||
|
@ -1347,6 +1274,9 @@ int main(int argc, char *argv[])
|
|||
|
||||
if (mode == MANAGE || mode == BUILD || mode == CREATE ||
|
||||
mode == GROW || (mode == ASSEMBLE && ! c.scan)) {
|
||||
struct stat stb;
|
||||
int ret;
|
||||
|
||||
if (devs_found < 1) {
|
||||
pr_err("an md device must be given in this mode\n");
|
||||
exit(2);
|
||||
|
@ -1359,6 +1289,12 @@ int main(int argc, char *argv[])
|
|||
mdfd = open_mddev(devlist->devname, 1);
|
||||
if (mdfd < 0)
|
||||
exit(1);
|
||||
|
||||
ret = fstat(mdfd, &stb);
|
||||
if (ret) {
|
||||
pr_err("fstat failed on %s.\n", devlist->devname);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
char *bname = basename(devlist->devname);
|
||||
|
||||
|
@ -1366,30 +1302,21 @@ int main(int argc, char *argv[])
|
|||
pr_err("Name %s is too long.\n", devlist->devname);
|
||||
exit(1);
|
||||
}
|
||||
/* non-existent device is OK */
|
||||
mdfd = open_mddev(devlist->devname, 0);
|
||||
}
|
||||
if (mdfd == -2) {
|
||||
pr_err("device %s exists but is not an md array.\n", devlist->devname);
|
||||
exit(1);
|
||||
}
|
||||
if ((int)ident.super_minor == -2) {
|
||||
struct stat stb;
|
||||
if (mdfd < 0) {
|
||||
|
||||
ret = stat(devlist->devname, &stb);
|
||||
if (ident.super_minor == -2 && ret != 0) {
|
||||
pr_err("--super-minor=dev given, and listed device %s doesn't exist.\n",
|
||||
devlist->devname);
|
||||
devlist->devname);
|
||||
exit(1);
|
||||
}
|
||||
fstat(mdfd, &stb);
|
||||
|
||||
if (!ret && !stat_is_md_dev(&stb)) {
|
||||
pr_err("device %s exists but is not an md array.\n", devlist->devname);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (ident.super_minor == -2)
|
||||
ident.super_minor = minor(stb.st_rdev);
|
||||
}
|
||||
if (mdfd >= 0 && mode != MANAGE && mode != GROW) {
|
||||
/* We don't really want this open yet, we just might
|
||||
* have wanted to check some things
|
||||
*/
|
||||
close(mdfd);
|
||||
mdfd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (s.raiddisks) {
|
||||
|
@ -1429,12 +1356,12 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
if (c.update && strcmp(c.update, "nodes") == 0 && c.nodes == 0) {
|
||||
if (c.update && c.update == UOPT_NODES && c.nodes == 0) {
|
||||
pr_err("Please specify nodes number with --nodes\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (c.backup_file && data_offset != INVALID_SECTORS) {
|
||||
if (c.backup_file && s.data_offset != INVALID_SECTORS) {
|
||||
pr_err("--backup-file and --data-offset are incompatible\n");
|
||||
exit(2);
|
||||
}
|
||||
|
@ -1474,10 +1401,10 @@ int main(int argc, char *argv[])
|
|||
/* readonly, add/remove, readwrite, runstop */
|
||||
if (c.readonly > 0)
|
||||
rv = Manage_ro(devlist->devname, mdfd, c.readonly);
|
||||
if (!rv && devs_found>1)
|
||||
if (!rv && devs_found > 1)
|
||||
rv = Manage_subdevs(devlist->devname, mdfd,
|
||||
devlist->next, c.verbose, c.test,
|
||||
c.update, c.force);
|
||||
devlist->next, c.verbose,
|
||||
c.test, c.update, c.force);
|
||||
if (!rv && c.readonly < 0)
|
||||
rv = Manage_ro(devlist->devname, mdfd, c.readonly);
|
||||
if (!rv && c.runstop > 0)
|
||||
|
@ -1605,8 +1532,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
rv = Create(ss, devlist->devname,
|
||||
ident.name, ident.uuid_set ? ident.uuid : NULL,
|
||||
devs_found-1, devlist->next,
|
||||
&s, &c, data_offset);
|
||||
devs_found - 1, devlist->next, &s, &c);
|
||||
break;
|
||||
case MISC:
|
||||
if (devmode == 'E') {
|
||||
|
@ -1724,10 +1650,9 @@ int main(int argc, char *argv[])
|
|||
c.verbose);
|
||||
else if (s.size > 0 || s.raiddisks || s.layout_str ||
|
||||
s.chunk != 0 || s.level != UnSet ||
|
||||
data_offset != INVALID_SECTORS) {
|
||||
s.data_offset != INVALID_SECTORS) {
|
||||
rv = Grow_reshape(devlist->devname, mdfd,
|
||||
devlist->next,
|
||||
data_offset, &c, &s);
|
||||
devlist->next, &c, &s);
|
||||
} else if (s.consistency_policy != CONSISTENCY_POLICY_UNKNOWN) {
|
||||
rv = Grow_consistency_policy(devlist->devname, mdfd, &c, &s);
|
||||
} else if (array_size == 0)
|
||||
|
@ -1999,7 +1924,7 @@ static int misc_list(struct mddev_dev *devlist,
|
|||
rv |= Kill_subarray(dv->devname, c->subarray, c->verbose);
|
||||
continue;
|
||||
case UpdateSubarray:
|
||||
if (c->update == NULL) {
|
||||
if (!c->update) {
|
||||
pr_err("-U/--update must be specified with --update-subarray\n");
|
||||
rv |= 1;
|
||||
continue;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
.SH NAME
|
||||
mdadm.conf \- configuration for management of Software RAID with mdadm
|
||||
.SH SYNOPSIS
|
||||
/etc/mdadm.conf
|
||||
{CONFFILE}
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
.I mdadm
|
||||
|
@ -88,7 +88,8 @@ but only the major and minor device numbers. It scans
|
|||
.I /dev
|
||||
to find the name that matches the numbers.
|
||||
|
||||
If no DEVICE line is present, then "DEVICE partitions containers" is assumed.
|
||||
If no DEVICE line is present in any config file,
|
||||
then "DEVICE partitions containers" is assumed.
|
||||
|
||||
For example:
|
||||
.IP
|
||||
|
@ -272,6 +273,10 @@ catenated with spaces to form the address.
|
|||
Note that this value cannot be set via the
|
||||
.I mdadm
|
||||
commandline. It is only settable via the config file.
|
||||
There should only be one
|
||||
.B MAILADDR
|
||||
line and it should have only one address. Any subsequent addresses
|
||||
are silently ignored.
|
||||
|
||||
.TP
|
||||
.B PROGRAM
|
||||
|
@ -286,7 +291,8 @@ device.
|
|||
|
||||
There should only be one
|
||||
.B program
|
||||
line and it should be give only one program.
|
||||
line and it should be given only one program. Any subsequent programs
|
||||
are silently ignored.
|
||||
|
||||
|
||||
.TP
|
||||
|
@ -295,7 +301,14 @@ The
|
|||
.B create
|
||||
line gives default values to be used when creating arrays, new members
|
||||
of arrays, and device entries for arrays.
|
||||
These include:
|
||||
|
||||
There should only be one
|
||||
.B create
|
||||
line. Any subsequent lines will override the previous settings.
|
||||
|
||||
Keywords used in the
|
||||
.I CREATE
|
||||
line and supported values are:
|
||||
|
||||
.RS 4
|
||||
.TP
|
||||
|
@ -325,21 +338,6 @@ missing device entries should be created.
|
|||
The name of the metadata format to use if none is explicitly given.
|
||||
This can be useful to impose a system-wide default of version-1 superblocks.
|
||||
|
||||
.TP
|
||||
.B symlinks=no
|
||||
Normally when creating devices in
|
||||
.B /dev/md/
|
||||
.I mdadm
|
||||
will create a matching symlink from
|
||||
.B /dev/
|
||||
with a name starting
|
||||
.B md
|
||||
or
|
||||
.BR md_ .
|
||||
Give
|
||||
.B symlinks=no
|
||||
to suppress this symlink creation.
|
||||
|
||||
.TP
|
||||
.B names=yes
|
||||
Since Linux 2.6.29 it has been possible to create
|
||||
|
@ -426,6 +424,23 @@ from any possible local name. e.g.
|
|||
.B /dev/md/1_1
|
||||
or
|
||||
.BR /dev/md/home_0 .
|
||||
|
||||
.TP
|
||||
.B HOMECLUSTER
|
||||
The
|
||||
.B homcluster
|
||||
line gives a default value for the
|
||||
.B \-\-homecluster=
|
||||
option to mdadm. It specifies the cluster name for the md device.
|
||||
The md device can be assembled only on the cluster which matches
|
||||
the name specified. If
|
||||
.B homcluster
|
||||
is not provided, mdadm tries to detect the cluster name automatically.
|
||||
|
||||
There should only be one
|
||||
.B homecluster
|
||||
line. Any subsequent lines will be silently ignored.
|
||||
|
||||
.TP
|
||||
.B AUTO
|
||||
A list of names of metadata format can be given, each preceded by a
|
||||
|
@ -475,8 +490,8 @@ The known metadata types are
|
|||
|
||||
.B AUTO
|
||||
should be given at most once. Subsequent lines are silently ignored.
|
||||
Thus an earlier config file in a config directory will over-ride
|
||||
the setting in a later config file.
|
||||
Thus a later config file in a config directory will not overwrite
|
||||
the setting in an earlier config file.
|
||||
|
||||
.TP
|
||||
.B POLICY
|
||||
|
@ -594,6 +609,7 @@ The
|
|||
line lists custom values of MD device's sysfs attributes which will be
|
||||
stored in sysfs after the array is assembled. Multiple lines are allowed and each
|
||||
line has to contain the uuid or the name of the device to which it relates.
|
||||
Lines are applied in reverse order.
|
||||
.RS 4
|
||||
.TP
|
||||
.B uuid=
|
||||
|
@ -621,7 +637,46 @@ is running in
|
|||
.B \-\-monitor
|
||||
mode.
|
||||
.B \-d/\-\-delay
|
||||
command line argument takes precedence over the config file
|
||||
command line argument takes precedence over the config file.
|
||||
|
||||
If multiple
|
||||
.B MINITORDELAY
|
||||
lines are provided, only first non-zero value is considered.
|
||||
|
||||
.SH FILES
|
||||
|
||||
.SS {CONFFILE}
|
||||
|
||||
The default config file location, used when
|
||||
.I mdadm
|
||||
is running without --config option.
|
||||
|
||||
.SS {CONFFILE}.d
|
||||
|
||||
The default directory with config files. Used when
|
||||
.I mdadm
|
||||
is running without --config option, after successful reading of the
|
||||
.B {CONFFILE}
|
||||
default config file. Files in that directory
|
||||
are read in lexical order.
|
||||
|
||||
|
||||
.SS {CONFFILE2}
|
||||
|
||||
Alternative config file that is read, when
|
||||
.I mdadm
|
||||
is running without --config option and the
|
||||
.B {CONFFILE}
|
||||
default config file was not opened successfully.
|
||||
|
||||
.SS {CONFFILE2}.d
|
||||
|
||||
The alternative directory with config files. Used when
|
||||
.I mdadm
|
||||
is runninng without --config option, after reading the
|
||||
.B {CONFFILE2}
|
||||
alternative config file whether it was successful or not. Files in
|
||||
that directory are read in lexical order.
|
||||
|
||||
.SH EXAMPLE
|
||||
DEVICE /dev/sd[bcdjkl]1
|
137
mdadm.h
137
mdadm.h
|
@ -33,8 +33,10 @@ extern __off64_t lseek64 __P ((int __fd, __off64_t __offset, int __whence));
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
@ -46,6 +48,7 @@ extern __off64_t lseek64 __P ((int __fd, __off64_t __offset, int __whence));
|
|||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <stdbool.h>
|
||||
#include <signal.h>
|
||||
/* Newer glibc requires sys/sysmacros.h directly for makedev() */
|
||||
#include <sys/sysmacros.h>
|
||||
#ifdef __dietlibc__
|
||||
|
@ -393,7 +396,6 @@ struct createinfo {
|
|||
int gid;
|
||||
int autof;
|
||||
int mode;
|
||||
int symlinks;
|
||||
int names;
|
||||
int bblist;
|
||||
struct supertype *supertype;
|
||||
|
@ -418,6 +420,7 @@ enum mode {
|
|||
};
|
||||
|
||||
extern char short_options[];
|
||||
extern char short_monitor_options[];
|
||||
extern char short_bitmap_options[];
|
||||
extern char short_bitmap_auto_options[];
|
||||
extern struct option long_options[];
|
||||
|
@ -440,7 +443,6 @@ enum special_options {
|
|||
BackupFile,
|
||||
HomeHost,
|
||||
AutoHomeHost,
|
||||
Symlinks,
|
||||
AutoDetect,
|
||||
Waitclean,
|
||||
DetailPlatform,
|
||||
|
@ -495,6 +497,51 @@ enum special_options {
|
|||
ConsistencyPolicy,
|
||||
};
|
||||
|
||||
enum update_opt {
|
||||
UOPT_NAME = 1,
|
||||
UOPT_PPL,
|
||||
UOPT_NO_PPL,
|
||||
UOPT_BITMAP,
|
||||
UOPT_NO_BITMAP,
|
||||
UOPT_SUBARRAY_ONLY,
|
||||
UOPT_SPARC22,
|
||||
UOPT_SUPER_MINOR,
|
||||
UOPT_SUMMARIES,
|
||||
UOPT_RESYNC,
|
||||
UOPT_UUID,
|
||||
UOPT_HOMEHOST,
|
||||
UOPT_HOME_CLUSTER,
|
||||
UOPT_NODES,
|
||||
UOPT_DEVICESIZE,
|
||||
UOPT_BBL,
|
||||
UOPT_NO_BBL,
|
||||
UOPT_FORCE_NO_BBL,
|
||||
UOPT_METADATA,
|
||||
UOPT_REVERT_RESHAPE,
|
||||
UOPT_LAYOUT_ORIGINAL,
|
||||
UOPT_LAYOUT_ALTERNATE,
|
||||
UOPT_LAYOUT_UNSPECIFIED,
|
||||
UOPT_BYTEORDER,
|
||||
UOPT_HELP,
|
||||
UOPT_USER_ONLY,
|
||||
/*
|
||||
* Code specific options, cannot be set by the user
|
||||
*/
|
||||
UOPT_SPEC_FORCE_ONE,
|
||||
UOPT_SPEC_FORCE_ARRAY,
|
||||
UOPT_SPEC_ASSEMBLE,
|
||||
UOPT_SPEC_LINEAR_GROW_NEW,
|
||||
UOPT_SPEC_LINEAR_GROW_UPDATE,
|
||||
UOPT_SPEC__RESHAPE_PROGRESS,
|
||||
UOPT_SPEC_WRITEMOSTLY,
|
||||
UOPT_SPEC_READWRITE,
|
||||
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);
|
||||
|
||||
enum prefix_standard {
|
||||
JEDEC,
|
||||
IEC
|
||||
|
@ -569,7 +616,7 @@ struct context {
|
|||
int export;
|
||||
int test;
|
||||
char *subarray;
|
||||
char *update;
|
||||
enum update_opt update;
|
||||
int scan;
|
||||
int SparcAdjust;
|
||||
int autof;
|
||||
|
@ -595,6 +642,7 @@ struct shape {
|
|||
int assume_clean;
|
||||
int write_behind;
|
||||
unsigned long long size;
|
||||
unsigned long long data_offset;
|
||||
int consistency_policy;
|
||||
};
|
||||
|
||||
|
@ -769,12 +817,12 @@ extern int restore_stripes(int *dest, unsigned long long *offsets,
|
|||
#endif
|
||||
|
||||
#define SYSLOG_FACILITY LOG_DAEMON
|
||||
|
||||
extern char *map_num_s(mapping_t *map, int num);
|
||||
extern char *map_num(mapping_t *map, int num);
|
||||
extern int map_name(mapping_t *map, char *name);
|
||||
extern mapping_t r0layout[], r5layout[], r6layout[],
|
||||
pers[], modes[], faultylayout[];
|
||||
extern mapping_t consistency_policies[], sysfs_array_states[];
|
||||
extern mapping_t consistency_policies[], sysfs_array_states[], update_options[];
|
||||
|
||||
extern char *map_dev_preferred(int major, int minor, int create,
|
||||
char *prefer);
|
||||
|
@ -795,6 +843,17 @@ static inline int is_fd_valid(int fd)
|
|||
return (fd > -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* is_level456() - check whether given level is between inclusive 4 and 6.
|
||||
* @level: level to check.
|
||||
*
|
||||
* Return: true if condition is met, false otherwise
|
||||
*/
|
||||
static inline bool is_level456(int level)
|
||||
{
|
||||
return (level >= 4 && level <= 6);
|
||||
}
|
||||
|
||||
/**
|
||||
* close_fd() - verify, close and unset file descriptor.
|
||||
* @fd: pointer to file descriptor.
|
||||
|
@ -952,7 +1011,7 @@ extern struct superswitch {
|
|||
* it will resume going in the opposite direction.
|
||||
*/
|
||||
int (*update_super)(struct supertype *st, struct mdinfo *info,
|
||||
char *update,
|
||||
enum update_opt update,
|
||||
char *devname, int verbose,
|
||||
int uuid_set, char *homehost);
|
||||
|
||||
|
@ -1078,9 +1137,15 @@ extern struct superswitch {
|
|||
/* Permit subarray's to be deleted from inactive containers */
|
||||
int (*kill_subarray)(struct supertype *st,
|
||||
char *subarray_id); /* optional */
|
||||
/* Permit subarray's to be modified */
|
||||
/**
|
||||
* update_subarray() - Permit subarray to be modified.
|
||||
* @st: Supertype.
|
||||
* @subarray: Subarray name.
|
||||
* @update: Update option.
|
||||
* @ident: Optional identifiers.
|
||||
*/
|
||||
int (*update_subarray)(struct supertype *st, char *subarray,
|
||||
char *update, struct mddev_ident *ident); /* optional */
|
||||
enum update_opt update, struct mddev_ident *ident);
|
||||
/* Check if reshape is supported for this external format.
|
||||
* st is obtained from super_by_fd() where st->subarray[0] is
|
||||
* initialized to indicate if reshape is being performed at the
|
||||
|
@ -1413,14 +1478,13 @@ extern int Manage_stop(char *devname, int fd, int quiet,
|
|||
int will_retry);
|
||||
extern int Manage_subdevs(char *devname, int fd,
|
||||
struct mddev_dev *devlist, int verbose, int test,
|
||||
char *update, int force);
|
||||
enum update_opt update, int force);
|
||||
extern int autodetect(void);
|
||||
extern int Grow_Add_device(char *devname, int fd, char *newdev);
|
||||
extern int Grow_addbitmap(char *devname, int fd,
|
||||
struct context *c, struct shape *s);
|
||||
extern int Grow_reshape(char *devname, int fd,
|
||||
struct mddev_dev *devlist,
|
||||
unsigned long long data_offset,
|
||||
struct context *c, struct shape *s);
|
||||
extern int Grow_restart(struct supertype *st, struct mdinfo *info,
|
||||
int *fdlist, int cnt, char *backup_file, int verbose);
|
||||
|
@ -1451,8 +1515,7 @@ extern int Create(struct supertype *st, char *mddev,
|
|||
char *name, int *uuid,
|
||||
int subdevs, struct mddev_dev *devlist,
|
||||
struct shape *s,
|
||||
struct context *c,
|
||||
unsigned long long data_offset);
|
||||
struct context *c);
|
||||
|
||||
extern int Detail(char *dev, struct context *c);
|
||||
extern int Detail_Platform(struct superswitch *ss, int scan, int verbose, int export, char *controller_path);
|
||||
|
@ -1469,7 +1532,7 @@ extern int Monitor(struct mddev_dev *devlist,
|
|||
|
||||
extern int Kill(char *dev, struct supertype *st, int force, int verbose, int noexcl);
|
||||
extern int Kill_subarray(char *dev, char *subarray, int verbose);
|
||||
extern int Update_subarray(char *dev, char *subarray, char *update, struct mddev_ident *ident, int quiet);
|
||||
extern int Update_subarray(char *dev, char *subarray, enum update_opt update, struct mddev_ident *ident, int quiet);
|
||||
extern int Wait(char *dev);
|
||||
extern int WaitClean(char *dev, int verbose);
|
||||
extern int SetAction(char *dev, char *action);
|
||||
|
@ -1511,6 +1574,7 @@ extern int get_linux_version(void);
|
|||
extern int mdadm_version(char *version);
|
||||
extern unsigned long long parse_size(char *size);
|
||||
extern int parse_uuid(char *str, int uuid[4]);
|
||||
int default_layout(struct supertype *st, int level, int verbose);
|
||||
extern int is_near_layout_10(int layout);
|
||||
extern int parse_layout_10(char *layout);
|
||||
extern int parse_layout_faulty(char *layout);
|
||||
|
@ -1528,6 +1592,7 @@ extern int stat_is_blkdev(char *devname, dev_t *rdev);
|
|||
extern bool is_dev_alive(char *path);
|
||||
extern int get_mdp_major(void);
|
||||
extern int get_maj_min(char *dev, int *major, int *minor);
|
||||
extern bool is_bit_set(int *val, unsigned char index);
|
||||
extern int dev_open(char *dev, int flags);
|
||||
extern int open_dev(char *devnm);
|
||||
extern void reopen_mddev(int mdfd);
|
||||
|
@ -1540,6 +1605,8 @@ extern void enable_fds(int devices);
|
|||
extern void manage_fork_fds(int close_all);
|
||||
extern int continue_via_systemd(char *devnm, char *service_name);
|
||||
|
||||
extern void ident_init(struct mddev_ident *ident);
|
||||
|
||||
extern int parse_auto(char *str, char *msg, int config);
|
||||
extern struct mddev_ident *conf_get_ident(char *dev);
|
||||
extern struct mddev_dev *conf_get_devs(void);
|
||||
|
@ -1634,6 +1701,7 @@ extern int create_mddev(char *dev, char *name, int autof, int trustworthy,
|
|||
#define FOREIGN 2
|
||||
#define METADATA 3
|
||||
extern int open_mddev(char *dev, int report_errors);
|
||||
extern int is_mddev(char *dev);
|
||||
extern int open_container(int fd);
|
||||
extern int metadata_container_matches(char *metadata, char *devnm);
|
||||
extern int metadata_subdev_matches(char *metadata, char *devnm);
|
||||
|
@ -1660,6 +1728,7 @@ void *super1_make_v0(struct supertype *st, struct mdinfo *info, mdp_super_t *sb0
|
|||
extern char *stat2kname(struct stat *st);
|
||||
extern char *fd2kname(int fd);
|
||||
extern char *stat2devnm(struct stat *st);
|
||||
bool stat_is_md_dev(struct stat *st);
|
||||
extern char *fd2devnm(int fd);
|
||||
extern void udev_block(char *devnm);
|
||||
extern void udev_unblock(void);
|
||||
|
@ -1705,6 +1774,10 @@ extern int cluster_get_dlmlock(void);
|
|||
extern int cluster_release_dlmlock(void);
|
||||
extern void set_dlm_hooks(void);
|
||||
|
||||
#define MSEC_TO_NSEC(msec) ((msec) * 1000000)
|
||||
#define USEC_TO_NSEC(usec) ((usec) * 1000)
|
||||
extern void sleep_for(unsigned int sec, long nsec, bool wake_after_interrupt);
|
||||
|
||||
#define _ROUND_UP(val, base) (((val) + (base) - 1) & ~(base - 1))
|
||||
#define ROUND_UP(val, base) _ROUND_UP(val, (typeof(val))(base))
|
||||
#define ROUND_UP_PTR(ptr, base) ((typeof(ptr)) \
|
||||
|
@ -1729,6 +1802,27 @@ static inline char *to_subarray(struct mdstat_ent *ent, char *container)
|
|||
return &ent->metadata_version[10+strlen(container)+1];
|
||||
}
|
||||
|
||||
/**
|
||||
* signal_s() - Wrapper for sigaction() with signal()-like interface.
|
||||
* @sig: The signal to set the signal handler to.
|
||||
* @handler: The signal handler.
|
||||
*
|
||||
* Return: previous handler or SIG_ERR on failure.
|
||||
*/
|
||||
static inline sighandler_t signal_s(int sig, sighandler_t handler)
|
||||
{
|
||||
struct sigaction new_act;
|
||||
struct sigaction old_act;
|
||||
|
||||
new_act.sa_handler = handler;
|
||||
new_act.sa_flags = 0;
|
||||
|
||||
if (sigaction(sig, &new_act, &old_act) == 0)
|
||||
return old_act.sa_handler;
|
||||
|
||||
return SIG_ERR;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
#define dprintf(fmt, arg...) \
|
||||
fprintf(stderr, "%s: %s: "fmt, Name, __func__, ##arg)
|
||||
|
@ -1740,8 +1834,7 @@ static inline char *to_subarray(struct mdstat_ent *ent, char *container)
|
|||
#define dprintf_cont(fmt, arg...) \
|
||||
({ if (0) fprintf(stderr, fmt, ##arg); 0; })
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
static inline int xasprintf(char **strp, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
@ -1885,3 +1978,17 @@ enum r0layout {
|
|||
* This is true for native and DDF, IMSM allows 16.
|
||||
*/
|
||||
#define MD_NAME_MAX 32
|
||||
|
||||
/**
|
||||
* is_container() - check if @level is &LEVEL_CONTAINER
|
||||
* @level: level value
|
||||
*
|
||||
* return:
|
||||
* 1 if level is equal to &LEVEL_CONTAINER, 0 otherwise.
|
||||
*/
|
||||
static inline int is_container(const int level)
|
||||
{
|
||||
if (level == LEVEL_CONTAINER)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
99
mdmon.c
99
mdmon.c
|
@ -56,7 +56,6 @@
|
|||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <dirent.h>
|
||||
#ifdef USE_PTHREADS
|
||||
#include <pthread.h>
|
||||
|
@ -100,7 +99,7 @@ static int clone_monitor(struct supertype *container)
|
|||
if (rc)
|
||||
return rc;
|
||||
while (mon_tid == -1)
|
||||
usleep(10);
|
||||
sleep_for(0, USEC_TO_NSEC(10), true);
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
mgr_tid = syscall(SYS_gettid);
|
||||
|
@ -210,7 +209,7 @@ static void try_kill_monitor(pid_t pid, char *devname, int sock)
|
|||
rv = kill(pid, SIGUSR1);
|
||||
if (rv < 0)
|
||||
break;
|
||||
usleep(200000);
|
||||
sleep_for(0, MSEC_TO_NSEC(200), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -289,6 +288,15 @@ void usage(void)
|
|||
exit(2);
|
||||
}
|
||||
|
||||
static bool is_duplicate_opt(const int opt, const int set_val, const char *long_name)
|
||||
{
|
||||
if (opt == set_val) {
|
||||
pr_err("--%s option duplicated!\n", long_name);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int mdmon(char *devnm, int must_fork, int takeover);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
@ -300,6 +308,7 @@ int main(int argc, char *argv[])
|
|||
int all = 0;
|
||||
int takeover = 0;
|
||||
int dofork = 1;
|
||||
bool help = false;
|
||||
static struct option options[] = {
|
||||
{"all", 0, NULL, 'a'},
|
||||
{"takeover", 0, NULL, 't'},
|
||||
|
@ -309,6 +318,41 @@ int main(int argc, char *argv[])
|
|||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "thaF", options, NULL)) != -1) {
|
||||
switch (opt) {
|
||||
case 'a':
|
||||
if (is_duplicate_opt(all, 1, "all"))
|
||||
exit(1);
|
||||
container_name = argv[optind-1];
|
||||
all = 1;
|
||||
break;
|
||||
case 't':
|
||||
if (is_duplicate_opt(takeover, 1, "takeover"))
|
||||
exit(1);
|
||||
takeover = 1;
|
||||
break;
|
||||
case 'F':
|
||||
if (is_duplicate_opt(dofork, 0, "foreground"))
|
||||
exit(1);
|
||||
dofork = 0;
|
||||
break;
|
||||
case OffRootOpt:
|
||||
if (is_duplicate_opt(argv[0][0], '@', "offroot"))
|
||||
exit(1);
|
||||
argv[0][0] = '@';
|
||||
break;
|
||||
case 'h':
|
||||
if (is_duplicate_opt(help, true, "help"))
|
||||
exit(1);
|
||||
help = true;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (in_initrd()) {
|
||||
/*
|
||||
* set first char of argv[0] to @. This is used by
|
||||
|
@ -318,42 +362,23 @@ int main(int argc, char *argv[])
|
|||
argv[0][0] = '@';
|
||||
}
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "thaF", options, NULL)) != -1) {
|
||||
switch (opt) {
|
||||
case 'a':
|
||||
container_name = argv[optind-1];
|
||||
all = 1;
|
||||
break;
|
||||
case 't':
|
||||
takeover = 1;
|
||||
break;
|
||||
case 'F':
|
||||
dofork = 0;
|
||||
break;
|
||||
case OffRootOpt:
|
||||
argv[0][0] = '@';
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
usage();
|
||||
break;
|
||||
if (all == 0 && container_name == NULL) {
|
||||
if (argv[optind]) {
|
||||
container_name = get_md_name(argv[optind]);
|
||||
if (!container_name)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (all == 0 && container_name == NULL) {
|
||||
if (argv[optind])
|
||||
container_name = argv[optind];
|
||||
}
|
||||
|
||||
if (container_name == NULL)
|
||||
usage();
|
||||
|
||||
if (argc - optind > 1)
|
||||
if (container_name == NULL || argc - optind > 1)
|
||||
usage();
|
||||
|
||||
if (strcmp(container_name, "/proc/mdstat") == 0)
|
||||
all = 1;
|
||||
|
||||
if (help)
|
||||
usage();
|
||||
|
||||
if (all) {
|
||||
struct mdstat_ent *mdstat, *e;
|
||||
int container_len = strlen(container_name);
|
||||
|
@ -377,21 +402,17 @@ int main(int argc, char *argv[])
|
|||
free_mdstat(mdstat);
|
||||
|
||||
return status;
|
||||
} else if (strncmp(container_name, "md", 2) == 0) {
|
||||
int id = devnm2devid(container_name);
|
||||
if (id)
|
||||
devnm = container_name;
|
||||
} else {
|
||||
struct stat st;
|
||||
int mdfd = open_mddev(container_name, 0);
|
||||
devnm = fd2devnm(mdfd);
|
||||
|
||||
if (stat(container_name, &st) == 0)
|
||||
devnm = xstrdup(stat2devnm(&st));
|
||||
close(mdfd);
|
||||
}
|
||||
|
||||
if (!devnm) {
|
||||
pr_err("%s is not a valid md device name\n",
|
||||
container_name);
|
||||
exit(1);
|
||||
return 1;
|
||||
}
|
||||
return mdmon(devnm, dofork && do_fork(), takeover);
|
||||
}
|
||||
|
|
17
mdopen.c
17
mdopen.c
|
@ -475,6 +475,23 @@ int open_mddev(char *dev, int report_errors)
|
|||
return mdfd;
|
||||
}
|
||||
|
||||
/**
|
||||
* is_mddev() - check that file name passed is an md device.
|
||||
* @dev: file name that has to be checked.
|
||||
* Return: 1 if file passed is an md device, 0 if not.
|
||||
*/
|
||||
int is_mddev(char *dev)
|
||||
{
|
||||
int fd = open_mddev(dev, 1);
|
||||
|
||||
if (fd >= 0) {
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *find_free_devnm(int use_partitions)
|
||||
{
|
||||
static char devnm[32];
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "mdmon.h"
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/select.h>
|
||||
#include <signal.h>
|
||||
|
||||
static char *array_states[] = {
|
||||
"clear", "inactive", "suspended", "readonly", "read-auto",
|
||||
|
@ -312,6 +311,9 @@ static int check_for_cleared_bb(struct active_array *a, struct mdinfo *mdi)
|
|||
struct md_bb *bb;
|
||||
int i;
|
||||
|
||||
if (!ss->get_bad_blocks)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Get a list of bad blocks for an array, then read list of
|
||||
* acknowledged bad blocks from kernel and compare it against metadata
|
||||
|
|
|
@ -512,7 +512,8 @@ static const struct imsm_orom *find_imsm_hba_orom(struct sys_dev *hba)
|
|||
#define AHCI_PROP "RstSataV"
|
||||
#define AHCI_SSATA_PROP "RstsSatV"
|
||||
#define AHCI_TSATA_PROP "RsttSatV"
|
||||
#define VMD_PROP "RstUefiV"
|
||||
#define VROC_VMD_PROP "RstUefiV"
|
||||
#define RST_VMD_PROP "RstVmdV"
|
||||
|
||||
#define VENDOR_GUID \
|
||||
EFI_GUID(0x193dfefa, 0xa445, 0x4302, 0x99, 0xd8, 0xef, 0x3a, 0xad, 0x1a, 0x04, 0xc6)
|
||||
|
@ -605,6 +606,7 @@ const struct imsm_orom *find_imsm_efi(struct sys_dev *hba)
|
|||
struct orom_entry *ret;
|
||||
static const char * const sata_efivars[] = {AHCI_PROP, AHCI_SSATA_PROP,
|
||||
AHCI_TSATA_PROP};
|
||||
static const char * const vmd_efivars[] = {VROC_VMD_PROP, RST_VMD_PROP};
|
||||
unsigned long i;
|
||||
|
||||
if (check_env("IMSM_TEST_AHCI_EFI") || check_env("IMSM_TEST_SCU_EFI"))
|
||||
|
@ -636,10 +638,16 @@ const struct imsm_orom *find_imsm_efi(struct sys_dev *hba)
|
|||
|
||||
break;
|
||||
case SYS_DEV_VMD:
|
||||
if (!read_efi_variable(&orom, sizeof(orom), VMD_PROP,
|
||||
VENDOR_GUID))
|
||||
break;
|
||||
return NULL;
|
||||
for (i = 0; i < ARRAY_SIZE(vmd_efivars); i++) {
|
||||
if (!read_efi_variable(&orom, sizeof(orom),
|
||||
vmd_efivars[i], VENDOR_GUID))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(vmd_efivars))
|
||||
return NULL;
|
||||
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "probe_roms.h"
|
||||
#include "mdadm.h"
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -69,7 +68,8 @@ static int probe_address16(const __u16 *ptr, __u16 *val)
|
|||
|
||||
void probe_roms_exit(void)
|
||||
{
|
||||
signal(SIGBUS, SIG_DFL);
|
||||
signal_s(SIGBUS, SIG_DFL);
|
||||
|
||||
if (rom_fd >= 0) {
|
||||
close(rom_fd);
|
||||
rom_fd = -1;
|
||||
|
@ -98,7 +98,7 @@ int probe_roms_init(unsigned long align)
|
|||
if (roms_init())
|
||||
return -1;
|
||||
|
||||
if (signal(SIGBUS, sigbus) == SIG_ERR)
|
||||
if (signal_s(SIGBUS, sigbus) == SIG_ERR)
|
||||
rc = -1;
|
||||
if (rc == 0) {
|
||||
fd = open("/dev/mem", O_RDONLY);
|
||||
|
|
25
raid6check.c
25
raid6check.c
|
@ -24,7 +24,6 @@
|
|||
|
||||
#include "mdadm.h"
|
||||
#include <stdint.h>
|
||||
#include <signal.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#define CHECK_PAGE_BITS (12)
|
||||
|
@ -130,30 +129,36 @@ void raid6_stats(int *disk, int *results, int raid_disks, int chunk_size)
|
|||
}
|
||||
|
||||
int lock_stripe(struct mdinfo *info, unsigned long long start,
|
||||
int chunk_size, int data_disks, sighandler_t *sig) {
|
||||
int chunk_size, int data_disks, sighandler_t *sig)
|
||||
{
|
||||
int rv;
|
||||
|
||||
sig[0] = signal_s(SIGTERM, SIG_IGN);
|
||||
sig[1] = signal_s(SIGINT, SIG_IGN);
|
||||
sig[2] = signal_s(SIGQUIT, SIG_IGN);
|
||||
|
||||
if (sig[0] == SIG_ERR || sig[1] == SIG_ERR || sig[2] == SIG_ERR)
|
||||
return 1;
|
||||
|
||||
if(mlockall(MCL_CURRENT | MCL_FUTURE) != 0) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
sig[0] = signal(SIGTERM, SIG_IGN);
|
||||
sig[1] = signal(SIGINT, SIG_IGN);
|
||||
sig[2] = signal(SIGQUIT, SIG_IGN);
|
||||
|
||||
rv = sysfs_set_num(info, NULL, "suspend_lo", start * chunk_size * data_disks);
|
||||
rv |= sysfs_set_num(info, NULL, "suspend_hi", (start + 1) * chunk_size * data_disks);
|
||||
return rv * 256;
|
||||
}
|
||||
|
||||
int unlock_all_stripes(struct mdinfo *info, sighandler_t *sig) {
|
||||
int unlock_all_stripes(struct mdinfo *info, sighandler_t *sig)
|
||||
{
|
||||
int rv;
|
||||
rv = sysfs_set_num(info, NULL, "suspend_lo", 0x7FFFFFFFFFFFFFFFULL);
|
||||
rv |= sysfs_set_num(info, NULL, "suspend_hi", 0);
|
||||
rv |= sysfs_set_num(info, NULL, "suspend_lo", 0);
|
||||
|
||||
signal(SIGQUIT, sig[2]);
|
||||
signal(SIGINT, sig[1]);
|
||||
signal(SIGTERM, sig[0]);
|
||||
signal_s(SIGQUIT, sig[2]);
|
||||
signal_s(SIGINT, sig[1]);
|
||||
signal_s(SIGTERM, sig[0]);
|
||||
|
||||
if(munlockall() != 0)
|
||||
return 3;
|
||||
|
|
183
super-ddf.c
183
super-ddf.c
|
@ -503,13 +503,6 @@ struct ddf_super {
|
|||
static int load_super_ddf_all(struct supertype *st, int fd,
|
||||
void **sbp, char *devname);
|
||||
static int get_svd_state(const struct ddf_super *, const struct vcl *);
|
||||
static int
|
||||
validate_geometry_ddf_container(struct supertype *st,
|
||||
int level, int layout, int raiddisks,
|
||||
int chunk, unsigned long long size,
|
||||
unsigned long long data_offset,
|
||||
char *dev, unsigned long long *freesize,
|
||||
int verbose);
|
||||
|
||||
static int validate_geometry_ddf_bvd(struct supertype *st,
|
||||
int level, int layout, int raiddisks,
|
||||
|
@ -1477,13 +1470,13 @@ static void examine_vds(struct ddf_super *sb)
|
|||
printf("\n");
|
||||
printf(" unit[%d] : %d\n", i, be16_to_cpu(ve->unit));
|
||||
printf(" state[%d] : %s, %s%s\n", i,
|
||||
map_num(ddf_state, ve->state & 7),
|
||||
map_num_s(ddf_state, ve->state & 7),
|
||||
(ve->state & DDF_state_morphing) ? "Morphing, ": "",
|
||||
(ve->state & DDF_state_inconsistent)? "Not Consistent" : "Consistent");
|
||||
printf(" init state[%d] : %s\n", i,
|
||||
map_num(ddf_init_state, ve->init_state&DDF_initstate_mask));
|
||||
map_num_s(ddf_init_state, ve->init_state & DDF_initstate_mask));
|
||||
printf(" access[%d] : %s\n", i,
|
||||
map_num(ddf_access, (ve->init_state & DDF_access_mask) >> 6));
|
||||
map_num_s(ddf_access, (ve->init_state & DDF_access_mask) >> 6));
|
||||
printf(" Name[%d] : %.16s\n", i, ve->name);
|
||||
examine_vd(i, sb, ve->guid);
|
||||
}
|
||||
|
@ -2146,75 +2139,6 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info, cha
|
|||
}
|
||||
}
|
||||
|
||||
static int update_super_ddf(struct supertype *st, struct mdinfo *info,
|
||||
char *update,
|
||||
char *devname, int verbose,
|
||||
int uuid_set, char *homehost)
|
||||
{
|
||||
/* For 'assemble' and 'force' we need to return non-zero if any
|
||||
* change was made. For others, the return value is ignored.
|
||||
* Update options are:
|
||||
* force-one : This device looks a bit old but needs to be included,
|
||||
* update age info appropriately.
|
||||
* assemble: clear any 'faulty' flag to allow this device to
|
||||
* be assembled.
|
||||
* force-array: Array is degraded but being forced, mark it clean
|
||||
* if that will be needed to assemble it.
|
||||
*
|
||||
* newdev: not used ????
|
||||
* grow: Array has gained a new device - this is currently for
|
||||
* linear only
|
||||
* resync: mark as dirty so a resync will happen.
|
||||
* uuid: Change the uuid of the array to match what is given
|
||||
* homehost: update the recorded homehost
|
||||
* name: update the name - preserving the homehost
|
||||
* _reshape_progress: record new reshape_progress position.
|
||||
*
|
||||
* Following are not relevant for this version:
|
||||
* sparc2.2 : update from old dodgey metadata
|
||||
* super-minor: change the preferred_minor number
|
||||
* summaries: update redundant counters.
|
||||
*/
|
||||
int rv = 0;
|
||||
// struct ddf_super *ddf = st->sb;
|
||||
// struct vd_config *vd = find_vdcr(ddf, info->container_member);
|
||||
// struct virtual_entry *ve = find_ve(ddf);
|
||||
|
||||
/* we don't need to handle "force-*" or "assemble" as
|
||||
* there is no need to 'trick' the kernel. When the metadata is
|
||||
* first updated to activate the array, all the implied modifications
|
||||
* will just happen.
|
||||
*/
|
||||
|
||||
if (strcmp(update, "grow") == 0) {
|
||||
/* FIXME */
|
||||
} else if (strcmp(update, "resync") == 0) {
|
||||
// info->resync_checkpoint = 0;
|
||||
} else if (strcmp(update, "homehost") == 0) {
|
||||
/* homehost is stored in controller->vendor_data,
|
||||
* or it is when we are the vendor
|
||||
*/
|
||||
// if (info->vendor_is_local)
|
||||
// strcpy(ddf->controller.vendor_data, homehost);
|
||||
rv = -1;
|
||||
} else if (strcmp(update, "name") == 0) {
|
||||
/* name is stored in virtual_entry->name */
|
||||
// memset(ve->name, ' ', 16);
|
||||
// strncpy(ve->name, info->name, 16);
|
||||
rv = -1;
|
||||
} else if (strcmp(update, "_reshape_progress") == 0) {
|
||||
/* We don't support reshape yet */
|
||||
} else if (strcmp(update, "assemble") == 0 ) {
|
||||
/* Do nothing, just succeed */
|
||||
rv = 0;
|
||||
} else
|
||||
rv = -1;
|
||||
|
||||
// update_all_csum(ddf);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void make_header_guid(char *guid)
|
||||
{
|
||||
be32 stamp;
|
||||
|
@ -3322,6 +3246,42 @@ static int reserve_space(struct supertype *st, int raiddisks,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
validate_geometry_ddf_container(struct supertype *st,
|
||||
int level, int raiddisks,
|
||||
unsigned long long data_offset,
|
||||
char *dev, unsigned long long *freesize,
|
||||
int verbose)
|
||||
{
|
||||
int fd;
|
||||
unsigned long long ldsize;
|
||||
|
||||
if (!is_container(level))
|
||||
return 0;
|
||||
if (!dev)
|
||||
return 1;
|
||||
|
||||
fd = dev_open(dev, O_RDONLY|O_EXCL);
|
||||
if (fd < 0) {
|
||||
if (verbose)
|
||||
pr_err("ddf: Cannot open %s: %s\n",
|
||||
dev, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if (!get_dev_size(fd, dev, &ldsize)) {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
close(fd);
|
||||
if (freesize) {
|
||||
*freesize = avail_size_ddf(st, ldsize >> 9, INVALID_SECTORS);
|
||||
if (*freesize == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int validate_geometry_ddf(struct supertype *st,
|
||||
int level, int layout, int raiddisks,
|
||||
int *chunk, unsigned long long size,
|
||||
|
@ -3340,20 +3300,18 @@ static int validate_geometry_ddf(struct supertype *st,
|
|||
* If given BVDs, we make an SVD, changing all the GUIDs in the process.
|
||||
*/
|
||||
|
||||
if (*chunk == UnSet)
|
||||
*chunk = DEFAULT_CHUNK;
|
||||
|
||||
if (level == LEVEL_NONE)
|
||||
level = LEVEL_CONTAINER;
|
||||
if (level == LEVEL_CONTAINER) {
|
||||
if (is_container(level)) {
|
||||
/* Must be a fresh device to add to a container */
|
||||
return validate_geometry_ddf_container(st, level, layout,
|
||||
raiddisks, *chunk,
|
||||
size, data_offset, dev,
|
||||
freesize,
|
||||
verbose);
|
||||
return validate_geometry_ddf_container(st, level, raiddisks,
|
||||
data_offset, dev,
|
||||
freesize, verbose);
|
||||
}
|
||||
|
||||
if (*chunk == UnSet)
|
||||
*chunk = DEFAULT_CHUNK;
|
||||
|
||||
if (!dev) {
|
||||
mdu_array_info_t array = {
|
||||
.level = level,
|
||||
|
@ -3449,43 +3407,6 @@ static int validate_geometry_ddf(struct supertype *st,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
validate_geometry_ddf_container(struct supertype *st,
|
||||
int level, int layout, int raiddisks,
|
||||
int chunk, unsigned long long size,
|
||||
unsigned long long data_offset,
|
||||
char *dev, unsigned long long *freesize,
|
||||
int verbose)
|
||||
{
|
||||
int fd;
|
||||
unsigned long long ldsize;
|
||||
|
||||
if (level != LEVEL_CONTAINER)
|
||||
return 0;
|
||||
if (!dev)
|
||||
return 1;
|
||||
|
||||
fd = dev_open(dev, O_RDONLY|O_EXCL);
|
||||
if (fd < 0) {
|
||||
if (verbose)
|
||||
pr_err("ddf: Cannot open %s: %s\n",
|
||||
dev, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if (!get_dev_size(fd, dev, &ldsize)) {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
close(fd);
|
||||
if (freesize) {
|
||||
*freesize = avail_size_ddf(st, ldsize >> 9, INVALID_SECTORS);
|
||||
if (*freesize == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int validate_geometry_ddf_bvd(struct supertype *st,
|
||||
int level, int layout, int raiddisks,
|
||||
int *chunk, unsigned long long size,
|
||||
|
@ -3498,7 +3419,7 @@ static int validate_geometry_ddf_bvd(struct supertype *st,
|
|||
struct dl *dl;
|
||||
unsigned long long maxsize;
|
||||
/* ddf/bvd supports lots of things, but not containers */
|
||||
if (level == LEVEL_CONTAINER) {
|
||||
if (is_container(level)) {
|
||||
if (verbose)
|
||||
pr_err("DDF cannot create a container within an container\n");
|
||||
return 0;
|
||||
|
@ -5125,13 +5046,16 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a,
|
|||
*/
|
||||
vc = find_vdcr(ddf, a->info.container_member, rv->disk.raid_disk,
|
||||
&n_bvd, &vcl);
|
||||
if (vc == NULL)
|
||||
if (vc == NULL) {
|
||||
free(rv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mu = xmalloc(sizeof(*mu));
|
||||
if (posix_memalign(&mu->space, 512, sizeof(struct vcl)) != 0) {
|
||||
free(mu);
|
||||
mu = NULL;
|
||||
free(rv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mu->len = ddf->conf_rec_len * 512 * vcl->conf.sec_elmnt_count;
|
||||
|
@ -5161,6 +5085,8 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a,
|
|||
pr_err("BUG: can't find disk %d (%d/%d)\n",
|
||||
di->disk.raid_disk,
|
||||
di->disk.major, di->disk.minor);
|
||||
free(mu);
|
||||
free(rv);
|
||||
return NULL;
|
||||
}
|
||||
vc->phys_refnum[i_prim] = ddf->phys->entries[dl->pdnum].refnum;
|
||||
|
@ -5216,7 +5142,6 @@ struct superswitch super_ddf = {
|
|||
.match_home = match_home_ddf,
|
||||
.uuid_from_super= uuid_from_super_ddf,
|
||||
.getinfo_super = getinfo_super_ddf,
|
||||
.update_super = update_super_ddf,
|
||||
|
||||
.avail_size = avail_size_ddf,
|
||||
|
||||
|
|
475
super-intel.c
475
super-intel.c
|
@ -366,6 +366,18 @@ struct migr_record {
|
|||
};
|
||||
ASSERT_SIZE(migr_record, 128)
|
||||
|
||||
/**
|
||||
* enum imsm_status - internal IMSM return values representation.
|
||||
* @STATUS_OK: function succeeded.
|
||||
* @STATUS_ERROR: General error ocurred (not specified).
|
||||
*
|
||||
* Typedefed to imsm_status_t.
|
||||
*/
|
||||
typedef enum imsm_status {
|
||||
IMSM_STATUS_ERROR = -1,
|
||||
IMSM_STATUS_OK = 0,
|
||||
} imsm_status_t;
|
||||
|
||||
struct md_list {
|
||||
/* usage marker:
|
||||
* 1: load metadata
|
||||
|
@ -851,6 +863,21 @@ static struct disk_info *get_disk_info(struct imsm_update_create_array *update)
|
|||
return inf;
|
||||
}
|
||||
|
||||
/**
|
||||
* __get_imsm_dev() - Get device with index from imsm_super.
|
||||
* @mpb: &imsm_super pointer, not NULL.
|
||||
* @index: Device index.
|
||||
*
|
||||
* Function works as non-NULL, aborting in such a case,
|
||||
* when NULL would be returned.
|
||||
*
|
||||
* Device index should be in range 0 up to num_raid_devs.
|
||||
* Function assumes the index was already verified.
|
||||
* Index must be valid, otherwise abort() is called.
|
||||
*
|
||||
* Return: Pointer to corresponding imsm_dev.
|
||||
*
|
||||
*/
|
||||
static struct imsm_dev *__get_imsm_dev(struct imsm_super *mpb, __u8 index)
|
||||
{
|
||||
int offset;
|
||||
|
@ -858,30 +885,47 @@ static struct imsm_dev *__get_imsm_dev(struct imsm_super *mpb, __u8 index)
|
|||
void *_mpb = mpb;
|
||||
|
||||
if (index >= mpb->num_raid_devs)
|
||||
return NULL;
|
||||
goto error;
|
||||
|
||||
/* devices start after all disks */
|
||||
offset = ((void *) &mpb->disk[mpb->num_disks]) - _mpb;
|
||||
|
||||
for (i = 0; i <= index; i++)
|
||||
for (i = 0; i <= index; i++, offset += sizeof_imsm_dev(_mpb + offset, 0))
|
||||
if (i == index)
|
||||
return _mpb + offset;
|
||||
else
|
||||
offset += sizeof_imsm_dev(_mpb + offset, 0);
|
||||
|
||||
return NULL;
|
||||
error:
|
||||
pr_err("cannot find imsm_dev with index %u in imsm_super\n", index);
|
||||
abort();
|
||||
}
|
||||
|
||||
/**
|
||||
* get_imsm_dev() - Get device with index from intel_super.
|
||||
* @super: &intel_super pointer, not NULL.
|
||||
* @index: Device index.
|
||||
*
|
||||
* Function works as non-NULL, aborting in such a case,
|
||||
* when NULL would be returned.
|
||||
*
|
||||
* Device index should be in range 0 up to num_raid_devs.
|
||||
* Function assumes the index was already verified.
|
||||
* Index must be valid, otherwise abort() is called.
|
||||
*
|
||||
* Return: Pointer to corresponding imsm_dev.
|
||||
*
|
||||
*/
|
||||
static struct imsm_dev *get_imsm_dev(struct intel_super *super, __u8 index)
|
||||
{
|
||||
struct intel_dev *dv;
|
||||
|
||||
if (index >= super->anchor->num_raid_devs)
|
||||
return NULL;
|
||||
goto error;
|
||||
|
||||
for (dv = super->devlist; dv; dv = dv->next)
|
||||
if (dv->index == index)
|
||||
return dv->dev;
|
||||
return NULL;
|
||||
error:
|
||||
pr_err("cannot find imsm_dev with index %u in intel_super\n", index);
|
||||
abort();
|
||||
}
|
||||
|
||||
static inline unsigned long long __le48_to_cpu(const struct bbm_log_block_addr
|
||||
|
@ -1151,7 +1195,7 @@ static void set_imsm_ord_tbl_ent(struct imsm_map *map, int slot, __u32 ord)
|
|||
map->disk_ord_tbl[slot] = __cpu_to_le32(ord);
|
||||
}
|
||||
|
||||
static int get_imsm_disk_slot(struct imsm_map *map, unsigned idx)
|
||||
static int get_imsm_disk_slot(struct imsm_map *map, const unsigned int idx)
|
||||
{
|
||||
int slot;
|
||||
__u32 ord;
|
||||
|
@ -1162,7 +1206,7 @@ static int get_imsm_disk_slot(struct imsm_map *map, unsigned idx)
|
|||
return slot;
|
||||
}
|
||||
|
||||
return -1;
|
||||
return IMSM_STATUS_ERROR;
|
||||
}
|
||||
|
||||
static int get_imsm_raid_level(struct imsm_map *map)
|
||||
|
@ -1177,6 +1221,23 @@ static int get_imsm_raid_level(struct imsm_map *map)
|
|||
return map->raid_level;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_disk_slot_in_dev() - retrieve disk slot from &imsm_dev.
|
||||
* @super: &intel_super pointer, not NULL.
|
||||
* @dev_idx: imsm device index.
|
||||
* @idx: disk index.
|
||||
*
|
||||
* Return: Slot on success, IMSM_STATUS_ERROR otherwise.
|
||||
*/
|
||||
static int get_disk_slot_in_dev(struct intel_super *super, const __u8 dev_idx,
|
||||
const unsigned int idx)
|
||||
{
|
||||
struct imsm_dev *dev = get_imsm_dev(super, dev_idx);
|
||||
struct imsm_map *map = get_imsm_map(dev, MAP_0);
|
||||
|
||||
return get_imsm_disk_slot(map, idx);
|
||||
}
|
||||
|
||||
static int cmp_extent(const void *av, const void *bv)
|
||||
{
|
||||
const struct extent *a = av;
|
||||
|
@ -1193,13 +1254,9 @@ static int count_memberships(struct dl *dl, struct intel_super *super)
|
|||
int memberships = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < super->anchor->num_raid_devs; i++) {
|
||||
struct imsm_dev *dev = get_imsm_dev(super, i);
|
||||
struct imsm_map *map = get_imsm_map(dev, MAP_0);
|
||||
|
||||
if (get_imsm_disk_slot(map, dl->index) >= 0)
|
||||
for (i = 0; i < super->anchor->num_raid_devs; i++)
|
||||
if (get_disk_slot_in_dev(super, i, dl->index) >= 0)
|
||||
memberships++;
|
||||
}
|
||||
|
||||
return memberships;
|
||||
}
|
||||
|
@ -1909,6 +1966,7 @@ void examine_migr_rec_imsm(struct intel_super *super)
|
|||
|
||||
/* first map under migration */
|
||||
map = get_imsm_map(dev, MAP_0);
|
||||
|
||||
if (map)
|
||||
slot = get_imsm_disk_slot(map, super->disks->index);
|
||||
if (map == NULL || slot > 1 || slot < 0) {
|
||||
|
@ -3835,8 +3893,8 @@ struct mdinfo *getinfo_super_disks_imsm(struct supertype *st)
|
|||
}
|
||||
|
||||
static int update_super_imsm(struct supertype *st, struct mdinfo *info,
|
||||
char *update, char *devname, int verbose,
|
||||
int uuid_set, char *homehost)
|
||||
enum update_opt update, char *devname,
|
||||
int verbose, int uuid_set, char *homehost)
|
||||
{
|
||||
/* For 'assemble' and 'force' we need to return non-zero if any
|
||||
* change was made. For others, the return value is ignored.
|
||||
|
@ -3872,7 +3930,8 @@ static int update_super_imsm(struct supertype *st, struct mdinfo *info,
|
|||
|
||||
mpb = super->anchor;
|
||||
|
||||
if (strcmp(update, "uuid") == 0) {
|
||||
switch (update) {
|
||||
case UOPT_UUID:
|
||||
/* We take this to mean that the family_num should be updated.
|
||||
* However that is much smaller than the uuid so we cannot really
|
||||
* allow an explicit uuid to be given. And it is hard to reliably
|
||||
|
@ -3896,10 +3955,14 @@ static int update_super_imsm(struct supertype *st, struct mdinfo *info,
|
|||
}
|
||||
if (rv == 0)
|
||||
mpb->orig_family_num = info->uuid[0];
|
||||
} else if (strcmp(update, "assemble") == 0)
|
||||
break;
|
||||
case UOPT_SPEC_ASSEMBLE:
|
||||
rv = 0;
|
||||
else
|
||||
break;
|
||||
default:
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* successful update? recompute checksum */
|
||||
if (rv == 0)
|
||||
|
@ -4364,8 +4427,7 @@ int check_mpb_migr_compatibility(struct intel_super *super)
|
|||
for (i = 0; i < super->anchor->num_raid_devs; i++) {
|
||||
struct imsm_dev *dev_iter = __get_imsm_dev(super->anchor, i);
|
||||
|
||||
if (dev_iter &&
|
||||
dev_iter->vol.migr_state == 1 &&
|
||||
if (dev_iter->vol.migr_state == 1 &&
|
||||
dev_iter->vol.migr_type == MIGR_GEN_MIGR) {
|
||||
/* This device is migrating */
|
||||
map0 = get_imsm_map(dev_iter, MAP_0);
|
||||
|
@ -4514,8 +4576,6 @@ static void clear_hi(struct intel_super *super)
|
|||
}
|
||||
for (i = 0; i < mpb->num_raid_devs; ++i) {
|
||||
struct imsm_dev *dev = get_imsm_dev(super, i);
|
||||
if (!dev)
|
||||
return;
|
||||
for (n = 0; n < 2; ++n) {
|
||||
struct imsm_map *map = get_imsm_map(dev, n);
|
||||
if (!map)
|
||||
|
@ -5220,7 +5280,7 @@ static int get_super_block(struct intel_super **super_list, char *devnm, char *d
|
|||
/* retry the load if we might have raced against mdmon */
|
||||
if (err == 3 && devnm && mdmon_running(devnm))
|
||||
for (retry = 0; retry < 3; retry++) {
|
||||
usleep(3000);
|
||||
sleep_for(0, MSEC_TO_NSEC(3), true);
|
||||
err = load_and_parse_mpb(dfd, s, NULL, keep_fd);
|
||||
if (err != 3)
|
||||
break;
|
||||
|
@ -5322,7 +5382,7 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname)
|
|||
|
||||
if (mdstat && mdmon_running(mdstat->devnm) && getpid() != mdmon_pid(mdstat->devnm)) {
|
||||
for (retry = 0; retry < 3; retry++) {
|
||||
usleep(3000);
|
||||
sleep_for(0, MSEC_TO_NSEC(3), true);
|
||||
rv = load_and_parse_mpb(fd, super, devname, 0);
|
||||
if (rv != 3)
|
||||
break;
|
||||
|
@ -5625,7 +5685,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
|
|||
free(dev);
|
||||
free(dv);
|
||||
pr_err("imsm does not support consistency policy %s\n",
|
||||
map_num(consistency_policies, s->consistency_policy));
|
||||
map_num_s(consistency_policies, s->consistency_policy));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -5734,6 +5794,10 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
|
|||
struct imsm_map *map;
|
||||
struct dl *dl, *df;
|
||||
int slot;
|
||||
int autolayout = 0;
|
||||
|
||||
if (!is_fd_valid(fd))
|
||||
autolayout = 1;
|
||||
|
||||
dev = get_imsm_dev(super, super->current_vol);
|
||||
map = get_imsm_map(dev, MAP_0);
|
||||
|
@ -5744,25 +5808,32 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (!is_fd_valid(fd)) {
|
||||
/* we're doing autolayout so grab the pre-marked (in
|
||||
* validate_geometry) raid_disk
|
||||
*/
|
||||
for (dl = super->disks; dl; dl = dl->next)
|
||||
for (dl = super->disks; dl ; dl = dl->next) {
|
||||
if (autolayout) {
|
||||
if (dl->raiddisk == dk->raid_disk)
|
||||
break;
|
||||
} else {
|
||||
for (dl = super->disks; dl ; dl = dl->next)
|
||||
if (dl->major == dk->major &&
|
||||
dl->minor == dk->minor)
|
||||
break;
|
||||
} else if (dl->major == dk->major && dl->minor == dk->minor)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dl) {
|
||||
pr_err("%s is not a member of the same container\n", devname);
|
||||
if (!autolayout)
|
||||
pr_err("%s is not a member of the same container.\n",
|
||||
devname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!autolayout && super->current_vol > 0) {
|
||||
int _slot = get_disk_slot_in_dev(super, 0, dl->index);
|
||||
|
||||
if (_slot != dk->raid_disk) {
|
||||
pr_err("Member %s is in %d slot for the first volume, but is in %d slot for a new volume.\n",
|
||||
dl->devname, _slot, dk->raid_disk);
|
||||
pr_err("Raid members are in different order than for the first volume, aborting.\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (mpb->num_disks == 0)
|
||||
if (!get_dev_sector_size(dl->fd, dl->devname,
|
||||
&super->sector_size))
|
||||
|
@ -5836,7 +5907,7 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
|
|||
struct imsm_dev *_dev = __get_imsm_dev(mpb, 0);
|
||||
|
||||
_disk = __get_imsm_disk(mpb, dl->index);
|
||||
if (!_dev || !_disk) {
|
||||
if (!_disk) {
|
||||
pr_err("BUG mpb setup error\n");
|
||||
return 1;
|
||||
}
|
||||
|
@ -6171,10 +6242,10 @@ static int write_super_imsm(struct supertype *st, int doclose)
|
|||
for (i = 0; i < mpb->num_raid_devs; i++) {
|
||||
struct imsm_dev *dev = __get_imsm_dev(mpb, i);
|
||||
struct imsm_dev *dev2 = get_imsm_dev(super, i);
|
||||
if (dev && dev2) {
|
||||
imsm_copy_dev(dev, dev2);
|
||||
mpb_size += sizeof_imsm_dev(dev, 0);
|
||||
}
|
||||
|
||||
imsm_copy_dev(dev, dev2);
|
||||
mpb_size += sizeof_imsm_dev(dev, 0);
|
||||
|
||||
if (is_gen_migration(dev2))
|
||||
clear_migration_record = 0;
|
||||
}
|
||||
|
@ -6467,7 +6538,7 @@ static int validate_ppl_imsm(struct supertype *st, struct mdinfo *info,
|
|||
if (mdmon_running(st->container_devnm))
|
||||
st->update_tail = &st->updates;
|
||||
|
||||
if (st->ss->update_subarray(st, subarray, "ppl", NULL)) {
|
||||
if (st->ss->update_subarray(st, subarray, UOPT_PPL, NULL)) {
|
||||
pr_err("Failed to update subarray %s\n",
|
||||
subarray);
|
||||
} else {
|
||||
|
@ -6661,7 +6732,7 @@ static int validate_geometry_imsm_container(struct supertype *st, int level,
|
|||
struct intel_super *super = NULL;
|
||||
int rv = 0;
|
||||
|
||||
if (level != LEVEL_CONTAINER)
|
||||
if (!is_container(level))
|
||||
return 0;
|
||||
if (!dev)
|
||||
return 1;
|
||||
|
@ -7467,11 +7538,27 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int imsm_get_free_size(struct supertype *st, int raiddisks,
|
||||
unsigned long long size, int chunk,
|
||||
unsigned long long *freesize)
|
||||
/**
|
||||
* imsm_get_free_size() - get the biggest, common free space from members.
|
||||
* @super: &intel_super pointer, not NULL.
|
||||
* @raiddisks: number of raid disks.
|
||||
* @size: requested size, could be 0 (means max size).
|
||||
* @chunk: requested chunk.
|
||||
* @freesize: pointer for returned size value.
|
||||
*
|
||||
* Return: &IMSM_STATUS_OK or &IMSM_STATUS_ERROR.
|
||||
*
|
||||
* @freesize is set to meaningful value, this can be @size, or calculated
|
||||
* max free size.
|
||||
* super->create_offset value is modified and set appropriately in
|
||||
* merge_extends() for further creation.
|
||||
*/
|
||||
static imsm_status_t imsm_get_free_size(struct intel_super *super,
|
||||
const int raiddisks,
|
||||
unsigned long long size,
|
||||
const int chunk,
|
||||
unsigned long long *freesize)
|
||||
{
|
||||
struct intel_super *super = st->sb;
|
||||
struct imsm_super *mpb = super->anchor;
|
||||
struct dl *dl;
|
||||
int i;
|
||||
|
@ -7515,12 +7602,10 @@ static int imsm_get_free_size(struct supertype *st, int raiddisks,
|
|||
/* chunk is in K */
|
||||
minsize = chunk * 2;
|
||||
|
||||
if (cnt < raiddisks ||
|
||||
(super->orom && used && used != raiddisks) ||
|
||||
maxsize < minsize ||
|
||||
maxsize == 0) {
|
||||
if (cnt < raiddisks || (super->orom && used && used != raiddisks) ||
|
||||
maxsize < minsize || maxsize == 0) {
|
||||
pr_err("not enough devices with space to create array.\n");
|
||||
return 0; /* No enough free spaces large enough */
|
||||
return IMSM_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
|
@ -7533,37 +7618,69 @@ static int imsm_get_free_size(struct supertype *st, int raiddisks,
|
|||
}
|
||||
if (mpb->num_raid_devs > 0 && size && size != maxsize)
|
||||
pr_err("attempting to create a second volume with size less then remaining space.\n");
|
||||
cnt = 0;
|
||||
for (dl = super->disks; dl; dl = dl->next)
|
||||
if (dl->e)
|
||||
dl->raiddisk = cnt++;
|
||||
|
||||
*freesize = size;
|
||||
|
||||
dprintf("imsm: imsm_get_free_size() returns : %llu\n", size);
|
||||
|
||||
return 1;
|
||||
return IMSM_STATUS_OK;
|
||||
}
|
||||
|
||||
static int reserve_space(struct supertype *st, int raiddisks,
|
||||
unsigned long long size, int chunk,
|
||||
unsigned long long *freesize)
|
||||
/**
|
||||
* autolayout_imsm() - automatically layout a new volume.
|
||||
* @super: &intel_super pointer, not NULL.
|
||||
* @raiddisks: number of raid disks.
|
||||
* @size: requested size, could be 0 (means max size).
|
||||
* @chunk: requested chunk.
|
||||
* @freesize: pointer for returned size value.
|
||||
*
|
||||
* We are being asked to automatically layout a new volume based on the current
|
||||
* contents of the container. If the parameters can be satisfied autolayout_imsm
|
||||
* will record the disks, start offset, and will return size of the volume to
|
||||
* be created. See imsm_get_free_size() for details.
|
||||
* add_to_super() and getinfo_super() detect when autolayout is in progress.
|
||||
* If first volume exists, slots are set consistently to it.
|
||||
*
|
||||
* Return: &IMSM_STATUS_OK on success, &IMSM_STATUS_ERROR otherwise.
|
||||
*
|
||||
* Disks are marked for creation via dl->raiddisk.
|
||||
*/
|
||||
static imsm_status_t autolayout_imsm(struct intel_super *super,
|
||||
const int raiddisks,
|
||||
unsigned long long size, const int chunk,
|
||||
unsigned long long *freesize)
|
||||
{
|
||||
struct intel_super *super = st->sb;
|
||||
struct dl *dl;
|
||||
int cnt;
|
||||
int rv = 0;
|
||||
int curr_slot = 0;
|
||||
struct dl *disk;
|
||||
int vol_cnt = super->anchor->num_raid_devs;
|
||||
imsm_status_t rv;
|
||||
|
||||
rv = imsm_get_free_size(st, raiddisks, size, chunk, freesize);
|
||||
if (rv) {
|
||||
cnt = 0;
|
||||
for (dl = super->disks; dl; dl = dl->next)
|
||||
if (dl->e)
|
||||
dl->raiddisk = cnt++;
|
||||
rv = 1;
|
||||
rv = imsm_get_free_size(super, raiddisks, size, chunk, freesize);
|
||||
if (rv != IMSM_STATUS_OK)
|
||||
return IMSM_STATUS_ERROR;
|
||||
|
||||
for (disk = super->disks; disk; disk = disk->next) {
|
||||
if (!disk->e)
|
||||
continue;
|
||||
|
||||
if (curr_slot == raiddisks)
|
||||
break;
|
||||
|
||||
if (vol_cnt == 0) {
|
||||
disk->raiddisk = curr_slot;
|
||||
} else {
|
||||
int _slot = get_disk_slot_in_dev(super, 0, disk->index);
|
||||
|
||||
if (_slot == -1) {
|
||||
pr_err("Disk %s is not used in first volume, aborting\n",
|
||||
disk->devname);
|
||||
return IMSM_STATUS_ERROR;
|
||||
}
|
||||
disk->raiddisk = _slot;
|
||||
}
|
||||
curr_slot++;
|
||||
}
|
||||
|
||||
return rv;
|
||||
return IMSM_STATUS_OK;
|
||||
}
|
||||
|
||||
static int validate_geometry_imsm(struct supertype *st, int level, int layout,
|
||||
|
@ -7580,7 +7697,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
|
|||
* if given unused devices create a container
|
||||
* if given given devices in a container create a member volume
|
||||
*/
|
||||
if (level == LEVEL_CONTAINER)
|
||||
if (is_container(level))
|
||||
/* Must be a fresh device to add to a container */
|
||||
return validate_geometry_imsm_container(st, level, raiddisks,
|
||||
data_offset, dev,
|
||||
|
@ -7599,35 +7716,35 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
|
|||
}
|
||||
|
||||
if (!dev) {
|
||||
if (st->sb) {
|
||||
struct intel_super *super = st->sb;
|
||||
if (!validate_geometry_imsm_orom(st->sb, level, layout,
|
||||
raiddisks, chunk, size,
|
||||
verbose))
|
||||
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;
|
||||
}
|
||||
|
||||
if (!validate_geometry_imsm_orom(st->sb, level, layout,
|
||||
raiddisks, chunk, size,
|
||||
verbose))
|
||||
return 0;
|
||||
|
||||
if (super->orom && freesize) {
|
||||
imsm_status_t rv;
|
||||
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;
|
||||
/* we are being asked to automatically layout a
|
||||
* new volume based on the current contents of
|
||||
* the container. If the the parameters can be
|
||||
* satisfied reserve_space will record the disks,
|
||||
* start offset, and size of the volume to be
|
||||
* created. add_to_super and getinfo_super
|
||||
* detect when autolayout is in progress.
|
||||
*/
|
||||
/* assuming that freesize is always given when array is
|
||||
created */
|
||||
if (super->orom && freesize) {
|
||||
int count;
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (freesize)
|
||||
return reserve_space(st, raiddisks, size,
|
||||
*chunk, freesize);
|
||||
|
||||
rv = autolayout_imsm(super, raiddisks, size, *chunk,
|
||||
freesize);
|
||||
if (rv != IMSM_STATUS_OK)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -7777,36 +7894,39 @@ static int kill_subarray_imsm(struct supertype *st, char *subarray_id)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int get_rwh_policy_from_update(char *update)
|
||||
/**
|
||||
* get_rwh_policy_from_update() - Get the rwh policy for update option.
|
||||
* @update: Update option.
|
||||
*/
|
||||
static int get_rwh_policy_from_update(enum update_opt update)
|
||||
{
|
||||
if (strcmp(update, "ppl") == 0)
|
||||
switch (update) {
|
||||
case UOPT_PPL:
|
||||
return RWH_MULTIPLE_DISTRIBUTED;
|
||||
else if (strcmp(update, "no-ppl") == 0)
|
||||
case UOPT_NO_PPL:
|
||||
return RWH_MULTIPLE_OFF;
|
||||
else if (strcmp(update, "bitmap") == 0)
|
||||
case UOPT_BITMAP:
|
||||
return RWH_BITMAP;
|
||||
else if (strcmp(update, "no-bitmap") == 0)
|
||||
case UOPT_NO_BITMAP:
|
||||
return RWH_OFF;
|
||||
return -1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return UOPT_UNDEFINED;
|
||||
}
|
||||
|
||||
static int update_subarray_imsm(struct supertype *st, char *subarray,
|
||||
char *update, struct mddev_ident *ident)
|
||||
enum update_opt update, struct mddev_ident *ident)
|
||||
{
|
||||
/* update the subarray currently referenced by ->current_vol */
|
||||
struct intel_super *super = st->sb;
|
||||
struct imsm_super *mpb = super->anchor;
|
||||
|
||||
if (strcmp(update, "name") == 0) {
|
||||
if (update == UOPT_NAME) {
|
||||
char *name = ident->name;
|
||||
char *ep;
|
||||
int vol;
|
||||
|
||||
if (is_subarray_active(subarray, st->devnm)) {
|
||||
pr_err("Unable to update name of active subarray\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (!check_name(super, name, 0))
|
||||
return 2;
|
||||
|
||||
|
@ -7836,7 +7956,7 @@ static int update_subarray_imsm(struct supertype *st, char *subarray,
|
|||
}
|
||||
super->updates_pending++;
|
||||
}
|
||||
} else if (get_rwh_policy_from_update(update) != -1) {
|
||||
} else if (get_rwh_policy_from_update(update) != UOPT_UNDEFINED) {
|
||||
int new_policy;
|
||||
char *ep;
|
||||
int vol = strtoul(subarray, &ep, 10);
|
||||
|
@ -9033,29 +9153,26 @@ static int imsm_rebuild_allowed(struct supertype *cont, int dev_idx, int failed)
|
|||
__u8 state;
|
||||
|
||||
dev2 = get_imsm_dev(cont->sb, dev_idx);
|
||||
if (dev2) {
|
||||
state = imsm_check_degraded(cont->sb, dev2, failed, MAP_0);
|
||||
if (state == IMSM_T_STATE_FAILED) {
|
||||
map = get_imsm_map(dev2, MAP_0);
|
||||
if (!map)
|
||||
return 1;
|
||||
for (slot = 0; slot < map->num_members; slot++) {
|
||||
/*
|
||||
* Check if failed disks are deleted from intel
|
||||
* disk list or are marked to be deleted
|
||||
*/
|
||||
idx = get_imsm_disk_idx(dev2, slot, MAP_X);
|
||||
idisk = get_imsm_dl_disk(cont->sb, idx);
|
||||
/*
|
||||
* Do not rebuild the array if failed disks
|
||||
* from failed sub-array are not removed from
|
||||
* container.
|
||||
*/
|
||||
if (idisk &&
|
||||
is_failed(&idisk->disk) &&
|
||||
(idisk->action != DISK_REMOVE))
|
||||
return 0;
|
||||
}
|
||||
|
||||
state = imsm_check_degraded(cont->sb, dev2, failed, MAP_0);
|
||||
if (state == IMSM_T_STATE_FAILED) {
|
||||
map = get_imsm_map(dev2, MAP_0);
|
||||
for (slot = 0; slot < map->num_members; slot++) {
|
||||
/*
|
||||
* Check if failed disks are deleted from intel
|
||||
* disk list or are marked to be deleted
|
||||
*/
|
||||
idx = get_imsm_disk_idx(dev2, slot, MAP_X);
|
||||
idisk = get_imsm_dl_disk(cont->sb, idx);
|
||||
/*
|
||||
* Do not rebuild the array if failed disks
|
||||
* from failed sub-array are not removed from
|
||||
* container.
|
||||
*/
|
||||
if (idisk &&
|
||||
is_failed(&idisk->disk) &&
|
||||
(idisk->action != DISK_REMOVE))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
@ -9629,10 +9746,9 @@ static int apply_update_activate_spare(struct imsm_update_activate_spare *u,
|
|||
/* count arrays using the victim in the metadata */
|
||||
found = 0;
|
||||
for (a = active_array; a ; a = a->next) {
|
||||
dev = get_imsm_dev(super, a->info.container_member);
|
||||
map = get_imsm_map(dev, MAP_0);
|
||||
int dev_idx = a->info.container_member;
|
||||
|
||||
if (get_imsm_disk_slot(map, victim) >= 0)
|
||||
if (get_disk_slot_in_dev(super, dev_idx, victim) >= 0)
|
||||
found++;
|
||||
}
|
||||
|
||||
|
@ -10089,7 +10205,6 @@ static void imsm_process_update(struct supertype *st,
|
|||
int victim = u->dev_idx;
|
||||
struct active_array *a;
|
||||
struct intel_dev **dp;
|
||||
struct imsm_dev *dev;
|
||||
|
||||
/* sanity check that we are not affecting the uuid of
|
||||
* active arrays, or deleting an active array
|
||||
|
@ -10105,8 +10220,7 @@ static void imsm_process_update(struct supertype *st,
|
|||
* is active in the container, so checking
|
||||
* mpb->num_raid_devs is just extra paranoia
|
||||
*/
|
||||
dev = get_imsm_dev(super, victim);
|
||||
if (a || !dev || mpb->num_raid_devs == 1) {
|
||||
if (a || mpb->num_raid_devs == 1 || victim >= super->anchor->num_raid_devs) {
|
||||
dprintf("failed to delete subarray-%d\n", victim);
|
||||
break;
|
||||
}
|
||||
|
@ -10140,7 +10254,7 @@ static void imsm_process_update(struct supertype *st,
|
|||
if (a->info.container_member == target)
|
||||
break;
|
||||
dev = get_imsm_dev(super, u->dev_idx);
|
||||
if (a || !dev || !check_name(super, name, 1)) {
|
||||
if (a || !check_name(super, name, 1)) {
|
||||
dprintf("failed to rename subarray-%d\n", target);
|
||||
break;
|
||||
}
|
||||
|
@ -10169,10 +10283,6 @@ static void imsm_process_update(struct supertype *st,
|
|||
struct imsm_update_rwh_policy *u = (void *)update->buf;
|
||||
int target = u->dev_idx;
|
||||
struct imsm_dev *dev = get_imsm_dev(super, target);
|
||||
if (!dev) {
|
||||
dprintf("could not find subarray-%d\n", target);
|
||||
break;
|
||||
}
|
||||
|
||||
if (dev->rwh_policy != u->new_policy) {
|
||||
dev->rwh_policy = u->new_policy;
|
||||
|
@ -11397,8 +11507,10 @@ static int imsm_create_metadata_update_for_migration(
|
|||
{
|
||||
struct intel_super *super = st->sb;
|
||||
int update_memory_size;
|
||||
int current_chunk_size;
|
||||
struct imsm_update_reshape_migration *u;
|
||||
struct imsm_dev *dev;
|
||||
struct imsm_dev *dev = get_imsm_dev(super, super->current_vol);
|
||||
struct imsm_map *map = get_imsm_map(dev, MAP_0);
|
||||
int previous_level = -1;
|
||||
|
||||
dprintf("(enter) New Level = %i\n", geo->level);
|
||||
|
@ -11415,23 +11527,15 @@ static int imsm_create_metadata_update_for_migration(
|
|||
u->new_disks[0] = -1;
|
||||
u->new_chunksize = -1;
|
||||
|
||||
dev = get_imsm_dev(super, u->subdev);
|
||||
if (dev) {
|
||||
struct imsm_map *map;
|
||||
current_chunk_size = __le16_to_cpu(map->blocks_per_strip) / 2;
|
||||
|
||||
map = get_imsm_map(dev, MAP_0);
|
||||
if (map) {
|
||||
int current_chunk_size =
|
||||
__le16_to_cpu(map->blocks_per_strip) / 2;
|
||||
|
||||
if (geo->chunksize != current_chunk_size) {
|
||||
u->new_chunksize = geo->chunksize / 1024;
|
||||
dprintf("imsm: chunk size change from %i to %i\n",
|
||||
current_chunk_size, u->new_chunksize);
|
||||
}
|
||||
previous_level = map->raid_level;
|
||||
}
|
||||
if (geo->chunksize != current_chunk_size) {
|
||||
u->new_chunksize = geo->chunksize / 1024;
|
||||
dprintf("imsm: chunk size change from %i to %i\n",
|
||||
current_chunk_size, u->new_chunksize);
|
||||
}
|
||||
previous_level = map->raid_level;
|
||||
|
||||
if (geo->level == 5 && previous_level == 0) {
|
||||
struct mdinfo *spares = NULL;
|
||||
|
||||
|
@ -11499,7 +11603,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
|
|||
unsigned long long current_size;
|
||||
unsigned long long free_size;
|
||||
unsigned long long max_size;
|
||||
int rv;
|
||||
imsm_status_t rv;
|
||||
|
||||
getinfo_super_imsm_volume(st, &info, NULL);
|
||||
if (geo->level != info.array.level && geo->level >= 0 &&
|
||||
|
@ -11618,9 +11722,10 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
|
|||
}
|
||||
/* check the maximum available size
|
||||
*/
|
||||
rv = imsm_get_free_size(st, dev->vol.map->num_members,
|
||||
0, chunk, &free_size);
|
||||
if (rv == 0)
|
||||
rv = imsm_get_free_size(super, dev->vol.map->num_members,
|
||||
0, chunk, &free_size);
|
||||
|
||||
if (rv != IMSM_STATUS_OK)
|
||||
/* Cannot find maximum available space
|
||||
*/
|
||||
max_size = 0;
|
||||
|
@ -11683,8 +11788,8 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
|
|||
struct imsm_super *mpb = super->anchor;
|
||||
|
||||
if (mpb->num_raid_devs > 1) {
|
||||
pr_err("Error. Cannot perform operation on %s- for this operation it MUST be single array in container\n",
|
||||
geo->dev_name);
|
||||
pr_err("Error. Cannot perform operation on %s- for this operation "
|
||||
"it MUST be single array in container\n", geo->dev_name);
|
||||
change = -1;
|
||||
}
|
||||
}
|
||||
|
@ -11757,7 +11862,7 @@ static int imsm_fix_size_mismatch(struct supertype *st, int subarray_index)
|
|||
unsigned long long d_size = imsm_dev_size(dev);
|
||||
int u_size;
|
||||
|
||||
if (calc_size == d_size || dev->vol.migr_type == MIGR_GEN_MIGR)
|
||||
if (calc_size == d_size)
|
||||
continue;
|
||||
|
||||
/* There is a difference, confirm that imsm_dev_size is
|
||||
|
@ -11772,10 +11877,6 @@ static int imsm_fix_size_mismatch(struct supertype *st, int subarray_index)
|
|||
geo.size = d_size;
|
||||
u_size = imsm_create_metadata_update_for_size_change(st, &geo,
|
||||
&update);
|
||||
if (u_size < 1) {
|
||||
dprintf("imsm: Cannot prepare size change update\n");
|
||||
goto exit;
|
||||
}
|
||||
imsm_update_metadata_locally(st, update, u_size);
|
||||
if (st->update_tail) {
|
||||
append_metadata_update(st, update, u_size);
|
||||
|
@ -11783,9 +11884,8 @@ static int imsm_fix_size_mismatch(struct supertype *st, int subarray_index)
|
|||
st->update_tail = &st->updates;
|
||||
} else {
|
||||
imsm_sync_metadata(st);
|
||||
free(update);
|
||||
}
|
||||
|
||||
free(update);
|
||||
}
|
||||
ret_val = 0;
|
||||
exit:
|
||||
|
@ -11992,7 +12092,7 @@ int wait_for_reshape_imsm(struct mdinfo *sra, int ndata)
|
|||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
usleep(30000);
|
||||
sleep_for(0, MSEC_TO_NSEC(30), true);
|
||||
} else
|
||||
break;
|
||||
} while (retry--);
|
||||
|
@ -12520,9 +12620,6 @@ static int validate_internal_bitmap_imsm(struct supertype *st)
|
|||
unsigned long long offset;
|
||||
struct dl *d;
|
||||
|
||||
if (!dev)
|
||||
return -1;
|
||||
|
||||
if (dev->rwh_policy != RWH_BITMAP)
|
||||
return 0;
|
||||
|
||||
|
@ -12568,16 +12665,8 @@ static int add_internal_bitmap_imsm(struct supertype *st, int *chunkp,
|
|||
return -1;
|
||||
|
||||
dev = get_imsm_dev(super, vol_idx);
|
||||
|
||||
if (!dev) {
|
||||
dprintf("cannot find the device for volume index %d\n",
|
||||
vol_idx);
|
||||
return -1;
|
||||
}
|
||||
dev->rwh_policy = RWH_BITMAP;
|
||||
|
||||
*chunkp = calculate_bitmap_chunksize(st, dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
109
super0.c
109
super0.c
|
@ -288,7 +288,7 @@ static void export_examine_super0(struct supertype *st)
|
|||
{
|
||||
mdp_super_t *sb = st->sb;
|
||||
|
||||
printf("MD_LEVEL=%s\n", map_num(pers, sb->level));
|
||||
printf("MD_LEVEL=%s\n", map_num_s(pers, sb->level));
|
||||
printf("MD_DEVICES=%d\n", sb->raid_disks);
|
||||
if (sb->minor_version >= 90)
|
||||
printf("MD_UUID=%08x:%08x:%08x:%08x\n",
|
||||
|
@ -491,7 +491,7 @@ static struct mdinfo *container_content0(struct supertype *st, char *subarray)
|
|||
}
|
||||
|
||||
static int update_super0(struct supertype *st, struct mdinfo *info,
|
||||
char *update,
|
||||
enum update_opt update,
|
||||
char *devname, int verbose,
|
||||
int uuid_set, char *homehost)
|
||||
{
|
||||
|
@ -503,18 +503,37 @@ static int update_super0(struct supertype *st, struct mdinfo *info,
|
|||
int uuid[4];
|
||||
mdp_super_t *sb = st->sb;
|
||||
|
||||
if (strcmp(update, "homehost") == 0 &&
|
||||
homehost) {
|
||||
/* note that 'homehost' is special as it is really
|
||||
if (update == UOPT_HOMEHOST && homehost) {
|
||||
/*
|
||||
* note that 'homehost' is special as it is really
|
||||
* a "uuid" update.
|
||||
*/
|
||||
uuid_set = 0;
|
||||
update = "uuid";
|
||||
update = UOPT_UUID;
|
||||
info->uuid[0] = sb->set_uuid0;
|
||||
info->uuid[1] = sb->set_uuid1;
|
||||
}
|
||||
|
||||
if (strcmp(update, "sparc2.2")==0 ) {
|
||||
switch (update) {
|
||||
case UOPT_UUID:
|
||||
if (!uuid_set && homehost) {
|
||||
char buf[20];
|
||||
memcpy(info->uuid+2,
|
||||
sha1_buffer(homehost, strlen(homehost), buf),
|
||||
8);
|
||||
}
|
||||
sb->set_uuid0 = info->uuid[0];
|
||||
sb->set_uuid1 = info->uuid[1];
|
||||
sb->set_uuid2 = info->uuid[2];
|
||||
sb->set_uuid3 = info->uuid[3];
|
||||
if (sb->state & (1<<MD_SB_BITMAP_PRESENT)) {
|
||||
struct bitmap_super_s *bm;
|
||||
bm = (struct bitmap_super_s *)(sb+1);
|
||||
uuid_from_super0(st, uuid);
|
||||
memcpy(bm->uuid, uuid, 16);
|
||||
}
|
||||
break;
|
||||
case UOPT_SPARC22: {
|
||||
/* 2.2 sparc put the events in the wrong place
|
||||
* So we copy the tail of the superblock
|
||||
* up 4 bytes before continuing
|
||||
|
@ -527,12 +546,15 @@ static int update_super0(struct supertype *st, struct mdinfo *info,
|
|||
if (verbose >= 0)
|
||||
pr_err("adjusting superblock of %s for 2.2/sparc compatibility.\n",
|
||||
devname);
|
||||
} else if (strcmp(update, "super-minor") ==0) {
|
||||
break;
|
||||
}
|
||||
case UOPT_SUPER_MINOR:
|
||||
sb->md_minor = info->array.md_minor;
|
||||
if (verbose > 0)
|
||||
pr_err("updating superblock of %s with minor number %d\n",
|
||||
devname, info->array.md_minor);
|
||||
} else if (strcmp(update, "summaries") == 0) {
|
||||
break;
|
||||
case UOPT_SUMMARIES: {
|
||||
unsigned int i;
|
||||
/* set nr_disks, active_disks, working_disks,
|
||||
* failed_disks, spare_disks based on disks[]
|
||||
|
@ -559,7 +581,9 @@ static int update_super0(struct supertype *st, struct mdinfo *info,
|
|||
sb->spare_disks++;
|
||||
} else if (i >= sb->raid_disks && sb->disks[i].number == 0)
|
||||
sb->disks[i].state = 0;
|
||||
} else if (strcmp(update, "force-one")==0) {
|
||||
break;
|
||||
}
|
||||
case UOPT_SPEC_FORCE_ONE: {
|
||||
/* Not enough devices for a working array, so
|
||||
* bring this one up-to-date.
|
||||
*/
|
||||
|
@ -569,7 +593,9 @@ static int update_super0(struct supertype *st, struct mdinfo *info,
|
|||
if (sb->events_hi != ehi ||
|
||||
sb->events_lo != elo)
|
||||
rv = 1;
|
||||
} else if (strcmp(update, "force-array")==0) {
|
||||
break;
|
||||
}
|
||||
case UOPT_SPEC_FORCE_ARRAY:
|
||||
/* degraded array and 'force' requested, so
|
||||
* maybe need to mark it 'clean'
|
||||
*/
|
||||
|
@ -579,7 +605,8 @@ static int update_super0(struct supertype *st, struct mdinfo *info,
|
|||
sb->state |= (1 << MD_SB_CLEAN);
|
||||
rv = 1;
|
||||
}
|
||||
} else if (strcmp(update, "assemble")==0) {
|
||||
break;
|
||||
case UOPT_SPEC_ASSEMBLE: {
|
||||
int d = info->disk.number;
|
||||
int wonly = sb->disks[d].state & (1<<MD_DISK_WRITEMOSTLY);
|
||||
int failfast = sb->disks[d].state & (1<<MD_DISK_FAILFAST);
|
||||
|
@ -609,7 +636,9 @@ static int update_super0(struct supertype *st, struct mdinfo *info,
|
|||
sb->reshape_position = info->reshape_progress;
|
||||
rv = 1;
|
||||
}
|
||||
} else if (strcmp(update, "linear-grow-new") == 0) {
|
||||
break;
|
||||
}
|
||||
case UOPT_SPEC_LINEAR_GROW_NEW:
|
||||
memset(&sb->disks[info->disk.number], 0, sizeof(sb->disks[0]));
|
||||
sb->disks[info->disk.number].number = info->disk.number;
|
||||
sb->disks[info->disk.number].major = info->disk.major;
|
||||
|
@ -617,7 +646,8 @@ static int update_super0(struct supertype *st, struct mdinfo *info,
|
|||
sb->disks[info->disk.number].raid_disk = info->disk.raid_disk;
|
||||
sb->disks[info->disk.number].state = info->disk.state;
|
||||
sb->this_disk = sb->disks[info->disk.number];
|
||||
} else if (strcmp(update, "linear-grow-update") == 0) {
|
||||
break;
|
||||
case UOPT_SPEC_LINEAR_GROW_UPDATE:
|
||||
sb->raid_disks = info->array.raid_disks;
|
||||
sb->nr_disks = info->array.nr_disks;
|
||||
sb->active_disks = info->array.active_disks;
|
||||
|
@ -628,29 +658,15 @@ static int update_super0(struct supertype *st, struct mdinfo *info,
|
|||
sb->disks[info->disk.number].minor = info->disk.minor;
|
||||
sb->disks[info->disk.number].raid_disk = info->disk.raid_disk;
|
||||
sb->disks[info->disk.number].state = info->disk.state;
|
||||
} else if (strcmp(update, "resync") == 0) {
|
||||
/* make sure resync happens */
|
||||
break;
|
||||
case UOPT_RESYNC:
|
||||
/*
|
||||
* make sure resync happens
|
||||
*/
|
||||
sb->state &= ~(1<<MD_SB_CLEAN);
|
||||
sb->recovery_cp = 0;
|
||||
} else if (strcmp(update, "uuid") == 0) {
|
||||
if (!uuid_set && homehost) {
|
||||
char buf[20];
|
||||
char *hash = sha1_buffer(homehost,
|
||||
strlen(homehost),
|
||||
buf);
|
||||
memcpy(info->uuid+2, hash, 8);
|
||||
}
|
||||
sb->set_uuid0 = info->uuid[0];
|
||||
sb->set_uuid1 = info->uuid[1];
|
||||
sb->set_uuid2 = info->uuid[2];
|
||||
sb->set_uuid3 = info->uuid[3];
|
||||
if (sb->state & (1<<MD_SB_BITMAP_PRESENT)) {
|
||||
struct bitmap_super_s *bm;
|
||||
bm = (struct bitmap_super_s*)(sb+1);
|
||||
uuid_from_super0(st, uuid);
|
||||
memcpy(bm->uuid, uuid, 16);
|
||||
}
|
||||
} else if (strcmp(update, "metadata") == 0) {
|
||||
break;
|
||||
case UOPT_METADATA:
|
||||
/* Create some v1.0 metadata to match ours but make the
|
||||
* ctime bigger. Also update info->array.*_version.
|
||||
* We need to arrange that store_super writes out
|
||||
|
@ -670,7 +686,8 @@ static int update_super0(struct supertype *st, struct mdinfo *info,
|
|||
uuid_from_super0(st, info->uuid);
|
||||
st->other = super1_make_v0(st, info, st->sb);
|
||||
}
|
||||
} else if (strcmp(update, "revert-reshape") == 0) {
|
||||
break;
|
||||
case UOPT_REVERT_RESHAPE:
|
||||
rv = -2;
|
||||
if (sb->minor_version <= 90)
|
||||
pr_err("No active reshape to revert on %s\n",
|
||||
|
@ -683,7 +700,7 @@ static int update_super0(struct supertype *st, struct mdinfo *info,
|
|||
int parity = sb->level == 6 ? 2 : 1;
|
||||
rv = 0;
|
||||
|
||||
if (sb->level >= 4 && sb->level <= 6 &&
|
||||
if (is_level456(sb->level) &&
|
||||
sb->reshape_position % (
|
||||
sb->new_chunk/512 *
|
||||
(sb->raid_disks - sb->delta_disks - parity))) {
|
||||
|
@ -702,16 +719,22 @@ static int update_super0(struct supertype *st, struct mdinfo *info,
|
|||
sb->new_chunk = sb->chunk_size;
|
||||
sb->chunk_size = tmp;
|
||||
}
|
||||
} else if (strcmp(update, "no-bitmap") == 0) {
|
||||
break;
|
||||
case UOPT_NO_BITMAP:
|
||||
sb->state &= ~(1<<MD_SB_BITMAP_PRESENT);
|
||||
} else if (strcmp(update, "_reshape_progress")==0)
|
||||
break;
|
||||
case UOPT_SPEC__RESHAPE_PROGRESS:
|
||||
sb->reshape_position = info->reshape_progress;
|
||||
else if (strcmp(update, "writemostly")==0)
|
||||
break;
|
||||
case UOPT_SPEC_WRITEMOSTLY:
|
||||
sb->state |= (1<<MD_DISK_WRITEMOSTLY);
|
||||
else if (strcmp(update, "readwrite")==0)
|
||||
break;
|
||||
case UOPT_SPEC_READWRITE:
|
||||
sb->state &= ~(1<<MD_DISK_WRITEMOSTLY);
|
||||
else
|
||||
break;
|
||||
default:
|
||||
rv = -1;
|
||||
}
|
||||
|
||||
sb->sb_csum = calc_sb0_csum(sb);
|
||||
return rv;
|
||||
|
@ -1273,7 +1296,7 @@ static int validate_geometry0(struct supertype *st, int level,
|
|||
if (get_linux_version() < 3001000)
|
||||
tbmax = 2;
|
||||
|
||||
if (level == LEVEL_CONTAINER) {
|
||||
if (is_container(level)) {
|
||||
if (verbose)
|
||||
pr_err("0.90 metadata does not support containers\n");
|
||||
return 0;
|
||||
|
|
207
super1.c
207
super1.c
|
@ -406,12 +406,18 @@ static void examine_super1(struct supertype *st, char *homehost)
|
|||
|
||||
st->ss->getinfo_super(st, &info, NULL);
|
||||
if (info.space_after != 1 &&
|
||||
!(__le32_to_cpu(sb->feature_map) & MD_FEATURE_NEW_OFFSET))
|
||||
printf(" Unused Space : before=%llu sectors, after=%llu sectors\n",
|
||||
info.space_before, info.space_after);
|
||||
|
||||
printf(" State : %s\n",
|
||||
(__le64_to_cpu(sb->resync_offset)+1)? "active":"clean");
|
||||
!(__le32_to_cpu(sb->feature_map) & MD_FEATURE_NEW_OFFSET)) {
|
||||
printf(" Unused Space : before=%llu sectors, ",
|
||||
info.space_before);
|
||||
if (info.space_after < INT64_MAX)
|
||||
printf("after=%llu sectors\n", info.space_after);
|
||||
else
|
||||
printf("after=-%llu sectors DEVICE TOO SMALL\n",
|
||||
UINT64_MAX - info.space_after);
|
||||
}
|
||||
printf(" State : %s%s\n",
|
||||
(__le64_to_cpu(sb->resync_offset)+1) ? "active":"clean",
|
||||
(info.space_after > INT64_MAX) ? " TRUNCATED DEVICE" : "");
|
||||
printf(" Device UUID : ");
|
||||
for (i=0; i<16; i++) {
|
||||
if ((i&3)==0 && i != 0)
|
||||
|
@ -671,7 +677,7 @@ static void export_examine_super1(struct supertype *st)
|
|||
int len = 32;
|
||||
int layout;
|
||||
|
||||
printf("MD_LEVEL=%s\n", map_num(pers, __le32_to_cpu(sb->level)));
|
||||
printf("MD_LEVEL=%s\n", map_num_s(pers, __le32_to_cpu(sb->level)));
|
||||
printf("MD_DEVICES=%d\n", __le32_to_cpu(sb->raid_disks));
|
||||
for (i = 0; i < 32; i++)
|
||||
if (sb->set_name[i] == '\n' || sb->set_name[i] == '\0') {
|
||||
|
@ -1202,7 +1208,7 @@ static struct mdinfo *container_content1(struct supertype *st, char *subarray)
|
|||
}
|
||||
|
||||
static int update_super1(struct supertype *st, struct mdinfo *info,
|
||||
char *update, char *devname, int verbose,
|
||||
enum update_opt update, char *devname, int verbose,
|
||||
int uuid_set, char *homehost)
|
||||
{
|
||||
/* NOTE: for 'assemble' and 'force' we need to return non-zero
|
||||
|
@ -1213,29 +1219,53 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
|
|||
struct mdp_superblock_1 *sb = st->sb;
|
||||
bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + MAX_SB_SIZE);
|
||||
|
||||
if (strcmp(update, "homehost") == 0 &&
|
||||
homehost) {
|
||||
/* Note that 'homehost' is special as it is really
|
||||
if (update == UOPT_HOMEHOST && homehost) {
|
||||
/*
|
||||
* Note that 'homehost' is special as it is really
|
||||
* a "name" update.
|
||||
*/
|
||||
char *c;
|
||||
update = "name";
|
||||
update = UOPT_NAME;
|
||||
c = strchr(sb->set_name, ':');
|
||||
if (c)
|
||||
strncpy(info->name, c+1, 31 - (c-sb->set_name));
|
||||
snprintf(info->name, sizeof(info->name), "%s", c+1);
|
||||
else
|
||||
strncpy(info->name, sb->set_name, 32);
|
||||
info->name[32] = 0;
|
||||
snprintf(info->name, sizeof(info->name), "%s", sb->set_name);
|
||||
}
|
||||
|
||||
if (strcmp(update, "force-one")==0) {
|
||||
switch (update) {
|
||||
case UOPT_NAME: {
|
||||
int namelen;
|
||||
|
||||
if (!info->name[0])
|
||||
snprintf(info->name, sizeof(info->name), "%d", info->array.md_minor);
|
||||
memset(sb->set_name, 0, sizeof(sb->set_name));
|
||||
|
||||
namelen = strnlen(homehost, MD_NAME_MAX) + 1 + strnlen(info->name, MD_NAME_MAX);
|
||||
if (homehost &&
|
||||
strchr(info->name, ':') == NULL &&
|
||||
namelen < MD_NAME_MAX) {
|
||||
strcpy(sb->set_name, homehost);
|
||||
strcat(sb->set_name, ":");
|
||||
strcat(sb->set_name, info->name);
|
||||
} else {
|
||||
namelen = min((int)strnlen(info->name, MD_NAME_MAX),
|
||||
(int)sizeof(sb->set_name) - 1);
|
||||
memcpy(sb->set_name, info->name, namelen);
|
||||
memset(&sb->set_name[namelen], '\0',
|
||||
sizeof(sb->set_name) - namelen);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case UOPT_SPEC_FORCE_ONE:
|
||||
/* Not enough devices for a working array,
|
||||
* so bring this one up-to-date
|
||||
*/
|
||||
if (sb->events != __cpu_to_le64(info->events))
|
||||
rv = 1;
|
||||
sb->events = __cpu_to_le64(info->events);
|
||||
} else if (strcmp(update, "force-array")==0) {
|
||||
break;
|
||||
case UOPT_SPEC_FORCE_ARRAY:
|
||||
/* Degraded array and 'force' requests to
|
||||
* maybe need to mark it 'clean'.
|
||||
*/
|
||||
|
@ -1248,7 +1278,8 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
|
|||
rv = 1;
|
||||
sb->resync_offset = MaxSector;
|
||||
}
|
||||
} else if (strcmp(update, "assemble")==0) {
|
||||
break;
|
||||
case UOPT_SPEC_ASSEMBLE: {
|
||||
int d = info->disk.number;
|
||||
int want;
|
||||
if (info->disk.state & (1<<MD_DISK_ACTIVE))
|
||||
|
@ -1281,7 +1312,9 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
|
|||
__cpu_to_le64(info->reshape_progress);
|
||||
rv = 1;
|
||||
}
|
||||
} else if (strcmp(update, "linear-grow-new") == 0) {
|
||||
break;
|
||||
}
|
||||
case UOPT_SPEC_LINEAR_GROW_NEW: {
|
||||
int i;
|
||||
int fd;
|
||||
int max = __le32_to_cpu(sb->max_dev);
|
||||
|
@ -1324,7 +1357,9 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
|
|||
ds - __le64_to_cpu(sb->data_offset));
|
||||
}
|
||||
}
|
||||
} else if (strcmp(update, "linear-grow-update") == 0) {
|
||||
break;
|
||||
}
|
||||
case UOPT_SPEC_LINEAR_GROW_UPDATE: {
|
||||
int max = __le32_to_cpu(sb->max_dev);
|
||||
int i = info->disk.number;
|
||||
if (max > MAX_DEVS || i > MAX_DEVS)
|
||||
|
@ -1336,19 +1371,20 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
|
|||
sb->raid_disks = __cpu_to_le32(info->array.raid_disks);
|
||||
sb->dev_roles[info->disk.number] =
|
||||
__cpu_to_le16(info->disk.raid_disk);
|
||||
} else if (strcmp(update, "resync") == 0) {
|
||||
/* make sure resync happens */
|
||||
sb->resync_offset = 0ULL;
|
||||
} else if (strcmp(update, "uuid") == 0) {
|
||||
break;
|
||||
}
|
||||
case UOPT_UUID:
|
||||
copy_uuid(sb->set_uuid, info->uuid, super1.swapuuid);
|
||||
|
||||
if (__le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET)
|
||||
memcpy(bms->uuid, sb->set_uuid, 16);
|
||||
} else if (strcmp(update, "no-bitmap") == 0) {
|
||||
break;
|
||||
case UOPT_NO_BITMAP:
|
||||
sb->feature_map &= ~__cpu_to_le32(MD_FEATURE_BITMAP_OFFSET);
|
||||
if (bms->version == BITMAP_MAJOR_CLUSTERED && !IsBitmapDirty(devname))
|
||||
sb->resync_offset = MaxSector;
|
||||
} else if (strcmp(update, "bbl") == 0) {
|
||||
break;
|
||||
case UOPT_BBL: {
|
||||
/* only possible if there is room after the bitmap, or if
|
||||
* there is no bitmap
|
||||
*/
|
||||
|
@ -1377,14 +1413,12 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
|
|||
bb_offset = bitmap_offset + bm_sectors;
|
||||
while (bb_offset < (long)sb_offset + 8 + 32*2 &&
|
||||
bb_offset + 8+8 <= (long)data_offset)
|
||||
/* too close to bitmap, and room to grow */
|
||||
bb_offset += 8;
|
||||
if (bb_offset + 8 <= (long)data_offset) {
|
||||
sb->bblog_size = __cpu_to_le16(8);
|
||||
sb->bblog_offset = __cpu_to_le32(bb_offset);
|
||||
}
|
||||
} else {
|
||||
/* 1.0 - Put bbl just before super block */
|
||||
if (bm_sectors && bitmap_offset < 0)
|
||||
space = -bitmap_offset - bm_sectors;
|
||||
else
|
||||
|
@ -1395,7 +1429,9 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
|
|||
sb->bblog_offset = __cpu_to_le32((unsigned)-8);
|
||||
}
|
||||
}
|
||||
} else if (strcmp(update, "no-bbl") == 0) {
|
||||
break;
|
||||
}
|
||||
case UOPT_NO_BBL:
|
||||
if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BAD_BLOCKS))
|
||||
pr_err("Cannot remove active bbl from %s\n",devname);
|
||||
else {
|
||||
|
@ -1403,12 +1439,14 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
|
|||
sb->bblog_shift = 0;
|
||||
sb->bblog_offset = 0;
|
||||
}
|
||||
} else if (strcmp(update, "force-no-bbl") == 0) {
|
||||
break;
|
||||
case UOPT_FORCE_NO_BBL:
|
||||
sb->feature_map &= ~ __cpu_to_le32(MD_FEATURE_BAD_BLOCKS);
|
||||
sb->bblog_size = 0;
|
||||
sb->bblog_shift = 0;
|
||||
sb->bblog_offset = 0;
|
||||
} else if (strcmp(update, "ppl") == 0) {
|
||||
break;
|
||||
case UOPT_PPL: {
|
||||
unsigned long long sb_offset = __le64_to_cpu(sb->super_offset);
|
||||
unsigned long long data_offset = __le64_to_cpu(sb->data_offset);
|
||||
unsigned long long data_size = __le64_to_cpu(sb->data_size);
|
||||
|
@ -1458,37 +1496,26 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
|
|||
sb->ppl.offset = __cpu_to_le16(offset);
|
||||
sb->ppl.size = __cpu_to_le16(space);
|
||||
sb->feature_map |= __cpu_to_le32(MD_FEATURE_PPL);
|
||||
} else if (strcmp(update, "no-ppl") == 0) {
|
||||
break;
|
||||
}
|
||||
case UOPT_NO_PPL:
|
||||
sb->feature_map &= ~__cpu_to_le32(MD_FEATURE_PPL |
|
||||
MD_FEATURE_MUTLIPLE_PPLS);
|
||||
} else if (strcmp(update, "name") == 0) {
|
||||
if (info->name[0] == 0)
|
||||
sprintf(info->name, "%d", info->array.md_minor);
|
||||
memset(sb->set_name, 0, sizeof(sb->set_name));
|
||||
if (homehost &&
|
||||
strchr(info->name, ':') == NULL &&
|
||||
strlen(homehost)+1+strlen(info->name) < 32) {
|
||||
strcpy(sb->set_name, homehost);
|
||||
strcat(sb->set_name, ":");
|
||||
strcat(sb->set_name, info->name);
|
||||
} else {
|
||||
int namelen;
|
||||
|
||||
namelen = min((int)strlen(info->name),
|
||||
(int)sizeof(sb->set_name) - 1);
|
||||
memcpy(sb->set_name, info->name, namelen);
|
||||
memset(&sb->set_name[namelen], '\0',
|
||||
sizeof(sb->set_name) - namelen);
|
||||
}
|
||||
} else if (strcmp(update, "devicesize") == 0 &&
|
||||
__le64_to_cpu(sb->super_offset) <
|
||||
__le64_to_cpu(sb->data_offset)) {
|
||||
/* set data_size to device size less data_offset */
|
||||
break;
|
||||
case UOPT_DEVICESIZE:
|
||||
if (__le64_to_cpu(sb->super_offset) >=
|
||||
__le64_to_cpu(sb->data_offset))
|
||||
break;
|
||||
/*
|
||||
* set data_size to device size less data_offset
|
||||
*/
|
||||
struct misc_dev_info *misc = (struct misc_dev_info*)
|
||||
(st->sb + MAX_SB_SIZE + BM_SUPER_SIZE);
|
||||
sb->data_size = __cpu_to_le64(
|
||||
misc->device_size - __le64_to_cpu(sb->data_offset));
|
||||
} else if (strncmp(update, "revert-reshape", 14) == 0) {
|
||||
break;
|
||||
case UOPT_SPEC_REVERT_RESHAPE_NOBACKUP:
|
||||
case UOPT_REVERT_RESHAPE:
|
||||
rv = -2;
|
||||
if (!(sb->feature_map &
|
||||
__cpu_to_le32(MD_FEATURE_RESHAPE_ACTIVE)))
|
||||
|
@ -1506,7 +1533,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
|
|||
* If that couldn't happen, the "-nobackup" version
|
||||
* will be used.
|
||||
*/
|
||||
if (strcmp(update, "revert-reshape-nobackup") == 0 &&
|
||||
if (update == UOPT_SPEC_REVERT_RESHAPE_NOBACKUP &&
|
||||
sb->reshape_position == 0 &&
|
||||
(__le32_to_cpu(sb->delta_disks) > 0 ||
|
||||
(__le32_to_cpu(sb->delta_disks) == 0 &&
|
||||
|
@ -1530,8 +1557,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
|
|||
* So we reject a revert-reshape unless the
|
||||
* alignment is good.
|
||||
*/
|
||||
if (__le32_to_cpu(sb->level) >= 4 &&
|
||||
__le32_to_cpu(sb->level) <= 6) {
|
||||
if (is_level456(__le32_to_cpu(sb->level))) {
|
||||
reshape_sectors =
|
||||
__le64_to_cpu(sb->reshape_position);
|
||||
reshape_chunk = __le32_to_cpu(sb->new_chunk);
|
||||
|
@ -1570,32 +1596,40 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
|
|||
}
|
||||
done:;
|
||||
}
|
||||
} else if (strcmp(update, "_reshape_progress") == 0)
|
||||
break;
|
||||
case UOPT_SPEC__RESHAPE_PROGRESS:
|
||||
sb->reshape_position = __cpu_to_le64(info->reshape_progress);
|
||||
else if (strcmp(update, "writemostly") == 0)
|
||||
break;
|
||||
case UOPT_SPEC_WRITEMOSTLY:
|
||||
sb->devflags |= WriteMostly1;
|
||||
else if (strcmp(update, "readwrite") == 0)
|
||||
break;
|
||||
case UOPT_SPEC_READWRITE:
|
||||
sb->devflags &= ~WriteMostly1;
|
||||
else if (strcmp(update, "failfast") == 0)
|
||||
break;
|
||||
case UOPT_SPEC_FAILFAST:
|
||||
sb->devflags |= FailFast1;
|
||||
else if (strcmp(update, "nofailfast") == 0)
|
||||
break;
|
||||
case UOPT_SPEC_NOFAILFAST:
|
||||
sb->devflags &= ~FailFast1;
|
||||
else if (strcmp(update, "layout-original") == 0 ||
|
||||
strcmp(update, "layout-alternate") == 0 ||
|
||||
strcmp(update, "layout-unspecified") == 0) {
|
||||
break;
|
||||
case UOPT_LAYOUT_ORIGINAL:
|
||||
case UOPT_LAYOUT_ALTERNATE:
|
||||
case UOPT_LAYOUT_UNSPECIFIED:
|
||||
if (__le32_to_cpu(sb->level) != 0) {
|
||||
pr_err("%s: %s only supported for RAID0\n",
|
||||
devname?:"", update);
|
||||
devname ?: "", map_num(update_options, update));
|
||||
rv = -1;
|
||||
} else if (strcmp(update, "layout-unspecified") == 0) {
|
||||
} else if (update == UOPT_LAYOUT_UNSPECIFIED) {
|
||||
sb->feature_map &= ~__cpu_to_le32(MD_FEATURE_RAID0_LAYOUT);
|
||||
sb->layout = 0;
|
||||
} else {
|
||||
sb->feature_map |= __cpu_to_le32(MD_FEATURE_RAID0_LAYOUT);
|
||||
sb->layout = __cpu_to_le32(update[7] == 'o' ? 1 : 2);
|
||||
sb->layout = __cpu_to_le32(update == UOPT_LAYOUT_ORIGINAL ? 1 : 2);
|
||||
}
|
||||
} else
|
||||
break;
|
||||
default:
|
||||
rv = -1;
|
||||
}
|
||||
|
||||
sb->sb_csum = calc_sb_1_csum(sb);
|
||||
|
||||
|
@ -2207,6 +2241,7 @@ static int load_super1(struct supertype *st, int fd, char *devname)
|
|||
tst.ss = &super1;
|
||||
for (tst.minor_version = 0; tst.minor_version <= 2;
|
||||
tst.minor_version++) {
|
||||
tst.ignore_hw_compat = st->ignore_hw_compat;
|
||||
switch(load_super1(&tst, fd, devname)) {
|
||||
case 0: super = tst.sb;
|
||||
if (bestvers == -1 ||
|
||||
|
@ -2313,7 +2348,6 @@ static int load_super1(struct supertype *st, int fd, char *devname)
|
|||
free(super);
|
||||
return 2;
|
||||
}
|
||||
st->sb = super;
|
||||
|
||||
bsb = (struct bitmap_super_s *)(((char*)super)+MAX_SB_SIZE);
|
||||
|
||||
|
@ -2323,6 +2357,21 @@ static int load_super1(struct supertype *st, int fd, char *devname)
|
|||
if (st->data_offset == INVALID_SECTORS)
|
||||
st->data_offset = __le64_to_cpu(super->data_offset);
|
||||
|
||||
if (st->minor_version >= 1 &&
|
||||
st->ignore_hw_compat == 0 &&
|
||||
(dsize < (__le64_to_cpu(super->data_offset) +
|
||||
__le64_to_cpu(super->size))
|
||||
||
|
||||
dsize < (__le64_to_cpu(super->data_offset) +
|
||||
__le64_to_cpu(super->data_size)))) {
|
||||
if (devname)
|
||||
pr_err("Device %s is not large enough for data described in superblock\n",
|
||||
devname);
|
||||
free(super);
|
||||
return 2;
|
||||
}
|
||||
st->sb = super;
|
||||
|
||||
/* Now check on the bitmap superblock */
|
||||
if ((__le32_to_cpu(super->feature_map)&MD_FEATURE_BITMAP_OFFSET) == 0)
|
||||
return 0;
|
||||
|
@ -2674,7 +2723,17 @@ static int write_bitmap1(struct supertype *st, int fd, enum bitmap_update update
|
|||
}
|
||||
|
||||
if (bms->version == BITMAP_MAJOR_CLUSTERED) {
|
||||
if (__cpu_to_le32(st->nodes) < bms->nodes) {
|
||||
if (st->nodes == 1) {
|
||||
/* the parameter for nodes is not valid */
|
||||
pr_err("Warning: cluster-md at least needs two nodes\n");
|
||||
return -EINVAL;
|
||||
} else if (st->nodes == 0) {
|
||||
/*
|
||||
* parameter "--nodes" is not specified, (eg, add a disk to
|
||||
* clustered raid)
|
||||
*/
|
||||
break;
|
||||
} else if (__cpu_to_le32(st->nodes) < bms->nodes) {
|
||||
/*
|
||||
* Since the nodes num is not increased, no
|
||||
* need to check the space enough or not,
|
||||
|
@ -2800,7 +2859,7 @@ static int validate_geometry1(struct supertype *st, int level,
|
|||
unsigned long long overhead;
|
||||
int fd;
|
||||
|
||||
if (level == LEVEL_CONTAINER) {
|
||||
if (is_container(level)) {
|
||||
if (verbose)
|
||||
pr_err("1.x metadata does not support containers\n");
|
||||
return 0;
|
||||
|
|
11
sysfs.c
11
sysfs.c
|
@ -689,7 +689,7 @@ int sysfs_set_array(struct mdinfo *info, int vers)
|
|||
if (info->array.level < 0)
|
||||
return 0; /* FIXME */
|
||||
rv |= sysfs_set_str(info, NULL, "level",
|
||||
map_num(pers, info->array.level));
|
||||
map_num_s(pers, info->array.level));
|
||||
if (info->reshape_active && info->delta_disks != UnSet)
|
||||
raid_disks -= info->delta_disks;
|
||||
rv |= sysfs_set_num(info, NULL, "raid_disks", raid_disks);
|
||||
|
@ -724,9 +724,10 @@ int sysfs_set_array(struct mdinfo *info, int vers)
|
|||
}
|
||||
|
||||
if (info->consistency_policy == CONSISTENCY_POLICY_PPL) {
|
||||
if (sysfs_set_str(info, NULL, "consistency_policy",
|
||||
map_num(consistency_policies,
|
||||
info->consistency_policy))) {
|
||||
char *policy = map_num_s(consistency_policies,
|
||||
info->consistency_policy);
|
||||
|
||||
if (sysfs_set_str(info, NULL, "consistency_policy", policy)) {
|
||||
pr_err("This kernel does not support PPL. Falling back to consistency-policy=resync.\n");
|
||||
info->consistency_policy = CONSISTENCY_POLICY_RESYNC;
|
||||
}
|
||||
|
@ -762,7 +763,7 @@ int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd, int resume)
|
|||
|
||||
rv = sysfs_set_num(sra, sd, "offset", sd->data_offset);
|
||||
rv |= sysfs_set_num(sra, sd, "size", (sd->component_size+1) / 2);
|
||||
if (sra->array.level != LEVEL_CONTAINER) {
|
||||
if (!is_container(sra->array.level)) {
|
||||
if (sra->consistency_policy == CONSISTENCY_POLICY_PPL) {
|
||||
rv |= sysfs_set_num(sra, sd, "ppl_sector", sd->ppl_sector);
|
||||
rv |= sysfs_set_num(sra, sd, "ppl_size", sd->ppl_size);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
[Unit]
|
||||
Description=Manage MD Reshape on /dev/%I
|
||||
DefaultDependencies=no
|
||||
Documentation=man:mdadm(8)
|
||||
|
||||
[Service]
|
||||
ExecStart=BINDIR/mdadm --grow --continue /dev/%I
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
Description=Activate md array %I even though degraded
|
||||
DefaultDependencies=no
|
||||
ConditionPathExists=!/sys/devices/virtual/block/%i/md/sync_action
|
||||
Documentation=man:mdadm(8)
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
|
||||
[Unit]
|
||||
Description=MD array scrubbing - continuation
|
||||
ConditionPathExistsGlob = /var/lib/mdcheck/MD_UUID_*
|
||||
ConditionPathExistsGlob=/var/lib/mdcheck/MD_UUID_*
|
||||
Documentation=man:mdadm(8)
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
[Unit]
|
||||
Description=MD array scrubbing
|
||||
Wants=mdcheck_continue.timer
|
||||
Documentation=man:mdadm(8)
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
Description=MD Metadata Monitor on /dev/%I
|
||||
DefaultDependencies=no
|
||||
Before=initrd-switch-root.target
|
||||
Documentation=man:mdmon(8)
|
||||
|
||||
[Service]
|
||||
# mdmon should never complain due to lack of a platform,
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
[Unit]
|
||||
Description=Reminder for degraded MD arrays
|
||||
Documentation=man:mdadm(8)
|
||||
|
||||
[Service]
|
||||
Environment=MDADM_MONITOR_ARGS=--scan
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
[Unit]
|
||||
Description=MD array monitor
|
||||
DefaultDependencies=no
|
||||
Documentation=man:mdadm(8)
|
||||
|
||||
[Service]
|
||||
Environment= MDADM_MONITOR_ARGS=--scan
|
||||
|
|
71
test
71
test
|
@ -10,6 +10,9 @@ devlist=
|
|||
|
||||
savelogs=0
|
||||
exitonerror=1
|
||||
ctrl_c_error=0
|
||||
skipbroken=0
|
||||
loop=1
|
||||
prefix='[0-9][0-9]'
|
||||
|
||||
# use loop devices by default if doesn't specify --dev
|
||||
|
@ -35,6 +38,7 @@ die() {
|
|||
|
||||
ctrl_c() {
|
||||
exitonerror=1
|
||||
ctrl_c_error=1
|
||||
}
|
||||
|
||||
# mdadm always adds --quiet, and we want to see any unexpected messages
|
||||
|
@ -79,8 +83,21 @@ mdadm() {
|
|||
do_test() {
|
||||
_script=$1
|
||||
_basename=`basename $_script`
|
||||
_broken=0
|
||||
|
||||
if [ -f "$_script" ]
|
||||
then
|
||||
if [ -f "${_script}.broken" ]; then
|
||||
_broken=1
|
||||
_broken_msg=$(head -n1 "${_script}.broken" | tr -d '\n')
|
||||
if [ "$skipbroken" == "all" ]; then
|
||||
return
|
||||
elif [ "$skipbroken" == "always" ] &&
|
||||
[[ "$_broken_msg" == *always* ]]; then
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
rm -f $targetdir/stderr
|
||||
# this might have been reset: restore the default.
|
||||
echo 2000 > /proc/sys/dev/raid/speed_limit_max
|
||||
|
@ -97,10 +114,15 @@ do_test() {
|
|||
else
|
||||
save_log fail
|
||||
_fail=1
|
||||
if [ "$_broken" == "1" ]; then
|
||||
echo " (KNOWN BROKEN TEST: $_broken_msg)"
|
||||
fi
|
||||
fi
|
||||
[ "$savelogs" == "1" ] &&
|
||||
mv -f $targetdir/log $logdir/$_basename.log
|
||||
[ "$_fail" == "1" -a "$exitonerror" == "1" ] && exit 1
|
||||
[ "$ctrl_c_error" == "1" ] && exit 1
|
||||
[ "$_fail" == "1" -a "$exitonerror" == "1" \
|
||||
-a "$_broken" == "0" ] && exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
@ -117,6 +139,9 @@ do_help() {
|
|||
--logdir=directory Directory to save all logfiles in
|
||||
--save-logs Usually use with --logdir together
|
||||
--keep-going | --no-error Don't stop on error, ie. run all tests
|
||||
--loop=N Run tests N times (0 to run forever)
|
||||
--skip-broken Skip tests that are known to be broken
|
||||
--skip-always-broken Skip tests that are known to always fail
|
||||
--dev=loop|lvm|ram|disk Use loop devices (default), LVM, RAM or disk
|
||||
--disks= Provide a bunch of physical devices for test
|
||||
--volgroup=name LVM volume group for LVM test
|
||||
|
@ -211,6 +236,15 @@ parse_args() {
|
|||
--keep-going | --no-error )
|
||||
exitonerror=0
|
||||
;;
|
||||
--loop=* )
|
||||
loop="${i##*=}"
|
||||
;;
|
||||
--skip-broken )
|
||||
skipbroken=all
|
||||
;;
|
||||
--skip-always-broken )
|
||||
skipbroken=always
|
||||
;;
|
||||
--disable-multipath )
|
||||
unset MULTIPATH
|
||||
;;
|
||||
|
@ -263,19 +297,30 @@ main() {
|
|||
echo "Testing on linux-$(uname -r) kernel"
|
||||
[ "$savelogs" == "1" ] &&
|
||||
echo "Saving logs to $logdir"
|
||||
if [ "x$TESTLIST" != "x" ]
|
||||
then
|
||||
for script in ${TESTLIST[@]}
|
||||
do
|
||||
do_test $testdir/$script
|
||||
done
|
||||
else
|
||||
for script in $testdir/$prefix $testdir/$prefix*[^~]
|
||||
do
|
||||
do_test $script
|
||||
done
|
||||
fi
|
||||
|
||||
while true; do
|
||||
if [ "x$TESTLIST" != "x" ]
|
||||
then
|
||||
for script in ${TESTLIST[@]}
|
||||
do
|
||||
do_test $testdir/$script
|
||||
done
|
||||
else
|
||||
for script in $testdir/$prefix $testdir/$prefix*[^~]
|
||||
do
|
||||
case $script in
|
||||
*.broken) ;;
|
||||
*)
|
||||
do_test $script
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
let loop=$loop-1
|
||||
if [ "$loop" == "0" ]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
|
93
tests/00createnames
Normal file
93
tests/00createnames
Normal file
|
@ -0,0 +1,93 @@
|
|||
set -x -e
|
||||
|
||||
# Test how <devname> and --name= are handled for create mode.
|
||||
# We need to check three properties, generated from those parameters:
|
||||
# - devnode name
|
||||
# - link in /dev/md/ (MD_DEVNAME property from --detail --export)
|
||||
# - name in metadata (MD_NAME property from --examine --export)
|
||||
|
||||
function _verify() {
|
||||
local DEVNODE_NAME="$1"
|
||||
local WANTED_LINK="$2"
|
||||
local WANTED_NAME="$3"
|
||||
|
||||
local RES="$(mdadm -D --export $DEVNODE_NAME | grep MD_DEVNAME)"
|
||||
if [[ "$?" != "0" ]]; then
|
||||
echo "Cannot get details for $DEVNODE_NAME - unexpected devnode."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$WANTED_LINK" != "empty" ]]; then
|
||||
local EXPECTED="MD_DEVNAME=$WANTED_LINK"
|
||||
if [[ "$RES" != "$EXPECTED" ]]; then
|
||||
echo "$RES doesn't match $EXPECTED."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
local RES="$(mdadm -E --export $dev0 | grep MD_NAME)"
|
||||
if [[ "$?" != "0" ]]; then
|
||||
echo "Cannot get metadata from $dev0."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local EXPECTED="MD_NAME=$(hostname):$WANTED_NAME"
|
||||
if [[ "$RES" != "$EXPECTED" ]]; then
|
||||
echo "$RES doesn't match $EXPECTED."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
function _create() {
|
||||
local DEVNAME=$1
|
||||
local NAME=$2
|
||||
|
||||
if [[ -z "$NAME" ]]; then
|
||||
mdadm -CR "$DEVNAME" -l0 -n 1 $dev0 --force
|
||||
else
|
||||
mdadm -CR "$DEVNAME" --name="$NAME" -l0 -n 1 $dev0 --force
|
||||
fi
|
||||
|
||||
if [[ "$?" != "0" ]]; then
|
||||
echo "Cannot create device."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# The most trivial case.
|
||||
_create "/dev/md/name"
|
||||
_verify "/dev/md127" "name" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
_create "name"
|
||||
_verify "/dev/md127" "name" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
# Use 'mdX' as name.
|
||||
_create "/dev/md/md0"
|
||||
_verify "/dev/md127" "md0" "md0"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
_create "md0"
|
||||
_verify "/dev/md127" "md0" "md0"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
# <devnode> is used to create MD_DEVNAME but, name is used to create MD_NAME.
|
||||
_create "/dev/md/devnode" "name"
|
||||
_verify "/dev/md127" "devnode" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
_create "devnode" "name"
|
||||
_verify "/dev/md127" "devnode" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
# Devnode points to /dev/ directory. MD_DEVNAME doesn't exist.
|
||||
_create "/dev/md0"
|
||||
_verify "/dev/md0" "empty" "0"
|
||||
mdadm -S "/dev/md0"
|
||||
|
||||
# Devnode points to /dev/ directory and name is set.
|
||||
_create "/dev/md0" "name"
|
||||
_verify "/dev/md0" "empty" "name"
|
||||
mdadm -S "/dev/md0"
|
|
@ -6,11 +6,9 @@ check raid0
|
|||
testdev $md0 3 $mdsize2_l 512
|
||||
mdadm -S $md0
|
||||
|
||||
# now with version-0.90 superblock
|
||||
# verify raid0 with layouts fail for 0.90
|
||||
mdadm -CR $md0 -e0.90 -l0 -n4 $dev0 $dev1 $dev2 $dev3
|
||||
check raid0
|
||||
testdev $md0 4 $mdsize0 512
|
||||
mdadm -S $md0
|
||||
check opposite_result
|
||||
|
||||
# now with no superblock
|
||||
mdadm -B $md0 -l0 -n5 $dev0 $dev1 $dev2 $dev3 $dev4
|
||||
|
@ -22,8 +20,8 @@ mdadm -S $md0
|
|||
# now same again with different chunk size
|
||||
for chunk in 4 32 256
|
||||
do
|
||||
mdadm -CR $md0 -e0.90 -l raid0 --chunk $chunk -n3 $dev0 $dev1 $dev2
|
||||
check raid0
|
||||
mdadm -CR $md0 -e0.90 -l linear --chunk $chunk -n3 $dev0 $dev1 $dev2
|
||||
check linear
|
||||
testdev $md0 3 $mdsize0 $chunk
|
||||
mdadm -S $md0
|
||||
|
||||
|
|
|
@ -4,10 +4,15 @@ for metadata in 0.9 1.0 1.1 1.2
|
|||
do
|
||||
for level in linear raid0 raid1 raid4 raid5 raid6 raid10
|
||||
do
|
||||
if [[ $metadata == "0.9" && $level == "raid0" ]];
|
||||
then
|
||||
continue
|
||||
fi
|
||||
mdadm -CR $md0 -l $level -n 4 --metadata=$metadata \
|
||||
$dev1 $dev2 $dev3 $dev4 --assume-clean
|
||||
check nosync
|
||||
check $level
|
||||
udevadm settle
|
||||
mdadm -ro $md0
|
||||
check readonly
|
||||
state=$(cat /sys/block/md0/md/array_state)
|
||||
|
|
7
tests/01r5integ.broken
Normal file
7
tests/01r5integ.broken
Normal file
|
@ -0,0 +1,7 @@
|
|||
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
|
7
tests/01raid6integ.broken
Normal file
7
tests/01raid6integ.broken
Normal file
|
@ -0,0 +1,7 @@
|
|||
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
|
|
@ -20,4 +20,6 @@ do
|
|||
testdev $md0 3 $sz 1
|
||||
|
||||
mdadm -S $md0
|
||||
mdadm --zero /dev/loop2
|
||||
mdadm --zero /dev/loop3
|
||||
done
|
||||
|
|
|
@ -68,9 +68,9 @@ mdadm -S $md2
|
|||
### Now for version 0...
|
||||
|
||||
mdadm --zero-superblock $dev0 $dev1 $dev2
|
||||
mdadm -CR $md2 -l0 --metadata=0.90 -n3 $dev0 $dev1 $dev2
|
||||
check raid0
|
||||
tst="testdev $md2 3 $mdsize0 512"
|
||||
mdadm -CR $md2 -llinear --metadata=0.90 -n3 $dev0 $dev1 $dev2
|
||||
check linear
|
||||
tst="testdev $md2 3 $mdsize0 1"
|
||||
$tst
|
||||
|
||||
uuid=`mdadm -Db $md2 | sed 's/.*UUID=//'`
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
# create a raid0, re-assemble with a different super-minor
|
||||
mdadm -CR -e 0.90 $md0 -l0 -n3 $dev0 $dev1 $dev2
|
||||
testdev $md0 3 $mdsize0 512
|
||||
mdadm -CR -e 0.90 $md0 -llinear -n3 $dev0 $dev1 $dev2
|
||||
testdev $md0 3 $mdsize0 1
|
||||
minor1=`mdadm -E $dev0 | sed -n -e 's/.*Preferred Minor : //p'`
|
||||
mdadm -S /dev/md0
|
||||
|
||||
|
|
7
tests/04r5swap.broken
Normal file
7
tests/04r5swap.broken
Normal file
|
@ -0,0 +1,7 @@
|
|||
always fails
|
||||
|
||||
Fails with errors:
|
||||
|
||||
mdadm: /dev/loop0 has no superblock - assembly aborted
|
||||
|
||||
ERROR: no recovery happening
|
|
@ -8,10 +8,14 @@ set -xe
|
|||
|
||||
dlist="$dev0 $dev1 $dev2 $dev3"
|
||||
|
||||
for ls in raid0/4 linear/4 raid1/1 raid5/3 raid6/2
|
||||
for ls in linear/4 raid1/1 raid5/3 raid6/2
|
||||
do
|
||||
s=${ls#*/} l=${ls%/*}
|
||||
mdadm -CR --assume-clean -e 0.90 $md0 --level $l -n 4 -c 64 $dlist
|
||||
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
|
||||
|
|
8
tests/07autoassemble.broken
Normal file
8
tests/07autoassemble.broken
Normal file
|
@ -0,0 +1,8 @@
|
|||
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
|
5
tests/07autodetect.broken
Normal file
5
tests/07autodetect.broken
Normal file
|
@ -0,0 +1,5 @@
|
|||
always fails
|
||||
|
||||
Fails with error:
|
||||
|
||||
ERROR: no resync happening
|
9
tests/07changelevelintr.broken
Normal file
9
tests/07changelevelintr.broken
Normal file
|
@ -0,0 +1,9 @@
|
|||
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
|
9
tests/07changelevels.broken
Normal file
9
tests/07changelevels.broken
Normal file
|
@ -0,0 +1,9 @@
|
|||
always fails
|
||||
|
||||
Fails with errors:
|
||||
|
||||
mdadm: /dev/loop0 is smaller than given size. 18976K < 19968K + metadata
|
||||
mdadm: /dev/loop1 is smaller than given size. 18976K < 19968K + metadata
|
||||
mdadm: /dev/loop2 is smaller than given size. 18976K < 19968K + metadata
|
||||
|
||||
ERROR: /dev/md0 isn't a block device.
|
45
tests/07reshape5intr.broken
Normal file
45
tests/07reshape5intr.broken
Normal file
|
@ -0,0 +1,45 @@
|
|||
always fails
|
||||
|
||||
This patch, recently added to md-next causes the test to always fail:
|
||||
|
||||
7e6ba434cc60 ("md: don't unregister sync_thread with reconfig_mutex
|
||||
held")
|
||||
|
||||
The new error is simply:
|
||||
|
||||
ERROR: no reshape happening
|
||||
|
||||
Before the patch, the error seen is below.
|
||||
|
||||
--
|
||||
|
||||
fails infrequently
|
||||
|
||||
Fails roughly 1 in 4 runs with errors:
|
||||
|
||||
mdadm: Merging with already-assembled /dev/md/0
|
||||
mdadm: cannot re-read metadata from /dev/loop6 - aborting
|
||||
|
||||
ERROR: no reshape happening
|
||||
|
||||
Also have seen a random deadlock:
|
||||
|
||||
INFO: task mdadm:109702 blocked for more than 30 seconds.
|
||||
Not tainted 5.18.0-rc3-eid-vmlocalyes-dbg-00095-g3c2b5427979d #2040
|
||||
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
|
||||
task:mdadm state:D stack: 0 pid:109702 ppid: 1 flags:0x00004000
|
||||
Call Trace:
|
||||
<TASK>
|
||||
__schedule+0x67e/0x13b0
|
||||
schedule+0x82/0x110
|
||||
mddev_suspend+0x2e1/0x330
|
||||
suspend_lo_store+0xbd/0x140
|
||||
md_attr_store+0xcb/0x130
|
||||
sysfs_kf_write+0x89/0xb0
|
||||
kernfs_fop_write_iter+0x202/0x2c0
|
||||
new_sync_write+0x222/0x330
|
||||
vfs_write+0x3bc/0x4d0
|
||||
ksys_write+0xd9/0x180
|
||||
__x64_sys_write+0x43/0x50
|
||||
do_syscall_64+0x3b/0x90
|
||||
entry_SYSCALL_64_after_hwframe+0x44/0xae
|
31
tests/07revert-grow.broken
Normal file
31
tests/07revert-grow.broken
Normal file
|
@ -0,0 +1,31 @@
|
|||
always fails
|
||||
|
||||
This patch, recently added to md-next causes the test to always fail:
|
||||
|
||||
7e6ba434cc60 ("md: don't unregister sync_thread with reconfig_mutex held")
|
||||
|
||||
The errors are:
|
||||
|
||||
mdadm: No active reshape to revert on /dev/loop0
|
||||
ERROR: active raid5 not found
|
||||
|
||||
Before the patch, the error seen is below.
|
||||
|
||||
--
|
||||
|
||||
fails rarely
|
||||
|
||||
Fails about 1 in every 30 runs with errors:
|
||||
|
||||
mdadm: Merging with already-assembled /dev/md/0
|
||||
mdadm: backup file /tmp/md-backup inaccessible: No such file or directory
|
||||
mdadm: failed to add /dev/loop1 to /dev/md/0: Invalid argument
|
||||
mdadm: failed to add /dev/loop2 to /dev/md/0: Invalid argument
|
||||
mdadm: failed to add /dev/loop3 to /dev/md/0: Invalid argument
|
||||
mdadm: failed to add /dev/loop0 to /dev/md/0: Invalid argument
|
||||
mdadm: /dev/md/0 assembled from 1 drive - need all 5 to start it
|
||||
(use --run to insist).
|
||||
|
||||
grep: /sys/block/md*/md/sync_action: No such file or directory
|
||||
|
||||
ERROR: active raid5 not found
|
9
tests/07revert-shrink.broken
Normal file
9
tests/07revert-shrink.broken
Normal file
|
@ -0,0 +1,9 @@
|
|||
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 53760
|
||||
|
||||
ERROR: active raid5 not found
|
12
tests/07testreshape5.broken
Normal file
12
tests/07testreshape5.broken
Normal file
|
@ -0,0 +1,12 @@
|
|||
always fails
|
||||
|
||||
Test seems to run 'test_stripe' at $dir directory, but $dir is never
|
||||
set. If $dir is adjusted to $PWD, the test still fails with:
|
||||
|
||||
mdadm: /dev/loop2 is not suitable for this array.
|
||||
mdadm: create aborted
|
||||
++ return 1
|
||||
++ cmp -s -n 8192 /dev/md0 /tmp/RandFile
|
||||
++ echo cmp failed
|
||||
cmp failed
|
||||
++ exit 2
|
6
tests/09imsm-assemble.broken
Normal file
6
tests/09imsm-assemble.broken
Normal file
|
@ -0,0 +1,6 @@
|
|||
fails infrequently
|
||||
|
||||
Fails roughly 1 in 10 runs with errors:
|
||||
|
||||
mdadm: /dev/loop2 is still in use, cannot remove.
|
||||
/dev/loop2 removal from /dev/md/container should have succeeded
|
5
tests/09imsm-create-fail-rebuild.broken
Normal file
5
tests/09imsm-create-fail-rebuild.broken
Normal file
|
@ -0,0 +1,5 @@
|
|||
always fails
|
||||
|
||||
Fails with error:
|
||||
|
||||
**Error**: Array size mismatch - expected 3072, actual 16384
|
|
@ -1,28 +0,0 @@
|
|||
|
||||
. tests/env-imsm-template
|
||||
|
||||
# create raid arrays with varying degress of overlap
|
||||
mdadm -CR $container -e imsm -n 6 $dev0 $dev1 $dev2 $dev3 $dev4 $dev5
|
||||
imsm_check container 6
|
||||
|
||||
size=1024
|
||||
level=1
|
||||
num_disks=2
|
||||
mdadm -CR $member0 $dev0 $dev1 -n $num_disks -l $level -z $size
|
||||
mdadm -CR $member1 $dev1 $dev2 -n $num_disks -l $level -z $size
|
||||
mdadm -CR $member2 $dev2 $dev3 -n $num_disks -l $level -z $size
|
||||
mdadm -CR $member3 $dev3 $dev4 -n $num_disks -l $level -z $size
|
||||
mdadm -CR $member4 $dev4 $dev5 -n $num_disks -l $level -z $size
|
||||
|
||||
udevadm settle
|
||||
|
||||
offset=0
|
||||
imsm_check member $member0 $num_disks $level $size 1024 $offset
|
||||
offset=$((offset+size+4096))
|
||||
imsm_check member $member1 $num_disks $level $size 1024 $offset
|
||||
offset=$((offset+size+4096))
|
||||
imsm_check member $member2 $num_disks $level $size 1024 $offset
|
||||
offset=$((offset+size+4096))
|
||||
imsm_check member $member3 $num_disks $level $size 1024 $offset
|
||||
offset=$((offset+size+4096))
|
||||
imsm_check member $member4 $num_disks $level $size 1024 $offset
|
7
tests/09imsm-overlap.broken
Normal file
7
tests/09imsm-overlap.broken
Normal file
|
@ -0,0 +1,7 @@
|
|||
always fails
|
||||
|
||||
Fails with errors:
|
||||
|
||||
**Error**: Offset mismatch - expected 15360, actual 0
|
||||
**Error**: Offset mismatch - expected 15360, actual 0
|
||||
/dev/md/vol3 failed check
|
6
tests/10ddf-assemble-missing.broken
Normal file
6
tests/10ddf-assemble-missing.broken
Normal file
|
@ -0,0 +1,6 @@
|
|||
always fails
|
||||
|
||||
Fails with errors:
|
||||
|
||||
ERROR: /dev/md/vol0 has unexpected state on /dev/loop10
|
||||
ERROR: unexpected number of online disks on /dev/loop10
|
7
tests/10ddf-fail-create-race.broken
Normal file
7
tests/10ddf-fail-create-race.broken
Normal file
|
@ -0,0 +1,7 @@
|
|||
usually fails
|
||||
|
||||
Fails about 9 out of 10 times with many errors:
|
||||
|
||||
mdadm: cannot open MISSING: No such file or directory
|
||||
ERROR: non-degraded array found
|
||||
ERROR: disk 0 not marked as failed in meta data
|
5
tests/10ddf-fail-two-spares.broken
Normal file
5
tests/10ddf-fail-two-spares.broken
Normal file
|
@ -0,0 +1,5 @@
|
|||
fails infrequently
|
||||
|
||||
Fails roughly 1 in 3 with error:
|
||||
|
||||
ERROR: /dev/md/vol1 should be optimal in meta data
|
9
tests/10ddf-incremental-wrong-order.broken
Normal file
9
tests/10ddf-incremental-wrong-order.broken
Normal file
|
@ -0,0 +1,9 @@
|
|||
always fails
|
||||
|
||||
Fails with errors:
|
||||
ERROR: sha1sum of /dev/md/vol0 has changed
|
||||
ERROR: /dev/md/vol0 has unexpected state on /dev/loop10
|
||||
ERROR: unexpected number of online disks on /dev/loop10
|
||||
ERROR: /dev/md/vol0 has unexpected state on /dev/loop8
|
||||
ERROR: unexpected number of online disks on /dev/loop8
|
||||
ERROR: sha1sum of /dev/md/vol0 has changed
|
5
tests/14imsm-r1_2d-grow-r1_3d.broken
Normal file
5
tests/14imsm-r1_2d-grow-r1_3d.broken
Normal file
|
@ -0,0 +1,5 @@
|
|||
always fails
|
||||
|
||||
Fails with error:
|
||||
|
||||
mdadm/tests/func.sh: line 325: dvsize/chunk: division by 0 (error token is "chunk")
|
6
tests/14imsm-r1_2d-takeover-r0_2d.broken
Normal file
6
tests/14imsm-r1_2d-takeover-r0_2d.broken
Normal file
|
@ -0,0 +1,6 @@
|
|||
always fails
|
||||
|
||||
Fails with error:
|
||||
|
||||
tests/func.sh: line 325: dvsize/chunk: division by 0 (error token
|
||||
is "chunk")
|
5
tests/18imsm-r10_4d-takeover-r0_2d.broken
Normal file
5
tests/18imsm-r10_4d-takeover-r0_2d.broken
Normal file
|
@ -0,0 +1,5 @@
|
|||
fails rarely
|
||||
|
||||
Fails about 1 run in 100 with message:
|
||||
|
||||
ERROR: size is wrong for /dev/md/vol0: 2 * 5120 (chunk=128) = 20480, not 0
|
6
tests/18imsm-r1_2d-takeover-r0_1d.broken
Normal file
6
tests/18imsm-r1_2d-takeover-r0_1d.broken
Normal file
|
@ -0,0 +1,6 @@
|
|||
always fails
|
||||
|
||||
Fails with error:
|
||||
|
||||
tests/func.sh: line 325: dvsize/chunk: division by 0 (error token
|
||||
is "chunk")
|
5
tests/19raid6auto-repair.broken
Normal file
5
tests/19raid6auto-repair.broken
Normal file
|
@ -0,0 +1,5 @@
|
|||
always fails
|
||||
|
||||
Fails with:
|
||||
|
||||
"should detect errors"
|
5
tests/19raid6repair.broken
Normal file
5
tests/19raid6repair.broken
Normal file
|
@ -0,0 +1,5 @@
|
|||
always fails
|
||||
|
||||
Fails with:
|
||||
|
||||
"should detect errors"
|
|
@ -3,7 +3,7 @@
|
|||
SUBSYSTEM!="block", GOTO="md_end"
|
||||
|
||||
# handle md arrays
|
||||
ACTION!="add|change", GOTO="md_end"
|
||||
ACTION=="remove", GOTO="md_end"
|
||||
KERNEL!="md*", GOTO="md_end"
|
||||
|
||||
# partitions have no md/{array_state,metadata_version}, but should not
|
||||
|
|
|
@ -11,6 +11,11 @@ SUBSYSTEM!="block", GOTO="md_inc_end"
|
|||
ENV{SYSTEMD_READY}=="0", GOTO="md_inc_end"
|
||||
|
||||
# handle potential components of arrays (the ones supported by md)
|
||||
# For member devices which are md/dm devices, we don't need to
|
||||
# handle add event. Because md/dm devices need to do some init jobs.
|
||||
# Then the change event happens.
|
||||
# When adding md/dm devices, ID_FS_TYPE can only be linux_raid_member
|
||||
# after change event happens.
|
||||
ENV{ID_FS_TYPE}=="linux_raid_member", GOTO="md_inc"
|
||||
|
||||
# "noiswmd" on kernel command line stops mdadm from handling
|
||||
|
@ -28,10 +33,14 @@ GOTO="md_inc_end"
|
|||
|
||||
LABEL="md_inc"
|
||||
|
||||
# Bare disks are ready when add event happens, the raid can be assembled.
|
||||
ACTION=="change", KERNEL!="dm-*|md*", GOTO="md_inc_end"
|
||||
|
||||
# remember you can limit what gets auto/incrementally assembled by
|
||||
# mdadm.conf(5)'s 'AUTO' and selectively whitelist using 'ARRAY'
|
||||
ACTION=="add|change", IMPORT{program}="BINDIR/mdadm --incremental --export $devnode --offroot $env{DEVLINKS}"
|
||||
ACTION=="add|change", ENV{MD_STARTED}=="*unsafe*", ENV{MD_FOREIGN}=="no", ENV{SYSTEMD_WANTS}+="mdadm-last-resort@$env{MD_DEVICE}.timer"
|
||||
ACTION!="remove", IMPORT{program}="BINDIR/mdadm --incremental --export $devnode --offroot $env{DEVLINKS}"
|
||||
ACTION!="remove", ENV{MD_STARTED}=="*unsafe*", ENV{MD_FOREIGN}=="no", ENV{SYSTEMD_WANTS}+="mdadm-last-resort@$env{MD_DEVICE}.timer"
|
||||
|
||||
ACTION=="remove", ENV{ID_PATH}=="?*", RUN+="BINDIR/mdadm -If $name --path $env{ID_PATH}"
|
||||
ACTION=="remove", ENV{ID_PATH}!="?*", RUN+="BINDIR/mdadm -If $name"
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ ENV{DEVTYPE}!="partition", GOTO="md_timeouts_end"
|
|||
|
||||
IMPORT{program}="/sbin/mdadm --examine --export $devnode"
|
||||
|
||||
ACTION=="add|change", \
|
||||
ACTION!="remove", \
|
||||
ENV{ID_FS_TYPE}=="linux_raid_member", \
|
||||
ENV{MD_LEVEL}=="raid[1-9]*", \
|
||||
TEST=="/sys/block/$parent/device/timeout", \
|
||||
|
|
112
util.c
112
util.c
|
@ -35,7 +35,6 @@
|
|||
#include <poll.h>
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <signal.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
|
||||
|
@ -167,7 +166,7 @@ retry:
|
|||
pr_err("error %d when get PW mode on lock %s\n", errno, str);
|
||||
/* let's try several times if EAGAIN happened */
|
||||
if (dlm_lock_res->lksb.sb_status == EAGAIN && retry_count < 10) {
|
||||
sleep(10);
|
||||
sleep_for(10, 0, true);
|
||||
retry_count++;
|
||||
goto retry;
|
||||
}
|
||||
|
@ -268,7 +267,7 @@ int md_array_active(int fd)
|
|||
* GET_ARRAY_INFO doesn't provide access to the proper state
|
||||
* information, so fallback to a basic check for raid_disks != 0
|
||||
*/
|
||||
ret = ioctl(fd, GET_ARRAY_INFO, &array);
|
||||
ret = md_get_array_info(fd, &array);
|
||||
}
|
||||
|
||||
return !ret;
|
||||
|
@ -969,47 +968,30 @@ dev_t devnm2devid(char *devnm)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_md_name() - Get main dev node of the md device.
|
||||
* @devnm: Md device name or path.
|
||||
*
|
||||
* Function checks if the full name was passed and returns md name
|
||||
* if it is the MD device.
|
||||
*
|
||||
* Return: Main dev node of the md device or NULL if not found.
|
||||
*/
|
||||
char *get_md_name(char *devnm)
|
||||
{
|
||||
/* find /dev/md%d or /dev/md/%d or make a device /dev/.tmp.md%d */
|
||||
/* if dev < 0, want /dev/md/d%d or find mdp in /proc/devices ... */
|
||||
|
||||
static char devname[50];
|
||||
static char devname[NAME_MAX];
|
||||
struct stat stb;
|
||||
dev_t rdev = devnm2devid(devnm);
|
||||
char *dn;
|
||||
|
||||
if (rdev == 0)
|
||||
return 0;
|
||||
if (strncmp(devnm, "md_", 3) == 0) {
|
||||
snprintf(devname, sizeof(devname), "/dev/md/%s",
|
||||
devnm + 3);
|
||||
if (stat(devname, &stb) == 0 &&
|
||||
(S_IFMT&stb.st_mode) == S_IFBLK && (stb.st_rdev == rdev))
|
||||
return devname;
|
||||
}
|
||||
snprintf(devname, sizeof(devname), "/dev/%s", devnm);
|
||||
if (stat(devname, &stb) == 0 && (S_IFMT&stb.st_mode) == S_IFBLK &&
|
||||
(stb.st_rdev == rdev))
|
||||
if (strncmp(devnm, "/dev/", 5) == 0)
|
||||
snprintf(devname, sizeof(devname), "%s", devnm);
|
||||
else
|
||||
snprintf(devname, sizeof(devname), "/dev/%s", devnm);
|
||||
|
||||
if (!is_mddev(devname))
|
||||
return NULL;
|
||||
if (stat(devname, &stb) == 0 && (S_IFMT&stb.st_mode) == S_IFBLK)
|
||||
return devname;
|
||||
|
||||
snprintf(devname, sizeof(devname), "/dev/md/%s", devnm+2);
|
||||
if (stat(devname, &stb) == 0 && (S_IFMT&stb.st_mode) == S_IFBLK &&
|
||||
(stb.st_rdev == rdev))
|
||||
return devname;
|
||||
|
||||
dn = map_dev(major(rdev), minor(rdev), 0);
|
||||
if (dn)
|
||||
return dn;
|
||||
snprintf(devname, sizeof(devname), "/dev/.tmp.%s", devnm);
|
||||
if (mknod(devname, S_IFBLK | 0600, rdev) == -1)
|
||||
if (errno != EEXIST)
|
||||
return NULL;
|
||||
|
||||
if (stat(devname, &stb) == 0 && (S_IFMT&stb.st_mode) == S_IFBLK &&
|
||||
(stb.st_rdev == rdev))
|
||||
return devname;
|
||||
unlink(devname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1028,6 +1010,20 @@ int get_maj_min(char *dev, int *major, int *minor)
|
|||
*e == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* is_bit_set() - get bit value by index.
|
||||
* @val: value.
|
||||
* @index: index of the bit (LSB numbering).
|
||||
*
|
||||
* Return: bit value.
|
||||
*/
|
||||
bool is_bit_set(int *val, unsigned char index)
|
||||
{
|
||||
if ((*val) & (1 << index))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int dev_open(char *dev, int flags)
|
||||
{
|
||||
/* like 'open', but if 'dev' matches %d:%d, create a temp
|
||||
|
@ -1086,7 +1082,7 @@ int open_dev_excl(char *devnm)
|
|||
int i;
|
||||
int flags = O_RDWR;
|
||||
dev_t devid = devnm2devid(devnm);
|
||||
long delay = 1000;
|
||||
unsigned int delay = 1; // miliseconds
|
||||
|
||||
sprintf(buf, "%d:%d", major(devid), minor(devid));
|
||||
for (i = 0; i < 25; i++) {
|
||||
|
@ -1099,8 +1095,8 @@ int open_dev_excl(char *devnm)
|
|||
}
|
||||
if (errno != EBUSY)
|
||||
return fd;
|
||||
usleep(delay);
|
||||
if (delay < 200000)
|
||||
sleep_for(0, MSEC_TO_NSEC(delay), true);
|
||||
if (delay < 200)
|
||||
delay *= 2;
|
||||
}
|
||||
return -1;
|
||||
|
@ -1124,7 +1120,7 @@ void wait_for(char *dev, int fd)
|
|||
{
|
||||
int i;
|
||||
struct stat stb_want;
|
||||
long delay = 1000;
|
||||
unsigned int delay = 1; // miliseconds
|
||||
|
||||
if (fstat(fd, &stb_want) != 0 ||
|
||||
(stb_want.st_mode & S_IFMT) != S_IFBLK)
|
||||
|
@ -1136,8 +1132,8 @@ void wait_for(char *dev, int fd)
|
|||
(stb.st_mode & S_IFMT) == S_IFBLK &&
|
||||
(stb.st_rdev == stb_want.st_rdev))
|
||||
return;
|
||||
usleep(delay);
|
||||
if (delay < 200000)
|
||||
sleep_for(0, MSEC_TO_NSEC(delay), true);
|
||||
if (delay < 200)
|
||||
delay *= 2;
|
||||
}
|
||||
if (i == 25)
|
||||
|
@ -1822,7 +1818,7 @@ int hot_remove_disk(int mdfd, unsigned long dev, int force)
|
|||
while ((ret = ioctl(mdfd, HOT_REMOVE_DISK, dev)) == -1 &&
|
||||
errno == EBUSY &&
|
||||
cnt-- > 0)
|
||||
usleep(10000);
|
||||
sleep_for(0, MSEC_TO_NSEC(10), true);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1835,7 +1831,7 @@ int sys_hot_remove_disk(int statefd, int force)
|
|||
while ((ret = write(statefd, "remove", 6)) == -1 &&
|
||||
errno == EBUSY &&
|
||||
cnt-- > 0)
|
||||
usleep(10000);
|
||||
sleep_for(0, MSEC_TO_NSEC(10), true);
|
||||
return ret == 6 ? 0 : -1;
|
||||
}
|
||||
|
||||
|
@ -2376,3 +2372,27 @@ out:
|
|||
close(fd_zero);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* sleep_for() - Sleeps for specified time.
|
||||
* @sec: Seconds to sleep for.
|
||||
* @nsec: Nanoseconds to sleep for, has to be less than one second.
|
||||
* @wake_after_interrupt: If set, wake up if interrupted.
|
||||
*
|
||||
* Function immediately returns if error different than EINTR occurs.
|
||||
*/
|
||||
void sleep_for(unsigned int sec, long nsec, bool wake_after_interrupt)
|
||||
{
|
||||
struct timespec delay = {.tv_sec = sec, .tv_nsec = nsec};
|
||||
|
||||
assert(nsec < MSEC_TO_NSEC(1000));
|
||||
|
||||
do {
|
||||
errno = 0;
|
||||
nanosleep(&delay, &delay);
|
||||
if (errno != 0 && errno != EINTR) {
|
||||
pr_err("Error sleeping for %us %ldns: %s\n", sec, nsec, strerror(errno));
|
||||
return;
|
||||
}
|
||||
} while (!wake_after_interrupt && errno == EINTR);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue