]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - util.c
Incremental: Remove redundant call for GET_ARRAY_INFO
[thirdparty/mdadm.git] / util.c
diff --git a/util.c b/util.c
index 818f8392177e4ff584067d8e9ffec2c30e98cb31..725877d105bb137658d30d598476a3102074f870 100644 (file)
--- a/util.c
+++ b/util.c
@@ -211,6 +211,15 @@ int cluster_release_dlmlock(int lockid)
 }
 #endif
 
+/*
+ * Get array info from the kernel. Longer term we want to deprecate the
+ * ioctl and get it from sysfs.
+ */
+int md_get_array_info(int fd, struct mdu_array_info_s *array)
+{
+       return ioctl(fd, GET_ARRAY_INFO, array);
+}
+
 /*
  * Parse a 128 bit uuid in 4 integers
  * format is 32 hexx nibbles with options :.<space> separator
@@ -539,8 +548,7 @@ int enough_fd(int fd)
        int i, rv;
        char *avail;
 
-       if (ioctl(fd, GET_ARRAY_INFO, &array) != 0 ||
-           array.raid_disks <= 0)
+       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++) {
@@ -811,7 +819,7 @@ unsigned long calc_csum(void *super, int bytes)
 #ifndef MDASSEMBLE
 char *human_size(long long bytes)
 {
-       static char buf[30];
+       static char buf[47];
 
        /* We convert bytes to either centi-M{ega,ibi}bytes or
         * centi-G{igi,ibi}bytes, with appropriate rounding,
@@ -828,14 +836,12 @@ char *human_size(long long bytes)
                long cMiB = (bytes * 200LL / (1LL<<20) + 1) / 2;
                long cMB  = (bytes / ( 1000000LL / 200LL ) +1) /2;
                snprintf(buf, sizeof(buf), " (%ld.%02ld MiB %ld.%02ld MB)",
-                       cMiB/100 , cMiB % 100,
-                       cMB/100, cMB % 100);
+                       cMiB/100, cMiB % 100, cMB/100, cMB % 100);
        } else {
                long cGiB = (bytes * 200LL / (1LL<<30) +1) / 2;
                long cGB  = (bytes / (1000000000LL/200LL ) +1) /2;
                snprintf(buf, sizeof(buf), " (%ld.%02ld GiB %ld.%02ld GB)",
-                       cGiB/100 , cGiB % 100,
-                       cGB/100, cGB % 100);
+                       cGiB/100, cGiB % 100, cGB/100, cGB % 100);
        }
        return buf;
 }
@@ -862,22 +868,22 @@ char *human_size_brief(long long bytes, int prefix)
                if (bytes < 2*1024LL*1024LL*1024LL) {
                        long cMiB = (bytes * 200LL / (1LL<<20) +1) /2;
                        snprintf(buf, sizeof(buf), "%ld.%02ldMiB",
-                               cMiB/100 , cMiB % 100);
+                                cMiB/100, cMiB % 100);
                } else {
                        long cGiB = (bytes * 200LL / (1LL<<30) +1) /2;
                        snprintf(buf, sizeof(buf), "%ld.%02ldGiB",
-                                       cGiB/100 , cGiB % 100);
+                                cGiB/100, cGiB % 100);
                }
        }
        else if (prefix == JEDEC) {
                if (bytes < 2*1024LL*1024LL*1024LL) {
                        long cMB  = (bytes / ( 1000000LL / 200LL ) +1) /2;
                        snprintf(buf, sizeof(buf), "%ld.%02ldMB",
-                                       cMB/100, cMB % 100);
+                                cMB/100, cMB % 100);
                } else {
                        long cGB  = (bytes / (1000000000LL/200LL ) +1) /2;
                        snprintf(buf, sizeof(buf), "%ld.%02ldGB",
-                                       cGB/100 , cGB % 100);
+                                cGB/100, cGB % 100);
                }
        }
        else
@@ -1093,7 +1099,7 @@ int open_dev_excl(char *devnm)
        long delay = 1000;
 
        sprintf(buf, "%d:%d", major(devid), minor(devid));
-       for (i = 0 ; i < 25 ; i++) {
+       for (i = 0; i < 25; i++) {
                int fd = dev_open(buf, flags|O_EXCL);
                if (fd >= 0)
                        return fd;
@@ -1134,7 +1140,7 @@ void wait_for(char *dev, int fd)
            (stb_want.st_mode & S_IFMT) != S_IFBLK)
                return;
 
-       for (i = 0 ; i < 25 ; i++) {
+       for (i = 0; i < 25; i++) {
                struct stat stb;
                if (stat(dev, &stb) == 0 &&
                    (stb.st_mode & S_IFMT) == S_IFBLK &&
@@ -1177,7 +1183,7 @@ struct supertype *super_by_fd(int fd, char **subarrayp)
                minor = sra->array.minor_version;
                verstr = sra->text_version;
        } else {
-               if (ioctl(fd, GET_ARRAY_INFO, &array))
+               if (md_get_array_info(fd, &array))
                        array.major_version = array.minor_version = 0;
                vers = array.major_version;
                minor = array.minor_version;
@@ -1205,7 +1211,7 @@ struct supertype *super_by_fd(int fd, char **subarrayp)
                        verstr = "-no-metadata-";
        }
 
-       for (i = 0; st == NULL && superlist[i] ; i++)
+       for (i = 0; st == NULL && superlist[i]; i++)
                st = superlist[i]->match_metadata_desc(verstr);
 
        sysfs_free(sra);
@@ -1270,7 +1276,7 @@ struct supertype *guess_super_type(int fd, enum guess_types guess_type)
        st = xcalloc(1, sizeof(*st));
        st->container_devnm[0] = 0;
 
-       for (i = 0 ; superlist[i]; i++) {
+       for (i = 0; superlist[i]; i++) {
                int rv;
                ss = superlist[i];
                if (guess_type == guess_array && ss->add_to_super == NULL)
@@ -1435,6 +1441,7 @@ static int get_last_partition_end(int fd, unsigned long long *endofpart)
        struct MBR boot_sect;
        unsigned long long curr_part_end;
        unsigned part_nr;
+       unsigned int sector_size;
        int retval = 0;
 
        *endofpart = 0;
@@ -1474,6 +1481,9 @@ static int get_last_partition_end(int fd, unsigned long long *endofpart)
                /* Unknown partition table */
                retval = -1;
        }
+       /* calculate number of 512-byte blocks */
+       if (get_dev_sector_size(fd, NULL, &sector_size))
+               *endofpart *= (sector_size / 512);
  abort:
        return retval;
 }
@@ -1485,9 +1495,8 @@ int check_partitions(int fd, char *dname, unsigned long long freesize,
         * Check where the last partition ends
         */
        unsigned long long endofpart;
-       int ret;
 
-       if ((ret = get_last_partition_end(fd, &endofpart)) > 0) {
+       if (get_last_partition_end(fd, &endofpart) > 0) {
                /* There appears to be a partition table here */
                if (freesize == 0) {
                        /* partitions will not be visible in new device */
@@ -1792,6 +1801,36 @@ int remove_disk(int mdfd, struct supertype *st,
        return rv;
 }
 
+int hot_remove_disk(int mdfd, unsigned long dev, int force)
+{
+       int cnt = force ? 500 : 5;
+       int ret;
+
+       /* HOT_REMOVE_DISK can fail with EBUSY if there are
+        * outstanding IO requests to the device.
+        * In this case, it can be helpful to wait a little while,
+        * up to 5 seconds if 'force' is set, or 50 msec if not.
+        */
+       while ((ret = ioctl(mdfd, HOT_REMOVE_DISK, dev)) == -1 &&
+              errno == EBUSY &&
+              cnt-- > 0)
+               usleep(10000);
+
+       return ret;
+}
+
+int sys_hot_remove_disk(int statefd, int force)
+{
+       int cnt = force ? 500 : 5;
+       int ret;
+
+       while ((ret = write(statefd, "remove", 6)) == -1 &&
+              errno == EBUSY &&
+              cnt-- > 0)
+               usleep(10000);
+       return ret == 6 ? 0 : -1;
+}
+
 int set_array_info(int mdfd, struct supertype *st, struct mdinfo *info)
 {
        /* Initialise kernel's knowledge of array.