diff ./Assemble.c~orig~ ./Assemble.c --- ./Assemble.c~orig~ 2004-11-01 13:36:30.000000000 +1100 +++ ./Assemble.c 2005-01-26 21:17:43.000000000 +1100 @@ -288,7 +288,7 @@ int Assemble(char *mddev, int mdfd, if (strcmp(update, "super-minor") ==0) { struct stat stb2; fstat(mdfd, &stb2); - super.md_minor = MINOR(stb2.st_rdev); + super.md_minor = minor(stb2.st_rdev); if (verbose) fprintf(stderr, Name ": updating superblock of %s with minor number %d\n", devname, super.md_minor); @@ -341,8 +341,8 @@ int Assemble(char *mddev, int mdfd, fprintf(stderr, Name ": %s is identified as a member of %s, slot %d.\n", devname, mddev, super.this_disk.raid_disk); devices[devcnt].devname = devname; - devices[devcnt].major = MAJOR(stb.st_rdev); - devices[devcnt].minor = MINOR(stb.st_rdev); + devices[devcnt].major = major(stb.st_rdev); + devices[devcnt].minor = minor(stb.st_rdev); devices[devcnt].oldmajor = super.this_disk.major; devices[devcnt].oldminor = super.this_disk.minor; devices[devcnt].events = md_event(&super); @@ -665,7 +665,7 @@ This doesnt work yet * so we can just start the array */ unsigned long dev; - dev = MKDEV(devices[chosen_drive].major, + dev = makedev(devices[chosen_drive].major, devices[chosen_drive].minor); if (ioctl(mdfd, START_ARRAY, dev)) { fprintf(stderr, Name ": Cannot start array: %s\n", diff ./Build.c~orig~ ./Build.c --- ./Build.c~orig~ 2004-11-01 13:36:30.000000000 +1100 +++ ./Build.c 2005-01-26 21:17:43.000000000 +1100 @@ -117,7 +117,7 @@ int Build(char *mddev, int mdfd, int chu array.raid_disks = raiddisks; array.md_minor = 0; if (fstat(mdfd, &stb)==0) - array.md_minor = MINOR(stb.st_rdev); + array.md_minor = minor(stb.st_rdev); array.not_persistent = 1; array.state = 0; /* not clean, but no errors */ if (assume_clean) @@ -153,8 +153,8 @@ int Build(char *mddev, int mdfd, int chu disk.number = i; disk.raid_disk = i; disk.state = 6; - disk.major = MAJOR(stb.st_rdev); - disk.minor = MINOR(stb.st_rdev); + disk.major = major(stb.st_rdev); + disk.minor = minor(stb.st_rdev); if (ioctl(mdfd, ADD_NEW_DISK, &disk)) { fprintf(stderr, Name ": ADD_NEW_DISK failed for %s: %s\n", dv->devname, strerror(errno)); diff ./ChangeLog~orig~ ./ChangeLog --- ./ChangeLog~orig~ 2004-12-07 10:38:02.000000000 +1100 +++ ./ChangeLog 2005-01-26 21:17:43.000000000 +1100 @@ -1,3 +1,6 @@ +Changes Prior to 1.9.0 release + - Change "dirty" status to "active" as it was confusing people. + Changes Prior to 1.8.0 release - Makefile cleanup from Luca Berra - --pid-file (-i) to set a pid file to use with --monitor --daemonise diff ./Create.c~orig~ ./Create.c --- ./Create.c~orig~ 2004-11-01 13:36:33.000000000 +1100 +++ ./Create.c 2005-01-26 21:17:43.000000000 +1100 @@ -305,7 +305,7 @@ int Create(char *mddev, int mdfd, */ array.md_minor = 0; if (fstat(mdfd, &stb)==0) - array.md_minor = MINOR(stb.st_rdev); + array.md_minor = minor(stb.st_rdev); array.not_persistent = 0; /*** FIX: Need to do something about RAID-6 here ***/ if ( ( (level == 5) && @@ -375,8 +375,8 @@ int Create(char *mddev, int mdfd, return 1; } fstat(fd, &stb); - disk.major = MAJOR(stb.st_rdev); - disk.minor = MINOR(stb.st_rdev); + disk.major = major(stb.st_rdev); + disk.minor = minor(stb.st_rdev); close(fd); } if (ioctl(mdfd, ADD_NEW_DISK, &disk)) { diff ./Detail.c~orig~ ./Detail.c --- ./Detail.c~orig~ 2004-11-01 13:36:30.000000000 +1100 +++ ./Detail.c 2005-01-26 21:17:43.000000000 +1100 @@ -124,7 +124,7 @@ int Detail(char *dev, int brief, int tes struct mdstat_ent *ms = mdstat_read(0); struct mdstat_ent *e; int devnum = array.md_minor; - if (MAJOR(stb.st_rdev) != MD_MAJOR) + if (major(stb.st_rdev) != MD_MAJOR) devnum = -1 - devnum; for (e=ms; e; e=e->next) @@ -161,7 +161,7 @@ int Detail(char *dev, int brief, int tes atime = array.utime; printf(" Update Time : %.24s\n", ctime(&atime)); printf(" State : %s%s%s\n", - (array.state&(1<percent < 0) ? "" : (e->resync) ? ", resyncing": ", recovering"); @@ -251,8 +251,8 @@ int Detail(char *dev, int brief, int tes * device from the array, and then put it back. * If this fails, we are rebuilding */ - int err = ioctl(fd, HOT_REMOVE_DISK, MKDEV(disk.major, disk.minor)); - if (err == 0) ioctl(fd, HOT_ADD_DISK, MKDEV(disk.major, disk.minor)); + int err = ioctl(fd, HOT_REMOVE_DISK, makedev(disk.major, disk.minor)); + if (err == 0) ioctl(fd, HOT_ADD_DISK, makedev(disk.major, disk.minor)); if (err && errno == EBUSY) printf(" rebuilding"); } diff ./Examine.c~orig~ ./Examine.c --- ./Examine.c~orig~ 2004-11-01 15:36:33.000000000 +1100 +++ ./Examine.c 2005-01-26 21:17:43.000000000 +1100 @@ -154,7 +154,7 @@ int Examine(mddev_dev_t devlist, int bri atime = super.utime; printf(" Update Time : %.24s\n", ctime(&atime)); printf(" State : %s\n", - (super.state&(1<devname, strerror(errno)); diff ./Monitor.c~orig~ ./Monitor.c --- ./Monitor.c~orig~ 2005-01-25 15:40:31.000000000 +1100 +++ ./Monitor.c 2005-01-26 21:17:43.000000000 +1100 @@ -246,10 +246,10 @@ int Monitor(mddev_dev_t devlist, struct stat stb; if (fstat(fd, &stb) == 0 && (S_IFMT&stb.st_mode)==S_IFBLK) { - if (MAJOR(stb.st_rdev) == MD_MAJOR) - st->devnum = MINOR(stb.st_rdev); + if (major(stb.st_rdev) == MD_MAJOR) + st->devnum = minor(stb.st_rdev); else - st->devnum = -1- (MINOR(stb.st_rdev)>>6); + st->devnum = -1- (minor(stb.st_rdev)>>6); } } @@ -323,7 +323,7 @@ int Monitor(mddev_dev_t devlist, alert("Fail", dev, dv, mailaddr, alert_cmd); else if (i >= (unsigned)array.raid_disks && (disc.major || disc.minor) && - st->devid[i] == MKDEV(disc.major, disc.minor) && + st->devid[i] == makedev(disc.major, disc.minor) && ((newstate&change)&(1<devstate[i] = disc.state; - st->devid[i] = MKDEV(disc.major, disc.minor); + st->devid[i] = makedev(disc.major, disc.minor); } close(fd); st->active = array.active_disks; diff ./Query.c~orig~ ./Query.c --- ./Query.c~orig~ 2004-11-01 13:36:30.000000000 +1100 +++ ./Query.c 2005-01-26 21:17:43.000000000 +1100 @@ -129,7 +129,7 @@ int Query(char *dev) if (md_get_version(fd) >= 9000 && ioctl(fd, GET_ARRAY_INFO, &array)>= 0) { if (ioctl(fd, GET_DISK_INFO, &disc) >= 0 && - MKDEV((unsigned)disc.major,(unsigned)disc.minor) == stb.st_rdev) + makedev((unsigned)disc.major,(unsigned)disc.minor) == stb.st_rdev) activity = "active"; else activity = "mismatch"; diff ./config.c~orig~ ./config.c --- ./config.c~orig~ 2004-11-01 13:36:30.000000000 +1100 +++ ./config.c 2005-01-26 21:17:43.000000000 +1100 @@ -202,13 +202,14 @@ struct conf_dev { char *name; } *cdevlist = NULL; -void load_partitions(void) +mddev_dev_t load_partitions(void) { FILE *f = fopen("/proc/partitions", "r"); char buf[1024]; + mddev_dev_t rv = NULL; if (f == NULL) { fprintf(stderr, Name ": cannot open /proc/partitions\n"); - return; + return NULL; } while (fgets(buf, 1024, f)) { int major, minor; @@ -223,15 +224,16 @@ void load_partitions(void) name = map_dev(major, minor); if (name) { - struct conf_dev *cd; + mddev_dev_t d; - cd = malloc(sizeof(*cd)); - cd->name = strdup(name); - cd->next = cdevlist; - cdevlist = cd; + d = malloc(sizeof(*d)); + d->devname = strdup(name); + d->next = rv; + rv = d; } } fclose(f); + return rv; } @@ -241,14 +243,11 @@ void devline(char *line) struct conf_dev *cd; for (w=dl_next(line); w != line; w=dl_next(w)) { - if (w[0] == '/') { + if (w[0] == '/' || strcasecmp(w, "partitions") == 0) { cd = malloc(sizeof(*cd)); cd->name = strdup(w); cd->next = cdevlist; cdevlist = cd; - } else if (strcasecmp(w, "partitions") == 0) { - /* read /proc/partitions, and look major/minor up in /dev */ - load_partitions(); } else { fprintf(stderr, Name ": unreconised word on DEVICE line: %s\n", w); @@ -422,7 +421,7 @@ void load_conffile(char *conffile) return; } if (strcmp(conffile, "partitions")==0) { - load_partitions(); + devline("DEV partitions"); loaded = 1; return; } @@ -497,8 +496,12 @@ mddev_dev_t conf_get_devs(char *conffile load_conffile(conffile); for (cd=cdevlist; cd; cd=cd->next) { - glob(cd->name, flags, NULL, &globbuf); - flags |= GLOB_APPEND; + if (strcasecmp(cd->name, "partitions")==0 && dlist == NULL) + dlist = load_partitions(); + else { + glob(cd->name, flags, NULL, &globbuf); + flags |= GLOB_APPEND; + } } if (flags & GLOB_APPEND) { for (i=0; i=0) /* already assembled, skip */ - continue; - rv |= Assemble(array_list->devname, mdfd, - array_list, configfile, - NULL, - readonly, runstop, NULL, verbose, force); + ; + else + rv |= Assemble(array_list->devname, mdfd, + array_list, configfile, + NULL, + readonly, runstop, NULL, verbose, force); + close(mdfd); } } break; @@ -780,6 +793,16 @@ int main(int argc, char *argv[]) /* apply to all devices in /proc/mdstat */ struct mdstat_ent *ms = mdstat_read(0); struct mdstat_ent *e; + if (devmode == 'S') { + /* reverse order so that arrays made of arrays are stopped properly */ + struct mdstat_ent *sm = NULL; + while ((e=ms) != NULL) { + ms = e->next; + e->next = sm; + sm = e; + } + ms = sm; + } for (e=ms ; e ; e=e->next) { char *name = get_md_name(e->devnum); @@ -792,8 +815,10 @@ int main(int argc, char *argv[]) rv |= Detail(name, !verbose, test); else if (devmode=='S') { mdfd = open_mddev(name, 0); - if (mdfd >= 0) + if (mdfd >= 0) { rv |= Manage_runstop(name, mdfd, -1); + close(mdfd); + } } put_md_name(name); } @@ -812,7 +837,7 @@ int main(int argc, char *argv[]) rv |= Query(dv->devname); continue; } mdfd = open_mddev(dv->devname, 0); - if (mdfd>=0) + if (mdfd>=0) { switch(dv->disposition) { case 'R': rv |= Manage_runstop(dv->devname, mdfd, 1); break; @@ -823,6 +848,8 @@ int main(int argc, char *argv[]) case 'w': rv |= Manage_ro(dv->devname, mdfd, -1); break; } + close(mdfd); + } } } break; diff ./mdadm.h~orig~ ./mdadm.h --- ./mdadm.h~orig~ 2004-11-01 13:36:30.000000000 +1100 +++ ./mdadm.h 2005-01-26 21:17:43.000000000 +1100 @@ -200,7 +200,7 @@ extern int check_reiser(int fd, char *na extern int check_raid(int fd, char *name); extern int get_mdp_major(void); -extern int is_standard(char *dev); +extern int is_standard(char *dev, int *nump); extern mddev_ident_t conf_get_ident(char *conffile, char *dev); diff ./mdadm.spec~orig~ ./mdadm.spec --- ./mdadm.spec~orig~ 2004-11-01 15:44:33.000000000 +1100 +++ ./mdadm.spec 2005-01-26 21:17:43.000000000 +1100 @@ -50,7 +50,7 @@ rm -rf $RPM_BUILD_ROOT - Set CXFLAGS instead of CFLAGS * Sat Apr 6 2002 -- change %install to use "make install" +- change install to use "make install" * Fri Mar 15 2002 - beautification diff ./mdopen.c~orig~ ./mdopen.c --- ./mdopen.c~orig~ 2005-01-25 15:33:49.000000000 +1100 +++ ./mdopen.c 2005-01-26 21:17:43.000000000 +1100 @@ -35,7 +35,7 @@ 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 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 */ @@ -49,21 +49,21 @@ void make_parts(char *dev, int cnt) return; if (!S_ISBLK(stb.st_mode)) return; - major = MAJOR(stb.st_rdev); - minor = MINOR(stb.st_rdev); + 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); + 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)) + if (stb2.st_rdev == makedev(major, minor+i)) continue; unlink(name); } else { stb2 = stb; } - mknod(name, S_IFBLK | 0600, MKDEV(major, minor+i)); + mknod(name, S_IFBLK | 0600, makedev(major, minor+i)); chown(name, stb2.st_uid, stb2.st_gid); chmod(name, stb2.st_mode & 07777); } @@ -75,7 +75,7 @@ void make_parts(char *dev, int cnt) * 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. + * If it now doesn't exist, we find a new md array and create the device. * Default ownership is user=0, group=0 perm=0600 */ int open_mddev(char *dev, int autof) @@ -92,6 +92,10 @@ int open_mddev(char *dev, int autof) /* autof is set, so we need to check that the name is ok, * and possibly create one if not */ + if (autof == -2 && !is_standard(dev, NULL)) { + fprintf(stderr, Name ": --auto=yes requires a 'standard' md device name, not %s\n", dev); + return -1; + } stb.st_mode = 0; if (lstat(dev, &stb)==0 && ! S_ISBLK(stb.st_mode)) { fprintf(stderr, Name ": %s is not a block device.\n", @@ -101,7 +105,7 @@ int open_mddev(char *dev, int autof) /* check major number is correct */ if (autof>0) major = get_mdp_major(); - if (stb.st_mode && MAJOR(stb.st_rdev) != major) + if (stb.st_mode && major(stb.st_rdev) != major) must_remove = 1; if (stb.st_mode && !must_remove) { mdu_array_info_t array; @@ -128,55 +132,81 @@ int open_mddev(char *dev, int autof) } } /* Ok, need to find a minor that is not in use. - * Easiest to read /proc/mdstat, and hunt through for + * If the device name is in a 'standard' format, + * intuit the minor from that, else + * 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 + switch(is_standard(dev, &num)) { + case -1: /* non partitioned */ + if (autof > 0) { + fprintf(stderr, Name ": that --auto option not compatable with device named %s\n", dev); + return -1; + } + minor = num; + num = -1-num; + break; + case 1: /* partitioned */ + if (autof == -1) { + fprintf(stderr, Name ": that --auto option not compatable with device named %s\n", dev); + return -1; + } + minor = num << MdpMinorShift; + major = get_mdp_major(); + break; + case 0: /* not standard, pick 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 */ - break; + char *dn; + if (autof > 0) + minor = (-1-num) << MdpMinorShift; + else + minor = num; + dn = map_dev(major,minor); + if (dn==NULL || is_standard(dn, NULL)) { + /* 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); + /* major and minor have been chosen */ + + /* If it was a 'standard' name and it is in-use, then + * the device could already be correct + */ + if (stb.st_mode && major(stb.st_rdev) == major && + minor(stb.st_rdev) == minor) + ; + else { + if (major(makedev(major,minor)) != major || + minor(makedev(major,minor)) != minor) { + fprintf(stderr, Name ": Need newer C library to use more than 4 partitionable md devices, sorry\n"); return -1; } - unlink(dev); - } + if (must_remove) + 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); + if (mknod(dev, S_IFBLK|0600, makedev(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); } - make_parts(dev,autof); } mdfd = open(dev, O_RDWR, 0); if (mdfd < 0) diff ./util.c~orig~ ./util.c --- ./util.c~orig~ 2004-11-01 13:40:37.000000000 +1100 +++ ./util.c 2005-01-26 21:17:43.000000000 +1100 @@ -94,7 +94,7 @@ int md_get_version(int fd) return (vers.major*10000) + (vers.minor*100) + vers.patchlevel; if (errno == EACCES) return -1; - if (MAJOR(stb.st_rdev) == MD_MAJOR) + if (major(stb.st_rdev) == MD_MAJOR) return (3600); return -1; } @@ -395,28 +395,37 @@ int map_name(mapping_t *map, char *name) } -int is_standard(char *dev) +int is_standard(char *dev, int *nump) { /* tests if dev is a "standard" md dev name. * i.e if the last component is "/dNN" or "/mdNN", * where NN is a string of digits */ - dev = strrchr(dev, '/'); - if (!dev) - return 0; - if (strncmp(dev, "/d",2)==0) - dev += 2; - else if (strncmp(dev, "/md", 3)==0) - dev += 3; + char *d = strrchr(dev, '/'); + int type=0; + int num; + if (!d) + return 0; + if (strncmp(d, "/d",2)==0) + d += 2, type=1; /* /dev/md/dN{pM} */ + else if (strncmp(d, "/md_d", 5)==0) + d += 5, type=1; /* /dev/md_dNpM */ + else if (strncmp(d, "/md", 3)==0) + d += 3, type=-1; /* /dev/mdN */ + else if (d-dev > 3 && strncmp(d-2, "md/", 3)==0) + type = -1; /* /dev/md/N */ else return 0; - if (!*dev) + if (!*d) return 0; - while (isdigit(*dev)) - dev++; - if (*dev) + num = atoi(d); + while (isdigit(*d)) + d++; + if (*d) return 0; - return 1; + if (nump) *nump = num; + + return type; } @@ -456,8 +465,8 @@ int add_dev(const char *name, const stru char *n = strdup(name); struct devmap *dm = malloc(sizeof(*dm)); if (dm) { - dm->major = MAJOR(stb->st_rdev); - dm->minor = MINOR(stb->st_rdev); + dm->major = major(stb->st_rdev); + dm->minor = minor(stb->st_rdev); dm->name = n; dm->next = devlist; devlist = dm; @@ -468,7 +477,7 @@ int add_dev(const char *name, const stru /* * Find a block device with the right major/minor number. - * Avoid /dev/mdNN and /dev/md/dNN is possible + * Avoid /dev/mdNN and /dev/md/dNN if possible */ char *map_dev(int major, int minor) { @@ -486,7 +495,7 @@ char *map_dev(int major, int minor) for (p=devlist; p; p=p->next) if (p->major == major && p->minor == minor) { - if (is_standard(p->name)) + if (is_standard(p->name, NULL)) std = p->name; else return p->name; @@ -600,14 +609,14 @@ char *get_md_name(int dev) if (dev < 0) { int mdp = get_mdp_major(); if (mdp < 0) return NULL; - rdev = MKDEV(mdp, (-1-dev)<<6); + rdev = makedev(mdp, (-1-dev)<<6); sprintf(devname, "/dev/md/d%d", -1-dev); if (stat(devname, &stb) == 0 && (S_IFMT&stb.st_mode) == S_IFBLK && (stb.st_rdev == rdev)) return devname; } else { - rdev = MKDEV(MD_MAJOR, dev); + rdev = makedev(MD_MAJOR, dev); sprintf(devname, "/dev/md%d", dev); if (stat(devname, &stb) == 0 && (S_IFMT&stb.st_mode) == S_IFBLK @@ -620,7 +629,7 @@ char *get_md_name(int dev) && (stb.st_rdev == rdev)) return devname; } - dn = map_dev(MAJOR(rdev), MINOR(rdev)); + dn = map_dev(major(rdev), minor(rdev)); if (dn) return dn; sprintf(devname, "/dev/.tmp.md%d", dev);