Merge branch 'subarray' into for-neil
Conflicts: mdadm.h super-intel.c
This commit is contained in:
commit
8cfc801c72
48
Grow.c
48
Grow.c
|
@ -931,8 +931,8 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
|
|||
* old stripes and a whole number of new stripes.
|
||||
* So LCM for (chunksize*datadisks).
|
||||
*/
|
||||
a = ochunk/512 * odata;
|
||||
b = nchunk/512 * ndata;
|
||||
a = (ochunk/512) * odata;
|
||||
b = (nchunk/512) * ndata;
|
||||
/* Find GCD */
|
||||
while (a != b) {
|
||||
if (a < b)
|
||||
|
@ -941,7 +941,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
|
|||
a -= b;
|
||||
}
|
||||
/* LCM == product / GCD */
|
||||
blocks = ochunk/512 * nchunk/512 * odata * ndata / a;
|
||||
blocks = (ochunk/512) * (nchunk/512) * odata * ndata / a;
|
||||
|
||||
sysfs_free(sra);
|
||||
sra = sysfs_read(fd, 0,
|
||||
|
@ -1284,7 +1284,7 @@ int grow_backup(struct mdinfo *sra,
|
|||
odata--;
|
||||
if (level == 6)
|
||||
odata--;
|
||||
sysfs_set_num(sra, NULL, "suspend_hi", (offset + stripes * chunk/512) * odata);
|
||||
sysfs_set_num(sra, NULL, "suspend_hi", (offset + stripes * (chunk/512)) * odata);
|
||||
/* Check that array hasn't become degraded, else we might backup the wrong data */
|
||||
sysfs_get_ll(sra, NULL, "degraded", &new_degraded);
|
||||
if (new_degraded != *degraded) {
|
||||
|
@ -1312,10 +1312,10 @@ int grow_backup(struct mdinfo *sra,
|
|||
}
|
||||
if (part) {
|
||||
bsb.arraystart2 = __cpu_to_le64(offset * odata);
|
||||
bsb.length2 = __cpu_to_le64(stripes * chunk/512 * odata);
|
||||
bsb.length2 = __cpu_to_le64(stripes * (chunk/512) * odata);
|
||||
} else {
|
||||
bsb.arraystart = __cpu_to_le64(offset * odata);
|
||||
bsb.length = __cpu_to_le64(stripes * chunk/512 * odata);
|
||||
bsb.length = __cpu_to_le64(stripes * (chunk/512) * odata);
|
||||
}
|
||||
if (part)
|
||||
bsb.magic[15] = '2';
|
||||
|
@ -1540,10 +1540,10 @@ static int child_grow(int afd, struct mdinfo *sra, unsigned long stripes,
|
|||
dests, destfd, destoffsets,
|
||||
0, °raded, buf);
|
||||
validate(afd, destfd[0], destoffsets[0]);
|
||||
wait_backup(sra, 0, stripes * chunk / 512, stripes * chunk / 512,
|
||||
wait_backup(sra, 0, stripes * (chunk / 512), stripes * (chunk / 512),
|
||||
dests, destfd, destoffsets,
|
||||
0);
|
||||
sysfs_set_num(sra, NULL, "suspend_lo", (stripes * chunk/512) * data);
|
||||
sysfs_set_num(sra, NULL, "suspend_lo", (stripes * (chunk/512)) * data);
|
||||
free(buf);
|
||||
/* FIXME this should probably be numeric */
|
||||
sysfs_set_str(sra, NULL, "sync_max", "max");
|
||||
|
@ -1562,12 +1562,12 @@ static int child_shrink(int afd, struct mdinfo *sra, unsigned long stripes,
|
|||
|
||||
if (posix_memalign((void**)&buf, 4096, disks * chunk))
|
||||
return 0;
|
||||
start = sra->component_size - stripes * chunk/512;
|
||||
start = sra->component_size - stripes * (chunk/512);
|
||||
sysfs_set_num(sra, NULL, "sync_max", start);
|
||||
sysfs_set_str(sra, NULL, "sync_action", "reshape");
|
||||
sysfs_set_num(sra, NULL, "suspend_lo", 0);
|
||||
sysfs_set_num(sra, NULL, "suspend_hi", 0);
|
||||
rv = wait_backup(sra, 0, start - stripes * chunk/512, stripes * chunk/512,
|
||||
rv = wait_backup(sra, 0, start - stripes * (chunk/512), stripes * (chunk/512),
|
||||
dests, destfd, destoffsets, 0);
|
||||
if (rv < 0)
|
||||
return 0;
|
||||
|
@ -1577,9 +1577,9 @@ static int child_shrink(int afd, struct mdinfo *sra, unsigned long stripes,
|
|||
dests, destfd, destoffsets,
|
||||
0, °raded, buf);
|
||||
validate(afd, destfd[0], destoffsets[0]);
|
||||
wait_backup(sra, start, stripes*chunk/512, 0,
|
||||
wait_backup(sra, start, stripes*(chunk/512), 0,
|
||||
dests, destfd, destoffsets, 0);
|
||||
sysfs_set_num(sra, NULL, "suspend_lo", (stripes * chunk/512) * data);
|
||||
sysfs_set_num(sra, NULL, "suspend_lo", (stripes * (chunk/512)) * data);
|
||||
free(buf);
|
||||
/* FIXME this should probably be numeric */
|
||||
sysfs_set_str(sra, NULL, "sync_max", "max");
|
||||
|
@ -1614,7 +1614,7 @@ static int child_same_size(int afd, struct mdinfo *sra, unsigned long stripes,
|
|||
disks, chunk, level, layout,
|
||||
dests, destfd, destoffsets,
|
||||
0, °raded, buf);
|
||||
grow_backup(sra, (start + stripes) * chunk/512, stripes,
|
||||
grow_backup(sra, (start + stripes) * (chunk/512), stripes,
|
||||
fds, offsets,
|
||||
disks, chunk, level, layout,
|
||||
dests, destfd, destoffsets,
|
||||
|
@ -1624,16 +1624,16 @@ static int child_same_size(int afd, struct mdinfo *sra, unsigned long stripes,
|
|||
start += stripes * 2; /* where to read next */
|
||||
size = sra->component_size / (chunk/512);
|
||||
while (start < size) {
|
||||
if (wait_backup(sra, (start-stripes*2)*chunk/512,
|
||||
stripes*chunk/512, 0,
|
||||
if (wait_backup(sra, (start-stripes*2)*(chunk/512),
|
||||
stripes*(chunk/512), 0,
|
||||
dests, destfd, destoffsets,
|
||||
part) < 0)
|
||||
return 0;
|
||||
sysfs_set_num(sra, NULL, "suspend_lo", start*chunk/512 * data);
|
||||
sysfs_set_num(sra, NULL, "suspend_lo", start*(chunk/512) * data);
|
||||
if (start + stripes > size)
|
||||
tailstripes = (size - start);
|
||||
|
||||
grow_backup(sra, start*chunk/512, tailstripes,
|
||||
grow_backup(sra, start*(chunk/512), tailstripes,
|
||||
fds, offsets,
|
||||
disks, chunk, level, layout,
|
||||
dests, destfd, destoffsets,
|
||||
|
@ -1642,15 +1642,15 @@ static int child_same_size(int afd, struct mdinfo *sra, unsigned long stripes,
|
|||
part = 1 - part;
|
||||
validate(afd, destfd[0], destoffsets[0]);
|
||||
}
|
||||
if (wait_backup(sra, (start-stripes*2) * chunk/512, stripes * chunk/512, 0,
|
||||
if (wait_backup(sra, (start-stripes*2) * (chunk/512), stripes * (chunk/512), 0,
|
||||
dests, destfd, destoffsets,
|
||||
part) < 0)
|
||||
return 0;
|
||||
sysfs_set_num(sra, NULL, "suspend_lo", ((start-stripes)*chunk/512) * data);
|
||||
wait_backup(sra, (start-stripes) * chunk/512, tailstripes * chunk/512, 0,
|
||||
sysfs_set_num(sra, NULL, "suspend_lo", ((start-stripes)*(chunk/512)) * data);
|
||||
wait_backup(sra, (start-stripes) * (chunk/512), tailstripes * (chunk/512), 0,
|
||||
dests, destfd, destoffsets,
|
||||
1-part);
|
||||
sysfs_set_num(sra, NULL, "suspend_lo", (size*chunk/512) * data);
|
||||
sysfs_set_num(sra, NULL, "suspend_lo", (size*(chunk/512)) * data);
|
||||
sysfs_set_num(sra, NULL, "sync_speed_min", speed);
|
||||
free(buf);
|
||||
return 1;
|
||||
|
@ -1991,8 +1991,8 @@ int Grow_continue(int mdfd, struct supertype *st, struct mdinfo *info,
|
|||
nchunk = info->new_chunk;
|
||||
|
||||
|
||||
a = ochunk/512 * odata;
|
||||
b = nchunk/512 * ndata;
|
||||
a = (ochunk/512) * odata;
|
||||
b = (nchunk/512) * ndata;
|
||||
/* Find GCD */
|
||||
while (a != b) {
|
||||
if (a < b)
|
||||
|
@ -2001,7 +2001,7 @@ int Grow_continue(int mdfd, struct supertype *st, struct mdinfo *info,
|
|||
a -= b;
|
||||
}
|
||||
/* LCM == product / GCD */
|
||||
blocks = ochunk/512 * nchunk/512 * odata * ndata / a;
|
||||
blocks = (ochunk/512) * (nchunk/512) * odata * ndata / a;
|
||||
|
||||
sra = sysfs_read(-1, devname2devnum(info->sys_name),
|
||||
GET_COMPONENT|GET_DEVS|GET_OFFSET|GET_STATE|
|
||||
|
|
78
Kill.c
78
Kill.c
|
@ -79,3 +79,81 @@ int Kill(char *dev, struct supertype *st, int force, int quiet, int noexcl)
|
|||
close(fd);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int Kill_subarray(char *dev, char *subarray, int quiet)
|
||||
{
|
||||
/* Delete a subarray out of a container, the subarry must be
|
||||
* inactive. The subarray string must be a subarray index
|
||||
* number.
|
||||
*
|
||||
* 0 = successfully deleted subarray from all container members
|
||||
* 1 = failed to sync metadata to one or more devices
|
||||
* 2 = failed to find the container, subarray, or other resource
|
||||
* issue
|
||||
*/
|
||||
struct supertype supertype, *st = &supertype;
|
||||
int fd, rv = 2;
|
||||
|
||||
memset(st, 0, sizeof(*st));
|
||||
|
||||
if (snprintf(st->subarray, sizeof(st->subarray), "%s", subarray) >=
|
||||
sizeof(st->subarray)) {
|
||||
if (!quiet)
|
||||
fprintf(stderr,
|
||||
Name ": Input overflow for subarray '%s' > %zu bytes\n",
|
||||
subarray, sizeof(st->subarray) - 1);
|
||||
return 2;
|
||||
}
|
||||
|
||||
fd = open_subarray(dev, st, quiet);
|
||||
if (fd < 0)
|
||||
return 2;
|
||||
|
||||
if (!st->ss->kill_subarray) {
|
||||
if (!quiet)
|
||||
fprintf(stderr,
|
||||
Name ": Operation not supported for %s metadata\n",
|
||||
st->ss->name);
|
||||
goto free_super;
|
||||
}
|
||||
|
||||
if (is_subarray_active(subarray, st->devname)) {
|
||||
if (!quiet)
|
||||
fprintf(stderr,
|
||||
Name ": Subarray-%s still active, aborting\n",
|
||||
subarray);
|
||||
goto free_super;
|
||||
}
|
||||
|
||||
if (mdmon_running(st->devnum))
|
||||
st->update_tail = &st->updates;
|
||||
|
||||
/* ok we've found our victim, drop the axe */
|
||||
rv = st->ss->kill_subarray(st);
|
||||
if (rv) {
|
||||
if (!quiet)
|
||||
fprintf(stderr,
|
||||
Name ": Failed to delete subarray-%s from %s\n",
|
||||
subarray, dev);
|
||||
goto free_super;
|
||||
}
|
||||
|
||||
/* FIXME these routines do not report success/failure */
|
||||
if (st->update_tail)
|
||||
flush_metadata_updates(st);
|
||||
else
|
||||
st->ss->sync_metadata(st);
|
||||
|
||||
if (!quiet)
|
||||
fprintf(stderr,
|
||||
Name ": Deleted subarray-%s from %s, UUIDs may have changed\n",
|
||||
subarray, dev);
|
||||
|
||||
rv = 0;
|
||||
|
||||
free_super:
|
||||
st->ss->free_super(st);
|
||||
close(fd);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
|
53
Manage.c
53
Manage.c
|
@ -869,4 +869,57 @@ int autodetect(void)
|
|||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
int Update_subarray(char *dev, char *subarray, char *update, mddev_ident_t ident, int quiet)
|
||||
{
|
||||
struct supertype supertype, *st = &supertype;
|
||||
int fd, rv = 2;
|
||||
|
||||
memset(st, 0, sizeof(*st));
|
||||
if (snprintf(st->subarray, sizeof(st->subarray), "%s", subarray) >=
|
||||
sizeof(st->subarray)) {
|
||||
if (!quiet)
|
||||
fprintf(stderr,
|
||||
Name ": Input overflow for subarray '%s' > %zu bytes\n",
|
||||
subarray, sizeof(st->subarray) - 1);
|
||||
return 2;
|
||||
}
|
||||
|
||||
fd = open_subarray(dev, st, quiet);
|
||||
if (fd < 0)
|
||||
return 2;
|
||||
|
||||
if (!st->ss->update_subarray) {
|
||||
if (!quiet)
|
||||
fprintf(stderr,
|
||||
Name ": Operation not supported for %s metadata\n",
|
||||
st->ss->name);
|
||||
goto free_super;
|
||||
}
|
||||
|
||||
if (mdmon_running(st->devnum))
|
||||
st->update_tail = &st->updates;
|
||||
|
||||
rv = st->ss->update_subarray(st, update, ident);
|
||||
|
||||
if (rv) {
|
||||
if (!quiet)
|
||||
fprintf(stderr, Name ": Failed to update %s of subarray-%s in %s\n",
|
||||
update, subarray, dev);
|
||||
} else if (st->update_tail)
|
||||
flush_metadata_updates(st);
|
||||
else
|
||||
st->ss->sync_metadata(st);
|
||||
|
||||
if (rv == 0 && strcmp(update, "name") == 0 && !quiet)
|
||||
fprintf(stderr,
|
||||
Name ": Updated subarray-%s name from %s, UUIDs may have changed\n",
|
||||
subarray, dev);
|
||||
|
||||
free_super:
|
||||
st->ss->free_super(st);
|
||||
close(fd);
|
||||
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
|
2
ReadMe.c
2
ReadMe.c
|
@ -108,6 +108,8 @@ struct option long_options[] = {
|
|||
{"examine-bitmap", 0, 0, 'X'},
|
||||
{"auto-detect", 0, 0, AutoDetect},
|
||||
{"detail-platform", 0, 0, DetailPlatform},
|
||||
{"kill-subarray", 1, 0, KillSubarray},
|
||||
{"update-subarray", 1, 0, UpdateSubarray},
|
||||
|
||||
/* synonyms */
|
||||
{"monitor", 0, 0, 'F'},
|
||||
|
|
40
mdadm.8
40
mdadm.8
|
@ -1172,6 +1172,24 @@ overwritten with zeros. With
|
|||
the block where the superblock would be is overwritten even if it
|
||||
doesn't appear to be valid.
|
||||
|
||||
.TP
|
||||
.B \-\-kill\-subarray=
|
||||
If the device is a container and the argument to \-\-kill\-subarray
|
||||
specifies an inactive subarray in the container, then the subarray is
|
||||
deleted. Deleting all subarrays will leave an 'empty-container' or
|
||||
spare superblock on the drives. See \-\-zero\-superblock for completely
|
||||
removing a superblock. Note that some formats depend on the subarray
|
||||
index for generating a UUID, this command will fail if it would change
|
||||
the UUID of an active subarray.
|
||||
|
||||
.TP
|
||||
.B \-\-update\-subarray=
|
||||
If the device is a container and the argument to \-\-update\-subarray
|
||||
specifies a subarray in the container, then attempt to update the given
|
||||
superblock field in the subarray. See below in
|
||||
.B MISC MODE
|
||||
for details.
|
||||
|
||||
.TP
|
||||
.BR \-t ", " \-\-test
|
||||
When used with
|
||||
|
@ -1747,6 +1765,28 @@ metadata is platform independent
|
|||
metadata failed to find its platform components on this system
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B \-\-update\-subarray=
|
||||
If the device is a container and the argument to \-\-update\-subarray
|
||||
specifies a subarray in the container, then attempt to update the given
|
||||
superblock field in the subarray. Similar to updating an array in
|
||||
"assemble" mode, the field to update is selected by
|
||||
.B \-U
|
||||
or
|
||||
.B \-\-update=
|
||||
option. Currently only
|
||||
.B name
|
||||
is supported.
|
||||
|
||||
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.
|
||||
|
||||
.TP
|
||||
.B \-\-examine
|
||||
The device should be a component of an md array.
|
||||
|
|
47
mdadm.c
47
mdadm.c
|
@ -103,6 +103,7 @@ int main(int argc, char *argv[])
|
|||
int dosyslog = 0;
|
||||
int rebuild_map = 0;
|
||||
int auto_update_home = 0;
|
||||
char *subarray = NULL;
|
||||
|
||||
int print_help = 0;
|
||||
FILE *outf;
|
||||
|
@ -216,6 +217,15 @@ int main(int argc, char *argv[])
|
|||
case 'W':
|
||||
case Waitclean:
|
||||
case DetailPlatform:
|
||||
case KillSubarray:
|
||||
case UpdateSubarray:
|
||||
if (opt == KillSubarray || opt == UpdateSubarray) {
|
||||
if (subarray) {
|
||||
fprintf(stderr, Name ": subarray can only be specified once\n");
|
||||
exit(2);
|
||||
}
|
||||
subarray = optarg;
|
||||
}
|
||||
case 'K': if (!mode) newmode = MISC; break;
|
||||
}
|
||||
if (mode && newmode == mode) {
|
||||
|
@ -589,11 +599,16 @@ int main(int argc, char *argv[])
|
|||
|
||||
case O(CREATE,'N'):
|
||||
case O(ASSEMBLE,'N'):
|
||||
case O(MISC,'N'):
|
||||
if (ident.name[0]) {
|
||||
fprintf(stderr, Name ": name cannot be set twice. "
|
||||
"Second value %s.\n", optarg);
|
||||
exit(2);
|
||||
}
|
||||
if (mode == MISC && !subarray) {
|
||||
fprintf(stderr, Name ": -N/--name only valid with --update-subarray in misc mode\n");
|
||||
exit(2);
|
||||
}
|
||||
if (strlen(optarg) > 32) {
|
||||
fprintf(stderr, Name ": name '%s' is too long, 32 chars max.\n",
|
||||
optarg);
|
||||
|
@ -620,11 +635,16 @@ int main(int argc, char *argv[])
|
|||
continue;
|
||||
|
||||
case O(ASSEMBLE,'U'): /* update the superblock */
|
||||
case O(MISC,'U'):
|
||||
if (update) {
|
||||
fprintf(stderr, Name ": Can only update one aspect of superblock, both %s and %s given.\n",
|
||||
update, optarg);
|
||||
exit(2);
|
||||
}
|
||||
if (mode == MISC && !subarray) {
|
||||
fprintf(stderr, Name ": Only subarrays can be updated in misc mode\n");
|
||||
exit(2);
|
||||
}
|
||||
update = optarg;
|
||||
if (strcmp(update, "sparc2.2")==0)
|
||||
continue;
|
||||
|
@ -807,10 +827,21 @@ int main(int argc, char *argv[])
|
|||
case O(MISC,'W'):
|
||||
case O(MISC, Waitclean):
|
||||
case O(MISC, DetailPlatform):
|
||||
case O(MISC, KillSubarray):
|
||||
case O(MISC, UpdateSubarray):
|
||||
if (devmode && devmode != opt &&
|
||||
(devmode == 'E' || (opt == 'E' && devmode != 'Q'))) {
|
||||
fprintf(stderr, Name ": --examine/-E cannot be given with -%c\n",
|
||||
devmode =='E'?opt:devmode);
|
||||
fprintf(stderr, Name ": --examine/-E cannot be given with ");
|
||||
if (devmode == 'E') {
|
||||
if (option_index >= 0)
|
||||
fprintf(stderr, "--%s\n",
|
||||
long_options[option_index].name);
|
||||
else
|
||||
fprintf(stderr, "-%c\n", opt);
|
||||
} else if (isalpha(devmode))
|
||||
fprintf(stderr, "-%c\n", devmode);
|
||||
else
|
||||
fprintf(stderr, "previous option\n");
|
||||
exit(2);
|
||||
}
|
||||
devmode = opt;
|
||||
|
@ -1403,6 +1434,18 @@ int main(int argc, char *argv[])
|
|||
rv |= Wait(dv->devname); continue;
|
||||
case Waitclean:
|
||||
rv |= WaitClean(dv->devname, -1, verbose-quiet); continue;
|
||||
case KillSubarray:
|
||||
rv |= Kill_subarray(dv->devname, subarray, quiet);
|
||||
continue;
|
||||
case UpdateSubarray:
|
||||
if (update == NULL) {
|
||||
fprintf(stderr,
|
||||
Name ": -U/--update must be specified with --update-subarray\n");
|
||||
rv |= 1;
|
||||
continue;
|
||||
}
|
||||
rv |= Update_subarray(dv->devname, subarray, update, &ident, quiet);
|
||||
continue;
|
||||
}
|
||||
mdfd = open_mddev(dv->devname, 1);
|
||||
if (mdfd>=0) {
|
||||
|
|
16
mdadm.h
16
mdadm.h
|
@ -258,6 +258,7 @@ extern char Version[], Usage[], Help[], OptionHelp[],
|
|||
|
||||
/* for option that don't have short equivilents, we assign arbitrary
|
||||
* small numbers. '1' means an undecorated option, so we start at '2'.
|
||||
* (note we must stop before we get to 65 i.e. 'A')
|
||||
*/
|
||||
enum special_options {
|
||||
AssumeClean = 2,
|
||||
|
@ -266,13 +267,15 @@ enum special_options {
|
|||
ReAdd,
|
||||
NoDegraded,
|
||||
Sparc22,
|
||||
BackupFile,
|
||||
BackupFile, /* 8 */
|
||||
HomeHost,
|
||||
AutoHomeHost,
|
||||
Symlinks,
|
||||
AutoDetect,
|
||||
Waitclean,
|
||||
DetailPlatform,
|
||||
KillSubarray,
|
||||
UpdateSubarray, /* 16 */
|
||||
};
|
||||
|
||||
/* structures read from config file */
|
||||
|
@ -611,6 +614,10 @@ extern struct superswitch {
|
|||
int (*default_layout)(int level); /* optional */
|
||||
/* query the supertype for default chunk size */
|
||||
int (*default_chunk)(struct supertype *st); /* optional */
|
||||
/* Permit subarray's to be deleted from inactive containers */
|
||||
int (*kill_subarray)(struct supertype *st); /* optional */
|
||||
/* Permit subarray's to be modified */
|
||||
int (*update_subarray)(struct supertype *st, char *update, mddev_ident_t ident); /* optional */
|
||||
|
||||
/* for mdmon */
|
||||
int (*open_new)(struct supertype *c, struct active_array *a,
|
||||
|
@ -807,6 +814,8 @@ extern int Monitor(mddev_dev_t devlist,
|
|||
int dosyslog, int test, char *pidfile, int increments);
|
||||
|
||||
extern int Kill(char *dev, struct supertype *st, int force, int quiet, int noexcl);
|
||||
extern int Kill_subarray(char *dev, char *subarray, int quiet);
|
||||
extern int Update_subarray(char *dev, char *subarray, char *update, mddev_ident_t ident, int quiet);
|
||||
extern int Wait(char *dev);
|
||||
extern int WaitClean(char *dev, int sock, int verbose);
|
||||
|
||||
|
@ -878,6 +887,7 @@ extern int enough(int level, int raid_disks, int layout, int clean,
|
|||
extern int ask(char *mesg);
|
||||
extern unsigned long long get_component_size(int fd);
|
||||
extern void remove_partitions(int fd);
|
||||
extern int test_partition(int fd);
|
||||
extern unsigned long long calc_array_size(int level, int raid_disks, int layout,
|
||||
int chunksize, unsigned long long devsize);
|
||||
extern int flush_metadata_updates(struct supertype *st);
|
||||
|
@ -912,6 +922,10 @@ extern int create_mddev(char *dev, char *name, int autof, int trustworthy,
|
|||
#define METADATA 3
|
||||
extern int open_mddev(char *dev, int report_errors);
|
||||
extern int open_container(int fd);
|
||||
extern int is_container_member(struct mdstat_ent *ent, char *devname);
|
||||
extern int is_subarray_active(char *subarray, char *devname);
|
||||
extern int open_subarray(char *dev, struct supertype *st, int quiet);
|
||||
extern struct superswitch *version_to_superswitch(char *vers);
|
||||
|
||||
extern char *pid_dir;
|
||||
extern int mdmon_running(int devnum);
|
||||
|
|
25
mdmon.c
25
mdmon.c
|
@ -104,15 +104,6 @@ int __clone2(int (*fn)(void *),
|
|||
return mon_tid;
|
||||
}
|
||||
|
||||
static struct superswitch *find_metadata_methods(char *vers)
|
||||
{
|
||||
if (strcmp(vers, "ddf") == 0)
|
||||
return &super_ddf;
|
||||
if (strcmp(vers, "imsm") == 0)
|
||||
return &super_imsm;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int make_pidfile(char *devname)
|
||||
{
|
||||
char path[100];
|
||||
|
@ -136,18 +127,6 @@ static int make_pidfile(char *devname)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int is_container_member(struct mdstat_ent *mdstat, char *container)
|
||||
{
|
||||
if (mdstat->metadata_version == NULL ||
|
||||
strncmp(mdstat->metadata_version, "external:", 9) != 0 ||
|
||||
!is_subarray(mdstat->metadata_version+9) ||
|
||||
strncmp(mdstat->metadata_version+10, container, strlen(container)) != 0 ||
|
||||
mdstat->metadata_version[10+strlen(container)] != '/')
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void try_kill_monitor(pid_t pid, char *devname, int sock)
|
||||
{
|
||||
char buf[100];
|
||||
|
@ -414,9 +393,9 @@ static int mdmon(char *devname, int devnum, int must_fork, int takeover)
|
|||
exit(3);
|
||||
}
|
||||
|
||||
container->ss = find_metadata_methods(mdi->text_version);
|
||||
container->ss = version_to_superswitch(mdi->text_version);
|
||||
if (container->ss == NULL) {
|
||||
fprintf(stderr, "mdmon: %s uses unknown metadata: %s\n",
|
||||
fprintf(stderr, "mdmon: %s uses unsupported metadata: %s\n",
|
||||
devname, mdi->text_version);
|
||||
exit(3);
|
||||
}
|
||||
|
|
29
super-ddf.c
29
super-ddf.c
|
@ -783,6 +783,10 @@ static int load_super_ddf(struct supertype *st, int fd,
|
|||
if (get_dev_size(fd, devname, &dsize) == 0)
|
||||
return 1;
|
||||
|
||||
if (test_partition(fd))
|
||||
/* DDF is not allowed on partitions */
|
||||
return 1;
|
||||
|
||||
/* 32M is a lower bound */
|
||||
if (dsize <= 32*1024*1024) {
|
||||
if (devname)
|
||||
|
@ -841,10 +845,18 @@ static int load_super_ddf(struct supertype *st, int fd,
|
|||
}
|
||||
|
||||
if (st->subarray[0]) {
|
||||
unsigned long val;
|
||||
struct vcl *v;
|
||||
char *ep;
|
||||
|
||||
val = strtoul(st->subarray, &ep, 10);
|
||||
if (*ep != '\0') {
|
||||
free(super);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (v = super->conflist; v; v = v->next)
|
||||
if (v->vcnum == atoi(st->subarray))
|
||||
if (v->vcnum == val)
|
||||
super->currentconf = v;
|
||||
if (!super->currentconf) {
|
||||
free(super);
|
||||
|
@ -2866,14 +2878,25 @@ static int load_super_ddf_all(struct supertype *st, int fd,
|
|||
return 1;
|
||||
}
|
||||
if (st->subarray[0]) {
|
||||
unsigned long val;
|
||||
struct vcl *v;
|
||||
char *ep;
|
||||
|
||||
val = strtoul(st->subarray, &ep, 10);
|
||||
if (*ep != '\0') {
|
||||
free(super);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (v = super->conflist; v; v = v->next)
|
||||
if (v->vcnum == atoi(st->subarray))
|
||||
if (v->vcnum == val)
|
||||
super->currentconf = v;
|
||||
if (!super->currentconf)
|
||||
if (!super->currentconf) {
|
||||
free(super);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
*sbp = super;
|
||||
if (st->ss == NULL) {
|
||||
st->ss = &super_ddf;
|
||||
|
|
299
super-intel.c
299
super-intel.c
|
@ -282,6 +282,8 @@ struct extent {
|
|||
enum imsm_update_type {
|
||||
update_activate_spare,
|
||||
update_create_array,
|
||||
update_kill_array,
|
||||
update_rename_array,
|
||||
update_add_disk,
|
||||
};
|
||||
|
||||
|
@ -303,6 +305,17 @@ struct imsm_update_create_array {
|
|||
struct imsm_dev dev;
|
||||
};
|
||||
|
||||
struct imsm_update_kill_array {
|
||||
enum imsm_update_type type;
|
||||
int dev_idx;
|
||||
};
|
||||
|
||||
struct imsm_update_rename_array {
|
||||
enum imsm_update_type type;
|
||||
__u8 name[MAX_RAID_SERIAL_LEN];
|
||||
int dev_idx;
|
||||
};
|
||||
|
||||
struct imsm_update_add_disk {
|
||||
enum imsm_update_type type;
|
||||
};
|
||||
|
@ -2759,11 +2772,20 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp,
|
|||
}
|
||||
|
||||
if (st->subarray[0]) {
|
||||
if (atoi(st->subarray) <= super->anchor->num_raid_devs)
|
||||
super->current_vol = atoi(st->subarray);
|
||||
unsigned long val;
|
||||
char *ep;
|
||||
|
||||
err = 1;
|
||||
val = strtoul(st->subarray, &ep, 10);
|
||||
if (*ep != '\0') {
|
||||
free_imsm(super);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (val < super->anchor->num_raid_devs)
|
||||
super->current_vol = val;
|
||||
else {
|
||||
free_imsm(super);
|
||||
err = 1;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
@ -2804,6 +2826,10 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname)
|
|||
return 0;
|
||||
#endif
|
||||
|
||||
if (test_partition(fd))
|
||||
/* IMSM not allowed on partitions */
|
||||
return 1;
|
||||
|
||||
free_super_imsm(st);
|
||||
|
||||
super = alloc_super();
|
||||
|
@ -2826,8 +2852,17 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname)
|
|||
}
|
||||
|
||||
if (st->subarray[0]) {
|
||||
if (atoi(st->subarray) <= super->anchor->num_raid_devs)
|
||||
super->current_vol = atoi(st->subarray);
|
||||
unsigned long val;
|
||||
char *ep;
|
||||
|
||||
val = strtoul(st->subarray, &ep, 10);
|
||||
if (*ep != '\0') {
|
||||
free_imsm(super);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (val < super->anchor->num_raid_devs)
|
||||
super->current_vol = val;
|
||||
else {
|
||||
free_imsm(super);
|
||||
return 1;
|
||||
|
@ -2917,6 +2952,30 @@ static void imsm_update_version_info(struct intel_super *super)
|
|||
}
|
||||
}
|
||||
|
||||
static int check_name(struct intel_super *super, char *name, int quiet)
|
||||
{
|
||||
struct imsm_super *mpb = super->anchor;
|
||||
char *reason = NULL;
|
||||
int i;
|
||||
|
||||
if (strlen(name) > MAX_RAID_SERIAL_LEN)
|
||||
reason = "must be 16 characters or less";
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (reason && !quiet)
|
||||
fprintf(stderr, Name ": imsm volume name %s\n", reason);
|
||||
|
||||
return !reason;
|
||||
}
|
||||
|
||||
static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
|
||||
unsigned long long size, char *name,
|
||||
char *homehost, int *uuid)
|
||||
|
@ -2968,16 +3027,8 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
|
|||
if (super->current_vol == 0)
|
||||
mpb->num_disks = 0;
|
||||
|
||||
for (i = 0; i < super->current_vol; i++) {
|
||||
dev = get_imsm_dev(super, i);
|
||||
if (strncmp((char *) dev->volume, name,
|
||||
MAX_RAID_SERIAL_LEN) == 0) {
|
||||
fprintf(stderr, Name": '%s' is already defined for this container\n",
|
||||
name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!check_name(super, name, 0))
|
||||
return 0;
|
||||
sprintf(st->subarray, "%d", idx);
|
||||
dv = malloc(sizeof(*dv));
|
||||
if (!dv) {
|
||||
|
@ -4020,6 +4071,129 @@ static int default_chunk_imsm(struct supertype *st)
|
|||
return imsm_orom_default_chunk(super->orom);
|
||||
}
|
||||
|
||||
static void handle_missing(struct intel_super *super, struct imsm_dev *dev);
|
||||
|
||||
static int kill_subarray_imsm(struct supertype *st)
|
||||
{
|
||||
/* remove the subarray currently referenced by ->current_vol */
|
||||
__u8 i;
|
||||
struct intel_dev **dp;
|
||||
struct intel_super *super = st->sb;
|
||||
__u8 current_vol = super->current_vol;
|
||||
struct imsm_super *mpb = super->anchor;
|
||||
|
||||
if (super->current_vol < 0)
|
||||
return 2;
|
||||
super->current_vol = -1; /* invalidate subarray cursor */
|
||||
|
||||
/* block deletions that would change the uuid of active subarrays
|
||||
*
|
||||
* FIXME when immutable ids are available, but note that we'll
|
||||
* also need to fixup the invalidated/active subarray indexes in
|
||||
* mdstat
|
||||
*/
|
||||
for (i = 0; i < mpb->num_raid_devs; i++) {
|
||||
char subarray[4];
|
||||
|
||||
if (i < current_vol)
|
||||
continue;
|
||||
sprintf(subarray, "%u", i);
|
||||
if (is_subarray_active(subarray, st->devname)) {
|
||||
fprintf(stderr,
|
||||
Name ": deleting subarray-%d would change the UUID of active subarray-%d, aborting\n",
|
||||
current_vol, i);
|
||||
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (st->update_tail) {
|
||||
struct imsm_update_kill_array *u = malloc(sizeof(*u));
|
||||
|
||||
if (!u)
|
||||
return 2;
|
||||
u->type = update_kill_array;
|
||||
u->dev_idx = current_vol;
|
||||
append_metadata_update(st, u, sizeof(*u));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (dp = &super->devlist; *dp;)
|
||||
if ((*dp)->index == current_vol) {
|
||||
*dp = (*dp)->next;
|
||||
} else {
|
||||
handle_missing(super, (*dp)->dev);
|
||||
if ((*dp)->index > current_vol)
|
||||
(*dp)->index--;
|
||||
dp = &(*dp)->next;
|
||||
}
|
||||
|
||||
/* no more raid devices, all active components are now spares,
|
||||
* but of course failed are still failed
|
||||
*/
|
||||
if (--mpb->num_raid_devs == 0) {
|
||||
struct dl *d;
|
||||
|
||||
for (d = super->disks; d; d = d->next)
|
||||
if (d->index > -2) {
|
||||
d->index = -1;
|
||||
d->disk.status = SPARE_DISK;
|
||||
}
|
||||
}
|
||||
|
||||
super->updates_pending++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int update_subarray_imsm(struct supertype *st, char *update, mddev_ident_t ident)
|
||||
{
|
||||
/* update the subarray currently referenced by ->current_vol */
|
||||
struct intel_super *super = st->sb;
|
||||
struct imsm_super *mpb = super->anchor;
|
||||
|
||||
if (super->current_vol < 0)
|
||||
return 2;
|
||||
|
||||
if (strcmp(update, "name") == 0) {
|
||||
char *name = ident->name;
|
||||
|
||||
if (is_subarray_active(st->subarray, st->devname)) {
|
||||
fprintf(stderr,
|
||||
Name ": Unable to update name of active subarray\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (!check_name(super, name, 0))
|
||||
return 2;
|
||||
|
||||
if (st->update_tail) {
|
||||
struct imsm_update_rename_array *u = malloc(sizeof(*u));
|
||||
|
||||
if (!u)
|
||||
return 2;
|
||||
u->type = update_rename_array;
|
||||
u->dev_idx = super->current_vol;
|
||||
snprintf((char *) u->name, MAX_RAID_SERIAL_LEN, "%s", name);
|
||||
append_metadata_update(st, u, sizeof(*u));
|
||||
} else {
|
||||
struct imsm_dev *dev;
|
||||
int i;
|
||||
|
||||
dev = get_imsm_dev(super, super->current_vol);
|
||||
snprintf((char *) dev->volume, MAX_RAID_SERIAL_LEN, "%s", name);
|
||||
for (i = 0; i < mpb->num_raid_devs; i++) {
|
||||
dev = get_imsm_dev(super, i);
|
||||
handle_missing(super, dev);
|
||||
}
|
||||
super->updates_pending++;
|
||||
}
|
||||
} else
|
||||
return 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* MDASSEMBLE */
|
||||
|
||||
static int is_rebuilding(struct imsm_dev *dev)
|
||||
|
@ -4360,6 +4534,24 @@ static void mark_missing(struct imsm_dev *dev, struct imsm_disk *disk, int idx)
|
|||
memmove(&disk->serial[0], &disk->serial[1], MAX_RAID_SERIAL_LEN - 1);
|
||||
}
|
||||
|
||||
static void handle_missing(struct intel_super *super, struct imsm_dev *dev)
|
||||
{
|
||||
__u8 map_state;
|
||||
struct dl *dl;
|
||||
int failed;
|
||||
|
||||
if (!super->missing)
|
||||
return;
|
||||
failed = imsm_count_failed(super, dev);
|
||||
map_state = imsm_check_degraded(super, dev, failed);
|
||||
|
||||
dprintf("imsm: mark missing\n");
|
||||
end_migration(dev, map_state);
|
||||
for (dl = super->missing; dl; dl = dl->next)
|
||||
mark_missing(dev, &dl->disk, dl->index);
|
||||
super->updates_pending++;
|
||||
}
|
||||
|
||||
/* Handle dirty -> clean transititions and resync. Degraded and rebuild
|
||||
* states are handled in imsm_set_disk() with one exception, when a
|
||||
* resync is stopped due to a new failure this routine will set the
|
||||
|
@ -4376,15 +4568,8 @@ static int imsm_set_array_state(struct active_array *a, int consistent)
|
|||
__u32 blocks_per_unit;
|
||||
|
||||
/* before we activate this array handle any missing disks */
|
||||
if (consistent == 2 && super->missing) {
|
||||
struct dl *dl;
|
||||
|
||||
dprintf("imsm: mark missing\n");
|
||||
end_migration(dev, map_state);
|
||||
for (dl = super->missing; dl; dl = dl->next)
|
||||
mark_missing(dev, &dl->disk, dl->index);
|
||||
super->updates_pending++;
|
||||
}
|
||||
if (consistent == 2)
|
||||
handle_missing(super, dev);
|
||||
|
||||
if (consistent == 2 &&
|
||||
(!is_resync_complete(&a->info) ||
|
||||
|
@ -5081,6 +5266,70 @@ static void imsm_process_update(struct supertype *st,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case update_kill_array: {
|
||||
struct imsm_update_kill_array *u = (void *) update->buf;
|
||||
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
|
||||
*
|
||||
* FIXME when immutable ids are available, but note that
|
||||
* we'll also need to fixup the invalidated/active
|
||||
* subarray indexes in mdstat
|
||||
*/
|
||||
for (a = st->arrays; a; a = a->next)
|
||||
if (a->info.container_member >= victim)
|
||||
break;
|
||||
/* by definition if mdmon is running at least one array
|
||||
* 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) {
|
||||
dprintf("failed to delete subarray-%d\n", victim);
|
||||
break;
|
||||
}
|
||||
|
||||
for (dp = &super->devlist; *dp;)
|
||||
if ((*dp)->index == super->current_vol) {
|
||||
*dp = (*dp)->next;
|
||||
} else {
|
||||
if ((*dp)->index > victim)
|
||||
(*dp)->index--;
|
||||
dp = &(*dp)->next;
|
||||
}
|
||||
mpb->num_raid_devs--;
|
||||
super->updates_pending++;
|
||||
break;
|
||||
}
|
||||
case update_rename_array: {
|
||||
struct imsm_update_rename_array *u = (void *) update->buf;
|
||||
char name[MAX_RAID_SERIAL_LEN+1];
|
||||
int target = u->dev_idx;
|
||||
struct active_array *a;
|
||||
struct imsm_dev *dev;
|
||||
|
||||
/* sanity check that we are not affecting the uuid of
|
||||
* an active array
|
||||
*/
|
||||
snprintf(name, MAX_RAID_SERIAL_LEN, "%s", (char *) u->name);
|
||||
name[MAX_RAID_SERIAL_LEN] = '\0';
|
||||
for (a = st->arrays; a; a = a->next)
|
||||
if (a->info.container_member == target)
|
||||
break;
|
||||
dev = get_imsm_dev(super, u->dev_idx);
|
||||
if (a || !dev || !check_name(super, name, 1)) {
|
||||
dprintf("failed to rename subarray-%d\n", target);
|
||||
break;
|
||||
}
|
||||
|
||||
snprintf((char *) dev->volume, MAX_RAID_SERIAL_LEN, name);
|
||||
super->updates_pending++;
|
||||
break;
|
||||
}
|
||||
case update_add_disk:
|
||||
|
||||
/* we may be able to repair some arrays if disks are
|
||||
|
@ -5257,6 +5506,8 @@ struct superswitch super_imsm = {
|
|||
.default_chunk = default_chunk_imsm,
|
||||
.add_to_super = add_to_super_imsm,
|
||||
.detail_platform = detail_platform_imsm,
|
||||
.kill_subarray = kill_subarray_imsm,
|
||||
.update_subarray = update_subarray_imsm,
|
||||
#endif
|
||||
.match_home = match_home_imsm,
|
||||
.uuid_from_super= uuid_from_super_imsm,
|
||||
|
|
162
util.c
162
util.c
|
@ -302,6 +302,31 @@ void remove_partitions(int fd)
|
|||
#endif
|
||||
}
|
||||
|
||||
int test_partition(int fd)
|
||||
{
|
||||
/* Check if fd is a whole-disk or a partition.
|
||||
* BLKPG will return EINVAL on a partition, and BLKPG_DEL_PARTITION
|
||||
* will return ENXIO on an invalid partition number.
|
||||
*/
|
||||
struct blkpg_ioctl_arg a;
|
||||
struct blkpg_partition p;
|
||||
a.op = BLKPG_DEL_PARTITION;
|
||||
a.data = (void*)&p;
|
||||
a.datalen = sizeof(p);
|
||||
a.flags = 0;
|
||||
memset(a.data, 0, a.datalen);
|
||||
p.pno = 1<<30;
|
||||
if (ioctl(fd, BLKPG, &a) == 0)
|
||||
/* Very unlikely, but not a partition */
|
||||
return 0;
|
||||
if (errno == ENXIO)
|
||||
/* not a partition */
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int enough(int level, int raid_disks, int layout, int clean,
|
||||
char *avail, int avail_disks)
|
||||
{
|
||||
|
@ -1367,6 +1392,143 @@ int open_container(int fd)
|
|||
return -1;
|
||||
}
|
||||
|
||||
struct superswitch *version_to_superswitch(char *vers)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; superlist[i]; i++) {
|
||||
struct superswitch *ss = superlist[i];
|
||||
|
||||
if (strcmp(vers, ss->name) == 0)
|
||||
return ss;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int is_container_member(struct mdstat_ent *mdstat, char *container)
|
||||
{
|
||||
if (mdstat->metadata_version == NULL ||
|
||||
strncmp(mdstat->metadata_version, "external:", 9) != 0 ||
|
||||
!is_subarray(mdstat->metadata_version+9) ||
|
||||
strncmp(mdstat->metadata_version+10, container, strlen(container)) != 0 ||
|
||||
mdstat->metadata_version[10+strlen(container)] != '/')
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int is_subarray_active(char *subarray, char *container)
|
||||
{
|
||||
struct mdstat_ent *mdstat = mdstat_read(0, 0);
|
||||
struct mdstat_ent *ent;
|
||||
|
||||
for (ent = mdstat; ent; ent = ent->next) {
|
||||
if (is_container_member(ent, container)) {
|
||||
char *inst = &ent->metadata_version[10+strlen(container)+1];
|
||||
|
||||
if (strcmp(inst, subarray) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free_mdstat(mdstat);
|
||||
|
||||
return ent != NULL;
|
||||
}
|
||||
|
||||
/* open_subarray - opens a subarray in a container
|
||||
* @dev: container device name
|
||||
* @st: supertype with only ->subarray set
|
||||
* @quiet: block reporting errors flag
|
||||
*
|
||||
* On success returns an fd to a container and fills in *st
|
||||
*/
|
||||
int open_subarray(char *dev, struct supertype *st, int quiet)
|
||||
{
|
||||
struct mdinfo *mdi;
|
||||
int fd, err = 1;
|
||||
|
||||
fd = open(dev, O_RDWR|O_EXCL);
|
||||
if (fd < 0) {
|
||||
if (!quiet)
|
||||
fprintf(stderr, Name ": Couldn't open %s, aborting\n",
|
||||
dev);
|
||||
return 2;
|
||||
}
|
||||
|
||||
st->devnum = fd2devnum(fd);
|
||||
if (st->devnum == NoMdDev) {
|
||||
if (!quiet)
|
||||
fprintf(stderr,
|
||||
Name ": Failed to determine device number for %s\n",
|
||||
dev);
|
||||
goto close_fd;
|
||||
}
|
||||
|
||||
mdi = sysfs_read(fd, st->devnum, GET_VERSION|GET_LEVEL);
|
||||
if (!mdi) {
|
||||
if (!quiet)
|
||||
fprintf(stderr, Name ": Failed to read sysfs for %s\n",
|
||||
dev);
|
||||
goto close_fd;
|
||||
}
|
||||
|
||||
if (mdi->array.level != UnSet) {
|
||||
if (!quiet)
|
||||
fprintf(stderr, Name ": %s is not a container\n", dev);
|
||||
goto free_sysfs;
|
||||
}
|
||||
|
||||
st->ss = version_to_superswitch(mdi->text_version);
|
||||
if (!st->ss) {
|
||||
if (!quiet)
|
||||
fprintf(stderr,
|
||||
Name ": Operation not supported for %s metadata\n",
|
||||
mdi->text_version);
|
||||
goto free_sysfs;
|
||||
}
|
||||
|
||||
st->devname = devnum2devname(st->devnum);
|
||||
if (!st->devname) {
|
||||
if (!quiet)
|
||||
fprintf(stderr, Name ": Failed to allocate device name\n");
|
||||
goto free_sysfs;
|
||||
}
|
||||
|
||||
if (st->ss->load_super(st, fd, NULL)) {
|
||||
if (!quiet)
|
||||
fprintf(stderr, Name ": Failed to find subarray-%s in %s\n",
|
||||
st->subarray, dev);
|
||||
goto free_name;
|
||||
}
|
||||
|
||||
if (!st->loaded_container) {
|
||||
if (!quiet)
|
||||
fprintf(stderr, Name ": %s is not a container\n", dev);
|
||||
goto free_super;
|
||||
}
|
||||
|
||||
err = 0;
|
||||
|
||||
free_super:
|
||||
if (err)
|
||||
st->ss->free_super(st);
|
||||
free_name:
|
||||
if (err)
|
||||
free(st->devname);
|
||||
free_sysfs:
|
||||
sysfs_free(mdi);
|
||||
close_fd:
|
||||
if (err)
|
||||
close(fd);
|
||||
|
||||
if (err)
|
||||
return -1;
|
||||
else
|
||||
return fd;
|
||||
}
|
||||
|
||||
int add_disk(int mdfd, struct supertype *st,
|
||||
struct mdinfo *sra, struct mdinfo *info)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue