mdctl-v0.3
This commit is contained in:
parent
64c4757e27
commit
682c705194
48
Assemble.c
48
Assemble.c
|
@ -107,7 +107,7 @@ int Assemble(char *mddev, int mdfd,
|
|||
int most_recent = 0;
|
||||
|
||||
if (!mddev && !scan) {
|
||||
fputs("mdctl: internal error - Assemble called with no devie or scan\n", stderr);
|
||||
fputs(Name ": internal error - Assemble called with no devie or scan\n", stderr);
|
||||
return 1;
|
||||
}
|
||||
if (!mddev) {
|
||||
|
@ -115,7 +115,7 @@ int Assemble(char *mddev, int mdfd,
|
|||
int found = 0;
|
||||
device_list = conf_get_uuids(conffile);
|
||||
if (!device_list) {
|
||||
fprintf(stderr, "mdctl: No devices found in config file\n");
|
||||
fprintf(stderr, Name ": No devices found in config file\n");
|
||||
return 1;
|
||||
}
|
||||
while (device_list) {
|
||||
|
@ -123,7 +123,7 @@ int Assemble(char *mddev, int mdfd,
|
|||
mdfd = open(device_list->devname, O_RDONLY, 0);
|
||||
if (mdfd < 0) {
|
||||
fprintf(stderr,
|
||||
"mdctl: error opening %s: %s\n",
|
||||
Name ": error opening %s: %s\n",
|
||||
device_list->devname,
|
||||
strerror(errno));
|
||||
continue;
|
||||
|
@ -140,7 +140,7 @@ int Assemble(char *mddev, int mdfd,
|
|||
}
|
||||
if (found)
|
||||
return 0;
|
||||
fprintf(stderr,"mdctl: Did not successful Assemble any devices\n");
|
||||
fprintf(stderr,Name ": Did not successful Assemble any devices\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -149,19 +149,19 @@ int Assemble(char *mddev, int mdfd,
|
|||
*/
|
||||
vers = md_get_version(mdfd);
|
||||
if (vers <= 0) {
|
||||
fprintf(stderr, "mdctl: %s appears not to be an md device.\n");
|
||||
fprintf(stderr, Name ": %s appears not to be an md device.\n");
|
||||
return 1;
|
||||
}
|
||||
if (vers < (90<<8)) {
|
||||
fprintf(stderr, "mdctl: Assemble requires driver version 0.90.0 or later.\n"
|
||||
if (vers < 9000) {
|
||||
fprintf(stderr, Name ": Assemble requires driver version 0.90.0 or later.\n"
|
||||
" Upgrade your kernel or try --Build\n");
|
||||
return 1;
|
||||
}
|
||||
if (get_linux_version() < 0x020400)
|
||||
if (get_linux_version() < 2004000)
|
||||
old_linux = 1;
|
||||
|
||||
if (ioctl(mdfd, GET_ARRAY_INFO, &array)>=0) {
|
||||
fprintf(stderr, "mdctl: device %s already active - cannot assemble it\n",
|
||||
fprintf(stderr, Name ": device %s already active - cannot assemble it\n",
|
||||
mddev);
|
||||
return 1;
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ int Assemble(char *mddev, int mdfd,
|
|||
device_list = device_list->next;
|
||||
|
||||
if (!device_list) {
|
||||
fprintf(stderr, "mdctl: --scan set and no uuid found for %s in config file.\n",
|
||||
fprintf(stderr, Name ": --scan set and no uuid found for %s in config file.\n",
|
||||
mddev);
|
||||
return 1;
|
||||
}
|
||||
|
@ -198,7 +198,7 @@ int Assemble(char *mddev, int mdfd,
|
|||
devlist = conf_get_devs(conffile);
|
||||
|
||||
if (subdevs == 0 && devlist == NULL) {
|
||||
fprintf(stderr, "mdctl: no devices given for %s\n", mddev);
|
||||
fprintf(stderr, Name ": no devices given for %s\n", mddev);
|
||||
return 1;
|
||||
}
|
||||
/* now for each device */
|
||||
|
@ -225,26 +225,26 @@ int Assemble(char *mddev, int mdfd,
|
|||
dfd = open(devname, O_RDONLY, 0);
|
||||
if (dfd < 0) {
|
||||
if (inargv || verbose)
|
||||
fprintf(stderr, "mdctl: cannot open device %s: %s\n",
|
||||
fprintf(stderr, Name ": cannot open device %s: %s\n",
|
||||
devname, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
if (fstat(dfd, &stb)< 0) {
|
||||
/* Impossible! */
|
||||
fprintf(stderr, "mdctl: fstat failed for %s: %s\n",
|
||||
fprintf(stderr, Name ": fstat failed for %s: %s\n",
|
||||
devname, strerror(errno));
|
||||
close(dfd);
|
||||
continue;
|
||||
}
|
||||
if ((stb.st_mode & S_IFMT) != S_IFBLK) {
|
||||
fprintf(stderr, "mdctl: %d is not a block device.\n",
|
||||
fprintf(stderr, Name ": %d is not a block device.\n",
|
||||
devname);
|
||||
close(dfd);
|
||||
continue;
|
||||
}
|
||||
if (load_super(dfd, &super)) {
|
||||
if (inargv || verbose)
|
||||
fprintf( stderr, "mdctl: no RAID superblock on %s\n",
|
||||
fprintf( stderr, Name ": no RAID superblock on %s\n",
|
||||
devname);
|
||||
close(dfd);
|
||||
continue;
|
||||
|
@ -252,7 +252,7 @@ int Assemble(char *mddev, int mdfd,
|
|||
close(dfd);
|
||||
if (compare_super(&first_super, &super)) {
|
||||
if (inargv || verbose)
|
||||
fprintf(stderr, "mdctl: superblock on %s doesn't match\n",
|
||||
fprintf(stderr, Name ": superblock on %s doesn't match\n",
|
||||
devname);
|
||||
continue;
|
||||
}
|
||||
|
@ -260,7 +260,7 @@ int Assemble(char *mddev, int mdfd,
|
|||
uuid_from_super(this_uuid, &first_super);
|
||||
if (!same_uuid(this_uuid, uuid)) {
|
||||
if (inargv || verbose)
|
||||
fprintf(stderr, "mdctl: %s has wrong uuid.\n",
|
||||
fprintf(stderr, Name ": %s has wrong uuid.\n",
|
||||
devname);
|
||||
continue;
|
||||
}
|
||||
|
@ -271,7 +271,7 @@ int Assemble(char *mddev, int mdfd,
|
|||
|
||||
/* Ok, this one is at least worth considering */
|
||||
if (devcnt >= MD_SB_DISKS) {
|
||||
fprintf(stderr, "mdctl: ouch - too many devices appear to be in this array. Ignoring %s\n",
|
||||
fprintf(stderr, Name ": ouch - too many devices appear to be in this array. Ignoring %s\n",
|
||||
devname);
|
||||
continue;
|
||||
}
|
||||
|
@ -295,7 +295,7 @@ int Assemble(char *mddev, int mdfd,
|
|||
}
|
||||
|
||||
if (devcnt == 0) {
|
||||
fprintf(stderr, "mdctl: no devices found for %s\n",
|
||||
fprintf(stderr, Name ": no devices found for %s\n",
|
||||
mddev);
|
||||
return 1;
|
||||
}
|
||||
|
@ -317,14 +317,14 @@ int Assemble(char *mddev, int mdfd,
|
|||
* not up-to-date, update the superblock
|
||||
* and add it.
|
||||
*/
|
||||
fprintf(stderr,"NoImplementedYet\n");
|
||||
fprintf(stderr,"NotImplementedYet\n");
|
||||
/* FIXME */
|
||||
exit(2);
|
||||
}
|
||||
/* Almost ready to actually *do* something */
|
||||
if (!old_linux) {
|
||||
if (ioctl(mdfd, SET_ARRAY_INFO, NULL) != 0) {
|
||||
fprintf(stderr, "mdctl: SET_ARRAY_INFO failed for %s: %s\n",
|
||||
fprintf(stderr, Name ": SET_ARRAY_INFO failed for %s: %s\n",
|
||||
mddev, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
@ -337,14 +337,14 @@ int Assemble(char *mddev, int mdfd,
|
|||
disk.major = devices[j].major;
|
||||
disk.minor = devices[j].minor;
|
||||
if (ioctl(mdfd, ADD_NEW_DISK, &disk)!=0) {
|
||||
fprintf(stderr, "mdctl: failed to add %s to %s: %s\n",
|
||||
fprintf(stderr, Name ": failed to add %s to %s: %s\n",
|
||||
devices[j].devname,
|
||||
mddev,
|
||||
strerror(errno));
|
||||
} else
|
||||
okcnt--;
|
||||
} else if (verbose)
|
||||
fprintf(stderr, "mdctl: no uptodate device for slot %d of %s\n",
|
||||
fprintf(stderr, Name ": no uptodate device for slot %d of %s\n",
|
||||
i, mddev);
|
||||
}
|
||||
if (runstop == 1 ||
|
||||
|
@ -352,7 +352,7 @@ int Assemble(char *mddev, int mdfd,
|
|||
enough(first_super.level, first_super.raid_disks, okcnt))) {
|
||||
if (ioctl(mdfd, RUN_ARRAY, NULL)==0)
|
||||
return 0;
|
||||
fprintf(stderr, "mdctl: failed to RUN_ARRAY %s: %s\n",
|
||||
fprintf(stderr, Name ": failed to RUN_ARRAY %s: %s\n",
|
||||
mddev, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
|
211
Create.c
211
Create.c
|
@ -28,10 +28,217 @@
|
|||
*/
|
||||
|
||||
#include "mdctl.h"
|
||||
#include "md_u.h"
|
||||
#include "md_p.h"
|
||||
|
||||
int Create(char *mddev, int mdfd,
|
||||
int chunk, int level, int layout, int raiddisks, int sparedisks,
|
||||
int chunk, int level, int layout, int size, int raiddisks, int sparedisks,
|
||||
int subdevs, char *subdev[],
|
||||
int runstop)
|
||||
int runstop, int verbose)
|
||||
{
|
||||
/*
|
||||
* Create a new raid array.
|
||||
*
|
||||
* First check that necessary details are available
|
||||
* (i.e. level, raid-disks)
|
||||
*
|
||||
* Then check each disk to see what might be on it
|
||||
* and report anything interesting.
|
||||
*
|
||||
* If anything looks odd, and runstop not set,
|
||||
* abort.
|
||||
*
|
||||
* SET_ARRAY_INFO and ADD_NEW_DISK, and
|
||||
* if runstop==run, or raiddisks diskswere used,
|
||||
* RUN_ARRAY
|
||||
*/
|
||||
int minsize, maxsize;
|
||||
int maxdisc= -1, mindisc = -1;
|
||||
int i;
|
||||
int fail=0, warn=0;
|
||||
|
||||
mdu_array_info_t array;
|
||||
mdu_param_t param;
|
||||
|
||||
|
||||
if (md_get_version(mdfd) < 9000) {
|
||||
fprintf(stderr, Name ": Create requires md driver verison 0.90.0 or later\n");
|
||||
return 1;
|
||||
}
|
||||
if (level == -10) {
|
||||
fprintf(stderr,
|
||||
Name ": a RAID level is needed to create an array.\n");
|
||||
return 1;
|
||||
}
|
||||
if (raiddisks < 1) {
|
||||
fprintf(stderr,
|
||||
Name ": a number of --raid-disks must be given to create an array\n");
|
||||
return 1;
|
||||
}
|
||||
if (raiddisks+sparedisks > MD_SB_DISKS) {
|
||||
fprintf(stderr,
|
||||
Name ": too many discs requested: %d+%d > %d\n",
|
||||
raiddisks, sparedisks, MD_SB_DISKS);
|
||||
return 1;
|
||||
}
|
||||
if (subdevs > raiddisks+sparedisks) {
|
||||
fprintf(stderr, Name ": You have listed more disks (%d) than are in the array(%d)!\n", subdevs, raiddisks+sparedisks);
|
||||
return 1;
|
||||
}
|
||||
/* now set some defaults */
|
||||
if (layout == -1)
|
||||
switch(level) {
|
||||
default: /* no layout */
|
||||
layout = 0;
|
||||
break;
|
||||
case 5:
|
||||
layout = map_name(r5layout, "default");
|
||||
if (verbose)
|
||||
fprintf(stderr,
|
||||
Name ": layout defaults to %s\n", map_num(r5layout, layout));
|
||||
break;
|
||||
}
|
||||
|
||||
if (chunk == 0) {
|
||||
chunk = 64;
|
||||
if (verbose)
|
||||
fprintf(stderr, Name ": chunk size defaults to 64K\n");
|
||||
}
|
||||
|
||||
/* now look at the subdevs */
|
||||
for (i=0; i<subdevs; i++) {
|
||||
char *dname = subdev[i];
|
||||
int dsize, freesize;
|
||||
int fd = open(dname, O_RDONLY, 0);
|
||||
if (fd <0 ) {
|
||||
fprintf(stderr, Name ": Cannot open %s: %s\n",
|
||||
dname, strerror(errno));
|
||||
fail=1;
|
||||
continue;
|
||||
}
|
||||
if (ioctl(fd, BLKGETSIZE, &dsize)) {
|
||||
fprintf(stderr, Name ": Cannot get size of %s: %s\n",
|
||||
dname, strerror(errno));
|
||||
fail = 1;
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
if (dsize < MD_RESERVED_SECTORS*2) {
|
||||
fprintf(stderr, Name ": %s is too small: %dK\n",
|
||||
dname, dsize/2);
|
||||
fail = 1;
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
freesize = MD_NEW_SIZE_SECTORS(dsize);
|
||||
freesize /= 2;
|
||||
|
||||
if (size && freesize < size) {
|
||||
fprintf(stderr, Name ": %s is smaller that given size."
|
||||
" %dK < %dK + superblock\n", dname, freesize, size);
|
||||
fail = 1;
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
if (maxdisc< 0 || (maxdisc>=0 && freesize > maxsize)) {
|
||||
maxdisc = i;
|
||||
maxsize = freesize;
|
||||
}
|
||||
if (mindisc < 0 || (mindisc >=0 && freesize < minsize)) {
|
||||
mindisc = i;
|
||||
minsize = freesize;
|
||||
}
|
||||
warn |= check_ext2(fd, dname);
|
||||
warn |= check_reiser(fd, dname);
|
||||
warn |= check_raid(fd, dname);
|
||||
close(fd);
|
||||
}
|
||||
if (fail) {
|
||||
fprintf(stderr, Name ": create aborted\n");
|
||||
return 1;
|
||||
}
|
||||
if (size == 0) {
|
||||
if (mindisc == -1) {
|
||||
fprintf(stderr, Name ": no size and no drives given - aborting create.\n");
|
||||
return 1;
|
||||
}
|
||||
size = minsize;
|
||||
if (verbose)
|
||||
fprintf(stderr, Name ": size set to %dK\n", size);
|
||||
}
|
||||
if ((maxsize-size)*100 > maxsize) {
|
||||
fprintf(stderr, Name ": largest drive (%s) exceed size (%dK) by more than 1%\n",
|
||||
subdev[maxdisc], size);
|
||||
warn = 1;
|
||||
}
|
||||
|
||||
if (warn) {
|
||||
if (runstop!= 1) {
|
||||
if (!ask("Continue creating array? ")) {
|
||||
fprintf(stderr, Name ": create aborted.\n");
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (verbose)
|
||||
fprintf(stderr, Name ": creation continuing despite oddities due to --run\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Ok, lets try some ioctls */
|
||||
|
||||
array.level = level;
|
||||
array.size = size;
|
||||
array.nr_disks = raiddisks+sparedisks;
|
||||
array.raid_disks = raiddisks;
|
||||
array.md_minor = 0;
|
||||
array.not_persistent = 0;
|
||||
array.state = 0; /* not clean, but no errors */
|
||||
array.active_disks=0;
|
||||
array.working_disks=0;
|
||||
array.spare_disks=0;
|
||||
array.failed_disks=0;
|
||||
array.layout = layout;
|
||||
array.chunk_size = chunk*1024;
|
||||
|
||||
if (ioctl(mdfd, SET_ARRAY_INFO, &array)) {
|
||||
fprintf(stderr, Name ": SET_ARRAY_INFO failed for %s: %s\n",
|
||||
mddev, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i=0; i<subdevs; i++) {
|
||||
int fd = open(subdev[i], O_RDONLY, 0);
|
||||
struct stat stb;
|
||||
mdu_disk_info_t disk;
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, Name ": failed to open %s after earlier success - aborting\n",
|
||||
subdev[i]);
|
||||
return 1;
|
||||
}
|
||||
fstat(fd, &stb);
|
||||
disk.number = i;
|
||||
disk.raid_disk = i;
|
||||
disk.state = 6; /* active and in sync */
|
||||
disk.major = MAJOR(stb.st_rdev);
|
||||
disk.minor = MINOR(stb.st_rdev);
|
||||
close(fd);
|
||||
if (ioctl(mdfd, ADD_NEW_DISK, &disk)) {
|
||||
fprintf(stderr, Name ": ADD_NEW_DISK for %s failed: %s\b",
|
||||
subdev[i], strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* param is not actually used */
|
||||
if (runstop == 1 || subdevs >= raiddisks) {
|
||||
if (ioctl(mdfd, RUN_ARRAY, ¶m)) {
|
||||
fprintf(stderr, Name ": RUN_ARRAY failed: %s\n",
|
||||
strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
fprintf(stderr, Name ": array %s started.\n", mddev);
|
||||
} else {
|
||||
fprintf(stderr, Name ": not starting array - not enough discs.\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
23
Detail.c
23
Detail.c
|
@ -43,31 +43,32 @@ int Detail(char *dev)
|
|||
mdu_array_info_t array;
|
||||
int d;
|
||||
time_t atime;
|
||||
char *c;
|
||||
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "mdctl: cannot open %s: %s\n",
|
||||
fprintf(stderr, Name ": cannot open %s: %s\n",
|
||||
dev, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
vers = md_get_version(fd);
|
||||
if (vers < 0) {
|
||||
fprintf(stderr, "mdctl: %s does not appear to be an md device\n",
|
||||
fprintf(stderr, Name ": %s does not appear to be an md device\n",
|
||||
dev);
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
if (vers < (90<<8)) {
|
||||
fprintf(stderr, "mdctl: cannot get detail for md device %s: driver version too old.\n",
|
||||
if (vers < 9000) {
|
||||
fprintf(stderr, Name ": cannot get detail for md device %s: driver version too old.\n",
|
||||
dev);
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
if (ioctl(fd, GET_ARRAY_INFO, &array)<0) {
|
||||
if (errno == ENODEV)
|
||||
fprintf(stderr, "mdctl: md device %s does not appear to be active.\n",
|
||||
fprintf(stderr, Name ": md device %s does not appear to be active.\n",
|
||||
dev);
|
||||
else
|
||||
fprintf(stderr, "mdctl: cannot get array detail for %s: %s\n",
|
||||
fprintf(stderr, Name ": cannot get array detail for %s: %s\n",
|
||||
dev, strerror(errno));
|
||||
close(fd);
|
||||
return 1;
|
||||
|
@ -78,7 +79,8 @@ int Detail(char *dev)
|
|||
array.major_version, array.minor_version, array.patch_version);
|
||||
atime = array.ctime;
|
||||
printf(" Creation Time : %.24s\n", ctime(&atime));
|
||||
printf(" Raid Level : %d\n", array.level);
|
||||
c = map_num(pers, array.level);
|
||||
printf(" Raid Level : %s\n", c?c:"-unknown-");
|
||||
printf(" Size : %d\n", array.size);
|
||||
printf(" Raid Disks : %d\n", array.raid_disks);
|
||||
printf(" Total Disks : %d\n", array.nr_disks);
|
||||
|
@ -96,7 +98,10 @@ int Detail(char *dev)
|
|||
printf(" Failed Drives : %d\n", array.failed_disks);
|
||||
printf(" Spare Drives : %d\n", array.spare_disks);
|
||||
printf("\n");
|
||||
printf(" Layout : %d\n", array.layout);
|
||||
if (array.level == 5) {
|
||||
c = map_num(r5layout, array.layout);
|
||||
printf(" Layout : %s\n", c?c:"-unknown-");
|
||||
}
|
||||
printf(" Chunk Size : %dK\n", array.chunk_size/1024);
|
||||
printf("\n");
|
||||
printf(" Number Major Minor RaidDisk State\n");
|
||||
|
@ -104,7 +109,7 @@ int Detail(char *dev)
|
|||
mdu_disk_info_t disk;
|
||||
disk.number = d;
|
||||
if (ioctl(fd, GET_DISK_INFO, &disk) < 0) {
|
||||
fprintf(stderr, "mdctl: cannot get disk detail for disk %d: %s\n",
|
||||
fprintf(stderr, Name ": cannot get disk detail for disk %d: %s\n",
|
||||
d, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
|
25
Examine.c
25
Examine.c
|
@ -51,10 +51,11 @@ int Examine(char *dev)
|
|||
time_t atime;
|
||||
mdp_super_t super;
|
||||
int d;
|
||||
char *c;
|
||||
int rv;
|
||||
|
||||
if (fd < 0) {
|
||||
fprintf(stderr,"mdctl: cannot open %s: %s\n",
|
||||
fprintf(stderr,Name ": cannot open %s: %s\n",
|
||||
dev, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
@ -63,30 +64,30 @@ int Examine(char *dev)
|
|||
close(fd);
|
||||
switch(rv) {
|
||||
case 1:
|
||||
fprintf(stderr, "mdctl: cannot find device size for %s: %s\n",
|
||||
fprintf(stderr, Name ": cannot find device size for %s: %s\n",
|
||||
dev, strerror(errno));
|
||||
return 1;
|
||||
case 2:
|
||||
/* fprintf(stderr, "mdctl: %s is too small for md: size is %ld sectors\n",
|
||||
/* fprintf(stderr, Name ": %s is too small for md: size is %ld sectors\n",
|
||||
dev, size);
|
||||
*/
|
||||
fprintf(stderr, "mdctl: %s is too small for md\n",
|
||||
fprintf(stderr, Name ": %s is too small for md\n",
|
||||
dev);
|
||||
return 1;
|
||||
case 3:
|
||||
fprintf(stderr, "mdctl: Cannot seek to superblock on %s: %s\n",
|
||||
fprintf(stderr, Name ": Cannot seek to superblock on %s: %s\n",
|
||||
dev, strerror(errno));
|
||||
return 1;
|
||||
case 4:
|
||||
fprintf(stderr, "mdctl: Cannot read superblock on %s\n",
|
||||
fprintf(stderr, Name ": Cannot read superblock on %s\n",
|
||||
dev);
|
||||
return 1;
|
||||
case 5:
|
||||
fprintf(stderr, "mdctl: No super block found on %s (Expected magic %08x, got %08x)\n",
|
||||
fprintf(stderr, Name ": No super block found on %s (Expected magic %08x, got %08x)\n",
|
||||
dev, MD_SB_MAGIC, super.md_magic);
|
||||
return 1;
|
||||
case 6:
|
||||
fprintf(stderr, "mdctl: Cannot interpret superblock on %s - version is %d\n",
|
||||
fprintf(stderr, Name ": Cannot interpret superblock on %s - version is %d\n",
|
||||
dev, super.major_version);
|
||||
return 1;
|
||||
}
|
||||
|
@ -104,7 +105,8 @@ int Examine(char *dev)
|
|||
|
||||
atime = super.ctime;
|
||||
printf(" Creation Time : %.24s\n", ctime(&atime));
|
||||
printf(" Raid Level : %d\n", super.level);
|
||||
c=map_num(pers, super.level);
|
||||
printf(" Raid Level : %s\n", c?c:"-unknown-");
|
||||
printf(" Size : %d\n", super.size);
|
||||
printf(" Raid Disks : %d\n", super.raid_disks);
|
||||
printf(" Total Disks : %d\n", super.nr_disks);
|
||||
|
@ -122,7 +124,10 @@ int Examine(char *dev)
|
|||
printf(" - checksum not checked yet - \n");
|
||||
printf(" Events : %d.%d\n", super.events_hi, super.events_lo);
|
||||
printf("\n");
|
||||
printf(" Layout : %d\n", super.layout);
|
||||
if (super.level == 5) {
|
||||
c = map_num(r5layout, super.layout);
|
||||
printf(" Layout : %s\n", c?c:"-unknown-");
|
||||
}
|
||||
printf(" Chunk Size : %dK\n", super.chunk_size/1024);
|
||||
printf("\n");
|
||||
printf(" Number Major Minor RaidDisk State\n");
|
||||
|
|
160
Manage.c
160
Manage.c
|
@ -28,16 +28,174 @@
|
|||
*/
|
||||
|
||||
#include "mdctl.h"
|
||||
#include "md_u.h"
|
||||
#include "md_p.h"
|
||||
|
||||
int Manage_ro(char *devname, int fd, int readonly)
|
||||
{
|
||||
/* switch to readonly or rw
|
||||
*
|
||||
* requires >= 0.90.0
|
||||
* first check that array is runing
|
||||
* use RESTART_ARRAY_RW or STOP_ARRAY_RO
|
||||
*
|
||||
*/
|
||||
mdu_array_info_t array;
|
||||
|
||||
if (md_get_version(fd) < 9000) {
|
||||
fprintf(stderr, Name ": need md driver version 0.90.0 or later\n");
|
||||
return 1;
|
||||
}
|
||||
if (ioctl(fd, GET_ARRAY_INFO, &array)) {
|
||||
fprintf(stderr, Name ": %s does not appear to be active.\n",
|
||||
devname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (readonly>0) {
|
||||
if (ioctl(fd, STOP_ARRAY_RO, NULL)) {
|
||||
fprintf(stderr, Name ": failed to set readonly for %s: %s\n",
|
||||
devname, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
} else if (readonly < 0) {
|
||||
if (ioctl(fd, RESTART_ARRAY_RW, NULL)) {
|
||||
fprintf(stderr, Name ": fail to re writable for %s: %s\n",
|
||||
devname, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Manage_runstop(char *devname, int fd, int runstop)
|
||||
{
|
||||
/* Run or stop the array. array must already be configured
|
||||
* required >= 0.90.0
|
||||
*/
|
||||
mdu_array_info_t array;
|
||||
mdu_param_t param; /* unused */
|
||||
|
||||
if (md_get_version(fd) < 9000) {
|
||||
fprintf(stderr, Name ": need md driver version 0.90.0 or later\n");
|
||||
return 1;
|
||||
}
|
||||
if (ioctl(fd, GET_ARRAY_INFO, &array)) {
|
||||
fprintf(stderr, Name ": %s does not appear to be active.\n",
|
||||
devname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (runstop>0) {
|
||||
if (ioctl(fd, RUN_ARRAY, ¶m)) {
|
||||
fprintf(stderr, Name ": failed to run array %s: %s\n",
|
||||
devname, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
} else if (runstop < 0){
|
||||
if (ioctl(fd, STOP_ARRAY, NULL)) {
|
||||
fprintf(stderr, Name ": fail to re writable for %s: %s\n",
|
||||
devname, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Manage_subdevs(char *devname, int fd,
|
||||
int devcnt, char *devnames[], int devmodes[])
|
||||
{
|
||||
{
|
||||
/* do something to each dev.
|
||||
* devmode can be
|
||||
* 'a' - add the device
|
||||
* try HOT_ADD_DISK
|
||||
* If that fails EINVAL, try ADD_NEW_DISK
|
||||
* 'r' - remove the device HOT_REMOVE_DISK
|
||||
* 'f' - set the device faulty SET_DISK_FAULTY
|
||||
*/
|
||||
mdu_array_info_t array;
|
||||
mdu_disk_info_t disc;
|
||||
struct stat stb;
|
||||
int i,j;
|
||||
|
||||
if (ioctl(fd, GET_ARRAY_INFO, &array)) {
|
||||
fprintf(stderr, Name ": cannot get array info for %s\n",
|
||||
devname);
|
||||
return 1;
|
||||
}
|
||||
for (i=0 ; i<devcnt; i++) {
|
||||
if (stat(devnames[i], &stb)) {
|
||||
fprintf(stderr, Name ": cannot find %s: %s\n",
|
||||
devnames[i], strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
if ((stb.st_mode & S_IFMT) != S_IFBLK) {
|
||||
fprintf(stderr, Name ": %s is not a block device.\n",
|
||||
devnames[i]);
|
||||
return 1;
|
||||
}
|
||||
switch(devmodes[i]){
|
||||
default:
|
||||
fprintf(stderr, Name ": internal error - devmode[%d]=%d\n",
|
||||
i, devmodes[i]);
|
||||
return 1;
|
||||
case 'a':
|
||||
/* add the device - hot or cold */
|
||||
if (ioctl(fd, HOT_ADD_DISK, stb.st_rdev)==0) {
|
||||
fprintf(stderr, Name ": hot added %s\n",
|
||||
devnames[i]);
|
||||
continue;
|
||||
}
|
||||
/* try ADD_NEW_DISK.
|
||||
* we might be creating, we might be assembling,
|
||||
* it is hard to tell.
|
||||
* set up number/raid_disk/state just
|
||||
* in case
|
||||
*/
|
||||
for (j=0; j<array.nr_disks; j++) {
|
||||
if (ioctl(fd, GET_DISK_INFO, &disc))
|
||||
break;
|
||||
if (disc.major==0 && disc.minor==0)
|
||||
break;
|
||||
if (disc.state & 8) /* removed */
|
||||
break;
|
||||
}
|
||||
disc.number =j;
|
||||
disc.raid_disk = j;
|
||||
disc.state = 0;
|
||||
disc.major = MAJOR(stb.st_rdev);
|
||||
disc.minor = MINOR(stb.st_rdev);
|
||||
if (ioctl(fd,ADD_NEW_DISK, &disc)) {
|
||||
fprintf(stderr, Name ": add new disk failed for %s: %s\n",
|
||||
devnames[i], strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
fprintf(stderr, Name ": added %s\n", devnames[i]);
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
/* hot remove */
|
||||
/* FIXME check that is is a current member */
|
||||
if (ioctl(fd, HOT_REMOVE_DISK, stb.st_rdev)) {
|
||||
fprintf(stderr, Name ": hot remove failed for %s: %s\n",
|
||||
devnames[i], strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
fprintf(stderr, Name ": hot removed %s\n", devnames[i]);
|
||||
break;
|
||||
|
||||
case 'f': /* set faulty */
|
||||
/* FIXME check current member */
|
||||
if (ioctl(fd, SET_DISK_FAULTY, stb.st_rdev)) {
|
||||
fprintf(stderr, Name ": set disk faulty failed for %s: %s\n",
|
||||
devnames[i], strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
fprintf(stderr, Name ": set %s faulty in %s\n",
|
||||
devnames[i], devname);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
|
43
ReadMe.c
43
ReadMe.c
|
@ -29,7 +29,7 @@
|
|||
|
||||
#include "mdctl.h"
|
||||
|
||||
char Version[] = "mdctl - v0.2 - 06 June 2001\n";
|
||||
char Version[] = Name " - v0.3 - 14 June 2001\n";
|
||||
/*
|
||||
* File: ReadMe.c
|
||||
*
|
||||
|
@ -78,7 +78,7 @@ char Version[] = "mdctl - v0.2 - 06 June 2001\n";
|
|||
* command, subsequent Manage commands can finish the job.
|
||||
*/
|
||||
|
||||
char short_options[]="-ABCDEhVvc:l:p:n:x:u:c:sarfRSow";
|
||||
char short_options[]="-ABCDEhVvc:l:p:n:x:u:c:z:sarfRSow";
|
||||
struct option long_options[] = {
|
||||
{"manage", 0, 0, '@'},
|
||||
{"assemble", 0, 0, 'A'},
|
||||
|
@ -99,6 +99,7 @@ struct option long_options[] = {
|
|||
{"layout", 1, 0, 'p'},
|
||||
{"raid-disks",1, 0, 'n'},
|
||||
{"spare-disks",1,0, 'x'},
|
||||
{"size" ,1, 0, 'z'},
|
||||
|
||||
/* For assemble */
|
||||
{"uuid", 1, 0, 'u'},
|
||||
|
@ -157,6 +158,7 @@ char Help[] =
|
|||
" --layout= : same as --parity\n"
|
||||
" --raid-disks= -n : number of active devices in array\n"
|
||||
" --spare-disks= -x : number of spares (eXtras) to allow space for\n"
|
||||
" --size= -z : Size (in K) of each drive in RAID1/4/5 - optional\n"
|
||||
"\n"
|
||||
" For assemble:\n"
|
||||
" --uuid= -u : uuid of array to assemble. Devices which don't\n"
|
||||
|
@ -192,6 +194,11 @@ char Help_create[] =
|
|||
" be run, though the presence of a '--run' can override this\n"
|
||||
" caution.\n"
|
||||
"\n"
|
||||
" If the --size option is given, it is not necessary to list any subdevices\n"
|
||||
" in this command. They can be added later, before a --run.\n"
|
||||
" If no --size is given, the apparent size of the smallest drive given\n"
|
||||
" is used.\n"
|
||||
"\n"
|
||||
" The General management options that are valid with --create are:\n"
|
||||
" --run : insist of running the array even if not all devices\n"
|
||||
" are present or some look odd.\n"
|
||||
|
@ -244,3 +251,35 @@ char Help_assemble[] =
|
|||
" not yet documented\n"
|
||||
"\n"
|
||||
;
|
||||
|
||||
|
||||
/* name/number mappings */
|
||||
|
||||
mapping_t r5layout[] = {
|
||||
{ "left_asymmetric", 0},
|
||||
{ "right_asymmetric", 1},
|
||||
{ "left_symmetric", 2},
|
||||
{ "right_symmetric", 3},
|
||||
|
||||
{ "default", 2},
|
||||
{ "la", 0},
|
||||
{ "ra", 1},
|
||||
{ "ls", 2},
|
||||
{ "rs", 3},
|
||||
{ NULL, 0}
|
||||
};
|
||||
|
||||
mapping_t pers[] = {
|
||||
{ "linear", -1},
|
||||
{ "raid0", 0},
|
||||
{ "0", 0},
|
||||
{ "stripe", 0},
|
||||
{ "raid1", 1},
|
||||
{ "1", 1},
|
||||
{ "mirror", 1},
|
||||
{ "raid4", 4},
|
||||
{ "4", 4},
|
||||
{ "raid5", 5},
|
||||
{ "5", 5},
|
||||
{ NULL, 0}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
|
||||
md_p.h,1316
|
||||
#define _MD_P_H16,582
|
||||
#define MD_RESERVED_BYTES 44,1414
|
||||
#define MD_RESERVED_SECTORS 45,1453
|
||||
#define MD_RESERVED_BLOCKS 46,1508
|
||||
#define MD_NEW_SIZE_SECTORS(MD_NEW_SIZE_SECTORS48,1570
|
||||
#define MD_NEW_SIZE_BLOCKS(MD_NEW_SIZE_BLOCKS49,1659
|
||||
#define MD_SB_BYTES 51,1746
|
||||
#define MD_SB_WORDS 52,1773
|
||||
#define MD_SB_BLOCKS 53,1813
|
||||
#define MD_SB_SECTORS 54,1863
|
||||
#define MD_SB_GENERIC_OFFSET 59,1960
|
||||
#define MD_SB_PERSONALITY_OFFSET 60,1992
|
||||
#define MD_SB_DISKS_OFFSET 61,2028
|
||||
#define MD_SB_DESCRIPTOR_OFFSET 62,2060
|
||||
#define MD_SB_GENERIC_CONSTANT_WORDS 64,2098
|
||||
#define MD_SB_GENERIC_STATE_WORDS 65,2138
|
||||
#define MD_SB_GENERIC_WORDS 66,2175
|
||||
#define MD_SB_PERSONALITY_WORDS 67,2263
|
||||
#define MD_SB_DESCRIPTOR_WORDS 68,2299
|
||||
#define MD_SB_DISKS 69,2334
|
||||
#define MD_SB_DISKS_WORDS 70,2359
|
||||
#define MD_SB_RESERVED_WORDS 71,2423
|
||||
#define MD_SB_EQUAL_WORDS 72,2553
|
||||
#define MD_DISK_FAULTY 77,2691
|
||||
#define MD_DISK_ACTIVE 78,2752
|
||||
#define MD_DISK_SYNC 79,2814
|
||||
#define MD_DISK_REMOVED 80,2878
|
||||
typedef struct mdp_device_descriptor_s mdp_device_descriptor_s82,2946
|
||||
} mdp_disk_t;mdp_disk_t89,3310
|
||||
#define MD_SB_MAGIC 91,3325
|
||||
#define MD_SB_CLEAN 96,3390
|
||||
#define MD_SB_ERRORS 97,3413
|
||||
typedef struct mdp_superblock_s mdp_superblock_s99,3438
|
||||
} mdp_super_t;mdp_super_t164,5820
|
||||
static inline __u64 md_event(166,5836
|
||||
|
||||
md_u.h,1118
|
||||
#define _MD_U_H16,590
|
||||
#define RAID_VERSION 21,634
|
||||
#define GET_ARRAY_INFO 22,693
|
||||
#define GET_DISK_INFO 23,757
|
||||
#define PRINT_RAID_DEBUG 24,819
|
||||
#define RAID_AUTORUN 25,865
|
||||
#define CLEAR_ARRAY 28,929
|
||||
#define ADD_NEW_DISK 29,971
|
||||
#define HOT_REMOVE_DISK 30,1032
|
||||
#define SET_ARRAY_INFO 31,1078
|
||||
#define SET_DISK_INFO 32,1142
|
||||
#define WRITE_RAID_INFO 33,1186
|
||||
#define UNPROTECT_ARRAY 34,1232
|
||||
#define PROTECT_ARRAY 35,1278
|
||||
#define HOT_ADD_DISK 36,1322
|
||||
#define SET_DISK_FAULTY 37,1365
|
||||
#define RUN_ARRAY 40,1424
|
||||
#define START_ARRAY 41,1478
|
||||
#define STOP_ARRAY 42,1520
|
||||
#define STOP_ARRAY_RO 43,1561
|
||||
#define RESTART_ARRAY_RW 44,1605
|
||||
typedef struct mdu_version_s mdu_version_s46,1652
|
||||
} mdu_version_t;mdu_version_t50,1724
|
||||
typedef struct mdu_array_info_s mdu_array_info_s52,1742
|
||||
} mdu_array_info_t;mdu_array_info_t83,2516
|
||||
typedef struct mdu_disk_info_s mdu_disk_info_s85,2537
|
||||
} mdu_disk_info_t;mdu_disk_info_t95,2693
|
||||
typedef struct mdu_start_info_s mdu_start_info_s97,2713
|
||||
} mdu_start_info_t;mdu_start_info_t106,2857
|
||||
typedef struct mdu_param_smdu_param_s108,2878
|
||||
} mdu_param_t;mdu_param_t113,3014
|
||||
|
||||
mdctl.h,823
|
||||
#define __USE_LARGEFILE6430,1115
|
||||
#define MD_MAJOR 47,1491
|
||||
extern char short_options[52,1531
|
||||
extern struct option long_options[53,1560
|
||||
extern char Version[54,1597
|
||||
extern char Version[], Usage[54,1597
|
||||
extern char Version[], Usage[], Help[54,1597
|
||||
extern char Version[], Usage[], Help[], Help_create[54,1597
|
||||
extern char Version[], Usage[], Help[], Help_create[], Help_build[54,1597
|
||||
extern char Version[], Usage[], Help[], Help_create[], Help_build[], Help_assemble[54,1597
|
||||
typedef struct mddev_uuid_s mddev_uuid_s58,1762
|
||||
} *mddev_uuid_t;mddev_uuid_t62,1852
|
||||
typedef struct mddev_dev_s mddev_dev_s65,1918
|
||||
} *mddev_dev_t;mddev_dev_t68,1990
|
||||
#define ALGORITHM_LEFT_ASYMMETRIC 73,2044
|
||||
#define ALGORITHM_RIGHT_ASYMMETRIC 74,2080
|
||||
#define ALGORITHM_LEFT_SYMMETRIC 75,2117
|
||||
#define ALGORITHM_RIGHT_SYMMETRIC 76,2152
|
||||
|
||||
Assemble.c,22
|
||||
int Assemble(34,1171
|
||||
|
||||
Build.c,19
|
||||
int Build(32,1135
|
||||
|
||||
Create.c,20
|
||||
int Create(32,1135
|
||||
|
||||
Detail.c,20
|
||||
int Detail(34,1171
|
||||
|
||||
Examine.c,21
|
||||
int Examine(34,1171
|
||||
|
||||
Manage.c,79
|
||||
int Manage_ro(32,1135
|
||||
int Manage_runstop(36,1191
|
||||
int Manage_subdevs(40,1251
|
||||
|
||||
ReadMe.c,231
|
||||
#define Name 32,1135
|
||||
char Version[33,1156
|
||||
char short_options[82,3241
|
||||
struct option long_options[83,3297
|
||||
char Usage[122,4441
|
||||
char Help[127,4498
|
||||
char Help_create[181,6989
|
||||
char Help_build[203,7973
|
||||
char Help_assemble[216,8513
|
||||
|
||||
config.c,102
|
||||
char DefaultConfFile[43,1371
|
||||
mddev_uuid_t conf_get_uuids(45,1416
|
||||
mddev_dev_t conf_get_devs(50,1482
|
||||
|
||||
mdctl.c,40
|
||||
int main(33,1153
|
||||
#define O(O131,3313
|
||||
|
||||
util.c,212
|
||||
int parse_uuid(40,1354
|
||||
int md_get_version(80,2091
|
||||
int get_linux_version(99,2448
|
||||
int enough(111,2639
|
||||
int same_uuid(127,2889
|
||||
void uuid_from_super(137,3018
|
||||
int compare_super(151,3295
|
||||
int load_super(185,4258
|
11
TODO
11
TODO
|
@ -1,7 +1,12 @@
|
|||
|
||||
- check superblock checksum in examine
|
||||
- report "chunk" or "rounding" depending on raid level
|
||||
- report "linear" instead of "-1" for raid level
|
||||
- decode ayout depending on raid level
|
||||
- report "linear" instead of "-1" for raid level DONE
|
||||
- decode ayout depending on raid level DONE
|
||||
- get Assemble to upgrade devices if force flag.
|
||||
- --verbose and --force flags.
|
||||
- --verbose and --force flags.
|
||||
|
||||
- set md_minor, *_disks for Create
|
||||
- for create raid5, how to choose between
|
||||
all working, but not insync
|
||||
one missing, one spare, insync
|
||||
|
|
6
makedist
6
makedist
|
@ -7,8 +7,8 @@ else echo $target is not a directory
|
|||
exit 2
|
||||
fi
|
||||
set `grep '^char Version' ReadMe.c `
|
||||
echo version = $6
|
||||
base=mdctl-$6.tgz
|
||||
echo version = $7
|
||||
base=mdctl-$7.tgz
|
||||
if [ -f $target/$base ]
|
||||
then
|
||||
echo $target/$base exists.
|
||||
|
@ -17,4 +17,4 @@ fi
|
|||
trap "rm $target/$base; exit" 1 2 3
|
||||
( cd .. ; tar czvf - mdctl ) > $target/$base
|
||||
chmod a+r $target/$base
|
||||
ls -l $target/$base
|
||||
ls -l $target/$base
|
||||
|
|
114
mdctl.c
114
mdctl.c
|
@ -40,6 +40,7 @@ int main(int argc, char *argv[])
|
|||
int i;
|
||||
|
||||
int chunk = 0;
|
||||
int size = 0;
|
||||
int level = -10;
|
||||
int layout = -1;
|
||||
int raiddisks = 0;
|
||||
|
@ -73,7 +74,7 @@ int main(int argc, char *argv[])
|
|||
case 'E':
|
||||
/* setting mode - only once */
|
||||
if (mode) {
|
||||
fprintf(stderr, "mdctl: --%s/-%c not allowed, mode already set to %s\n",
|
||||
fprintf(stderr, Name ": --%s/-%c not allowed, mode already set to %s\n",
|
||||
long_options[opt-'A'+1].name,
|
||||
long_options[opt-'A'+1].val,
|
||||
long_options[mode-'A'+1].name);
|
||||
|
@ -107,7 +108,7 @@ int main(int argc, char *argv[])
|
|||
mddev = optarg;
|
||||
else {
|
||||
if (subdevs +1 >= MD_SB_DISKS) {
|
||||
fprintf(stderr, "mdctl: too many devices at %s - current limit -s %d\n",
|
||||
fprintf(stderr, Name ": too many devices at %s - current limit -s %d\n",
|
||||
optarg, MD_SB_DISKS);
|
||||
exit(2);
|
||||
}
|
||||
|
@ -133,46 +134,52 @@ int main(int argc, char *argv[])
|
|||
case O('C','c'):
|
||||
case O('B','c'): /* chunk or rounding */
|
||||
if (chunk) {
|
||||
fprintf(stderr, "mdctl: chunk/rounding may only be specified once. "
|
||||
fprintf(stderr, Name ": chunk/rounding may only be specified once. "
|
||||
"Second value is %s.\n", optarg);
|
||||
exit(2);
|
||||
}
|
||||
chunk = strtol(optarg, &c, 10);
|
||||
if (!optarg[0] || *c) {
|
||||
fprintf(stderr, "mdctl: invalid chunk/rounding value: %s\n",
|
||||
if (!optarg[0] || *c || chunk<4 || ((chunk-1)&chunk)) {
|
||||
fprintf(stderr, Name ": invalid chunk/rounding value: %s\n",
|
||||
optarg);
|
||||
exit(2);
|
||||
}
|
||||
continue;
|
||||
|
||||
case O('c','z'): /* size */
|
||||
if (size) {
|
||||
fprintf(stderr, Name ": size may only be specified once. "
|
||||
"Second value is %s.\n", optarg);
|
||||
exit(2);
|
||||
}
|
||||
size = strtol(optarg, &c, 10);
|
||||
if (!optarg[0] || *c || size < 4) {
|
||||
fprintf(stderr, Name ": invalid size: %s\n",
|
||||
optarg);
|
||||
exit(2);
|
||||
}
|
||||
continue;
|
||||
|
||||
case O('C','l'):
|
||||
case O('B','l'): /* set raid level*/
|
||||
if (level != -10) {
|
||||
fprintf(stderr, "mdctl: raid level may only be set once. "
|
||||
fprintf(stderr, Name ": raid level may only be set once. "
|
||||
"Second value is %s.\n", optarg);
|
||||
exit(2);
|
||||
}
|
||||
if (strcmp(optarg,"linear")==0)
|
||||
level = -1;
|
||||
else if (strlen(optarg)==1 && strchr("01245", optarg[0]))
|
||||
level = optarg[0]-'0';
|
||||
else {
|
||||
fprintf(stderr, "mdctl: invalid raid level: %s\n",
|
||||
level = map_name(pers, optarg);
|
||||
if (level == -10) {
|
||||
fprintf(stderr, Name ": invalid raid level: %s\n",
|
||||
optarg);
|
||||
exit(2);
|
||||
}
|
||||
if (level > 0 && mode == 'B') {
|
||||
fprintf(stderr, "mdctl: Raid level %s not permitted with --build.\n",
|
||||
optarg);
|
||||
exit(2);
|
||||
}
|
||||
if (layout >=0 && level < 4) {
|
||||
fprintf(stderr, "mdctl: raid level %s is incompatible with layout setting\n",
|
||||
fprintf(stderr, Name ": Raid level %s not permitted with --build.\n",
|
||||
optarg);
|
||||
exit(2);
|
||||
}
|
||||
if (sparedisks > 0 && level < 1) {
|
||||
fprintf(stderr, "mdctl: raid level %s is incompatible with spare-disks setting.\n",
|
||||
fprintf(stderr, Name ": raid level %s is incompatible with spare-disks setting.\n",
|
||||
optarg);
|
||||
exit(2);
|
||||
}
|
||||
|
@ -180,39 +187,40 @@ int main(int argc, char *argv[])
|
|||
|
||||
case O('C','p'): /* raid5 layout */
|
||||
if (layout >= 0) {
|
||||
fprintf(stderr,"mdctl: layout may only be sent once. "
|
||||
fprintf(stderr,Name ": layout may only be sent once. "
|
||||
"Second value was %s\n", optarg);
|
||||
exit(2);
|
||||
}
|
||||
if (level > -10 && level < 4) {
|
||||
fprintf(stderr,"mdctl: layout is incompatible with raid levels below 4.\n");
|
||||
exit(2);
|
||||
}
|
||||
if (strcmp(optarg, "left-symmetric")==0 || strcmp(optarg,"ls")==0)
|
||||
layout = ALGORITHM_LEFT_SYMMETRIC;
|
||||
else if (strcmp(optarg, "left-asymmetric")==0 || strcmp(optarg,"la")==0)
|
||||
layout = ALGORITHM_LEFT_ASYMMETRIC;
|
||||
else if (strcmp(optarg, "right-symmetric")==0 || strcmp(optarg,"rs")==0)
|
||||
layout = ALGORITHM_RIGHT_SYMMETRIC;
|
||||
else if (strcmp(optarg, "right-asymmetric")==0 || strcmp(optarg,"ra")==0)
|
||||
layout = ALGORITHM_RIGHT_ASYMMETRIC;
|
||||
else {
|
||||
fprintf(stderr,"mdctl: %s is not a valid layout value\n",
|
||||
optarg);
|
||||
exit(2);
|
||||
switch(level) {
|
||||
default:
|
||||
fprintf(stderr, Name ": layout now meaningful for %s arrays.\n",
|
||||
map_num(pers, level));
|
||||
exit(2);
|
||||
case -10:
|
||||
fprintf(stderr, Name ": raid level must be given before layout.\n");
|
||||
exit(2);
|
||||
|
||||
case 5:
|
||||
layout = map_name(r5layout, optarg);
|
||||
if (layout==-10) {
|
||||
fprintf(stderr, Name ": layout %s not understood for raid5.\n",
|
||||
optarg);
|
||||
exit(2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
|
||||
case O('C','n'):
|
||||
case O('B','n'): /* number of raid disks */
|
||||
if (raiddisks) {
|
||||
fprintf(stderr, "mdctl: raid-disks set twice: %d and %s\n",
|
||||
fprintf(stderr, Name ": raid-disks set twice: %d and %s\n",
|
||||
raiddisks, optarg);
|
||||
exit(2);
|
||||
}
|
||||
raiddisks = strtol(optarg, &c, 10);
|
||||
if (!optarg[0] || *c || raiddisks<=0 || raiddisks > MD_SB_DISKS) {
|
||||
fprintf(stderr, "mdctl: invalid number of raid disks: %s\n",
|
||||
fprintf(stderr, Name ": invalid number of raid disks: %s\n",
|
||||
optarg);
|
||||
exit(2);
|
||||
}
|
||||
|
@ -220,18 +228,18 @@ int main(int argc, char *argv[])
|
|||
|
||||
case O('C','x'): /* number of spare (eXtra) discs */
|
||||
if (sparedisks) {
|
||||
fprintf(stderr,"mdctl: spare-disks set twice: %d and %s\n",
|
||||
fprintf(stderr,Name ": spare-disks set twice: %d and %s\n",
|
||||
sparedisks, optarg);
|
||||
exit(2);
|
||||
}
|
||||
if (level > -10 && level < 1) {
|
||||
fprintf(stderr, "mdctl: spare-disks setting is incompatible with raid level %d\n",
|
||||
fprintf(stderr, Name ": spare-disks setting is incompatible with raid level %d\n",
|
||||
level);
|
||||
exit(2);
|
||||
}
|
||||
sparedisks = strtol(optarg, &c, 10);
|
||||
if (!optarg[0] || *c || sparedisks < 0 || sparedisks > MD_SB_DISKS - raiddisks) {
|
||||
fprintf(stderr, "mdctl: invalid number of spare disks: %s\n",
|
||||
fprintf(stderr, Name ": invalid number of spare disks: %s\n",
|
||||
optarg);
|
||||
exit(2);
|
||||
}
|
||||
|
@ -243,21 +251,21 @@ int main(int argc, char *argv[])
|
|||
continue;
|
||||
case O('A','u'): /* uuid of array */
|
||||
if (uuidset) {
|
||||
fprintf(stderr, "mdctl: uuid cannot bet set twice. "
|
||||
fprintf(stderr, Name ": uuid cannot bet set twice. "
|
||||
"Second value %s.\n", optarg);
|
||||
exit(2);
|
||||
}
|
||||
if (parse_uuid(optarg, uuid))
|
||||
uuidset = 1;
|
||||
else {
|
||||
fprintf(stderr,"mdctl: Bad uuid: %s\n", optarg);
|
||||
fprintf(stderr,Name ": Bad uuid: %s\n", optarg);
|
||||
exit(2);
|
||||
}
|
||||
continue;
|
||||
|
||||
case O('A','c'): /* config file */
|
||||
if (configfile) {
|
||||
fprintf(stderr, "mdctl: configfile cannot be set twice. "
|
||||
fprintf(stderr, Name ": configfile cannot be set twice. "
|
||||
"Second value is %s.\n", optarg);
|
||||
exit(2);
|
||||
}
|
||||
|
@ -289,14 +297,14 @@ int main(int argc, char *argv[])
|
|||
case O('B','R'):
|
||||
case O('C','R'): /* Run the array */
|
||||
if (runstop < 0) {
|
||||
fprintf(stderr, "mdctl: Cannot both Stop and Run an array\n");
|
||||
fprintf(stderr, Name ": Cannot both Stop and Run an array\n");
|
||||
exit(2);
|
||||
}
|
||||
runstop = 1;
|
||||
continue;
|
||||
case O('@','S'):
|
||||
if (runstop > 0) {
|
||||
fprintf(stderr, "mdctl: Cannot both Run and Stop an array\n");
|
||||
fprintf(stderr, Name ": Cannot both Run and Stop an array\n");
|
||||
exit(2);
|
||||
}
|
||||
runstop = -1;
|
||||
|
@ -304,7 +312,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
case O('@','o'):
|
||||
if (readonly < 0) {
|
||||
fprintf(stderr, "mdctl: Cannot have both readonly and readwrite\n");
|
||||
fprintf(stderr, Name ": Cannot have both readonly and readwrite\n");
|
||||
exit(2);
|
||||
}
|
||||
readonly = 1;
|
||||
|
@ -320,7 +328,7 @@ int main(int argc, char *argv[])
|
|||
/* We have now processed all the valid options. Anything else is
|
||||
* an error
|
||||
*/
|
||||
fprintf(stderr, "mdctl: option %c not valid in mode %c\n",
|
||||
fprintf(stderr, Name ": option %c not valid in mode %c\n",
|
||||
opt, mode);
|
||||
exit(2);
|
||||
|
||||
|
@ -341,17 +349,17 @@ int main(int argc, char *argv[])
|
|||
*/
|
||||
if (mode !='D' && mode !='E' && ! (mode =='A' && scan)) {
|
||||
if (!mddev) {
|
||||
fprintf(stderr, "mdctl: an md device must be given in this mode\n");
|
||||
fprintf(stderr, Name ": an md device must be given in this mode\n");
|
||||
exit(2);
|
||||
}
|
||||
mdfd = open(mddev, O_RDWR, 0);
|
||||
if (mdfd < 0) {
|
||||
fprintf(stderr,"mdctl: error opening %s: %s\n",
|
||||
fprintf(stderr,Name ": error opening %s: %s\n",
|
||||
mddev, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
if (md_get_version(mdfd) <= 0) {
|
||||
fprintf(stderr, "mdctl: %s does not appear to be an md device\n",
|
||||
fprintf(stderr, Name ": %s does not appear to be an md device\n",
|
||||
mddev);
|
||||
close(mdfd);
|
||||
exit(1);
|
||||
|
@ -378,8 +386,8 @@ int main(int argc, char *argv[])
|
|||
rv = Build(mddev, mdfd, chunk, level, raiddisks, subdevs,subdev);
|
||||
break;
|
||||
case 'C': /* Create */
|
||||
rv = Create(mddev, mdfd, chunk, level, layout, raiddisks, sparedisks,
|
||||
subdevs,subdev,runstop);
|
||||
rv = Create(mddev, mdfd, chunk, level, layout, size, raiddisks, sparedisks,
|
||||
subdevs,subdev,runstop, verbose);
|
||||
break;
|
||||
case 'D': /* Detail */
|
||||
for (i=0; i<subdevs; i++)
|
||||
|
|
25
mdctl.h
25
mdctl.h
|
@ -49,6 +49,8 @@ extern __off64_t lseek64 __P ((int __fd, __off64_t __offset, int __whence));
|
|||
|
||||
#include "md_u.h"
|
||||
|
||||
#define Name "mdctl"
|
||||
|
||||
extern char short_options[];
|
||||
extern struct option long_options[];
|
||||
extern char Version[], Usage[], Help[], Help_create[], Help_build[], Help_assemble[];
|
||||
|
@ -67,13 +69,15 @@ typedef struct mddev_dev_s {
|
|||
struct mddev_dev_s *next;
|
||||
} *mddev_dev_t;
|
||||
|
||||
/*
|
||||
* RAID5 supported algorithms
|
||||
*/
|
||||
#define ALGORITHM_LEFT_ASYMMETRIC 0
|
||||
#define ALGORITHM_RIGHT_ASYMMETRIC 1
|
||||
#define ALGORITHM_LEFT_SYMMETRIC 2
|
||||
#define ALGORITHM_RIGHT_SYMMETRIC 3
|
||||
typedef struct mapping {
|
||||
char *name;
|
||||
int num;
|
||||
} mapping_t;
|
||||
|
||||
extern char *map_num(mapping_t *map, int num);
|
||||
extern int map_name(mapping_t *map, char *name);
|
||||
extern mapping_t r5layout[], pers[];
|
||||
|
||||
|
||||
|
||||
extern int Manage_ro(char *devname, int fd, int readonly);
|
||||
|
@ -95,9 +99,9 @@ extern int Build(char *mddev, int mdfd, int chunk, int level,
|
|||
|
||||
|
||||
extern int Create(char *mddev, int mdfd,
|
||||
int chunk, int level, int layout, int raiddisks, int sparedisks,
|
||||
int chunk, int level, int layout, int size, int raiddisks, int sparedisks,
|
||||
int subdevs, char *subdev[],
|
||||
int runstop);
|
||||
int runstop, int verbose);
|
||||
|
||||
extern int Detail(char *dev);
|
||||
extern int Examine(char *dev);
|
||||
|
@ -105,6 +109,9 @@ extern int Examine(char *dev);
|
|||
extern int md_get_version(int fd);
|
||||
extern int get_linux_version();
|
||||
extern int parse_uuid(char *str, int uuid[4]);
|
||||
extern int check_ext2(int fd, char *name);
|
||||
extern int check_reiser(int fd, char *name);
|
||||
extern int check_raid(int fd, char *name);
|
||||
|
||||
extern mddev_uuid_t conf_get_uuids(char *);
|
||||
extern mddev_dev_t conf_get_devs(char *);
|
||||
|
|
119
util.c
119
util.c
|
@ -88,10 +88,10 @@ int md_get_version(int fd)
|
|||
return -1;
|
||||
|
||||
if (ioctl(fd, RAID_VERSION, &vers) == 0)
|
||||
return (vers.major<<16) | (vers.minor<<8) | vers.patchlevel;
|
||||
return (vers.major*10000) + (vers.minor*100) + vers.patchlevel;
|
||||
|
||||
if (MAJOR(stb.st_rdev) == MD_MAJOR)
|
||||
return (36<<8);
|
||||
return (3600);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,7 @@ int get_linux_version()
|
|||
|
||||
if (sscanf(name.release, "%d.%d.%d", &a,&b,&c)!= 3)
|
||||
return -1;
|
||||
return (a<<16)+(b<<8)+c;
|
||||
return (a*1000000)+(b*1000)+c;
|
||||
}
|
||||
|
||||
int enough(int level, int raid_disks, int avail_disks)
|
||||
|
@ -211,7 +211,7 @@ int load_super(int fd, mdp_super_t *super)
|
|||
if (lseek64(fd, offset, 0)< 0LL)
|
||||
return 3;
|
||||
|
||||
if (read(fd, &super, sizeof(super)) != sizeof(super))
|
||||
if (read(fd, super, sizeof(*super)) != sizeof(*super))
|
||||
return 4;
|
||||
|
||||
if (super->md_magic != MD_SB_MAGIC)
|
||||
|
@ -222,3 +222,114 @@ int load_super(int fd, mdp_super_t *super)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int check_ext2(int fd, char *name)
|
||||
{
|
||||
/*
|
||||
* Check for an ext2fs file system.
|
||||
* Superblock is always 1K at 1K offset
|
||||
*
|
||||
* s_magic is le16 at 56 == 0xEF53
|
||||
* report mtime - le32 at 44
|
||||
* blocks - le32 at 4
|
||||
* logblksize - le32 at 24
|
||||
*/
|
||||
unsigned char sb[1024];
|
||||
time_t mtime;
|
||||
int size, bsize;
|
||||
if (lseek(fd, 1024,0)!= 1024)
|
||||
return 0;
|
||||
if (read(fd, sb, 1024)!= 1024)
|
||||
return 0;
|
||||
if (sb[56] != 0x53 || sb[57] != 0xef)
|
||||
return 0;
|
||||
|
||||
mtime = sb[44]|(sb[45]|(sb[46]|sb[47]<<8)<<8)<<8;
|
||||
bsize = sb[24]|(sb[25]|(sb[26]|sb[27]<<8)<<8)<<8;
|
||||
size = sb[4]|(sb[5]|(sb[6]|sb[7]<<8)<<8)<<8;
|
||||
fprintf(stderr, Name ": %s appears to contain an ext2fs file system\n",
|
||||
name);
|
||||
fprintf(stderr," size=%dK mtime=%s",
|
||||
size*(1<<bsize), ctime(&mtime));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int check_reiser(int fd, char *name)
|
||||
{
|
||||
/*
|
||||
* superblock is at 64K
|
||||
* size is 1024;
|
||||
* Magic string "ReIsErFs" or "ReIsEr2Fs" at 52
|
||||
*
|
||||
*/
|
||||
unsigned char sb[1024];
|
||||
int size;
|
||||
if (lseek(fd, 64*1024, 0) != 64*1024)
|
||||
return 0;
|
||||
if (read(fd, sb, 1024) != 1024)
|
||||
return 0;
|
||||
if (strncmp(sb+52, "ReIsErFs",8)!=0 &&
|
||||
strncmp(sb+52, "ReIsEr2Fs",9)!=0)
|
||||
return 0;
|
||||
fprintf(stderr, Name ": %s appears to contain a reiserfs file system\n",name);
|
||||
size = sb[0]|(sb[1]|(sb[2]|sb[3]<<8)<<8)<<8;
|
||||
fprintf(stderr, " size = %dK\n", size*4);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int check_raid(int fd, char *name)
|
||||
{
|
||||
mdp_super_t super;
|
||||
time_t crtime;
|
||||
if (load_super(fd, &super))
|
||||
return 0;
|
||||
/* Looks like a raid array .. */
|
||||
fprintf(stderr, Name ": %s appear to be part of a raid array:\n",
|
||||
name);
|
||||
crtime = super.ctime;
|
||||
fprintf(stderr, " level=%d disks=%d ctime=%s",
|
||||
super.level, super.raid_disks, ctime(&crtime));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int ask(char *mesg)
|
||||
{
|
||||
char *add = "";
|
||||
int i;
|
||||
for (i=0; i<5; i++) {
|
||||
char buf[100];
|
||||
fprintf(stderr, "%s%s", mesg, add);
|
||||
fflush(stderr);
|
||||
if (fgets(buf, 100, stdin)==NULL)
|
||||
return 0;
|
||||
if (buf[0]=='y' || buf[0]=='Y')
|
||||
return 1;
|
||||
if (buf[0]=='n' || buf[0]=='N')
|
||||
return 0;
|
||||
add = "(y/n) ";
|
||||
}
|
||||
fprintf(stderr, Name ": assuming 'no'\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *map_num(mapping_t *map, int num)
|
||||
{
|
||||
while (map->name) {
|
||||
if (map->num == num)
|
||||
return map->name;
|
||||
map++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int map_name(mapping_t *map, char *name)
|
||||
{
|
||||
while (map->name) {
|
||||
if (strcmp(map->name, name)==0)
|
||||
return map->num;
|
||||
map++;
|
||||
}
|
||||
return -10;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue