Merging upstream version 4.2+20231026.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
bb079da599
commit
a701b01644
30 changed files with 956 additions and 423 deletions
12
Assemble.c
12
Assemble.c
|
@ -428,8 +428,6 @@ static int select_devices(struct mddev_dev *devlist,
|
|||
|
||||
/* make sure we finished the loop */
|
||||
tmpdev = NULL;
|
||||
free(st);
|
||||
st = NULL;
|
||||
goto loop;
|
||||
} else {
|
||||
content = *contentp;
|
||||
|
@ -1992,12 +1990,10 @@ int assemble_container_content(struct supertype *st, int mdfd,
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(sra->text_version, content->text_version) != 0) {
|
||||
if (content->array.major_version == -1 &&
|
||||
content->array.minor_version == -2 &&
|
||||
c->readonly &&
|
||||
content->text_version[0] == '/')
|
||||
content->text_version[0] = '-';
|
||||
/* Fill sysfs properties only if they are not set. Determine it by checking text_version
|
||||
* and ignoring special character on the first place.
|
||||
*/
|
||||
if (strcmp(sra->text_version + 1, content->text_version + 1) != 0) {
|
||||
if (sysfs_set_array(content, 9003) != 0) {
|
||||
sysfs_free(sra);
|
||||
return 1;
|
||||
|
|
21
Build.c
21
Build.c
|
@ -24,8 +24,8 @@
|
|||
|
||||
#include "mdadm.h"
|
||||
|
||||
int Build(char *mddev, struct mddev_dev *devlist,
|
||||
struct shape *s, struct context *c)
|
||||
int Build(struct mddev_ident *ident, struct mddev_dev *devlist, struct shape *s,
|
||||
struct context *c)
|
||||
{
|
||||
/* Build a linear or raid0 arrays without superblocks
|
||||
* We cannot really do any checks, we just do it.
|
||||
|
@ -75,13 +75,12 @@ int Build(char *mddev, struct mddev_dev *devlist,
|
|||
|
||||
/* We need to create the device. It can have no name. */
|
||||
map_lock(&map);
|
||||
mdfd = create_mddev(mddev, NULL, c->autof, LOCAL,
|
||||
mdfd = create_mddev(ident->devname, NULL, c->autof, LOCAL,
|
||||
chosen_name, 0);
|
||||
if (mdfd < 0) {
|
||||
map_unlock(&map);
|
||||
return 1;
|
||||
}
|
||||
mddev = chosen_name;
|
||||
|
||||
map_update(&map, fd2devnm(mdfd), "none", uuid, chosen_name);
|
||||
map_unlock(&map);
|
||||
|
@ -93,7 +92,7 @@ int Build(char *mddev, struct mddev_dev *devlist,
|
|||
array.nr_disks = s->raiddisks;
|
||||
array.raid_disks = s->raiddisks;
|
||||
array.md_minor = 0;
|
||||
if (fstat_is_blkdev(mdfd, mddev, &rdev))
|
||||
if (fstat_is_blkdev(mdfd, chosen_name, &rdev))
|
||||
array.md_minor = minor(rdev);
|
||||
array.not_persistent = 1;
|
||||
array.state = 0; /* not clean, but no errors */
|
||||
|
@ -108,8 +107,7 @@ int Build(char *mddev, struct mddev_dev *devlist,
|
|||
array.chunk_size = s->chunk*1024;
|
||||
array.layout = s->layout;
|
||||
if (md_set_array_info(mdfd, &array)) {
|
||||
pr_err("md_set_array_info() failed for %s: %s\n",
|
||||
mddev, strerror(errno));
|
||||
pr_err("md_set_array_info() failed for %s: %s\n", chosen_name, strerror(errno));
|
||||
goto abort;
|
||||
}
|
||||
|
||||
|
@ -178,8 +176,8 @@ int Build(char *mddev, struct mddev_dev *devlist,
|
|||
}
|
||||
if (bitmap_fd >= 0) {
|
||||
if (ioctl(mdfd, SET_BITMAP_FILE, bitmap_fd) < 0) {
|
||||
pr_err("Cannot set bitmap file for %s: %s\n",
|
||||
mddev, strerror(errno));
|
||||
pr_err("Cannot set bitmap file for %s: %s\n", chosen_name,
|
||||
strerror(errno));
|
||||
goto abort;
|
||||
}
|
||||
}
|
||||
|
@ -193,9 +191,8 @@ int Build(char *mddev, struct mddev_dev *devlist,
|
|||
}
|
||||
|
||||
if (c->verbose >= 0)
|
||||
pr_err("array %s built and started.\n",
|
||||
mddev);
|
||||
wait_for(mddev, mdfd);
|
||||
pr_err("array %s built and started.\n", chosen_name);
|
||||
wait_for(chosen_name, mdfd);
|
||||
close(mdfd);
|
||||
return 0;
|
||||
|
||||
|
|
35
Create.c
35
Create.c
|
@ -471,11 +471,8 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int Create(struct supertype *st, char *mddev,
|
||||
char *name, int *uuid,
|
||||
int subdevs, struct mddev_dev *devlist,
|
||||
struct shape *s,
|
||||
struct context *c)
|
||||
int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
|
||||
struct mddev_dev *devlist, struct shape *s, struct context *c)
|
||||
{
|
||||
/*
|
||||
* Create a new raid array.
|
||||
|
@ -497,6 +494,8 @@ int Create(struct supertype *st, char *mddev,
|
|||
unsigned long long minsize = 0, maxsize = 0;
|
||||
char *mindisc = NULL;
|
||||
char *maxdisc = NULL;
|
||||
char *name = ident->name;
|
||||
int *uuid = ident->uuid_set == 1 ? ident->uuid : NULL;
|
||||
int dnum;
|
||||
struct mddev_dev *dv;
|
||||
dev_t rdev;
|
||||
|
@ -1015,7 +1014,7 @@ int Create(struct supertype *st, char *mddev,
|
|||
|
||||
/* We need to create the device */
|
||||
map_lock(&map);
|
||||
mdfd = create_mddev(mddev, name, c->autof, LOCAL, chosen_name, 1);
|
||||
mdfd = create_mddev(ident->devname, ident->name, c->autof, LOCAL, chosen_name, 1);
|
||||
if (mdfd < 0) {
|
||||
map_unlock(&map);
|
||||
return 1;
|
||||
|
@ -1032,7 +1031,6 @@ int Create(struct supertype *st, char *mddev,
|
|||
udev_unblock();
|
||||
return 1;
|
||||
}
|
||||
mddev = chosen_name;
|
||||
|
||||
memset(&inf, 0, sizeof(inf));
|
||||
md_get_array_info(mdfd, &inf);
|
||||
|
@ -1050,7 +1048,7 @@ int Create(struct supertype *st, char *mddev,
|
|||
* with, but it chooses to trust me instead. Sigh
|
||||
*/
|
||||
info.array.md_minor = 0;
|
||||
if (fstat_is_blkdev(mdfd, mddev, &rdev))
|
||||
if (fstat_is_blkdev(mdfd, chosen_name, &rdev))
|
||||
info.array.md_minor = minor(rdev);
|
||||
info.array.not_persistent = 0;
|
||||
|
||||
|
@ -1102,8 +1100,8 @@ int Create(struct supertype *st, char *mddev,
|
|||
info.array.layout = s->layout;
|
||||
info.array.chunk_size = s->chunk*1024;
|
||||
|
||||
if (name == NULL || *name == 0) {
|
||||
/* base name on mddev */
|
||||
if (*name == 0) {
|
||||
/* base name on devname */
|
||||
/* /dev/md0 -> 0
|
||||
* /dev/md_d0 -> d0
|
||||
* /dev/md_foo -> foo
|
||||
|
@ -1113,15 +1111,16 @@ int Create(struct supertype *st, char *mddev,
|
|||
* /dev/mdhome -> home
|
||||
*/
|
||||
/* FIXME compare this with rules in create_mddev */
|
||||
name = strrchr(mddev, '/');
|
||||
name = strrchr(chosen_name, '/');
|
||||
|
||||
if (name) {
|
||||
name++;
|
||||
if (strncmp(name, "md_", 3) == 0 &&
|
||||
strlen(name) > 3 && (name-mddev) == 5 /* /dev/ */)
|
||||
strlen(name) > 3 && (name - chosen_name) == 5 /* /dev/ */)
|
||||
name += 3;
|
||||
else if (strncmp(name, "md", 2) == 0 &&
|
||||
strlen(name) > 2 && isdigit(name[2]) &&
|
||||
(name-mddev) == 5 /* /dev/ */)
|
||||
(name - chosen_name) == 5 /* /dev/ */)
|
||||
name += 2;
|
||||
}
|
||||
}
|
||||
|
@ -1215,8 +1214,7 @@ int Create(struct supertype *st, char *mddev,
|
|||
}
|
||||
rv = set_array_info(mdfd, st, &info);
|
||||
if (rv) {
|
||||
pr_err("failed to set array info for %s: %s\n",
|
||||
mddev, strerror(errno));
|
||||
pr_err("failed to set array info for %s: %s\n", chosen_name, strerror(errno));
|
||||
goto abort_locked;
|
||||
}
|
||||
|
||||
|
@ -1237,8 +1235,7 @@ int Create(struct supertype *st, char *mddev,
|
|||
goto abort_locked;
|
||||
}
|
||||
if (ioctl(mdfd, SET_BITMAP_FILE, bitmap_fd) < 0) {
|
||||
pr_err("Cannot set bitmap file for %s: %s\n",
|
||||
mddev, strerror(errno));
|
||||
pr_err("Cannot set bitmap file for %s: %s\n", chosen_name, strerror(errno));
|
||||
goto abort_locked;
|
||||
}
|
||||
}
|
||||
|
@ -1254,7 +1251,7 @@ int Create(struct supertype *st, char *mddev,
|
|||
* create links */
|
||||
sysfs_uevent(&info, "change");
|
||||
if (c->verbose >= 0)
|
||||
pr_err("container %s prepared.\n", mddev);
|
||||
pr_err("container %s prepared.\n", chosen_name);
|
||||
wait_for(chosen_name, mdfd);
|
||||
} else if (c->runstop == 1 || subdevs >= s->raiddisks) {
|
||||
if (st->ss->external) {
|
||||
|
@ -1312,7 +1309,7 @@ int Create(struct supertype *st, char *mddev,
|
|||
ioctl(mdfd, RESTART_ARRAY_RW, NULL);
|
||||
}
|
||||
if (c->verbose >= 0)
|
||||
pr_info("array %s started.\n", mddev);
|
||||
pr_info("array %s started.\n", chosen_name);
|
||||
if (st->ss->external && st->container_devnm[0]) {
|
||||
if (need_mdmon)
|
||||
start_mdmon(st->container_devnm);
|
||||
|
|
17
Detail.c
17
Detail.c
|
@ -254,11 +254,9 @@ int Detail(char *dev, struct context *c)
|
|||
fname_from_uuid(st, info, nbuf, ':');
|
||||
printf("MD_UUID=%s\n", nbuf + 5);
|
||||
mp = map_by_uuid(&map, info->uuid);
|
||||
if (mp && mp->path && strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) {
|
||||
printf("MD_DEVNAME=");
|
||||
print_escape(mp->path + DEV_MD_DIR_LEN);
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
if (mp && mp->path && strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0)
|
||||
printf("MD_DEVNAME=%s\n", mp->path + DEV_MD_DIR_LEN);
|
||||
|
||||
if (st->ss->export_detail_super)
|
||||
st->ss->export_detail_super(st);
|
||||
|
@ -271,12 +269,9 @@ int Detail(char *dev, struct context *c)
|
|||
__fname_from_uuid(mp->uuid, 0, nbuf, ':');
|
||||
printf("MD_UUID=%s\n", nbuf+5);
|
||||
}
|
||||
if (mp && mp->path &&
|
||||
strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) {
|
||||
printf("MD_DEVNAME=");
|
||||
print_escape(mp->path + DEV_MD_DIR_LEN);
|
||||
putchar('\n');
|
||||
}
|
||||
if (mp && mp->path && strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0)
|
||||
printf("MD_DEVNAME=%s\n", mp->path + DEV_MD_DIR_LEN);
|
||||
|
||||
map_free(map);
|
||||
}
|
||||
if (!c->no_devices && sra) {
|
||||
|
|
|
@ -1467,17 +1467,6 @@ static int Incremental_container(struct supertype *st, char *devname,
|
|||
|
||||
st->ss->getinfo_super(st, &info, NULL);
|
||||
|
||||
if ((c->runstop > 0 && info.container_enough >= 0) ||
|
||||
info.container_enough > 0)
|
||||
/* pass */;
|
||||
else {
|
||||
if (c->export) {
|
||||
printf("MD_STARTED=no\n");
|
||||
} else if (c->verbose)
|
||||
pr_err("not enough devices to start the container\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
match = conf_match(st, &info, devname, c->verbose, &rv);
|
||||
if (match == NULL && rv == 2)
|
||||
return rv;
|
||||
|
@ -1628,54 +1617,18 @@ release:
|
|||
return rv;
|
||||
}
|
||||
|
||||
static void run_udisks(char *arg1, char *arg2)
|
||||
{
|
||||
int pid = fork();
|
||||
int status;
|
||||
if (pid == 0) {
|
||||
manage_fork_fds(1);
|
||||
execl("/usr/bin/udisks", "udisks", arg1, arg2, NULL);
|
||||
execl("/bin/udisks", "udisks", arg1, arg2, NULL);
|
||||
exit(1);
|
||||
}
|
||||
while (pid > 0 && wait(&status) != pid)
|
||||
;
|
||||
}
|
||||
|
||||
static int force_remove(char *devnm, int fd, struct mdinfo *mdi, int verbose)
|
||||
{
|
||||
int rv;
|
||||
int devid = devnm2devid(devnm);
|
||||
|
||||
run_udisks("--unmount", map_dev(major(devid), minor(devid), 0));
|
||||
rv = Manage_stop(devnm, fd, verbose, 1);
|
||||
if (rv) {
|
||||
/* At least we can try to trigger a 'remove' */
|
||||
sysfs_uevent(mdi, "remove");
|
||||
if (verbose)
|
||||
pr_err("Fail to stop %s too.\n", devnm);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void remove_from_member_array(struct mdstat_ent *memb,
|
||||
struct mddev_dev *devlist, int verbose)
|
||||
{
|
||||
int rv;
|
||||
struct mdinfo mmdi;
|
||||
int subfd = open_dev(memb->devnm);
|
||||
|
||||
if (subfd >= 0) {
|
||||
rv = Manage_subdevs(memb->devnm, subfd, devlist, verbose,
|
||||
0, UOPT_UNDEFINED, 0);
|
||||
if (rv & 2) {
|
||||
if (sysfs_init(&mmdi, -1, memb->devnm))
|
||||
pr_err("unable to initialize sysfs for: %s\n",
|
||||
memb->devnm);
|
||||
else
|
||||
force_remove(memb->devnm, subfd, &mmdi,
|
||||
verbose);
|
||||
}
|
||||
/*
|
||||
* Ignore the return value because it's necessary
|
||||
* to handle failure condition here.
|
||||
*/
|
||||
Manage_subdevs(memb->devnm, subfd, devlist, verbose,
|
||||
0, UOPT_UNDEFINED, 0);
|
||||
close(subfd);
|
||||
}
|
||||
}
|
||||
|
@ -1758,21 +1711,19 @@ int IncrementalRemove(char *devname, char *id_path, int verbose)
|
|||
}
|
||||
free_mdstat(mdstat);
|
||||
} else {
|
||||
rv |= Manage_subdevs(ent->devnm, mdfd, &devlist,
|
||||
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.
|
||||
/*
|
||||
* This 'I' incremental remove is a try-best effort,
|
||||
* the failure condition can be safely ignored
|
||||
* because of the following up 'r' remove.
|
||||
*/
|
||||
rv = force_remove(ent->devnm, mdfd, &mdi, verbose);
|
||||
goto end;
|
||||
}
|
||||
Manage_subdevs(ent->devnm, mdfd, &devlist,
|
||||
verbose, 0, UOPT_UNDEFINED, 0);
|
||||
}
|
||||
|
||||
devlist.disposition = 'r';
|
||||
rv = Manage_subdevs(ent->devnm, mdfd, &devlist,
|
||||
verbose, 0, UOPT_UNDEFINED, 0);
|
||||
end:
|
||||
|
||||
close(mdfd);
|
||||
free_mdstat(ent);
|
||||
return rv;
|
||||
|
|
41
Makefile
41
Makefile
|
@ -30,7 +30,7 @@
|
|||
|
||||
# define "CXFLAGS" to give extra flags to CC.
|
||||
# e.g. make CXFLAGS=-O to optimise
|
||||
CXFLAGS ?=-O2
|
||||
CXFLAGS ?=-O2 -D_FORTIFY_SOURCE=2
|
||||
TCC = tcc
|
||||
UCLIBC_GCC = $(shell for nm in i386-uclibc-linux-gcc i386-uclibc-gcc; do which $$nm > /dev/null && { echo $$nm ; exit; } ; done; echo false No uclibc found )
|
||||
#DIET_GCC = diet gcc
|
||||
|
@ -50,14 +50,30 @@ ifeq ($(origin CC),default)
|
|||
CC := $(CROSS_COMPILE)gcc
|
||||
endif
|
||||
CXFLAGS ?= -ggdb
|
||||
CWFLAGS = -Wall -Werror -Wstrict-prototypes -Wextra -Wno-unused-parameter
|
||||
CWFLAGS ?= -Wall -Werror -Wstrict-prototypes -Wextra -Wno-unused-parameter -Wformat -Wformat-security -Werror=format-security -fstack-protector-strong -fPIE -Warray-bounds
|
||||
ifdef WARN_UNUSED
|
||||
CWFLAGS += -Wp,-D_FORTIFY_SOURCE=2 -O3
|
||||
CWFLAGS += -Wp -O3
|
||||
endif
|
||||
|
||||
FALLTHROUGH := $(shell gcc -v --help 2>&1 | grep "implicit-fallthrough" | wc -l)
|
||||
ifneq "$(FALLTHROUGH)" "0"
|
||||
CWFLAGS += -Wimplicit-fallthrough=0
|
||||
ifeq ($(origin FALLTHROUGH), undefined)
|
||||
FALLTHROUGH := $(shell gcc -Q --help=warnings 2>&1 | grep "implicit-fallthrough" | wc -l)
|
||||
ifneq "$(FALLTHROUGH)" "0"
|
||||
CWFLAGS += -Wimplicit-fallthrough=0
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(origin FORMATOVERFLOW), undefined)
|
||||
FORMATOVERFLOW := $(shell gcc -Q --help=warnings 2>&1 | grep "format-overflow" | wc -l)
|
||||
ifneq "$(FORMATOVERFLOW)" "0"
|
||||
CWFLAGS += -Wformat-overflow
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(origin STRINGOPOVERFLOW), undefined)
|
||||
STRINGOPOVERFLOW := $(shell gcc -Q --help=warnings 2>&1 | grep "stringop-overflow" | wc -l)
|
||||
ifneq "$(STRINGOPOVERFLOW)" "0"
|
||||
CWFLAGS += -Wstringop-overflow
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef DEBIAN
|
||||
|
@ -116,10 +132,12 @@ CFLAGS += -DUSE_PTHREADS
|
|||
MON_LDFLAGS += -pthread
|
||||
endif
|
||||
|
||||
LDFLAGS = -Wl,-z,now,-z,noexecstack
|
||||
|
||||
# If you want a static binary, you might uncomment these
|
||||
# LDFLAGS = -static
|
||||
# LDFLAGS += -static
|
||||
# STRIP = -s
|
||||
LDLIBS = -ldl
|
||||
LDLIBS = -ldl -pie
|
||||
|
||||
# To explicitly disable libudev, set -DNO_LIBUDEV in CXFLAGS
|
||||
ifeq (, $(findstring -DNO_LIBUDEV, $(CXFLAGS)))
|
||||
|
@ -209,14 +227,13 @@ mdadm.Os : $(SRCS) $(INCL)
|
|||
$(CC) -o mdadm.Os $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -DHAVE_STDINT_H -Os $(SRCS) $(LDLIBS)
|
||||
|
||||
mdadm.O2 : $(SRCS) $(INCL) mdmon.O2
|
||||
$(CC) -o mdadm.O2 $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -DHAVE_STDINT_H -O2 -D_FORTIFY_SOURCE=2 $(SRCS) $(LDLIBS)
|
||||
$(CC) -o mdadm.O2 $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -DHAVE_STDINT_H -O2 $(SRCS) $(LDLIBS)
|
||||
|
||||
mdmon.O2 : $(MON_SRCS) $(INCL) mdmon.h
|
||||
$(CC) -o mdmon.O2 $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(MON_LDFLAGS) -DHAVE_STDINT_H -O2 -D_FORTIFY_SOURCE=2 $(MON_SRCS) $(LDLIBS)
|
||||
$(CC) -o mdmon.O2 $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(MON_LDFLAGS) -DHAVE_STDINT_H -O2 $(MON_SRCS) $(LDLIBS)
|
||||
|
||||
# use '-z now' to guarantee no dynamic linker interactions with the monitor thread
|
||||
mdmon : $(MON_OBJS) | check_rundir
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(MON_LDFLAGS) -Wl,-z,now -o mdmon $(MON_OBJS) $(LDLIBS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(MON_LDFLAGS) -o mdmon $(MON_OBJS) $(LDLIBS)
|
||||
msg.o: msg.c msg.h
|
||||
|
||||
test_stripe : restripe.c xmalloc.o mdadm.h
|
||||
|
|
24
Manage.c
24
Manage.c
|
@ -704,6 +704,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
|
|||
struct supertype *dev_st;
|
||||
int j;
|
||||
mdu_disk_info_t disc;
|
||||
struct map_ent *map = NULL;
|
||||
|
||||
if (!get_dev_size(tfd, dv->devname, &ldsize)) {
|
||||
if (dv->disposition == 'M')
|
||||
|
@ -907,6 +908,9 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
|
|||
disc.raid_disk = 0;
|
||||
}
|
||||
|
||||
if (map_lock(&map))
|
||||
pr_err("failed to get exclusive lock on mapfile when add disk\n");
|
||||
|
||||
if (array->not_persistent==0) {
|
||||
int dfd;
|
||||
if (dv->disposition == 'j')
|
||||
|
@ -918,9 +922,9 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
|
|||
dfd = dev_open(dv->devname, O_RDWR | O_EXCL|O_DIRECT);
|
||||
if (tst->ss->add_to_super(tst, &disc, dfd,
|
||||
dv->devname, INVALID_SECTORS))
|
||||
return -1;
|
||||
goto unlock;
|
||||
if (tst->ss->write_init_super(tst))
|
||||
return -1;
|
||||
goto unlock;
|
||||
} else if (dv->disposition == 'A') {
|
||||
/* this had better be raid1.
|
||||
* As we are "--re-add"ing we must find a spare slot
|
||||
|
@ -978,14 +982,14 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
|
|||
pr_err("add failed for %s: could not get exclusive access to container\n",
|
||||
dv->devname);
|
||||
tst->ss->free_super(tst);
|
||||
return -1;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/* Check if metadata handler is able to accept the drive */
|
||||
if (!tst->ss->validate_geometry(tst, LEVEL_CONTAINER, 0, 1, NULL,
|
||||
0, 0, dv->devname, NULL, 0, 1)) {
|
||||
close(container_fd);
|
||||
return -1;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
Kill(dv->devname, NULL, 0, -1, 0);
|
||||
|
@ -994,7 +998,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
|
|||
dv->devname, INVALID_SECTORS)) {
|
||||
close(dfd);
|
||||
close(container_fd);
|
||||
return -1;
|
||||
goto unlock;
|
||||
}
|
||||
if (!mdmon_running(tst->container_devnm))
|
||||
tst->ss->sync_metadata(tst);
|
||||
|
@ -1005,7 +1009,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
|
|||
dv->devname);
|
||||
close(container_fd);
|
||||
tst->ss->free_super(tst);
|
||||
return -1;
|
||||
goto unlock;
|
||||
}
|
||||
sra->array.level = LEVEL_CONTAINER;
|
||||
/* Need to set data_offset and component_size */
|
||||
|
@ -1020,7 +1024,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
|
|||
pr_err("add new device to external metadata failed for %s\n", dv->devname);
|
||||
close(container_fd);
|
||||
sysfs_free(sra);
|
||||
return -1;
|
||||
goto unlock;
|
||||
}
|
||||
ping_monitor(devnm);
|
||||
sysfs_free(sra);
|
||||
|
@ -1034,7 +1038,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
|
|||
else
|
||||
pr_err("add new device failed for %s as %d: %s\n",
|
||||
dv->devname, j, strerror(errno));
|
||||
return -1;
|
||||
goto unlock;
|
||||
}
|
||||
if (dv->disposition == 'j') {
|
||||
pr_err("Journal added successfully, making %s read-write\n", devname);
|
||||
|
@ -1045,7 +1049,11 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
|
|||
}
|
||||
if (verbose >= 0)
|
||||
pr_err("added %s\n", dv->devname);
|
||||
map_unlock(&map);
|
||||
return 1;
|
||||
unlock:
|
||||
map_unlock(&map);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Manage_remove(struct supertype *tst, int fd, struct mddev_dev *dv,
|
||||
|
|
184
config.c
184
config.c
|
@ -122,7 +122,7 @@ int match_keyword(char *word)
|
|||
/**
|
||||
* is_devname_ignore() - check if &devname is a special "<ignore>" keyword.
|
||||
*/
|
||||
bool is_devname_ignore(char *devname)
|
||||
bool is_devname_ignore(const char *devname)
|
||||
{
|
||||
static const char keyword[] = "<ignore>";
|
||||
|
||||
|
@ -131,6 +131,34 @@ bool is_devname_ignore(char *devname)
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* ident_log() - generate and write message to the user.
|
||||
* @param_name: name of the property.
|
||||
* @value: value of the property.
|
||||
* @reason: meaningful description.
|
||||
* @cmdline: context dependent actions, see below.
|
||||
*
|
||||
* The function is made to provide similar error handling for both config and cmdline. The behavior
|
||||
* is configurable via @cmdline. Message has following format:
|
||||
* "Value "@value" cannot be set for @param_name. Reason: @reason."
|
||||
*
|
||||
* If cmdline is on:
|
||||
* - message is written to stderr.
|
||||
* otherwise:
|
||||
* - message is written to stdout.
|
||||
* - "Value ignored" is added at the end of the message.
|
||||
*/
|
||||
static void ident_log(const char *param_name, const char *value, const char *reason,
|
||||
const bool cmdline)
|
||||
{
|
||||
if (cmdline == true)
|
||||
pr_err("Value \"%s\" cannot be set as %s. Reason: %s.\n", value, param_name,
|
||||
reason);
|
||||
else
|
||||
pr_info("Value \"%s\" cannot be set as %s. Reason: %s. Value ignored.\n", value,
|
||||
param_name, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* ident_init() - Set defaults.
|
||||
* @ident: ident pointer, not NULL.
|
||||
|
@ -159,6 +187,127 @@ inline void ident_init(struct mddev_ident *ident)
|
|||
ident->uuid_set = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* _ident_set_devname()- verify devname and set it in &mddev_ident.
|
||||
* @ident: pointer to &mddev_ident.
|
||||
* @devname: devname to be set.
|
||||
* @cmdline: context dependent actions. If set, ignore keyword is not allowed.
|
||||
*
|
||||
* @devname can have following forms:
|
||||
* '<ignore>' keyword (if allowed)
|
||||
* /dev/md{number}
|
||||
* /dev/md_d{number} (legacy)
|
||||
* /dev/md_{name}
|
||||
* /dev/md/{name}
|
||||
* {name}
|
||||
*
|
||||
* {name} must follow name's criteria and be POSIX compatible.
|
||||
* If criteria passed, duplicate memory and set devname in @ident.
|
||||
*
|
||||
* Return: %MDADM_STATUS_SUCCESS or %MDADM_STATUS_ERROR.
|
||||
*/
|
||||
mdadm_status_t _ident_set_devname(struct mddev_ident *ident, const char *devname,
|
||||
const bool cmdline)
|
||||
{
|
||||
assert(ident);
|
||||
assert(devname);
|
||||
|
||||
static const char named_dev_pref[] = DEV_NUM_PREF "_";
|
||||
static const int named_dev_pref_size = sizeof(named_dev_pref) - 1;
|
||||
const char *prop_name = "devname";
|
||||
const char *name;
|
||||
|
||||
if (ident->devname) {
|
||||
ident_log(prop_name, devname, "Already defined", cmdline);
|
||||
return MDADM_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if (is_devname_ignore(devname) == true) {
|
||||
if (!cmdline)
|
||||
goto pass;
|
||||
|
||||
ident_log(prop_name, devname, "Special keyword is invalid in this context",
|
||||
cmdline);
|
||||
return MDADM_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if (is_devname_md_numbered(devname) == true || is_devname_md_d_numbered(devname) == true)
|
||||
goto pass;
|
||||
|
||||
if (strncmp(devname, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0)
|
||||
name = devname + DEV_MD_DIR_LEN;
|
||||
else if (strncmp(devname, named_dev_pref, named_dev_pref_size) == 0)
|
||||
name = devname + named_dev_pref_size;
|
||||
else
|
||||
name = devname;
|
||||
|
||||
if (is_name_posix_compatible(name) == false) {
|
||||
ident_log(prop_name, name, "Not POSIX compatible", cmdline);
|
||||
return MDADM_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if (is_string_lq(name, MD_NAME_MAX + 1) == false) {
|
||||
ident_log(prop_name, devname, "Invalid length", cmdline);
|
||||
return MDADM_STATUS_ERROR;
|
||||
}
|
||||
pass:
|
||||
ident->devname = xstrdup(devname);
|
||||
return MDADM_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* _ident_set_name()- set name in &mddev_ident.
|
||||
* @ident: pointer to &mddev_ident.
|
||||
* @name: name to be set.
|
||||
* @cmdline: context dependent actions.
|
||||
*
|
||||
* If criteria passed, set name in @ident.
|
||||
*
|
||||
* Return: %MDADM_STATUS_SUCCESS or %MDADM_STATUS_ERROR.
|
||||
*/
|
||||
static mdadm_status_t _ident_set_name(struct mddev_ident *ident, const char *name,
|
||||
const bool cmdline)
|
||||
{
|
||||
assert(name);
|
||||
assert(ident);
|
||||
|
||||
const char *prop_name = "name";
|
||||
|
||||
if (ident->name[0]) {
|
||||
ident_log(prop_name, name, "Already defined", cmdline);
|
||||
return MDADM_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if (is_string_lq(name, MD_NAME_MAX + 1) == false) {
|
||||
ident_log(prop_name, name, "Too long or empty", cmdline);
|
||||
return MDADM_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if (is_name_posix_compatible(name) == false) {
|
||||
ident_log(prop_name, name, "Not POSIX compatible", cmdline);
|
||||
return MDADM_STATUS_ERROR;
|
||||
}
|
||||
|
||||
snprintf(ident->name, MD_NAME_MAX + 1, "%s", name);
|
||||
return MDADM_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* ident_set_devname()- exported, for cmdline.
|
||||
*/
|
||||
mdadm_status_t ident_set_devname(struct mddev_ident *ident, const char *name)
|
||||
{
|
||||
return _ident_set_devname(ident, name, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* ident_set_name()- exported, for cmdline.
|
||||
*/
|
||||
mdadm_status_t ident_set_name(struct mddev_ident *ident, const char *name)
|
||||
{
|
||||
return _ident_set_name(ident, name, true);
|
||||
}
|
||||
|
||||
struct conf_dev {
|
||||
struct conf_dev *next;
|
||||
char *name;
|
||||
|
@ -396,29 +545,7 @@ void arrayline(char *line)
|
|||
|
||||
for (w = dl_next(line); w != line; w = dl_next(w)) {
|
||||
if (w[0] == '/' || strchr(w, '=') == NULL) {
|
||||
/* This names the device, or is '<ignore>'.
|
||||
* The rules match those in create_mddev.
|
||||
* 'w' must be:
|
||||
* /dev/md/{anything}
|
||||
* /dev/mdNN
|
||||
* /dev/md_dNN
|
||||
* <ignore>
|
||||
* or anything that doesn't start '/' or '<'
|
||||
*/
|
||||
if (is_devname_ignore(w) == true ||
|
||||
strncmp(w, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0 ||
|
||||
(w[0] != '/' && w[0] != '<') ||
|
||||
is_devname_md_numbered(w) == true ||
|
||||
is_devname_md_d_numbered(w) == true) {
|
||||
/* This is acceptable */;
|
||||
if (mis.devname)
|
||||
pr_err("only give one device per ARRAY line: %s and %s\n",
|
||||
mis.devname, w);
|
||||
else
|
||||
mis.devname = w;
|
||||
}else {
|
||||
pr_err("%s is an invalid name for an md device - ignored.\n", w);
|
||||
}
|
||||
_ident_set_devname(&mis, w, false);
|
||||
} else if (strncasecmp(w, "uuid=", 5) == 0) {
|
||||
if (mis.uuid_set)
|
||||
pr_err("only specify uuid once, %s ignored.\n",
|
||||
|
@ -444,14 +571,7 @@ void arrayline(char *line)
|
|||
mis.super_minor = minor;
|
||||
}
|
||||
} else if (strncasecmp(w, "name=", 5) == 0) {
|
||||
if (mis.name[0])
|
||||
pr_err("only specify name once, %s ignored.\n",
|
||||
w);
|
||||
else if (strlen(w + 5) > 32)
|
||||
pr_err("name too long, ignoring %s\n", w);
|
||||
else
|
||||
strcpy(mis.name, w + 5);
|
||||
|
||||
_ident_set_name(&mis, w + 5, false);
|
||||
} else if (strncasecmp(w, "bitmap=", 7) == 0) {
|
||||
if (mis.bitmap_file)
|
||||
pr_err("only specify bitmap file once. %s ignored\n",
|
||||
|
|
76
lib.c
76
lib.c
|
@ -27,6 +27,24 @@
|
|||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
|
||||
/**
|
||||
* is_string_lq() - Check if string length with NULL byte is lower or equal to requested.
|
||||
* @str: string to check.
|
||||
* @max_len: max length.
|
||||
*
|
||||
* @str length must be bigger than 0 and be lower or equal @max_len, including termination byte.
|
||||
*/
|
||||
bool is_string_lq(const char * const str, size_t max_len)
|
||||
{
|
||||
assert(str);
|
||||
|
||||
size_t _len = strnlen(str, max_len);
|
||||
|
||||
if (_len > 0 && _len < max_len)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_dev_alive(char *path)
|
||||
{
|
||||
if (!path)
|
||||
|
@ -465,24 +483,50 @@ void print_quoted(char *str)
|
|||
putchar(q);
|
||||
}
|
||||
|
||||
void print_escape(char *str)
|
||||
/**
|
||||
* is_alphanum() - Check if sign is letter or digit.
|
||||
* @c: char to analyze.
|
||||
*
|
||||
* Similar to isalnum() but additional locales are excluded.
|
||||
*
|
||||
* Return: %true on success, %false otherwise.
|
||||
*/
|
||||
bool is_alphanum(const char c)
|
||||
{
|
||||
/* print str, but change space and tab to '_'
|
||||
* as is suitable for device names
|
||||
*/
|
||||
for (; *str; str++) {
|
||||
switch (*str) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
putchar('_');
|
||||
break;
|
||||
case '/':
|
||||
putchar('-');
|
||||
break;
|
||||
default:
|
||||
putchar(*str);
|
||||
}
|
||||
if (isupper(c) || islower(c) || isdigit(c) != 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* is_name_posix_compatible() - Check if name is POSIX compatible.
|
||||
* @name: name to check.
|
||||
*
|
||||
* POSIX portable file name character set contains ASCII letters,
|
||||
* digits, '_', '.', and '-'. Also forbid leading '-'.
|
||||
* The length of the name cannot exceed NAME_MAX - 1 (ensure NULL ending).
|
||||
*
|
||||
* Return: %true on success, %false otherwise.
|
||||
*/
|
||||
bool is_name_posix_compatible(const char * const name)
|
||||
{
|
||||
assert(name);
|
||||
|
||||
char allowed_symbols[] = "-_.";
|
||||
const char *n = name;
|
||||
|
||||
if (!is_string_lq(name, NAME_MAX))
|
||||
return false;
|
||||
|
||||
if (*n == '-')
|
||||
return false;
|
||||
|
||||
while (*n != '\0') {
|
||||
if (!is_alphanum(*n) && !strchr(allowed_symbols, *n))
|
||||
return false;
|
||||
n++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int check_env(char *name)
|
||||
|
|
70
mdadm.8.in
70
mdadm.8.in
|
@ -364,7 +364,7 @@ Use the Intel(R) Matrix Storage Manager metadata format. This creates a
|
|||
which is managed in a similar manner to DDF, and is supported by an
|
||||
option-rom on some platforms:
|
||||
.IP
|
||||
.B https://www.intel.com/content/www/us/en/support/products/122484/memory-and-storage/ssd-software/intel-virtual-raid-on-cpu-intel-vroc.html
|
||||
.B https://www.intel.com/content/www/us/en/support/products/122484
|
||||
.PP
|
||||
.RE
|
||||
|
||||
|
@ -932,17 +932,14 @@ option will be ignored.
|
|||
.BR \-N ", " \-\-name=
|
||||
Set a
|
||||
.B name
|
||||
for the array. This is currently only effective when creating an
|
||||
array with a version-1 superblock, or an array in a DDF container.
|
||||
The name is a simple textual string that can be used to identify array
|
||||
components when assembling. If name is needed but not specified, it
|
||||
is taken from the basename of the device that is being created.
|
||||
e.g. when creating
|
||||
.I /dev/md/home
|
||||
the
|
||||
.B name
|
||||
will default to
|
||||
.IR home .
|
||||
for the array. It must be
|
||||
.BR "POSIX PORTABLE NAME"
|
||||
compatible and cannot be longer than 32 chars. This is effective when creating an array
|
||||
with a v1 metadata, or an external array.
|
||||
|
||||
If name is needed but not specified, it is taken from the basename of the device
|
||||
that is being created. See
|
||||
.BR "DEVICE NAMES"
|
||||
|
||||
.TP
|
||||
.BR \-R ", " \-\-run
|
||||
|
@ -1132,8 +1129,10 @@ is much safer.
|
|||
|
||||
.TP
|
||||
.BR \-N ", " \-\-name=
|
||||
Specify the name of the array to assemble. This must be the name
|
||||
that was specified when creating the array. It must either match
|
||||
Specify the name of the array to assemble. It must be
|
||||
.BR "POSIX PORTABLE NAME"
|
||||
compatible and cannot be longer than 32 chars. This must be the name
|
||||
that was specified when creating the array. It must either match
|
||||
the name stored in the superblock exactly, or it must match
|
||||
with the current
|
||||
.I homehost
|
||||
|
@ -2179,14 +2178,17 @@ Usage:
|
|||
.I md-device
|
||||
.BI \-\-chunk= X
|
||||
.BI \-\-level= Y
|
||||
.br
|
||||
.BI \-\-raid\-devices= Z
|
||||
.I devices
|
||||
|
||||
.PP
|
||||
This usage will initialise a new md array, associate some devices with
|
||||
This usage will initialize a new md array, associate some devices with
|
||||
it, and activate the array.
|
||||
|
||||
.I md-device
|
||||
is a new device. This could be standard name or chosen name. For details see:
|
||||
.BR "DEVICE NAMES"
|
||||
|
||||
The named device will normally not exist when
|
||||
.I "mdadm \-\-create"
|
||||
is run, but will be created by
|
||||
|
@ -2227,24 +2229,6 @@ array. This feature can be overridden with the
|
|||
.B \-\-force
|
||||
option.
|
||||
|
||||
When creating an array with version-1 metadata a name for the array is
|
||||
required.
|
||||
If this is not given with the
|
||||
.B \-\-name
|
||||
option,
|
||||
.I mdadm
|
||||
will choose a name based on the last component of the name of the
|
||||
device being created. So if
|
||||
.B /dev/md3
|
||||
is being created, then the name
|
||||
.B 3
|
||||
will be chosen.
|
||||
If
|
||||
.B /dev/md/home
|
||||
is being created, then the name
|
||||
.B home
|
||||
will be used.
|
||||
|
||||
When creating a partition based array, using
|
||||
.I mdadm
|
||||
with version-1.x metadata, the partition type should be set to
|
||||
|
@ -2429,12 +2413,10 @@ and
|
|||
|
||||
The
|
||||
.B name
|
||||
option updates the subarray name in the metadata, it may not affect the
|
||||
device node name or the device node symlink until the subarray is
|
||||
re\-assembled. If updating
|
||||
.B name
|
||||
would change the UUID of an active subarray this operation is blocked,
|
||||
and the command will end in an error.
|
||||
option updates the subarray name in the metadata. It must be
|
||||
.BR "POSIX PORTABLE NAME"
|
||||
compatible and cannot be longer than 32 chars. If successes, new value will be respected after
|
||||
next assembly.
|
||||
|
||||
The
|
||||
.B ppl
|
||||
|
@ -3395,6 +3377,10 @@ When
|
|||
.B \-\-incremental
|
||||
mode is used, this file gets a list of arrays currently being created.
|
||||
|
||||
.SH POSIX PORTABLE NAME
|
||||
A valid name can only consist of characters "A-Za-z0-9.-_".
|
||||
The name cannot start with a leading "-" and cannot exceed 255 chars.
|
||||
|
||||
.SH DEVICE NAMES
|
||||
|
||||
.I mdadm
|
||||
|
@ -3416,6 +3402,10 @@ can be given, or just the suffix of the second sort of name, such as
|
|||
.I home
|
||||
can be given.
|
||||
|
||||
In every style, raw name must be compatible with
|
||||
.BR "POSIX PORTABLE NAME"
|
||||
and has to be no longer than 32 chars.
|
||||
|
||||
When
|
||||
.I mdadm
|
||||
chooses device names during auto-assembly or incremental assembly, it
|
||||
|
|
73
mdadm.c
73
mdadm.c
|
@ -690,20 +690,14 @@ int main(int argc, char *argv[])
|
|||
case O(CREATE,'N'):
|
||||
case O(ASSEMBLE,'N'):
|
||||
case O(MISC,'N'):
|
||||
if (ident.name[0]) {
|
||||
pr_err("name cannot be set twice. Second value %s.\n", optarg);
|
||||
exit(2);
|
||||
}
|
||||
if (mode == MISC && !c.subarray) {
|
||||
pr_err("-N/--name only valid with --update-subarray in misc mode\n");
|
||||
exit(2);
|
||||
}
|
||||
if (strlen(optarg) > 32) {
|
||||
pr_err("name '%s' is too long, 32 chars max.\n",
|
||||
optarg);
|
||||
|
||||
if (ident_set_name(&ident, optarg) != MDADM_STATUS_SUCCESS)
|
||||
exit(2);
|
||||
}
|
||||
strcpy(ident.name, optarg);
|
||||
|
||||
continue;
|
||||
|
||||
case O(ASSEMBLE,'m'): /* super-minor for array */
|
||||
|
@ -1290,37 +1284,33 @@ int main(int argc, char *argv[])
|
|||
pr_err("an md device must be given in this mode\n");
|
||||
exit(2);
|
||||
}
|
||||
if (ident_set_devname(&ident, devlist->devname) != MDADM_STATUS_SUCCESS)
|
||||
exit(1);
|
||||
|
||||
if ((int)ident.super_minor == -2 && c.autof) {
|
||||
pr_err("--super-minor=dev is incompatible with --auto\n");
|
||||
exit(2);
|
||||
}
|
||||
if (mode == MANAGE || mode == GROW) {
|
||||
mdfd = open_mddev(devlist->devname, 1);
|
||||
mdfd = open_mddev(ident.devname, 1);
|
||||
if (mdfd < 0)
|
||||
exit(1);
|
||||
|
||||
ret = fstat(mdfd, &stb);
|
||||
if (ret) {
|
||||
pr_err("fstat failed on %s.\n", devlist->devname);
|
||||
pr_err("fstat failed on %s.\n", ident.devname);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
char *bname = basename(devlist->devname);
|
||||
|
||||
if (strlen(bname) > MD_NAME_MAX) {
|
||||
pr_err("Name %s is too long.\n", devlist->devname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = stat(devlist->devname, &stb);
|
||||
ret = stat(ident.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);
|
||||
ident.devname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!ret && !stat_is_md_dev(&stb)) {
|
||||
pr_err("device %s exists but is not an md array.\n", devlist->devname);
|
||||
pr_err("device %s exists but is not an md array.\n", ident.devname);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -1408,17 +1398,17 @@ int main(int argc, char *argv[])
|
|||
case MANAGE:
|
||||
/* readonly, add/remove, readwrite, runstop */
|
||||
if (c.readonly > 0)
|
||||
rv = Manage_ro(devlist->devname, mdfd, c.readonly);
|
||||
rv = Manage_ro(ident.devname, mdfd, c.readonly);
|
||||
if (!rv && devs_found > 1)
|
||||
rv = Manage_subdevs(devlist->devname, mdfd,
|
||||
rv = Manage_subdevs(ident.devname, mdfd,
|
||||
devlist->next, c.verbose,
|
||||
c.test, c.update, c.force);
|
||||
if (!rv && c.readonly < 0)
|
||||
rv = Manage_ro(devlist->devname, mdfd, c.readonly);
|
||||
rv = Manage_ro(ident.devname, mdfd, c.readonly);
|
||||
if (!rv && c.runstop > 0)
|
||||
rv = Manage_run(devlist->devname, mdfd, &c);
|
||||
rv = Manage_run(ident.devname, mdfd, &c);
|
||||
if (!rv && c.runstop < 0)
|
||||
rv = Manage_stop(devlist->devname, mdfd, c.verbose, 0);
|
||||
rv = Manage_stop(ident.devname, mdfd, c.verbose, 0);
|
||||
break;
|
||||
case ASSEMBLE:
|
||||
if (!c.scan && c.runstop == -1) {
|
||||
|
@ -1428,22 +1418,19 @@ int main(int argc, char *argv[])
|
|||
ident.super_minor == UnSet && ident.name[0] == 0 &&
|
||||
!c.scan) {
|
||||
/* Only a device has been given, so get details from config file */
|
||||
struct mddev_ident *array_ident = conf_get_ident(devlist->devname);
|
||||
struct mddev_ident *array_ident = conf_get_ident(ident.devname);
|
||||
if (array_ident == NULL) {
|
||||
pr_err("%s not identified in config file.\n",
|
||||
devlist->devname);
|
||||
pr_err("%s not identified in config file.\n", ident.devname);
|
||||
rv |= 1;
|
||||
if (mdfd >= 0)
|
||||
close(mdfd);
|
||||
} else {
|
||||
if (array_ident->autof == 0)
|
||||
array_ident->autof = c.autof;
|
||||
rv |= Assemble(ss, devlist->devname, array_ident,
|
||||
NULL, &c);
|
||||
rv |= Assemble(ss, ident.devname, array_ident, NULL, &c);
|
||||
}
|
||||
} else if (!c.scan)
|
||||
rv = Assemble(ss, devlist->devname, &ident,
|
||||
devlist->next, &c);
|
||||
rv = Assemble(ss, ident.devname, &ident, devlist->next, &c);
|
||||
else if (devs_found > 0) {
|
||||
if (c.update && devs_found > 1) {
|
||||
pr_err("can only update a single array at a time\n");
|
||||
|
@ -1501,7 +1488,7 @@ int main(int argc, char *argv[])
|
|||
break;
|
||||
}
|
||||
}
|
||||
rv = Build(devlist->devname, devlist->next, &s, &c);
|
||||
rv = Build(&ident, devlist->next, &s, &c);
|
||||
break;
|
||||
case CREATE:
|
||||
if (c.delay == 0)
|
||||
|
@ -1538,9 +1525,7 @@ int main(int argc, char *argv[])
|
|||
break;
|
||||
}
|
||||
|
||||
rv = Create(ss, devlist->devname,
|
||||
ident.name, ident.uuid_set ? ident.uuid : NULL,
|
||||
devs_found - 1, devlist->next, &s, &c);
|
||||
rv = Create(ss, &ident, devs_found - 1, devlist->next, &s, &c);
|
||||
break;
|
||||
case MISC:
|
||||
if (devmode == 'E') {
|
||||
|
@ -1637,8 +1622,7 @@ int main(int argc, char *argv[])
|
|||
break;
|
||||
}
|
||||
for (dv = devlist->next; dv; dv = dv->next) {
|
||||
rv = Grow_Add_device(devlist->devname, mdfd,
|
||||
dv->devname);
|
||||
rv = Grow_Add_device(ident.devname, mdfd, dv->devname);
|
||||
if (rv)
|
||||
break;
|
||||
}
|
||||
|
@ -1651,18 +1635,15 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
if (c.delay == 0)
|
||||
c.delay = DEFAULT_BITMAP_DELAY;
|
||||
rv = Grow_addbitmap(devlist->devname, mdfd, &c, &s);
|
||||
rv = Grow_addbitmap(ident.devname, mdfd, &c, &s);
|
||||
} else if (grow_continue)
|
||||
rv = Grow_continue_command(devlist->devname,
|
||||
mdfd, c.backup_file,
|
||||
c.verbose);
|
||||
rv = Grow_continue_command(ident.devname, mdfd, c.backup_file, c.verbose);
|
||||
else if (s.size > 0 || s.raiddisks || s.layout_str ||
|
||||
s.chunk != 0 || s.level != UnSet ||
|
||||
s.data_offset != INVALID_SECTORS) {
|
||||
rv = Grow_reshape(devlist->devname, mdfd,
|
||||
devlist->next, &c, &s);
|
||||
rv = Grow_reshape(ident.devname, mdfd, devlist->next, &c, &s);
|
||||
} else if (s.consistency_policy != CONSISTENCY_POLICY_UNKNOWN) {
|
||||
rv = Grow_consistency_policy(devlist->devname, mdfd, &c, &s);
|
||||
rv = Grow_consistency_policy(ident.devname, mdfd, &c, &s);
|
||||
} else if (array_size == 0)
|
||||
pr_err("no changes to --grow\n");
|
||||
break;
|
||||
|
|
|
@ -717,10 +717,6 @@ ARRAY /dev/md/home UUID=9187a482:5dde19d9:eea3cc4a:d646ab8b
|
|||
.br
|
||||
auto=part
|
||||
.br
|
||||
# The name of this array contains a space.
|
||||
.br
|
||||
ARRAY /dev/md9 name='Data Storage'
|
||||
.sp
|
||||
POLICY domain=domain1 metadata=imsm path=pci-0000:00:1f.2-scsi-*
|
||||
.br
|
||||
action=spare
|
||||
|
|
39
mdadm.h
39
mdadm.h
|
@ -294,6 +294,11 @@ static inline void __put_unaligned32(__u32 val, void *p)
|
|||
#define KIB_TO_BYTES(x) ((x) << 10)
|
||||
#define SEC_TO_BYTES(x) ((x) << 9)
|
||||
|
||||
/**
|
||||
* This is true for native and DDF, IMSM allows 16.
|
||||
*/
|
||||
#define MD_NAME_MAX 32
|
||||
|
||||
extern const char Name[];
|
||||
|
||||
struct md_bb_entry {
|
||||
|
@ -372,9 +377,6 @@ struct mdinfo {
|
|||
int container_member; /* for assembling external-metatdata arrays
|
||||
* This is to be used internally by metadata
|
||||
* handler only */
|
||||
int container_enough; /* flag external handlers can set to
|
||||
* indicate that subarrays have not enough (-1),
|
||||
* enough to start (0), or all expected disks (1) */
|
||||
char sys_name[32];
|
||||
struct mdinfo *devs;
|
||||
struct mdinfo *next;
|
||||
|
@ -425,6 +427,12 @@ struct spare_criteria {
|
|||
unsigned int sector_size;
|
||||
};
|
||||
|
||||
typedef enum mdadm_status {
|
||||
MDADM_STATUS_SUCCESS = 0,
|
||||
MDADM_STATUS_ERROR,
|
||||
MDADM_STATUS_UNDEF,
|
||||
} mdadm_status_t;
|
||||
|
||||
enum mode {
|
||||
ASSEMBLE=1,
|
||||
BUILD,
|
||||
|
@ -593,7 +601,7 @@ struct mddev_ident {
|
|||
|
||||
int uuid_set;
|
||||
int uuid[4];
|
||||
char name[33];
|
||||
char name[MD_NAME_MAX + 1];
|
||||
|
||||
int super_minor;
|
||||
|
||||
|
@ -1531,14 +1539,11 @@ extern int Assemble(struct supertype *st, char *mddev,
|
|||
struct mddev_dev *devlist,
|
||||
struct context *c);
|
||||
|
||||
extern int Build(char *mddev, struct mddev_dev *devlist,
|
||||
struct shape *s, struct context *c);
|
||||
extern int Build(struct mddev_ident *ident, struct mddev_dev *devlist, struct shape *s,
|
||||
struct context *c);
|
||||
|
||||
extern int Create(struct supertype *st, char *mddev,
|
||||
char *name, int *uuid,
|
||||
int subdevs, struct mddev_dev *devlist,
|
||||
struct shape *s,
|
||||
struct context *c);
|
||||
extern int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
|
||||
struct mddev_dev *devlist, struct shape *s, 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);
|
||||
|
@ -1609,9 +1614,11 @@ extern int check_raid(int fd, char *name);
|
|||
extern int check_partitions(int fd, char *dname,
|
||||
unsigned long long freesize,
|
||||
unsigned long long size);
|
||||
extern bool is_name_posix_compatible(const char *path);
|
||||
extern int fstat_is_blkdev(int fd, char *devname, dev_t *rdev);
|
||||
extern int stat_is_blkdev(char *devname, dev_t *rdev);
|
||||
|
||||
extern bool is_string_lq(const char * const str, size_t max_len);
|
||||
extern bool is_dev_alive(char *path);
|
||||
extern int get_mdp_major(void);
|
||||
extern int get_maj_min(char *dev, int *major, int *minor);
|
||||
|
@ -1629,6 +1636,8 @@ extern void manage_fork_fds(int close_all);
|
|||
extern int continue_via_systemd(char *devnm, char *service_name, char *prefix);
|
||||
|
||||
extern void ident_init(struct mddev_ident *ident);
|
||||
extern mdadm_status_t ident_set_devname(struct mddev_ident *ident, const char *devname);
|
||||
extern mdadm_status_t ident_set_name(struct mddev_ident *ident, const char *name);
|
||||
|
||||
extern int parse_auto(char *str, char *msg, int config);
|
||||
extern struct mddev_ident *conf_get_ident(char *dev);
|
||||
|
@ -1646,11 +1655,10 @@ extern int conf_get_monitor_delay(void);
|
|||
extern char *conf_line(FILE *file);
|
||||
extern char *conf_word(FILE *file, int allow_key);
|
||||
extern void print_quoted(char *str);
|
||||
extern void print_escape(char *str);
|
||||
extern int use_udev(void);
|
||||
extern unsigned long GCD(unsigned long a, unsigned long b);
|
||||
extern int conf_name_is_free(char *name);
|
||||
extern bool is_devname_ignore(char *devname);
|
||||
extern bool is_devname_ignore(const char *devname);
|
||||
extern bool is_devname_md_numbered(const char *devname);
|
||||
extern bool is_devname_md_d_numbered(const char *devname);
|
||||
extern int conf_verify_devnames(struct mddev_ident *array_list);
|
||||
|
@ -2005,11 +2013,6 @@ enum r0layout {
|
|||
/* And another special number needed for --data_offset=variable */
|
||||
#define VARIABLE_OFFSET 3
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
|
@ -1975,7 +1975,6 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info, char *m
|
|||
info->array.ctime = DECADE + __be32_to_cpu(*cptr);
|
||||
|
||||
info->array.chunk_size = 0;
|
||||
info->container_enough = 1;
|
||||
|
||||
info->disk.major = 0;
|
||||
info->disk.minor = 0;
|
||||
|
@ -1984,12 +1983,14 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info, char *m
|
|||
info->disk.number = be32_to_cpu(ddf->dlist->disk.refnum);
|
||||
info->disk.raid_disk = find_phys(ddf, ddf->dlist->disk.refnum);
|
||||
|
||||
if (info->disk.raid_disk < 0)
|
||||
return;
|
||||
|
||||
info->data_offset = be64_to_cpu(ddf->phys->
|
||||
entries[info->disk.raid_disk].
|
||||
config_size);
|
||||
info->component_size = ddf->dlist->size - info->data_offset;
|
||||
if (info->disk.raid_disk >= 0)
|
||||
pde = ddf->phys->entries + info->disk.raid_disk;
|
||||
pde = ddf->phys->entries + info->disk.raid_disk;
|
||||
if (pde &&
|
||||
!(be16_to_cpu(pde->state) & DDF_Failed) &&
|
||||
!(be16_to_cpu(pde->state) & DDF_Missing))
|
||||
|
|
|
@ -3806,7 +3806,6 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
|
|||
struct intel_super *super = st->sb;
|
||||
struct imsm_disk *disk;
|
||||
int map_disks = info->array.raid_disks;
|
||||
int max_enough = -1;
|
||||
int i;
|
||||
struct imsm_super *mpb;
|
||||
|
||||
|
@ -3848,12 +3847,9 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
|
|||
|
||||
for (i = 0; i < mpb->num_raid_devs; i++) {
|
||||
struct imsm_dev *dev = get_imsm_dev(super, i);
|
||||
int failed, enough, j, missing = 0;
|
||||
int j = 0;
|
||||
struct imsm_map *map;
|
||||
__u8 state;
|
||||
|
||||
failed = imsm_count_failed(super, dev, MAP_0);
|
||||
state = imsm_check_degraded(super, dev, failed, MAP_0);
|
||||
map = get_imsm_map(dev, MAP_0);
|
||||
|
||||
/* any newly missing disks?
|
||||
|
@ -3868,36 +3864,10 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
|
|||
|
||||
if (!(ord & IMSM_ORD_REBUILD) &&
|
||||
get_imsm_missing(super, idx)) {
|
||||
missing = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (state == IMSM_T_STATE_FAILED)
|
||||
enough = -1;
|
||||
else if (state == IMSM_T_STATE_DEGRADED &&
|
||||
(state != map->map_state || missing))
|
||||
enough = 0;
|
||||
else /* we're normal, or already degraded */
|
||||
enough = 1;
|
||||
if (is_gen_migration(dev) && missing) {
|
||||
/* during general migration we need all disks
|
||||
* that process is running on.
|
||||
* No new missing disk is allowed.
|
||||
*/
|
||||
max_enough = -1;
|
||||
enough = -1;
|
||||
/* no more checks necessary
|
||||
*/
|
||||
break;
|
||||
}
|
||||
/* in the missing/failed disk case check to see
|
||||
* if at least one array is runnable
|
||||
*/
|
||||
max_enough = max(max_enough, enough);
|
||||
}
|
||||
dprintf("enough: %d\n", max_enough);
|
||||
info->container_enough = max_enough;
|
||||
|
||||
if (super->disks) {
|
||||
__u32 reserved = imsm_reserved_sectors(super, super->disks);
|
||||
|
@ -5561,40 +5531,37 @@ static void imsm_update_version_info(struct intel_super *super)
|
|||
}
|
||||
}
|
||||
|
||||
static int check_name(struct intel_super *super, char *name, int quiet)
|
||||
/**
|
||||
* imsm_check_name() - check imsm naming criteria.
|
||||
* @super: &intel_super pointer, not NULL.
|
||||
* @name: name to check.
|
||||
* @verbose: verbose level.
|
||||
*
|
||||
* Name must be no longer than &MAX_RAID_SERIAL_LEN and must be unique across volumes.
|
||||
*
|
||||
* Returns: &true if @name matches, &false otherwise.
|
||||
*/
|
||||
static bool imsm_is_name_allowed(struct intel_super *super, const char * const name,
|
||||
const int verbose)
|
||||
{
|
||||
struct imsm_super *mpb = super->anchor;
|
||||
char *reason = NULL;
|
||||
char *start = name;
|
||||
size_t len = strlen(name);
|
||||
int i;
|
||||
|
||||
if (len > 0) {
|
||||
while (isspace(start[len - 1]))
|
||||
start[--len] = 0;
|
||||
while (*start && isspace(*start))
|
||||
++start, --len;
|
||||
memmove(name, start, len + 1);
|
||||
if (is_string_lq(name, MAX_RAID_SERIAL_LEN + 1) == false) {
|
||||
pr_vrb("imsm: Name \"%s\" is too long\n", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (len > MAX_RAID_SERIAL_LEN)
|
||||
reason = "must be 16 characters or less";
|
||||
else if (len == 0)
|
||||
reason = "must be a non-empty string";
|
||||
|
||||
for (i = 0; i < mpb->num_raid_devs; i++) {
|
||||
struct imsm_dev *dev = get_imsm_dev(super, i);
|
||||
|
||||
if (strncmp((char *) dev->volume, name, MAX_RAID_SERIAL_LEN) == 0) {
|
||||
reason = "already exists";
|
||||
break;
|
||||
pr_vrb("imsm: Name \"%s\" already exists\n", name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (reason && !quiet)
|
||||
pr_err("imsm volume name %s\n", reason);
|
||||
|
||||
return !reason;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
|
||||
|
@ -5689,8 +5656,9 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
|
|||
}
|
||||
}
|
||||
|
||||
if (!check_name(super, name, 0))
|
||||
if (imsm_is_name_allowed(super, name, 1) == false)
|
||||
return 0;
|
||||
|
||||
dv = xmalloc(sizeof(*dv));
|
||||
dev = xcalloc(1, sizeof(*dev) + sizeof(__u32) * (info->raid_disks - 1));
|
||||
/*
|
||||
|
@ -8018,7 +7986,7 @@ static int update_subarray_imsm(struct supertype *st, char *subarray,
|
|||
char *ep;
|
||||
int vol;
|
||||
|
||||
if (!check_name(super, name, 0))
|
||||
if (imsm_is_name_allowed(super, name, 1) == false)
|
||||
return 2;
|
||||
|
||||
vol = strtoul(subarray, &ep, 10);
|
||||
|
@ -10345,7 +10313,8 @@ 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 || !check_name(super, name, 1)) {
|
||||
|
||||
if (a || !dev || imsm_is_name_allowed(super, name, 0) == false) {
|
||||
dprintf("failed to rename subarray-%d\n", target);
|
||||
break;
|
||||
}
|
||||
|
|
19
super1.c
19
super1.c
|
@ -1967,6 +1967,14 @@ fail_to_write:
|
|||
return 1;
|
||||
}
|
||||
|
||||
static bool has_raid0_layout(struct mdp_superblock_1 *sb)
|
||||
{
|
||||
if (sb->level == 0 && sb->layout != 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static int write_init_super1(struct supertype *st)
|
||||
{
|
||||
struct mdp_superblock_1 *sb = st->sb;
|
||||
|
@ -1978,12 +1986,17 @@ static int write_init_super1(struct supertype *st)
|
|||
unsigned long long sb_offset;
|
||||
unsigned long long data_offset;
|
||||
long bm_offset;
|
||||
int raid0_need_layout = 0;
|
||||
bool raid0_need_layout = false;
|
||||
|
||||
/* Since linux kernel v5.4, raid0 always has a layout */
|
||||
if (has_raid0_layout(sb) && get_linux_version() >= 5004000)
|
||||
raid0_need_layout = true;
|
||||
|
||||
for (di = st->info; di; di = di->next) {
|
||||
if (di->disk.state & (1 << MD_DISK_JOURNAL))
|
||||
sb->feature_map |= __cpu_to_le32(MD_FEATURE_JOURNAL);
|
||||
if (sb->level == 0 && sb->layout != 0) {
|
||||
if (has_raid0_layout(sb) && !raid0_need_layout) {
|
||||
|
||||
struct devinfo *di2 = st->info;
|
||||
unsigned long long s1, s2;
|
||||
s1 = di->dev_size;
|
||||
|
@ -1995,7 +2008,7 @@ static int write_init_super1(struct supertype *st)
|
|||
s2 -= di2->data_offset;
|
||||
s2 /= __le32_to_cpu(sb->chunksize);
|
||||
if (s1 != s2)
|
||||
raid0_need_layout = 1;
|
||||
raid0_need_layout = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
8
test
8
test
|
@ -107,8 +107,12 @@ do_test() {
|
|||
echo -ne "$_script... "
|
||||
if ( set -ex ; . $_script ) &> $targetdir/log
|
||||
then
|
||||
dmesg | grep -iq "error\|call trace\|segfault" &&
|
||||
die "dmesg prints errors when testing $_basename!"
|
||||
if [ -f "${_script}.inject_error" ]; then
|
||||
echo "dmesg checking is skipped because test inject error"
|
||||
else
|
||||
dmesg | grep -iq "error\|call trace\|segfault" &&
|
||||
die "dmesg prints errors when testing $_basename!"
|
||||
fi
|
||||
echo "succeeded"
|
||||
_fail=0
|
||||
else
|
||||
|
|
107
tests/00confnames
Normal file
107
tests/00confnames
Normal file
|
@ -0,0 +1,107 @@
|
|||
set -x -e
|
||||
. tests/templates/names_template
|
||||
|
||||
# Test how <devname> and <name> from config are handled during Incremental assemblation.
|
||||
# 1-6 <devnode> only tests (no <name> in config).
|
||||
# 6-10 <devname> and <name> combinations are tested.
|
||||
# 11-13 corner cases.
|
||||
|
||||
names_create "/dev/md/name"
|
||||
local _UUID="$(mdadm -D --export /dev/md127 | grep MD_UUID | cut -d'=' -f2)"
|
||||
[[ "$_UUID" == "" ]] && echo "Cannot obtain UUID for $DEVNODE_NAME" && exit 1
|
||||
|
||||
|
||||
# 1. <devname> definition consistent with metadata name.
|
||||
names_make_conf $_UUID "/dev/md/name" "empty" $config
|
||||
mdadm -S "/dev/md127"
|
||||
mdadm -I $dev0 --config=$config
|
||||
names_verify "/dev/md127" "name" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
# 2. Same as 1, but use short name form of <devname>.
|
||||
names_make_conf $_UUID "name" "empty" $config
|
||||
mdadm -I $dev0 --config=$config
|
||||
names_verify "/dev/md127" "name" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
# 3. Same as 1, but use different <devname> than metadata provides.
|
||||
names_make_conf $_UUID "/dev/md/other" "empty" $config
|
||||
mdadm -I $dev0 --config=$config
|
||||
names_verify "/dev/md127" "other" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
# 4. Same as 3, but use short name form of <devname>.
|
||||
names_make_conf $_UUID "other" "empty" $config
|
||||
mdadm -I $dev0 --config=$config
|
||||
names_verify "/dev/md127" "other" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
# 5. Force particular node creation by setting <devname> to /dev/mdX. Link is not created in this
|
||||
# case.
|
||||
names_make_conf $_UUID "/dev/md4" "empty" $config
|
||||
mdadm -I $dev0 --config=$config
|
||||
names_verify "/dev/md4" "empty" "name"
|
||||
mdadm -S "/dev/md4"
|
||||
|
||||
# 6. <devname> set to /dev/mdX, <name> same as in metadata.
|
||||
# Metadata name and default node used - controversial. Current behavior documented.
|
||||
names_make_conf $_UUID "/dev/md22" "name" $config
|
||||
mdadm -I $dev0 --config=$config
|
||||
names_verify "/dev/md127" "name" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
# 7. <devname> set to /dev/mdX, <name> different than in metadata.
|
||||
# Metadata name and default node used - controversial. Current behavior documented.
|
||||
names_make_conf $_UUID "/dev/md8" "other" $config
|
||||
mdadm -I $dev0 --config=$config
|
||||
names_verify "/dev/md127" "name" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
# 8. Both <devname> and <name> different than in metadata.
|
||||
# Metadata name and default node used - controversial. Current behavior documented.
|
||||
names_make_conf $_UUID "devnode" "other_name" $config
|
||||
mdadm -I $dev0 --config=$config
|
||||
names_verify "/dev/md127" "name" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
# 9. <devname> set to metadata name, <name> different than in metadata.
|
||||
# Metadata name and default node used - controversial. Current behavior documented.
|
||||
names_make_conf $_UUID "name" "other_name" $config
|
||||
mdadm -I $dev0 --config=$config
|
||||
names_verify "/dev/md127" "name" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
# 10. Bad <devname> set, no <name>.
|
||||
# Metadata name and default node used - expected.
|
||||
names_make_conf $_UUID "/im/bad/devname" "empty" $config
|
||||
mdadm -I $dev0 --config=$config
|
||||
names_verify "/dev/md127" "name" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
# 11. <devname> with some special symbols and locales, no <name>.
|
||||
# <devname> should be ignored.
|
||||
names_make_conf $_UUID "tźż-\.,<>st+-" "empty" $config
|
||||
mdadm -I $dev0 --config=$config
|
||||
names_verify "/dev/md127" "name" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
# 12. No <devname> and <name> set.
|
||||
# Metadata name and default node used - expected.
|
||||
names_make_conf $_UUID "empty" "empty" $config
|
||||
mdadm -I $dev0 --config=$config
|
||||
names_verify "/dev/md127" "name" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
# 13. No <devname>, <name> set to /dev/mdX.
|
||||
# Entry should be ignored, it is not ignored but result is good anyway.
|
||||
names_make_conf $_UUID "empty" "/dev/md12" $config
|
||||
mdadm -I $dev0 --config=$config
|
||||
names_verify "/dev/md127" "name" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
# 13. No <devname>, <name> with special symbols and locales.
|
||||
# Entry should be ignored, it is not ignored but result is good anyway.
|
||||
names_make_conf $_UUID "empty" "./\śćń#&" $config
|
||||
mdadm -I $dev0 --config=$config
|
||||
names_verify "/dev/md127" "name" "name"
|
||||
mdadm -S "/dev/md127"
|
|
@ -1,93 +1,44 @@
|
|||
set -x -e
|
||||
. tests/templates/names_template
|
||||
|
||||
# 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"
|
||||
names_create "/dev/md/name"
|
||||
names_verify "/dev/md127" "name" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
_create "name"
|
||||
_verify "/dev/md127" "name" "name"
|
||||
names_create "name"
|
||||
names_verify "/dev/md127" "name" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
# Use 'mdX' as name.
|
||||
_create "/dev/md/md0"
|
||||
_verify "/dev/md127" "md0" "md0"
|
||||
names_create "/dev/md/md0"
|
||||
names_verify "/dev/md127" "md0" "md0"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
_create "md0"
|
||||
_verify "/dev/md127" "md0" "md0"
|
||||
names_create "md0"
|
||||
names_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"
|
||||
names_create "/dev/md/devnode" "name"
|
||||
names_verify "/dev/md127" "devnode" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
_create "devnode" "name"
|
||||
_verify "/dev/md127" "devnode" "name"
|
||||
names_create "devnode" "name"
|
||||
names_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"
|
||||
names_create "/dev/md0"
|
||||
names_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"
|
||||
names_create "/dev/md0" "name"
|
||||
names_verify "/dev/md0" "empty" "name"
|
||||
mdadm -S "/dev/md0"
|
||||
|
||||
# Devnode is a special ignore keyword. Should be rejected.
|
||||
names_create "<ignore>" "name", "true"
|
||||
|
|
|
@ -3,8 +3,8 @@ set -x
|
|||
# create an array with a name
|
||||
|
||||
mdadm -CR $md0 -l0 -n2 --metadata=1 --name="Fred" $dev0 $dev1
|
||||
mdadm -E $dev0 | grep 'Name : [^:]*:Fred ' > /dev/null || exit 1
|
||||
mdadm -D $md0 | grep 'Name : [^:]*:Fred ' > /dev/null || exit 1
|
||||
mdadm -E $dev0 | grep 'Name : Fred' > /dev/null || exit 1
|
||||
mdadm -D $md0 | grep 'Name : Fred' > /dev/null || exit 1
|
||||
mdadm -S $md0
|
||||
|
||||
mdadm -A $md0 --name="Fred" $devlist
|
||||
|
|
34
tests/23rdev-lifetime
Normal file
34
tests/23rdev-lifetime
Normal file
|
@ -0,0 +1,34 @@
|
|||
devname=${dev0##*/}
|
||||
devt=`cat /sys/block/$devname/dev`
|
||||
pid=""
|
||||
runtime=2
|
||||
|
||||
clean_up_test() {
|
||||
pill -9 $pid
|
||||
echo clear > /sys/block/md0/md/array_state
|
||||
}
|
||||
|
||||
trap 'clean_up_test' EXIT
|
||||
|
||||
add_by_sysfs() {
|
||||
while true; do
|
||||
echo $devt > /sys/block/md0/md/new_dev
|
||||
done
|
||||
}
|
||||
|
||||
remove_by_sysfs(){
|
||||
while true; do
|
||||
echo remove > /sys/block/md0/md/dev-${devname}/state
|
||||
done
|
||||
}
|
||||
|
||||
echo md0 > /sys/module/md_mod/parameters/new_array || die "create md0 failed"
|
||||
|
||||
add_by_sysfs &
|
||||
pid="$pid $!"
|
||||
|
||||
remove_by_sysfs &
|
||||
pid="$pid $!"
|
||||
|
||||
sleep $runtime
|
||||
exit 0
|
88
tests/24raid10deadlock
Normal file
88
tests/24raid10deadlock
Normal file
|
@ -0,0 +1,88 @@
|
|||
devs="$dev0 $dev1 $dev2 $dev3"
|
||||
runtime=120
|
||||
pid=""
|
||||
action_pid=""
|
||||
|
||||
set_up_injection()
|
||||
{
|
||||
echo -1 > /sys/kernel/debug/fail_make_request/times
|
||||
echo 1 > /sys/kernel/debug/fail_make_request/probability
|
||||
echo 0 > /sys/kernel/debug/fail_make_request/verbose
|
||||
echo 1 > /sys/block/${1##*/}/make-it-fail
|
||||
}
|
||||
|
||||
clean_up_injection()
|
||||
{
|
||||
echo 0 > /sys/block/${1##*/}/make-it-fail
|
||||
echo 0 > /sys/kernel/debug/fail_make_request/times
|
||||
echo 0 > /sys/kernel/debug/fail_make_request/probability
|
||||
echo 2 > /sys/kernel/debug/fail_make_request/verbose
|
||||
}
|
||||
|
||||
test_rdev()
|
||||
{
|
||||
while true; do
|
||||
mdadm -f $md0 $1 &> /dev/null
|
||||
mdadm -r $md0 $1 &> /dev/null
|
||||
mdadm --zero-superblock $1 &> /dev/null
|
||||
mdadm -a $md0 $1 &> /dev/null
|
||||
sleep $2
|
||||
done
|
||||
}
|
||||
|
||||
test_write_action()
|
||||
{
|
||||
while true; do
|
||||
echo frozen > /sys/block/md0/md/sync_action
|
||||
echo idle > /sys/block/md0/md/sync_action
|
||||
sleep 0.1
|
||||
done
|
||||
}
|
||||
|
||||
set_up_test()
|
||||
{
|
||||
fio -h &> /dev/null || die "fio not found"
|
||||
|
||||
# create a simple raid10
|
||||
mdadm -Cv -R -n 4 -l10 $md0 $devs || die "create raid10 failed"
|
||||
}
|
||||
|
||||
clean_up_test()
|
||||
{
|
||||
clean_up_injection $dev0
|
||||
pkill -9 fio
|
||||
kill -9 $pid
|
||||
kill -9 $action_pid
|
||||
|
||||
sleep 1
|
||||
|
||||
if ps $action_pid | tail -1 | awk '{print $3}' | grep D; then
|
||||
die "thread that is writing sysfs is stuck in D state, deadlock is triggered"
|
||||
fi
|
||||
mdadm -S $md0
|
||||
}
|
||||
|
||||
cat /sys/kernel/debug/fail_make_request/times || die "fault injection is not enabled"
|
||||
|
||||
trap 'clean_up_test' EXIT
|
||||
|
||||
set_up_test || die "set up test failed"
|
||||
|
||||
# backgroup io pressure
|
||||
fio -filename=$md0 -rw=randwrite -direct=1 -name=test -bs=4k -numjobs=16 -iodepth=16 &
|
||||
|
||||
# trigger add/remove device by io failure
|
||||
set_up_injection $dev0
|
||||
test_rdev $dev0 2 &
|
||||
pid="$pid $!"
|
||||
|
||||
# add/remove device directly
|
||||
test_rdev $dev3 10 &
|
||||
pid="$pid $!"
|
||||
|
||||
test_write_action &
|
||||
action_pid="$!"
|
||||
|
||||
sleep $runtime
|
||||
|
||||
exit 0
|
0
tests/24raid10deadlock.inject_error
Normal file
0
tests/24raid10deadlock.inject_error
Normal file
58
tests/24raid456deadlock
Normal file
58
tests/24raid456deadlock
Normal file
|
@ -0,0 +1,58 @@
|
|||
devs="$dev0 $dev1 $dev2 $dev3 $dev4 $dev5"
|
||||
runtime=120
|
||||
pid=""
|
||||
old=`cat /proc/sys/vm/dirty_background_ratio`
|
||||
|
||||
test_write_action()
|
||||
{
|
||||
while true; do
|
||||
echo check > /sys/block/md0/md/sync_action &> /dev/null
|
||||
sleep 0.1
|
||||
echo idle > /sys/block/md0/md/sync_action &> /dev/null
|
||||
done
|
||||
}
|
||||
|
||||
test_write_back()
|
||||
{
|
||||
fio -filename=$md0 -bs=4k -rw=write -numjobs=1 -name=test \
|
||||
-time_based -runtime=$runtime &> /dev/null
|
||||
}
|
||||
|
||||
set_up_test()
|
||||
{
|
||||
fio -h &> /dev/null || die "fio not found"
|
||||
|
||||
# create a simple raid6
|
||||
mdadm -Cv -R -n 6 -l6 $md0 $devs --assume-clean || die "create raid6 failed"
|
||||
|
||||
# trigger dirty pages write back
|
||||
echo 0 > /proc/sys/vm/dirty_background_ratio
|
||||
}
|
||||
|
||||
clean_up_test()
|
||||
{
|
||||
echo $old > /proc/sys/vm/dirty_background_ratio
|
||||
|
||||
pkill -9 fio
|
||||
kill -9 $pid
|
||||
|
||||
sleep 1
|
||||
|
||||
if ps $pid | tail -1 | awk '{print $3}' | grep D; then
|
||||
die "thread that is writing sysfs is stuck in D state, deadlock is triggered"
|
||||
fi
|
||||
mdadm -S $md0
|
||||
}
|
||||
|
||||
trap 'clean_up_test' EXIT
|
||||
|
||||
set_up_test || die "set up test failed"
|
||||
|
||||
test_write_back &
|
||||
|
||||
test_write_action &
|
||||
pid="$!"
|
||||
|
||||
sleep $runtime
|
||||
|
||||
exit 0
|
33
tests/25raid456-recovery-while-reshape
Normal file
33
tests/25raid456-recovery-while-reshape
Normal file
|
@ -0,0 +1,33 @@
|
|||
devs="$dev0 $dev1 $dev2"
|
||||
|
||||
set_up_test()
|
||||
{
|
||||
mdadm -Cv -R -n 3 -l5 $md0 $devs --assume-clean --size=50M || die "create array failed"
|
||||
mdadm -a $md0 $dev3 $dev4 || die "failed to bind new disk to array"
|
||||
echo 1000 > /sys/block/md0/md/sync_speed_max
|
||||
}
|
||||
|
||||
clean_up_test()
|
||||
{
|
||||
mdadm -S $md0
|
||||
}
|
||||
|
||||
trap 'clean_up_test' EXIT
|
||||
|
||||
set_up_test || die "set up test failed"
|
||||
|
||||
# trigger reshape
|
||||
mdadm --grow -l 6 $md0
|
||||
sleep 1
|
||||
|
||||
# set up replacement
|
||||
echo frozen > /sys/block/md0/md/sync_action
|
||||
echo want_replacement > /sys/block/md0/md/rd0/state
|
||||
echo reshape > /sys/block/md0/md/sync_action
|
||||
sleep 1
|
||||
|
||||
# reassemeble array
|
||||
mdadm -S $md0 || die "can't stop array"
|
||||
mdadm --assemble $md0 $devs $dev3 $dev4 || die "can't assemble array"
|
||||
|
||||
exit 0
|
35
tests/25raid456-reshape-corrupt-data
Normal file
35
tests/25raid456-reshape-corrupt-data
Normal file
|
@ -0,0 +1,35 @@
|
|||
devs="$dev0 $dev1 $dev2"
|
||||
|
||||
set_up_test()
|
||||
{
|
||||
mdadm -Cv -R -n 3 -l5 $md0 $devs --size=50M || die "create array failed"
|
||||
mdadm -a $md0 $dev3 || die "failed to bind new disk to array"
|
||||
mkfs.xfs -f $md0 || die "mkfs failed"
|
||||
xfs_ncheck $md0 || die "check fs failed"
|
||||
}
|
||||
|
||||
clean_up_test()
|
||||
{
|
||||
mdadm -S $md0
|
||||
}
|
||||
|
||||
trap 'clean_up_test' EXIT
|
||||
|
||||
set_up_test || die "set up test failed"
|
||||
|
||||
# trigger reshape
|
||||
echo 1000 > /sys/block/md0/md/sync_speed_max
|
||||
mdadm --grow -l 6 $md0
|
||||
sleep 1
|
||||
|
||||
# stop and start reshape
|
||||
echo frozen > /sys/block/md0/md/sync_action
|
||||
echo system > /sys/block/md0/md/sync_speed_max
|
||||
echo reshape > /sys/block/md0/md/sync_action
|
||||
|
||||
mdadm -W $md0
|
||||
|
||||
# check if data is corrupted
|
||||
xfs_ncheck $md0 || die "data is corrupted after reshape"
|
||||
|
||||
exit 0
|
34
tests/25raid456-reshape-deadlock
Normal file
34
tests/25raid456-reshape-deadlock
Normal file
|
@ -0,0 +1,34 @@
|
|||
devs="$dev0 $dev1 $dev2"
|
||||
|
||||
set_up_test()
|
||||
{
|
||||
mdadm -Cv -R -n 3 -l5 $md0 $devs --size=50M || die "create array failed"
|
||||
mdadm -a $md0 $dev3 || die "failed to bind new disk to array"
|
||||
echo 1000 > /sys/block/md0/md/sync_speed_max
|
||||
}
|
||||
|
||||
clean_up_test()
|
||||
{
|
||||
echo idle > /sys/block/md0/md/sync_action
|
||||
mdadm -S $md0
|
||||
}
|
||||
|
||||
trap 'clean_up_test' EXIT
|
||||
|
||||
set_up_test || die "set up test failed"
|
||||
|
||||
# trigger reshape
|
||||
mdadm --grow -l 6 $md0
|
||||
sleep 1
|
||||
|
||||
# stop reshape
|
||||
echo frozen > /sys/block/md0/md/sync_action
|
||||
|
||||
# read accross reshape
|
||||
dd if=$md0 of=/dev/NULL bs=1m count=100 iflag=direct &> /dev/null &
|
||||
sleep 2
|
||||
|
||||
# suspend array
|
||||
echo 1 > /sys/block/md0/md/suspend_lo
|
||||
|
||||
exit 0
|
32
tests/25raid456-reshape-while-recovery
Normal file
32
tests/25raid456-reshape-while-recovery
Normal file
|
@ -0,0 +1,32 @@
|
|||
devs="$dev0 $dev1 $dev2"
|
||||
|
||||
set_up_test()
|
||||
{
|
||||
mdadm -Cv -R -n 3 -l5 $md0 $devs --assume-clean --size=50M || die "create array failed"
|
||||
mdadm -a $md0 $dev3 $dev4 || die "failed to bind new disk to array"
|
||||
echo 1000 > /sys/block/md0/md/sync_speed_max
|
||||
}
|
||||
|
||||
clean_up_test()
|
||||
{
|
||||
mdadm -S $md0
|
||||
}
|
||||
|
||||
trap 'clean_up_test' EXIT
|
||||
|
||||
set_up_test || die "set up test failed"
|
||||
|
||||
# set up replacement
|
||||
echo want_replacement > /sys/block/md0/md/rd0/state
|
||||
sleep 1
|
||||
|
||||
# trigger reshape
|
||||
echo frozen > /sys/block/md0/md/sync_action
|
||||
mdadm --grow -l 6 $md0
|
||||
sleep 1
|
||||
|
||||
# reassemeble array
|
||||
mdadm -S $md0 || die "can't stop array"
|
||||
mdadm --assemble $md0 $devs $dev3 $dev4 || die "can't assemble array"
|
||||
|
||||
exit 0
|
|
@ -170,7 +170,6 @@ do_setup() {
|
|||
dd if=/dev/zero of=$targetdir/mdtest$d count=$sz bs=1K > /dev/null 2>&1
|
||||
# make sure udev doesn't touch
|
||||
mdadm --zero $targetdir/mdtest$d 2> /dev/null
|
||||
[ -b /dev/loop$d ] || mknod /dev/loop$d b 7 $d
|
||||
if [ $d -eq 7 ]
|
||||
then
|
||||
losetup /dev/loop$d $targetdir/mdtest6 # for multipath use
|
||||
|
|
80
tests/templates/names_template
Normal file
80
tests/templates/names_template
Normal file
|
@ -0,0 +1,80 @@
|
|||
# NAME is optional. Testing with native 1.2 superblock.
|
||||
function names_create() {
|
||||
local DEVNAME=$1
|
||||
local NAME=$2
|
||||
local NEG_TEST=$3
|
||||
|
||||
if [[ -z "$NAME" ]]; then
|
||||
mdadm -CR "$DEVNAME" -l0 -n 1 $dev0 --force
|
||||
else
|
||||
mdadm -CR "$DEVNAME" --name="$NAME" --metadata=1.2 -l0 -n 1 $dev0 --force
|
||||
fi
|
||||
|
||||
if [[ "$NEG_TEST" == "true" ]]; then
|
||||
[[ "$?" == "0" ]] && return 0
|
||||
echo "Negative verification failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$?" != "0" ]]; then
|
||||
echo "Cannot create device."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Three properties to check:
|
||||
# - devnode name
|
||||
# - link in /dev/md/ (MD_DEVNAME property from --detail --export)
|
||||
# - name in metadata (MD_NAME property from --detail --export)- that works only with 1.2 sb.
|
||||
function names_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"
|
||||
fi
|
||||
|
||||
if [[ "$RES" != "$EXPECTED" ]]; then
|
||||
echo "$RES doesn't match $EXPECTED."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local RES="$(mdadm -D --export $DEVNODE_NAME | 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
|
||||
}
|
||||
|
||||
# Generate ARRAYLINE for tested array.
|
||||
names_make_conf() {
|
||||
local UUID="$1"
|
||||
local WANTED_DEVNAME="$2"
|
||||
local WANTED_NAME="$3"
|
||||
local CONF="$4"
|
||||
|
||||
local LINE="ARRAY metadata=1.2 UUID=$UUID"
|
||||
|
||||
if [[ "$WANTED_DEVNAME" != "empty" ]]; then
|
||||
LINE="$LINE $WANTED_DEVNAME"
|
||||
fi
|
||||
|
||||
if [[ "$WANTED_NAME" != "empty" ]]; then
|
||||
LINE="$LINE name=$WANTED_NAME"
|
||||
fi
|
||||
|
||||
echo $LINE > $CONF
|
||||
}
|
Loading…
Add table
Reference in a new issue