]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - util.c
Create arrays via metadata-update
[thirdparty/mdadm.git] / util.c
diff --git a/util.c b/util.c
index 08c6bb0b0e977acbb8c2bba724a96f456b1e58cd..49c36a06cafb43127e5be0214db8f87c4e6c6038 100644 (file)
--- a/util.c
+++ b/util.c
@@ -29,7 +29,9 @@
 
 #include       "mdadm.h"
 #include       "md_p.h"
+#include       <sys/socket.h>
 #include       <sys/utsname.h>
+#include       <sys/un.h>
 #include       <ctype.h>
 #include       <dirent.h>
 #include       <signal.h>
@@ -788,8 +790,6 @@ struct superswitch *superlist[] = { &super0, &super1, &super_ddf, &super_imsm, N
 
 #if !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO)
 
-struct supertype supertype_container_member;
-
 struct supertype *super_by_fd(int fd)
 {
        mdu_array_info_t array;
@@ -800,6 +800,7 @@ struct supertype *super_by_fd(int fd)
        char *verstr;
        char version[20];
        int i;
+       char *subarray = NULL;
 
        sra = sysfs_read(fd, 0, GET_VERSION);
 
@@ -819,16 +820,37 @@ struct supertype *super_by_fd(int fd)
                sprintf(version, "%d.%d", vers, minor);
                verstr = version;
        }
-       if (minor == -2 && verstr[0] == '/')
-               st = &supertype_container_member;
-       else
-               for (i = 0; st == NULL && superlist[i] ; i++)
-                       st = superlist[i]->match_metadata_desc(verstr);
+       if (minor == -2 && verstr[0] == '/') {
+               char *dev = verstr+1;
+               subarray = strchr(dev, '/');
+               int devnum;
+               if (subarray)
+                       *subarray++ = '\0';
+               if (strncmp(dev, "md_d", 4) == 0)
+                       devnum = -1-atoi(dev+4);
+               else
+                       devnum = atoi(dev+2);
+               subarray = strdup(subarray);
+               if (sra)
+                       sysfs_free(sra);
+               sra = sysfs_read(-1, devnum, GET_VERSION);
+               verstr = sra->text_version ? : "-no-metadata-";
+       }
+
+       for (i = 0; st == NULL && superlist[i] ; i++)
+               st = superlist[i]->match_metadata_desc(verstr);
 
        if (sra)
                sysfs_free(sra);
-       if (st)
+       if (st) {
                st->sb = NULL;
+               if (subarray) {
+                       strncpy(st->subarray, subarray, 32);
+                       st->subarray[31] = 0;
+                       free(subarray);
+               } else
+                       st->subarray[0] = 0;
+       }
        return st;
 }
 #endif /* !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO) */
@@ -838,6 +860,8 @@ struct supertype *dup_super(struct supertype *orig)
 {
        struct supertype *st;
 
+       if (!orig)
+               return orig;
        st = malloc(sizeof(*st));
        if (!st)
                return st;
@@ -845,6 +869,7 @@ struct supertype *dup_super(struct supertype *orig)
        st->ss = orig->ss;
        st->max_devs = orig->max_devs;
        st->minor_version = orig->minor_version;
+       strcpy(st->subarray, orig->subarray);
        st->sb = NULL;
        st->info = NULL;
        return st;
@@ -1042,6 +1067,47 @@ int signal_mdmon(int devnum)
 }
 
 
+int flush_metadata_updates(struct supertype *st)
+{
+       int sfd;
+       if (!st->updates) {
+               st->update_tail = NULL;
+               return -1;
+       }
+
+       sfd = connect_monitor(devnum2devname(st->container_dev));
+       if (sfd < 0)
+               return -1;
+
+       while (st->updates) {
+               struct metadata_update *mu = st->updates;
+               st->updates = mu->next;
+
+               send_message(sfd, mu, 0);
+               wait_reply(sfd, 0);
+               free(mu->buf);
+               free(mu);
+       }
+       ack(sfd, 0);
+       wait_reply(sfd, 0);
+       close(sfd);
+       st->update_tail = NULL;
+       return 0;
+}
+
+void append_metadata_update(struct supertype *st, void *buf, int len)
+{
+
+       struct metadata_update *mu = malloc(sizeof(*mu));
+
+       mu->buf = buf;
+       mu->len = len;
+       mu->space = NULL;
+       mu->next = NULL;
+       *st->update_tail = mu;
+       st->update_tail = &mu->next;
+}
+
 
 #ifdef __TINYC__
 /* tinyc doesn't optimize this check in ioctl.h out ... */