]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - util.c
Check all member devices in enough_fd
[thirdparty/mdadm.git] / util.c
diff --git a/util.c b/util.c
index cc6ccb4d25f99ae737ce65996cd3d1c71d80477a..e92be4fe608a214f4be96f6013e97f657b7ecc58 100644 (file)
--- a/util.c
+++ b/util.c
@@ -370,10 +370,14 @@ int enough_fd(int fd)
            array.raid_disks <= 0)
                return 0;
        avail = calloc(array.raid_disks, 1);
-       for (i=0; i<array.raid_disks + array.nr_disks; i++) {
+       for (i=0; i < 1024 && array.nr_disks > 0; i++) {
                disk.number = i;
                if (ioctl(fd, GET_DISK_INFO, &disk) != 0)
                        continue;
+               if (disk.major == 0 && disk.minor == 0)
+                       continue;
+               array.nr_disks--;
+
                if (! (disk.state & (1<<MD_DISK_SYNC)))
                        continue;
                if (disk.raid_disk < 0 || disk.raid_disk >= array.raid_disks)
@@ -566,27 +570,6 @@ int ask(char *mesg)
 }
 #endif /* MDASSEMBLE */
 
-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 UnSet;
-}
-
-
 int is_standard(char *dev, int *nump)
 {
        /* tests if dev is a "standard" md dev name.
@@ -623,122 +606,6 @@ int is_standard(char *dev, int *nump)
        return type;
 }
 
-
-/*
- * convert a major/minor pair for a block device into a name in /dev, if possible.
- * On the first call, walk /dev collecting name.
- * Put them in a simple linked listfor now.
- */
-struct devmap {
-    int major, minor;
-    char *name;
-    struct devmap *next;
-} *devlist = NULL;
-int devlist_ready = 0;
-
-int add_dev(const char *name, const struct stat *stb, int flag, struct FTW *s)
-{
-       struct stat st;
-
-       if (S_ISLNK(stb->st_mode)) {
-               if (stat(name, &st) != 0)
-                       return 0;
-               stb = &st;
-       }
-
-       if ((stb->st_mode&S_IFMT)== S_IFBLK) {
-               char *n = strdup(name);
-               struct devmap *dm = malloc(sizeof(*dm));
-               if (strncmp(n, "/dev/./", 7)==0)
-                       strcpy(n+4, name+6);
-               if (dm) {
-                       dm->major = major(stb->st_rdev);
-                       dm->minor = minor(stb->st_rdev);
-                       dm->name = n;
-                       dm->next = devlist;
-                       devlist = dm;
-               }
-       }
-       return 0;
-}
-
-#ifndef HAVE_NFTW
-#ifdef HAVE_FTW
-int add_dev_1(const char *name, const struct stat *stb, int flag)
-{
-       return add_dev(name, stb, flag, NULL);
-}
-int nftw(const char *path, int (*han)(const char *name, const struct stat *stb, int flag, struct FTW *s), int nopenfd, int flags)
-{
-       return ftw(path, add_dev_1, nopenfd);
-}
-#else
-int nftw(const char *path, int (*han)(const char *name, const struct stat *stb, int flag, struct FTW *s), int nopenfd, int flags)
-{
-       return 0;
-}
-#endif /* HAVE_FTW */
-#endif /* HAVE_NFTW */
-
-/*
- * Find a block device with the right major/minor number.
- * If we find multiple names, choose the shortest.
- * If we find a name in /dev/md/, we prefer that.
- * This applies only to names for MD devices.
- */
-char *map_dev(int major, int minor, int create)
-{
-       struct devmap *p;
-       char *regular = NULL, *preferred=NULL;
-       int did_check = 0;
-
-       if (major == 0 && minor == 0)
-                       return NULL;
-
- retry:
-       if (!devlist_ready) {
-               char *dev = "/dev";
-               struct stat stb;
-               while(devlist) {
-                       struct devmap *d = devlist;
-                       devlist = d->next;
-                       free(d->name);
-                       free(d);
-               }
-               if (lstat(dev, &stb)==0 &&
-                   S_ISLNK(stb.st_mode))
-                       dev = "/dev/.";
-               nftw(dev, add_dev, 10, FTW_PHYS);
-               devlist_ready=1;
-               did_check = 1;
-       }
-
-       for (p=devlist; p; p=p->next)
-               if (p->major == major &&
-                   p->minor == minor) {
-                       if (strncmp(p->name, "/dev/md/",8) == 0) {
-                               if (preferred == NULL ||
-                                   strlen(p->name) < strlen(preferred))
-                                       preferred = p->name;
-                       } else {
-                               if (regular == NULL ||
-                                   strlen(p->name) < strlen(regular))
-                                       regular = p->name;
-                       }
-               }
-       if (!regular && !preferred && !did_check) {
-               devlist_ready = 0;
-               goto retry;
-       }
-       if (create && !regular && !preferred) {
-               static char buf[30];
-               snprintf(buf, sizeof(buf), "%d:%d", major, minor);
-               regular = buf;
-       }
-
-       return preferred ? preferred : regular;
-}
-
 unsigned long calc_csum(void *super, int bytes)
 {
        unsigned long long newcsum = 0;
@@ -849,34 +716,6 @@ unsigned long long calc_array_size(int level, int raid_disks, int layout,
        return data_disks * devsize;
 }
 
-int get_mdp_major(void)
-{
-static int mdp_major = -1;
-       FILE *fl;
-       char *w;
-       int have_block = 0;
-       int have_devices = 0;
-       int last_num = -1;
-
-       if (mdp_major != -1)
-               return mdp_major;
-       fl = fopen("/proc/devices", "r");
-       if (!fl)
-               return -1;
-       while ((w = conf_word(fl, 1))) {
-               if (have_block && strcmp(w, "devices:")==0)
-                       have_devices = 1;
-               have_block =  (strcmp(w, "Block")==0);
-               if (isdigit(w[0]))
-                       last_num = atoi(w);
-               if (have_devices && strcmp(w, "mdp")==0)
-                       mdp_major = last_num;
-               free(w);
-       }
-       fclose(fl);
-       return mdp_major;
-}
-
 #if !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO)
 char *get_md_name(int dev)
 {
@@ -998,24 +837,34 @@ int dev_open(char *dev, int flags)
        return fd;
 }
 
-int open_dev(int devnum)
+int open_dev_flags(int devnum, int flags)
 {
        char buf[20];
 
        sprintf(buf, "%d:%d", dev2major(devnum), dev2minor(devnum));
-       return dev_open(buf, O_RDONLY);
+       return dev_open(buf, flags);
+}
+
+int open_dev(int devnum)
+{
+       return open_dev_flags(devnum, O_RDONLY);
 }
 
 int open_dev_excl(int devnum)
 {
        char buf[20];
        int i;
+       int flags = O_RDWR;
 
        sprintf(buf, "%d:%d", dev2major(devnum), dev2minor(devnum));
        for (i=0 ; i<25 ; i++) {
-               int fd = dev_open(buf, O_RDWR|O_EXCL);
+               int fd = dev_open(buf, flags|O_EXCL);
                if (fd >= 0)
                        return fd;
+               if (errno == EACCES && flags == O_RDWR) {
+                       flags = O_RDONLY;
+                       continue;
+               }
                if (errno != EBUSY)
                        return fd;
                usleep(200000);
@@ -1191,6 +1040,7 @@ struct supertype *guess_super_type(int fd, enum guess_types guess_type)
                if (guess_type == guess_partitions && ss->add_to_super != NULL)
                        continue;
                memset(st, 0, sizeof(*st));
+               st->ignore_hw_compat = 1;
                rv = ss->load_super(st, fd, NULL);
                if (rv == 0) {
                        struct mdinfo info;
@@ -1206,9 +1056,11 @@ struct supertype *guess_super_type(int fd, enum guess_types guess_type)
        if (bestsuper != -1) {
                int rv;
                memset(st, 0, sizeof(*st));
+               st->ignore_hw_compat = 1;
                rv = superlist[bestsuper]->load_super(st, fd, NULL);
                if (rv == 0) {
                        superlist[bestsuper]->free_super(st);
+                       st->ignore_hw_compat = 0;
                        return st;
                }
        }
@@ -1408,10 +1260,13 @@ int check_partitions(int fd, char *dname, unsigned long long freesize,
 void get_one_disk(int mdfd, mdu_array_info_t *ainf, mdu_disk_info_t *disk)
 {
        int d;
+
        ioctl(mdfd, GET_ARRAY_INFO, ainf);
-       for (d = 0 ; d < ainf->raid_disks + ainf->nr_disks ; d++)
-               if (ioctl(mdfd, GET_DISK_INFO, disk) == 0)
+       for (d = 0 ; d < 1024 ; d++) {
+               if (ioctl(mdfd, GET_DISK_INFO, disk) == 0 &&
+                   (disk->major || disk->minor))
                        return;
+       }
 }
 
 int open_container(int fd)
@@ -1692,73 +1547,6 @@ unsigned long long min_recovery_start(struct mdinfo *array)
        return recovery_start;
 }
 
-void fmt_devname(char *name, int num)
-{
-       if (num >= 0)
-               sprintf(name, "md%d", num);
-       else
-               sprintf(name, "md_d%d", -1-num);
-}
-
-char *devnum2devname(int num)
-{
-       char name[100];
-       fmt_devname(name,num);
-       return strdup(name);
-}
-
-int devname2devnum(char *name)
-{
-       char *ep;
-       int num;
-       if (strncmp(name, "md_d", 4)==0)
-               num = -1-strtoul(name+4, &ep, 10);
-       else
-               num = strtoul(name+2, &ep, 10);
-       return num;
-}
-
-int stat2devnum(struct stat *st)
-{
-       char path[30];
-       char link[200];
-       char *cp;
-       int n;
-
-       if ((S_IFMT & st->st_mode) == S_IFBLK) {
-               if (major(st->st_rdev) == MD_MAJOR)
-                       return minor(st->st_rdev);
-               else if (major(st->st_rdev) == (unsigned)get_mdp_major())
-                       return -1- (minor(st->st_rdev)>>MdpMinorShift);
-
-               /* must be an extended-minor partition. Look at the
-                * /sys/dev/block/%d:%d link which must look like
-                * ../../block/mdXXX/mdXXXpYY
-                */
-               sprintf(path, "/sys/dev/block/%d:%d", major(st->st_rdev),
-                       minor(st->st_rdev));
-               n = readlink(path, link, sizeof(link)-1);
-               if (n <= 0)
-                       return NoMdDev;
-               link[n] = 0;
-               cp = strrchr(link, '/');
-               if (cp) *cp = 0;
-               cp = strrchr(link, '/');
-               if (cp && strncmp(cp, "/md", 3) == 0)
-                       return devname2devnum(cp+1);
-       }
-       return NoMdDev;
-
-}
-
-int fd2devnum(int fd)
-{
-       struct stat stb;
-       if (fstat(fd, &stb) == 0)
-               return stat2devnum(&stb);
-       return NoMdDev;
-}
-
 int mdmon_pid(int devnum)
 {
        char path[100];