summaryrefslogtreecommitdiffstats
path: root/mdadm.c
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2004-11-01 04:49:34 +0000
committerNeil Brown <neilb@suse.de>2004-11-01 04:49:34 +0000
commitb5e64645037e99b5f05c9499b27b422ae60d23a9 (patch)
treef0999c8649d1488a367ee3d9442aff538ae366a8 /mdadm.c
parente5329c3747a4e9eb7addbfaa59b8d5e8688ce2a1 (diff)
downloadmdadm-b5e64645037e99b5f05c9499b27b422ae60d23a9.tar.gz
mdadm-b5e64645037e99b5f05c9499b27b422ae60d23a9.tar.xz
mdadm-b5e64645037e99b5f05c9499b27b422ae60d23a9.zip
mdadm-1.8.0mdadm-1.8.0
Diffstat (limited to 'mdadm.c')
-rw-r--r--mdadm.c240
1 files changed, 59 insertions, 181 deletions
diff --git a/mdadm.c b/mdadm.c
index e181673..d40008e 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -32,167 +32,6 @@
#include <ctype.h>
-void make_parts(char *dev, int cnt)
-{
- /* make 'cnt' partition devices for 'dev'
- * We use the major/minor from dev and add 1..cnt
- * If dev ends with a digit, we add "_p%d" else "%d"
- * If the name exists, we use it's owner/mode,
- * else that of dev
- */
- struct stat stb;
- int major, minor;
- int i;
- char *name = malloc(strlen(dev) + 20);
- int dig = isdigit(dev[strlen(dev)-1]);
-
- if (stat(dev, &stb)!= 0)
- return;
- if (!S_ISBLK(stb.st_mode))
- return;
- major = MAJOR(stb.st_rdev);
- minor = MINOR(stb.st_rdev);
- for (i=1; i <= cnt ; i++) {
- struct stat stb2;
- sprintf(name, "%s%s%d", dev, dig?"_p":"", i);
- if (stat(name, &stb2)==0) {
- if (!S_ISBLK(stb2.st_mode))
- continue;
- if (stb2.st_rdev == MKDEV(major, minor+i))
- continue;
- unlink(name);
- } else {
- stb2 = stb;
- }
- mknod(name, S_IFBLK | 0600, MKDEV(major, minor+i));
- chown(name, stb2.st_uid, stb2.st_gid);
- chmod(name, stb2.st_mode & 07777);
- }
-}
-
-/*
- * Open a given md device, and check that it really is one.
- * If 'autof' is given, then we need to create, or recreate, the md device.
- * If the name already exists, and is not a block device, we fail.
- * If it exists and is not an md device, is not the right type (partitioned or not),
- * or is currently in-use, we remove the device, but remember the owner and mode.
- * If it now doesn't exist, we find a few md array and create the device.
- * Default ownership is user=0, group=0 perm=0600
- */
-int open_mddev(char *dev, int autof)
-{
- int mdfd;
- struct stat stb;
- int major = MD_MAJOR;
- int minor;
- int must_remove = 0;
- struct mdstat_ent *mdlist;
- int num;
-
- if (autof) {
- /* autof is set, so we need to check that the name is ok,
- * and possibly create one if not
- */
- stb.st_mode = 0;
- if (lstat(dev, &stb)==0 && ! S_ISBLK(stb.st_mode)) {
- fprintf(stderr, Name ": %s is not a block device.\n",
- dev);
- return -1;
- }
- /* check major number is correct */
- if (autof>0)
- major = get_mdp_major();
- if (stb.st_mode && MAJOR(stb.st_rdev) != major)
- must_remove = 1;
- if (stb.st_mode && !must_remove) {
- mdu_array_info_t array;
- /* looks ok, see if it is available */
- mdfd = open(dev, O_RDWR, 0);
- if (mdfd < 0) {
- fprintf(stderr, Name ": error opening %s: %s\n",
- dev, strerror(errno));
- return -1;
- } else if (md_get_version(mdfd) <= 0) {
- fprintf(stderr, Name ": %s does not appear to be an md device\n",
- dev);
- close(mdfd);
- return -1;
- }
- if (ioctl(mdfd, GET_ARRAY_INFO, &array)==0) {
- /* already active */
- must_remove = 1;
- close(mdfd);
- } else {
- if (autof > 0)
- make_parts(dev, autof);
- return mdfd;
- }
- }
- /* Ok, need to find a minor that is not in use.
- * Easiest to read /proc/mdstat, and hunt through for
- * an unused number
- */
- mdlist = mdstat_read(0);
- for (num= (autof>0)?-1:0 ; ; num+= (autof>2)?-1:1) {
- struct mdstat_ent *me;
- for (me=mdlist; me; me=me->next)
- if (me->devnum == num)
- break;
- if (!me) {
- /* doesn't exist if mdstat.
- * make sure it is new to /dev too
- */
- char *dn;
- if (autof > 0)
- minor = (-1-num) << MdpMinorShift;
- else
- minor = num;
- dn = map_dev(major,minor);
- if (dn==NULL || is_standard(dn)) {
- /* this number only used by a 'standard' name,
- * so it is safe to use
- */
- break;
- }
- }
- }
- /* 'num' is the number to use, >=0 for md, <0 for mdp */
- if (must_remove) {
- /* never remove a device name that ends /mdNN or /dNN,
- * that would be confusing
- */
- if (is_standard(dev)) {
- fprintf(stderr, Name ": --auto refusing to remove %s as it looks like a standard name.\n",
- dev);
- return -1;
- }
- unlink(dev);
- }
-
- if (mknod(dev, S_IFBLK|0600, MKDEV(major, minor))!= 0) {
- fprintf(stderr, Name ": failed to create %s\n", dev);
- return -1;
- }
- if (must_remove) {
- chown(dev, stb.st_uid, stb.st_gid);
- chmod(dev, stb.st_mode & 07777);
- }
- make_parts(dev,autof);
- }
- mdfd = open(dev, O_RDWR, 0);
- if (mdfd < 0)
- fprintf(stderr, Name ": error opening %s: %s\n",
- dev, strerror(errno));
- else if (md_get_version(mdfd) <= 0) {
- fprintf(stderr, Name ": %s does not appear to be an md device\n",
- dev);
- close(mdfd);
- mdfd = -1;
- }
- return mdfd;
-}
-
-
int main(int argc, char *argv[])
{
@@ -233,6 +72,7 @@ int main(int argc, char *argv[])
char *program = NULL;
int delay = 0;
int daemonise = 0;
+ char *pidfile = NULL;
int oneshot = 0;
int copies;
@@ -420,6 +260,7 @@ int main(int argc, char *argv[])
}
continue;
+ case O(GROW,'l'): /* hack - needed to understand layout */
case O(CREATE,'l'):
case O(BUILD,'l'): /* set raid level*/
if (level != UnSet) {
@@ -433,7 +274,7 @@ int main(int argc, char *argv[])
optarg);
exit(2);
}
- if (level != 0 && level != -1 && level != 1 && level != -4 && mode == BUILD) {
+ if (level != 0 && level != -1 && level != 1 && level != -4 && level != -5 && mode == BUILD) {
fprintf(stderr, Name ": Raid level %s not permitted with --build.\n",
optarg);
exit(2);
@@ -447,6 +288,8 @@ int main(int argc, char *argv[])
continue;
case O(CREATE,'p'): /* raid5 layout */
+ case O(BUILD,'p'): /* faulty layout */
+ case O(GROW, 'p'): /* faulty reconfig */
if (layout != UnSet) {
fprintf(stderr,Name ": layout may only be sent once. "
"Second value was %s\n", optarg);
@@ -485,6 +328,23 @@ int main(int argc, char *argv[])
else
layout = 1 + (copies<<8);
break;
+ case -5: /* Faulty
+ * modeNNN
+ */
+
+ {
+ int ln = strcspn(optarg, "0123456789");
+ char *m = strdup(optarg);
+ int mode;
+ m[ln] = 0;
+ mode = map_name(faultylayout, m);
+ if (mode == UnSet) {
+ fprintf(stderr, Name ": layout %s not understood for faulty.\n",
+ optarg);
+ exit(2);
+ }
+ layout = mode | (atoi(optarg+ln)<< ModeShift);
+ }
}
continue;
@@ -507,7 +367,7 @@ int main(int argc, char *argv[])
optarg);
exit(2);
}
- if (raiddisks == 1 && !force) {
+ if (raiddisks == 1 && !force && level != -5) {
fprintf(stderr, Name ": '1' is an unusual number of drives for an array, so it is probably\n"
" a mistake. If you really mean it you will need to specify --force before\n"
" setting the number of drives.\n");
@@ -677,6 +537,13 @@ int main(int argc, char *argv[])
case O(MONITOR,'f'): /* daemonise */
daemonise = 1;
continue;
+ case O(MONITOR,'i'): /* pid */
+ if (pidfile)
+ fprintf(stderr, Name ": only specify one pid file. %s ignored.\n",
+ optarg);
+ else
+ pidfile = optarg;
+ continue;
case O(MONITOR,'1'): /* oneshot */
oneshot = 1;
continue;
@@ -820,19 +687,20 @@ int main(int argc, char *argv[])
ident.super_minor == UnSet && !scan ) {
/* Only a device has been given, so get details from config file */
mddev_ident_t array_ident = conf_get_ident(configfile, devlist->devname);
- mdfd = open_mddev(devlist->devname, array_ident->autof);
- if (mdfd < 0)
+ if (array_ident == NULL) {
+ fprintf(stderr, Name ": %s not identified in config file.\n",
+ devlist->devname);
rv |= 1;
- else {
- if (array_ident == NULL) {
- fprintf(stderr, Name ": %s not identified in config file.\n",
- devlist->devname);
+ } else {
+ mdfd = open_mddev(devlist->devname, array_ident->autof);
+ if (mdfd < 0)
rv |= 1;
- }
- else
+ else {
rv |= Assemble(devlist->devname, mdfd, array_ident, configfile,
NULL,
readonly, runstop, update, verbose, force);
+ close(mdfd);
+ }
}
} else if (!scan)
rv = Assemble(devlist->devname, mdfd, &ident, configfile,
@@ -845,20 +713,21 @@ int main(int argc, char *argv[])
}
for (dv = devlist ; dv ; dv=dv->next) {
mddev_ident_t array_ident = conf_get_ident(configfile, dv->devname);
- mdfd = open_mddev(dv->devname, array_ident->autof);
- if (mdfd < 0) {
- rv |= 1;
- continue;
- }
if (array_ident == NULL) {
fprintf(stderr, Name ": %s not identified in config file.\n",
dv->devname);
rv |= 1;
continue;
}
+ mdfd = open_mddev(dv->devname, array_ident->autof);
+ if (mdfd < 0) {
+ rv |= 1;
+ continue;
+ }
rv |= Assemble(dv->devname, mdfd, array_ident, configfile,
NULL,
readonly, runstop, update, verbose, force);
+ close(mdfd);
}
} else {
mddev_ident_t array_list = conf_get_ident(configfile, NULL);
@@ -884,7 +753,7 @@ int main(int argc, char *argv[])
}
break;
case BUILD:
- rv = Build(devlist->devname, mdfd, chunk, level, raiddisks, devlist->next, assume_clean);
+ rv = Build(devlist->devname, mdfd, chunk, level, layout, raiddisks, devlist->next, assume_clean);
break;
case CREATE:
rv = Create(devlist->devname, mdfd, chunk, level, layout, size<0 ? 0 : size,
@@ -963,8 +832,13 @@ int main(int argc, char *argv[])
rv = 1;
break;
}
+ if (pidfile && !daemonise) {
+ fprintf(stderr, Name ": Cannot write a pid file when not in daemon mode\n");
+ rv = 1;
+ break;
+ }
rv= Monitor(devlist, mailaddr, program,
- delay?delay:60, daemonise, scan, oneshot, configfile, test);
+ delay?delay:60, daemonise, scan, oneshot, configfile, test, pidfile);
break;
case GROW:
@@ -981,12 +855,16 @@ int main(int argc, char *argv[])
if (rv)
break;
}
- } else if (size >= 0 && raiddisks) {
- fprintf(stderr, Name ": can only grow size OR raiddisks, not both\n");
+ } else if ((size >= 0) + (raiddisks != 0) + (layout != UnSet) > 1) {
+ fprintf(stderr, Name ": can change at most one of size, raiddisks, and layout\n");
rv = 1;
break;
- } else
+ } else if (layout != UnSet)
+ rv = Manage_reconfig(devlist->devname, mdfd, layout);
+ else if (size >= 0 || raiddisks)
rv = Manage_resize(devlist->devname, mdfd, size, raiddisks);
+ else
+ fprintf(stderr, Name ": no changes to --grow\n");
break;
}
exit(rv);