]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - util.c
util: Code is 80 characters wide
[thirdparty/mdadm.git] / util.c
diff --git a/util.c b/util.c
index 56daee34c5b76c3195d52beb9064be200040492a..68af38193e117c6cfec5af40d67ccda348dbd1d3 100644 (file)
--- a/util.c
+++ b/util.c
@@ -89,7 +89,6 @@ int dlm_funs_ready(void)
        return is_dlm_hooks_ready ? 1 : 0;
 }
 
-#ifndef MDASSEMBLE
 static struct dlm_hooks *dlm_hooks = NULL;
 struct dlm_lock_resource *dlm_lock_res = NULL;
 static int ast_called = 0;
@@ -148,9 +147,9 @@ int cluster_get_dlmlock(int *lockid)
        }
 
        snprintf(str, 64, "bitmap%s", cluster_name);
-       ret = dlm_hooks->ls_lock(dlm_lock_res->ls, LKM_PWMODE, &dlm_lock_res->lksb,
-                         flags, str, strlen(str), 0, dlm_ast,
-                         dlm_lock_res, NULL, NULL);
+       ret = dlm_hooks->ls_lock(dlm_lock_res->ls, LKM_PWMODE,
+                                &dlm_lock_res->lksb, flags, str, strlen(str),
+                                0, dlm_ast, dlm_lock_res, NULL, NULL);
        if (ret) {
                pr_err("error %d when get PW mode on lock %s\n", errno, str);
                dlm_hooks->release_lockspace(cluster_name, dlm_lock_res->ls, 1);
@@ -184,7 +183,8 @@ int cluster_release_dlmlock(int lockid)
 
        errno = dlm_lock_res->lksb.sb_status;
        if (errno != EUNLOCK) {
-               pr_err("error %d happened in ast when unlock lockspace\n", errno);
+               pr_err("error %d happened in ast when unlock lockspace\n",
+                      errno);
                /* XXX make sure the lockspace is unlocked eventually */
                 goto out;
        }
@@ -200,16 +200,60 @@ int cluster_release_dlmlock(int lockid)
 out:
        return ret;
 }
-#else
-int cluster_get_dlmlock(int *lockid)
+
+int md_array_valid(int fd)
 {
-       return -1;
+       struct mdinfo *sra;
+       int ret;
+
+       sra = sysfs_read(fd, NULL, GET_ARRAY_STATE);
+       if (sra) {
+               if (sra->array_state != ARRAY_UNKNOWN_STATE)
+                       ret = 0;
+               else
+                       ret = -ENODEV;
+
+               free(sra);
+       } else {
+               /*
+                * GET_ARRAY_INFO doesn't provide access to the proper state
+                * information, so fallback to a basic check for raid_disks != 0
+                */
+               ret = ioctl(fd, RAID_VERSION);
+       }
+
+       return !ret;
 }
-int cluster_release_dlmlock(int lockid)
+
+int md_array_active(int fd)
 {
-       return -1;
+       struct mdinfo *sra;
+       struct mdu_array_info_s array;
+       int ret = 0;
+
+       sra = sysfs_read(fd, NULL, GET_ARRAY_STATE);
+       if (sra) {
+               if (!md_array_is_active(sra))
+                       ret = -ENODEV;
+
+               free(sra);
+       } else {
+               /*
+                * GET_ARRAY_INFO doesn't provide access to the proper state
+                * information, so fallback to a basic check for raid_disks != 0
+                */
+               ret = ioctl(fd, GET_ARRAY_INFO, &array);
+       }
+
+       return !ret;
+}
+
+int md_array_is_active(struct mdinfo *info)
+{
+       return (info->array_state != ARRAY_CLEAR &&
+               info->array_state != ARRAY_INACTIVE &&
+               info->array_state != ARRAY_UNKNOWN_STATE);
 }
-#endif
 
 /*
  * Get array info from the kernel. Longer term we want to deprecate the
@@ -273,35 +317,6 @@ int parse_uuid(char *str, int uuid[4])
        return 0;
 }
 
-/*
- * Get the md version number.
- * We use the RAID_VERSION ioctl if it is supported
- * If not, but we have a block device with major '9', we assume
- * 0.36.0
- *
- * Return version number as 24 but number - assume version parts
- * always < 255
- */
-
-int md_get_version(int fd)
-{
-       struct stat stb;
-       mdu_version_t vers;
-
-       if (fstat(fd, &stb)<0)
-               return -1;
-       if ((S_IFMT&stb.st_mode) != S_IFBLK)
-               return -1;
-
-       if (ioctl(fd, RAID_VERSION, &vers) == 0)
-               return  (vers.major*10000) + (vers.minor*100) + vers.patchlevel;
-       if (errno == EACCES)
-               return -1;
-       if (major(stb.st_rdev) == MD_MAJOR)
-               return (3600);
-       return -1;
-}
-
 int get_linux_version()
 {
        struct utsname name;
@@ -320,7 +335,6 @@ int get_linux_version()
        return (a*1000000)+(b*1000)+c;
 }
 
-#ifndef MDASSEMBLE
 int mdadm_version(char *version)
 {
        int a, b, c;
@@ -426,7 +440,6 @@ long parse_num(char *num)
        else
                return rv;
 }
-#endif
 
 int parse_cluster_confirm_arg(char *input, char **devname, int *slot)
 {
@@ -557,37 +570,6 @@ int enough(int level, int raid_disks, int layout, int clean, char *avail)
        }
 }
 
-int enough_fd(int fd)
-{
-       struct mdu_array_info_s array;
-       struct mdu_disk_info_s disk;
-       int i, rv;
-       char *avail;
-
-       if (md_get_array_info(fd, &array) != 0 || array.raid_disks <= 0)
-               return 0;
-       avail = xcalloc(array.raid_disks, 1);
-       for (i = 0; i < MAX_DISKS && array.nr_disks > 0; i++) {
-               disk.number = i;
-               if (md_get_disk_info(fd, &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)
-                       continue;
-               avail[disk.raid_disk] = 1;
-       }
-       /* This is used on an active array, so assume it is clean */
-       rv = enough(array.level, array.raid_disks, array.layout,
-                   1, avail);
-       free(avail);
-       return rv;
-}
-
 const int uuid_zero[4] = { 0, 0, 0, 0 };
 
 int same_uuid(int a[4], int b[4], int swapuuid)
@@ -658,17 +640,18 @@ char *__fname_from_uuid(int id[4], int swap, char *buf, char sep)
 
 }
 
-char *fname_from_uuid(struct supertype *st, struct mdinfo *info, char *buf, char sep)
+char *fname_from_uuid(struct supertype *st, struct mdinfo *info,
+                     char *buf, char sep)
 {
        // dirty hack to work around an issue with super1 superblocks...
        // super1 superblocks need swapuuid set in order for assembly to
        // work, but can't have it set if we want this printout to match
        // all the other uuid printouts in super1.c, so we force swapuuid
        // to 1 to make our printout match the rest of super1
-       return __fname_from_uuid(info->uuid, (st->ss == &super1) ? 1 : st->ss->swapuuid, buf, sep);
+       return __fname_from_uuid(info->uuid, (st->ss == &super1) ? 1 :
+                                st->ss->swapuuid, buf, sep);
 }
 
-#ifndef MDASSEMBLE
 int check_ext2(int fd, char *name)
 {
        /*
@@ -753,6 +736,40 @@ int check_raid(int fd, char *name)
        return 1;
 }
 
+int fstat_is_blkdev(int fd, char *devname, dev_t *rdev)
+{
+       struct stat stb;
+
+       if (fstat(fd, &stb) != 0) {
+               pr_err("fstat failed for %s: %s\n", devname, strerror(errno));
+               return 0;
+       }
+       if ((S_IFMT & stb.st_mode) != S_IFBLK) {
+               pr_err("%s is not a block device.\n", devname);
+               return 0;
+       }
+       if (rdev)
+               *rdev = stb.st_rdev;
+       return 1;
+}
+
+int stat_is_blkdev(char *devname, dev_t *rdev)
+{
+       struct stat stb;
+
+       if (stat(devname, &stb) != 0) {
+               pr_err("stat failed for %s: %s\n", devname, strerror(errno));
+               return 0;
+       }
+       if ((S_IFMT & stb.st_mode) != S_IFBLK) {
+               pr_err("%s is not a block device.\n", devname);
+               return 0;
+       }
+       if (rdev)
+               *rdev = stb.st_rdev;
+       return 1;
+}
+
 int ask(char *mesg)
 {
        char *add = "";
@@ -772,7 +789,6 @@ int ask(char *mesg)
        pr_err("assuming 'no'\n");
        return 0;
 }
-#endif /* MDASSEMBLE */
 
 int is_standard(char *dev, int *nump)
 {
@@ -832,7 +848,6 @@ unsigned long calc_csum(void *super, int bytes)
        return csum;
 }
 
-#ifndef MDASSEMBLE
 char *human_size(long long bytes)
 {
        static char buf[47];
@@ -924,7 +939,6 @@ void print_r10_layout(int layout)
        if (near*far == 1)
                printf("NO REDUNDANCY");
 }
-#endif
 
 unsigned long long calc_array_size(int level, int raid_disks, int layout,
                                   int chunksize, unsigned long long devsize)
@@ -991,7 +1005,6 @@ dev_t devnm2devid(char *devnm)
        return 0;
 }
 
-#if !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO)
 char *get_md_name(char *devnm)
 {
        /* find /dev/md%d or /dev/md/%d or make a device /dev/.tmp.md%d */
@@ -1007,21 +1020,18 @@ char *get_md_name(char *devnm)
        if (strncmp(devnm, "md_", 3) == 0) {
                snprintf(devname, sizeof(devname), "/dev/md/%s",
                        devnm + 3);
-               if (stat(devname, &stb) == 0
-                   && (S_IFMT&stb.st_mode) == S_IFBLK
-                   && (stb.st_rdev == rdev))
+               if (stat(devname, &stb) == 0 &&
+                   (S_IFMT&stb.st_mode) == S_IFBLK && (stb.st_rdev == rdev))
                        return devname;
        }
        snprintf(devname, sizeof(devname), "/dev/%s", devnm);
-       if (stat(devname, &stb) == 0
-           && (S_IFMT&stb.st_mode) == S_IFBLK
-           && (stb.st_rdev == rdev))
+       if (stat(devname, &stb) == 0 && (S_IFMT&stb.st_mode) == S_IFBLK &&
+           (stb.st_rdev == rdev))
                return devname;
 
        snprintf(devname, sizeof(devname), "/dev/md/%s", devnm+2);
-       if (stat(devname, &stb) == 0
-           && (S_IFMT&stb.st_mode) == S_IFBLK
-           && (stb.st_rdev == rdev))
+       if (stat(devname, &stb) == 0 && (S_IFMT&stb.st_mode) == S_IFBLK &&
+           (stb.st_rdev == rdev))
                return devname;
 
        dn = map_dev(major(rdev), minor(rdev), 0);
@@ -1032,9 +1042,8 @@ char *get_md_name(char *devnm)
                if (errno != EEXIST)
                        return NULL;
 
-       if (stat(devname, &stb) == 0
-           && (S_IFMT&stb.st_mode) == S_IFBLK
-           && (stb.st_rdev == rdev))
+       if (stat(devname, &stb) == 0 && (S_IFMT&stb.st_mode) == S_IFBLK &&
+           (stb.st_rdev == rdev))
                return devname;
        unlink(devname);
        return NULL;
@@ -1045,7 +1054,6 @@ void put_md_name(char *name)
        if (strncmp(name, "/dev/.tmp.md", 12) == 0)
                unlink(name);
 }
-#endif /* !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO) */
 
 int get_maj_min(char *dev, int *major, int *minor)
 {
@@ -1079,9 +1087,11 @@ int dev_open(char *dev, int flags)
                }
                if (fd < 0) {
                        /* Try /tmp as /dev appear to be read-only */
-                       snprintf(devname, sizeof(devname), "/tmp/.tmp.md.%d:%d:%d",
+                       snprintf(devname, sizeof(devname),
+                                "/tmp/.tmp.md.%d:%d:%d",
                                 (int)getpid(), major, minor);
-                       if (mknod(devname, S_IFBLK|0600, makedev(major, minor)) == 0) {
+                       if (mknod(devname, S_IFBLK|0600,
+                                 makedev(major, minor)) == 0) {
                                fd = open(devname, flags);
                                unlink(devname);
                        }
@@ -1167,7 +1177,7 @@ void wait_for(char *dev, int fd)
                        delay *= 2;
        }
        if (i == 25)
-               dprintf("timeout waiting for %s\n", dev);
+               pr_err("timeout waiting for %s\n", dev);
 }
 
 struct superswitch *superlist[] =
@@ -1175,9 +1185,8 @@ struct superswitch *superlist[] =
        &super0, &super1,
        &super_ddf, &super_imsm,
        &mbr, &gpt,
-       NULL };
-
-#if !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO)
+       NULL
+};
 
 struct supertype *super_by_fd(int fd, char **subarrayp)
 {
@@ -1242,7 +1251,6 @@ struct supertype *super_by_fd(int fd, char **subarrayp)
 
        return st;
 }
-#endif /* !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO) */
 
 int dev_size_from_id(dev_t id, unsigned long long *size)
 {
@@ -1261,6 +1269,23 @@ int dev_size_from_id(dev_t id, unsigned long long *size)
        return 0;
 }
 
+int dev_sector_size_from_id(dev_t id, unsigned int *size)
+{
+       char buf[20];
+       int fd;
+
+       sprintf(buf, "%d:%d", major(id), minor(id));
+       fd = dev_open(buf, O_RDONLY);
+       if (fd < 0)
+               return 0;
+       if (get_dev_sector_size(fd, NULL, size)) {
+               close(fd);
+               return 1;
+       }
+       close(fd);
+       return 0;
+}
+
 struct supertype *dup_super(struct supertype *orig)
 {
        struct supertype *st;
@@ -1782,7 +1807,7 @@ int add_disk(int mdfd, struct supertype *st,
 {
        /* Add a device to an array, in one of 2 ways. */
        int rv;
-#ifndef MDASSEMBLE
+
        if (st->ss->external) {
                if (info->disk.state & (1<<MD_DISK_SYNC))
                        info->recovery_start = MaxSector;
@@ -1802,7 +1827,6 @@ int add_disk(int mdfd, struct supertype *st,
                        }
                }
        } else
-#endif
                rv = ioctl(mdfd, ADD_NEW_DISK, &info->disk);
        return rv;
 }
@@ -1811,12 +1835,11 @@ int remove_disk(int mdfd, struct supertype *st,
                struct mdinfo *sra, struct mdinfo *info)
 {
        int rv;
+
        /* Remove the disk given by 'info' from the array */
-#ifndef MDASSEMBLE
        if (st->ss->external)
                rv = sysfs_set_str(sra, info, "slot", "none");
        else
-#endif
                rv = ioctl(mdfd, HOT_REMOVE_DISK, makedev(info->disk.major,
                                                          info->disk.minor));
        return rv;
@@ -1858,22 +1881,17 @@ int set_array_info(int mdfd, struct supertype *st, struct mdinfo *info)
         * This varies between externally managed arrays
         * and older kernels
         */
-       int vers = md_get_version(mdfd);
+       mdu_array_info_t inf;
        int rv;
 
-#ifndef MDASSEMBLE
        if (st->ss->external)
-               rv = sysfs_set_array(info, vers);
-       else
-#endif
-               if ((vers % 100) >= 1) { /* can use different versions */
-               mdu_array_info_t inf;
-               memset(&inf, 0, sizeof(inf));
-               inf.major_version = info->array.major_version;
-               inf.minor_version = info->array.minor_version;
-               rv = md_set_array_info(mdfd, &inf);
-       } else
-               rv = md_set_array_info(mdfd, NULL);
+               return sysfs_set_array(info, 9003);
+               
+       memset(&inf, 0, sizeof(inf));
+       inf.major_version = info->array.major_version;
+       inf.minor_version = info->array.minor_version;
+       rv = md_set_array_info(mdfd, &inf);
+
        return rv;
 }
 
@@ -2047,7 +2065,6 @@ use_random:
        memcpy(buf, r, 16);
 }
 
-#ifndef MDASSEMBLE
 int flush_metadata_updates(struct supertype *st)
 {
        int sfd;
@@ -2089,7 +2106,6 @@ void append_metadata_update(struct supertype *st, void *buf, int len)
        *st->update_tail = mu;
        st->update_tail = &mu->next;
 }
-#endif /* MDASSEMBLE */
 
 #ifdef __TINYC__
 /* tinyc doesn't optimize this check in ioctl.h out ... */
@@ -2112,7 +2128,7 @@ int experimental(void)
  * if spare_group given add it to domains of each spare
  * metadata allows to test domains using metadata of destination array */
 struct mdinfo *container_choose_spares(struct supertype *st,
-                                      unsigned long long min_size,
+                                      struct spare_criteria *criteria,
                                       struct domainlist *domlist,
                                       char *spare_group,
                                       const char *metadata, int get_one)
@@ -2134,12 +2150,24 @@ struct mdinfo *container_choose_spares(struct supertype *st,
                if (d->disk.state == 0) {
                        /* check if size is acceptable */
                        unsigned long long dev_size;
+                       unsigned int dev_sector_size;
+                       int size_valid = 0;
+                       int sector_size_valid = 0;
+
                        dev_t dev = makedev(d->disk.major,d->disk.minor);
 
-                       if (!min_size ||
+                       if (!criteria->min_size ||
                           (dev_size_from_id(dev,  &dev_size) &&
-                           dev_size >= min_size))
-                               found = 1;
+                           dev_size >= criteria->min_size))
+                               size_valid = 1;
+
+                       if (!criteria->sector_size ||
+                           (dev_sector_size_from_id(dev, &dev_sector_size) &&
+                            criteria->sector_size == dev_sector_size))
+                               sector_size_valid = 1;
+
+                       found = size_valid && sector_size_valid;
+
                        /* check if domain matches */
                        if (found && domlist) {
                                struct dev_policy *pol = devid_policy(dev);
@@ -2193,8 +2221,7 @@ void enable_fds(int devices)
 {
        unsigned int fds = 20 + devices;
        struct rlimit lim;
-       if (getrlimit(RLIMIT_NOFILE, &lim) != 0
-           || lim.rlim_cur >= fds)
+       if (getrlimit(RLIMIT_NOFILE, &lim) != 0 || lim.rlim_cur >= fds)
                return;
        if (lim.rlim_max < fds)
                lim.rlim_max = fds;
@@ -2229,7 +2256,6 @@ void reopen_mddev(int mdfd)
                dup2(fd, mdfd);
 }
 
-#ifndef MDASSEMBLE
 static struct cmap_hooks *cmap_hooks = NULL;
 static int is_cmap_hooks_ready = 0;
 
@@ -2240,8 +2266,10 @@ void set_cmap_hooks(void)
        if (!cmap_hooks->cmap_handle)
                return;
 
-       cmap_hooks->initialize = dlsym(cmap_hooks->cmap_handle, "cmap_initialize");
-       cmap_hooks->get_string = dlsym(cmap_hooks->cmap_handle, "cmap_get_string");
+       cmap_hooks->initialize =
+               dlsym(cmap_hooks->cmap_handle, "cmap_initialize");
+       cmap_hooks->get_string =
+               dlsym(cmap_hooks->cmap_handle, "cmap_get_string");
        cmap_hooks->finalize = dlsym(cmap_hooks->cmap_handle, "cmap_finalize");
 
        if (!cmap_hooks->initialize || !cmap_hooks->get_string ||
@@ -2284,8 +2312,10 @@ void set_dlm_hooks(void)
        if (!dlm_hooks->dlm_handle)
                return;
 
-       dlm_hooks->create_lockspace = dlsym(dlm_hooks->dlm_handle, "dlm_create_lockspace");
-       dlm_hooks->release_lockspace = dlsym(dlm_hooks->dlm_handle, "dlm_release_lockspace");
+       dlm_hooks->create_lockspace =
+               dlsym(dlm_hooks->dlm_handle, "dlm_create_lockspace");
+       dlm_hooks->release_lockspace =
+               dlsym(dlm_hooks->dlm_handle, "dlm_release_lockspace");
        dlm_hooks->ls_lock = dlsym(dlm_hooks->dlm_handle, "dlm_ls_lock");
        dlm_hooks->ls_unlock = dlsym(dlm_hooks->dlm_handle, "dlm_ls_unlock");
        dlm_hooks->ls_get_fd = dlsym(dlm_hooks->dlm_handle, "dlm_ls_get_fd");
@@ -2304,4 +2334,3 @@ void set_hooks(void)
        set_dlm_hooks();
        set_cmap_hooks();
 }
-#endif