summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Assemble.c48
-rw-r--r--Create.c211
-rw-r--r--Detail.c23
-rw-r--r--Examine.c25
-rw-r--r--Makefile3
-rw-r--r--Manage.c160
-rw-r--r--ReadMe.c43
-rw-r--r--TAGS140
-rw-r--r--TODO11
-rwxr-xr-xmakedist6
-rw-r--r--mdctl.c114
-rw-r--r--mdctl.h25
-rw-r--r--util.c119
13 files changed, 808 insertions, 120 deletions
diff --git a/Assemble.c b/Assemble.c
index 504bde7..fdaff09 100644
--- a/Assemble.c
+++ b/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;
}
diff --git a/Create.c b/Create.c
index dda54fd..ac776c2 100644
--- a/Create.c
+++ b/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, &param)) {
+ 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;
}
diff --git a/Detail.c b/Detail.c
index 9f81e04..3349c3a 100644
--- a/Detail.c
+++ b/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;
}
diff --git a/Examine.c b/Examine.c
index ea223c6..f2498ec 100644
--- a/Examine.c
+++ b/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");
diff --git a/Makefile b/Makefile
index 4fe9ba8..0168923 100644
--- a/Makefile
+++ b/Makefile
@@ -42,3 +42,6 @@ clean :
dist : clean
./makedist
+
+TAGS :
+ etags *.h *.c
diff --git a/Manage.c b/Manage.c
index 302a425..7357339 100644
--- a/Manage.c
+++ b/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, &param)) {
+ 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;
+
}
diff --git a/ReadMe.c b/ReadMe.c
index e07cc42..9bee800 100644
--- a/ReadMe.c
+++ b/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}
+};
diff --git a/TAGS b/TAGS
new file mode 100644
index 0000000..bceb7ad
--- /dev/null
+++ b/TAGS
@@ -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
diff --git a/TODO b/TODO
index 62dab1c..f093277 100644
--- a/TODO
+++ b/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. \ No newline at end of file
+- --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
diff --git a/makedist b/makedist
index 5b6db54..789a80a 100755
--- a/makedist
+++ b/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 \ No newline at end of file
+ls -l $target/$base
diff --git a/mdctl.c b/mdctl.c
index a2ece91..5a16646 100644
--- a/mdctl.c
+++ b/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++)
diff --git a/mdctl.h b/mdctl.h
index 7e7c389..0e3b917 100644
--- a/mdctl.h
+++ b/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 *);
diff --git a/util.c b/util.c
index bd7f1d8..bb370dd 100644
--- a/util.c
+++ b/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;
+}