]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - util.c
change back 0644 permission for Grow.c
[thirdparty/mdadm.git] / util.c
diff --git a/util.c b/util.c
index 970d48476e86044843fe8769b4993af2423cc6d8..21a63c9a638ca9e6bbb6d5a1b2ea4b5e6d3efaa5 100644 (file)
--- a/util.c
+++ b/util.c
@@ -24,7 +24,6 @@
 
 #include       "mdadm.h"
 #include       "md_p.h"
-#include       <sys/poll.h>
 #include       <sys/socket.h>
 #include       <sys/utsname.h>
 #include       <sys/wait.h>
@@ -32,6 +31,7 @@
 #include       <sys/resource.h>
 #include       <sys/vfs.h>
 #include       <linux/magic.h>
+#include       <poll.h>
 #include       <ctype.h>
 #include       <dirent.h>
 #include       <signal.h>
@@ -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;
@@ -147,13 +146,7 @@ int cluster_get_dlmlock(int *lockid)
                return -ENOMEM;
        }
 
-       /* Conversions need the lockid in the LKSB */
-       if (flags & LKF_CONVERT)
-               dlm_lock_res->lksb.sb_lkid = *lockid;
-
        snprintf(str, 64, "bitmap%s", cluster_name);
-       /* if flags with LKF_CONVERT causes below return ENOENT which means
-        * "No such file or directory" */
        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);
@@ -177,8 +170,6 @@ int cluster_release_dlmlock(int lockid)
        if (!cluster_name)
                return -1;
 
-       /* if flags with LKF_CONVERT causes below return EINVAL which means
-        * "Invalid argument" */
        ret = dlm_hooks->ls_unlock(dlm_lock_res->ls, lockid, 0,
                                     &dlm_lock_res->lksb, dlm_lock_res);
        if (ret) {
@@ -208,16 +199,58 @@ int cluster_release_dlmlock(int lockid)
 out:
        return ret;
 }
-#else
-int cluster_get_dlmlock(int *lockid)
+
+int md_array_active(int fd)
 {
-       return -1;
+       struct mdinfo *sra;
+       struct mdu_array_info_s array;
+       int ret;
+
+       sra = sysfs_read(fd, NULL, GET_ARRAY_STATE);
+       if (sra) {
+               if (sra->array_state != ARRAY_CLEAR &&
+                   sra->array_state != ARRAY_INACTIVE &&
+                   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, GET_ARRAY_INFO, &array);
+       }
+
+       return !ret;
 }
-int cluster_release_dlmlock(int lockid)
+
+/*
+ * 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 -1;
+       return ioctl(fd, GET_ARRAY_INFO, array);
+}
+
+/*
+ * Set array info
+ */
+int md_set_array_info(int fd, struct mdu_array_info_s *array)
+{
+       return ioctl(fd, SET_ARRAY_INFO, array);
+}
+
+/*
+ * Get disk info from the kernel.
+ */
+int md_get_disk_info(int fd, struct mdu_disk_info_s *disk)
+{
+       return ioctl(fd, GET_DISK_INFO, disk);
 }
-#endif
 
 /*
  * Parse a 128 bit uuid in 4 integers
@@ -256,35 +289,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;
@@ -303,7 +307,6 @@ int get_linux_version()
        return (a*1000000)+(b*1000)+c;
 }
 
-#ifndef MDASSEMBLE
 int mdadm_version(char *version)
 {
        int a, b, c;
@@ -409,7 +412,6 @@ long parse_num(char *num)
        else
                return rv;
 }
-#endif
 
 int parse_cluster_confirm_arg(char *input, char **devname, int *slot)
 {
@@ -540,38 +542,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 (ioctl(fd, GET_ARRAY_INFO, &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 (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)
-                       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)
@@ -652,7 +622,6 @@ char *fname_from_uuid(struct supertype *st, struct mdinfo *info, char *buf, char
        return __fname_from_uuid(info->uuid, (st->ss == &super1) ? 1 : st->ss->swapuuid, buf, sep);
 }
 
-#ifndef MDASSEMBLE
 int check_ext2(int fd, char *name)
 {
        /*
@@ -718,17 +687,22 @@ int check_raid(int fd, char *name)
 
        if (!st)
                return 0;
-       st->ss->load_super(st, fd, name);
-       /* Looks like a raid array .. */
-       pr_err("%s appears to be part of a raid array:\n",
-               name);
-       st->ss->getinfo_super(st, &info, NULL);
-       st->ss->free_super(st);
-       crtime = info.array.ctime;
-       level = map_num(pers, info.array.level);
-       if (!level) level = "-unknown-";
-       cont_err("level=%s devices=%d ctime=%s",
-                level, info.array.raid_disks, ctime(&crtime));
+       if (st->ss->add_to_super != NULL) {
+               st->ss->load_super(st, fd, name);
+               /* Looks like a raid array .. */
+               pr_err("%s appears to be part of a raid array:\n", name);
+               st->ss->getinfo_super(st, &info, NULL);
+               st->ss->free_super(st);
+               crtime = info.array.ctime;
+               level = map_num(pers, info.array.level);
+               if (!level)
+                       level = "-unknown-";
+               cont_err("level=%s devices=%d ctime=%s",
+                       level, info.array.raid_disks, ctime(&crtime));
+       } else {
+               /* Looks like GPT or MBR */
+               pr_err("partition table exists on %s\n", name);
+       }
        return 1;
 }
 
@@ -751,7 +725,6 @@ int ask(char *mesg)
        pr_err("assuming 'no'\n");
        return 0;
 }
-#endif /* MDASSEMBLE */
 
 int is_standard(char *dev, int *nump)
 {
@@ -811,10 +784,9 @@ unsigned long calc_csum(void *super, int bytes)
        return csum;
 }
 
-#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,
@@ -831,14 +803,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;
 }
@@ -865,22 +835,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
@@ -905,7 +875,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)
@@ -936,7 +905,7 @@ int get_data_disks(int level, int layout, int raid_disks)
        return data_disks;
 }
 
-int devnm2devid(char *devnm)
+dev_t devnm2devid(char *devnm)
 {
        /* First look in /sys/block/$DEVNM/dev for %d:%d
         * If that fails, try parsing out a number
@@ -972,7 +941,6 @@ int 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 */
@@ -1026,7 +994,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)
 {
@@ -1047,7 +1014,8 @@ int dev_open(char *dev, int flags)
        int major;
        int minor;
 
-       if (!dev) return -1;
+       if (!dev)
+               return -1;
        flags |= O_DIRECT;
 
        if (get_maj_min(dev, &major, &minor)) {
@@ -1073,7 +1041,7 @@ int dev_open(char *dev, int flags)
 
 int open_dev_flags(char *devnm, int flags)
 {
-       int devid;
+       dev_t devid;
        char buf[20];
 
        devid = devnm2devid(devnm);
@@ -1091,11 +1059,11 @@ int open_dev_excl(char *devnm)
        char buf[20];
        int i;
        int flags = O_RDWR;
-       int devid = devnm2devid(devnm);
+       dev_t devid = devnm2devid(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;
@@ -1136,7 +1104,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 &&
@@ -1155,9 +1123,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)
 {
@@ -1179,7 +1146,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;
@@ -1199,8 +1166,7 @@ struct supertype *super_by_fd(int fd, char **subarrayp)
                        subarray = xstrdup(subarray);
                }
                strcpy(container, dev);
-               if (sra)
-                       sysfs_free(sra);
+               sysfs_free(sra);
                sra = sysfs_read(-1, container, GET_VERSION);
                if (sra && sra->text_version[0])
                        verstr = sra->text_version;
@@ -1208,11 +1174,10 @@ 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);
 
-       if (sra)
-               sysfs_free(sra);
+       sysfs_free(sra);
        if (st) {
                st->sb = NULL;
                if (subarrayp)
@@ -1224,7 +1189,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)
 {
@@ -1267,14 +1231,14 @@ struct supertype *guess_super_type(int fd, enum guess_types guess_type)
         */
        struct superswitch  *ss;
        struct supertype *st;
-       time_t besttime = 0;
+       unsigned int besttime = 0;
        int bestsuper = -1;
        int i;
 
        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)
@@ -1328,7 +1292,7 @@ int get_dev_size(int fd, char *dname, unsigned long long *sizep)
                        ldsize <<= 9;
                } else {
                        if (dname)
-                               pr_err("Cannot get size of %s: %s\b",
+                               pr_err("Cannot get size of %s: %s\n",
                                        dname, strerror(errno));
                        return 0;
                }
@@ -1337,14 +1301,35 @@ int get_dev_size(int fd, char *dname, unsigned long long *sizep)
        return 1;
 }
 
+/* Return sector size of device in bytes */
+int get_dev_sector_size(int fd, char *dname, unsigned int *sectsizep)
+{
+       unsigned int sectsize;
+
+       if (ioctl(fd, BLKSSZGET, &sectsize) != 0) {
+               if (dname)
+                       pr_err("Cannot get sector size of %s: %s\n",
+                               dname, strerror(errno));
+               return 0;
+       }
+
+       *sectsizep = sectsize;
+       return 1;
+}
+
 /* Return true if this can only be a container, not a member device.
  * i.e. is and md device and size is zero
  */
 int must_be_container(int fd)
 {
+       struct mdinfo *mdi;
        unsigned long long size;
-       if (md_get_version(fd) < 0)
+
+       mdi = sysfs_read(fd, NULL, GET_VERSION);
+       if (!mdi)
                return 0;
+       sysfs_free(mdi);
+
        if (get_dev_size(fd, NULL, &size) == 0)
                return 1;
        if (size == 0)
@@ -1366,12 +1351,15 @@ static int get_gpt_last_partition_end(int fd, unsigned long long *endofpart)
        unsigned long long curr_part_end;
        unsigned all_partitions, entry_size;
        unsigned part_nr;
+       unsigned int sector_size = 0;
 
        *endofpart = 0;
 
        BUILD_BUG_ON(sizeof(gpt) != 512);
        /* skip protective MBR */
-       lseek(fd, 512, SEEK_SET);
+       if (!get_dev_sector_size(fd, NULL, &sector_size))
+               return 0;
+       lseek(fd, sector_size, SEEK_SET);
        /* read GPT header */
        if (read(fd, &gpt, 512) != 512)
                return 0;
@@ -1391,6 +1379,8 @@ static int get_gpt_last_partition_end(int fd, unsigned long long *endofpart)
 
        part = (struct GPT_part_entry *)buf;
 
+       /* set offset to third block (GPT entries) */
+       lseek(fd, sector_size*2, SEEK_SET);
        for (part_nr = 0; part_nr < all_partitions; part_nr++) {
                /* read partition entry */
                if (read(fd, buf, entry_size) != (ssize_t)entry_size)
@@ -1416,9 +1406,9 @@ static int get_gpt_last_partition_end(int fd, unsigned long long *endofpart)
 static int get_last_partition_end(int fd, unsigned long long *endofpart)
 {
        struct MBR boot_sect;
-       struct MBR_part_record *part;
        unsigned long long curr_part_end;
        unsigned part_nr;
+       unsigned int sector_size;
        int retval = 0;
 
        *endofpart = 0;
@@ -1433,26 +1423,34 @@ static int get_last_partition_end(int fd, unsigned long long *endofpart)
        if (boot_sect.magic == MBR_SIGNATURE_MAGIC) {
                retval = 1;
                /* found the correct signature */
-               part = boot_sect.parts;
 
                for (part_nr = 0; part_nr < MBR_PARTITIONS; part_nr++) {
+                       /*
+                        * Have to make every access through boot_sect rather
+                        * than using a pointer to the partition table (or an
+                        * entry), since the entries are not properly aligned.
+                        */
+
                        /* check for GPT type */
-                       if (part->part_type == MBR_GPT_PARTITION_TYPE) {
+                       if (boot_sect.parts[part_nr].part_type ==
+                           MBR_GPT_PARTITION_TYPE) {
                                retval = get_gpt_last_partition_end(fd, endofpart);
                                break;
                        }
                        /* check the last used lba for the current partition  */
-                       curr_part_end = __le32_to_cpu(part->first_sect_lba) +
-                               __le32_to_cpu(part->blocks_num);
+                       curr_part_end =
+                               __le32_to_cpu(boot_sect.parts[part_nr].first_sect_lba) +
+                               __le32_to_cpu(boot_sect.parts[part_nr].blocks_num);
                        if (curr_part_end > *endofpart)
                                *endofpart = curr_part_end;
-
-                       part++;
                }
        } else {
                /* 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;
 }
@@ -1464,9 +1462,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 */
@@ -1731,7 +1728,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;
@@ -1751,7 +1748,6 @@ int add_disk(int mdfd, struct supertype *st,
                        }
                }
        } else
-#endif
                rv = ioctl(mdfd, ADD_NEW_DISK, &info->disk);
        return rv;
 }
@@ -1760,39 +1756,63 @@ 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;
 }
 
+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.
         * 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 = ioctl(mdfd, SET_ARRAY_INFO, &inf);
-       } else
-               rv = ioctl(mdfd, SET_ARRAY_INFO, 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;
 }
 
@@ -1945,7 +1965,27 @@ __u32 random32(void)
        return rv;
 }
 
-#ifndef MDASSEMBLE
+void random_uuid(__u8 *buf)
+{
+       int fd, i, len;
+       __u32 r[4];
+
+       fd = open("/dev/urandom", O_RDONLY);
+       if (fd < 0)
+               goto use_random;
+       len = read(fd, buf, 16);
+       close(fd);
+       if (len != 16)
+               goto use_random;
+
+       return;
+
+use_random:
+       for (i = 0; i < 4; i++)
+               r[i] = random();
+       memcpy(buf, r, 16);
+}
+
 int flush_metadata_updates(struct supertype *st)
 {
        int sfd;
@@ -1987,7 +2027,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 ... */
@@ -2127,7 +2166,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;
 
@@ -2202,4 +2240,3 @@ void set_hooks(void)
        set_dlm_hooks();
        set_cmap_hooks();
 }
-#endif