]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Detail.c
Create.c: fix uclibc build
[thirdparty/mdadm.git] / Detail.c
index 24fa462e76c0124032e13a5709a7e41da9043227..55a086d3378ff2172d307c0ad3ecf0bdb01f531a 100644 (file)
--- a/Detail.c
+++ b/Detail.c
@@ -49,6 +49,30 @@ static int add_device(const char *dev, char ***p_devices,
        return n_devices + 1;
 }
 
+/**
+ * detail_fname_from_uuid() - generate uuid string with special super1 handling.
+ * @mp: map entry to parse.
+ * @buf: buf to write.
+ *
+ * Hack to workaround an issue with super1 superblocks. It 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.
+ *
+ * Always convert uuid if host is big endian.
+ */
+char *detail_fname_from_uuid(struct map_ent *mp, char *buf)
+{
+#if __BYTE_ORDER == BIG_ENDIAN
+       bool swap = true;
+#else
+       bool swap = false;
+#endif
+       if (strncmp(mp->metadata, "1.", 2) == 0)
+               swap = true;
+
+       return __fname_from_uuid(mp->uuid, swap, buf, ':');
+}
+
 int Detail(char *dev, struct context *c)
 {
        /*
@@ -66,11 +90,11 @@ int Detail(char *dev, struct context *c)
        int spares = 0;
        struct stat stb;
        int failed = 0;
-       struct supertype *st;
+       struct supertype *st = NULL;
        char *subarray = NULL;
        int max_disks = MD_SB_DISKS; /* just a default */
        struct mdinfo *info = NULL;
-       struct mdinfo *sra;
+       struct mdinfo *sra = NULL;
        struct mdinfo *subdev;
        char *member = NULL;
        char *container = NULL;
@@ -93,8 +117,7 @@ int Detail(char *dev, struct context *c)
        if (!sra) {
                if (md_get_array_info(fd, &array)) {
                        pr_err("%s does not appear to be an md device\n", dev);
-                       close(fd);
-                       return rv;
+                       goto out;
                }
        }
        external = (sra != NULL && sra->array.major_version == -1 &&
@@ -108,16 +131,13 @@ int Detail(char *dev, struct context *c)
                            sra->devs == NULL) {
                                pr_err("Array associated with md device %s does not exist.\n",
                                       dev);
-                               close(fd);
-                               sysfs_free(sra);
-                               return rv;
+                               goto out;
                        }
                        array = sra->array;
                } else {
                        pr_err("cannot get array detail for %s: %s\n",
                               dev, strerror(errno));
-                       close(fd);
-                       return rv;
+                       goto out;
                }
        }
 
@@ -224,9 +244,15 @@ int Detail(char *dev, struct context *c)
        }
 
        /* Ok, we have some info to print... */
-       str = map_num(pers, array.level);
+       if (inactive && info)
+               str = map_num(pers, info->array.level);
+       else
+               str = map_num(pers, array.level);
 
        if (c->export) {
+               char nbuf[64];
+               struct map_ent *mp = NULL, *map = NULL;
+
                if (array.raid_disks) {
                        if (str)
                                printf("MD_LEVEL=%s\n", str);
@@ -248,38 +274,22 @@ int Detail(char *dev, struct context *c)
                                       array.minor_version);
                }
 
-               if (st && st->sb && info) {
-                       char nbuf[64];
-                       struct map_ent *mp, *map = NULL;
+               if (info)
+                       mp = map_by_uuid(&map, info->uuid);
+               if (!mp)
+                       mp = map_by_devnm(&map, fd2devnm(fd));
 
-                       fname_from_uuid(st, info, nbuf, ':');
+               if (mp) {
+                       detail_fname_from_uuid(mp, nbuf);
                        printf("MD_UUID=%s\n", nbuf + 5);
-                       mp = map_by_uuid(&map, info->uuid);
-                       if (mp && mp->path &&
-                           strncmp(mp->path, "/dev/md/", 8) == 0) {
-                               printf("MD_DEVNAME=");
-                               print_escape(mp->path + 8);
-                               putchar('\n');
-                       }
+                       if (mp->path && strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0)
+                               printf("MD_DEVNAME=%s\n", mp->path + DEV_MD_DIR_LEN);
+               }
 
+               map_free(map);
+               if (st && st->sb) {
                        if (st->ss->export_detail_super)
                                st->ss->export_detail_super(st);
-                       map_free(map);
-               } else {
-                       struct map_ent *mp, *map = NULL;
-                       char nbuf[64];
-                       mp = map_by_devnm(&map, fd2devnm(fd));
-                       if (mp) {
-                               __fname_from_uuid(mp->uuid, 0, nbuf, ':');
-                               printf("MD_UUID=%s\n", nbuf+5);
-                       }
-                       if (mp && mp->path &&
-                           strncmp(mp->path, "/dev/md/", 8) == 0) {
-                               printf("MD_DEVNAME=");
-                               print_escape(mp->path+8);
-                               putchar('\n');
-                       }
-                       map_free(map);
                }
                if (!c->no_devices && sra) {
                        struct mdinfo *mdi;
@@ -304,6 +314,7 @@ int Detail(char *dev, struct context *c)
                                if (path)
                                        printf("MD_DEVICE_%s_DEV=%s\n",
                                               sysdev, path);
+                               free(sysdev);
                        }
                }
                goto out;
@@ -352,9 +363,14 @@ int Detail(char *dev, struct context *c)
        avail = xcalloc(array.raid_disks, 1);
 
        for (d = 0; d < array.raid_disks; d++) {
-
-               if ((disks[d*2].state & (1<<MD_DISK_SYNC)) ||
-                   (disks[d*2+1].state & (1<<MD_DISK_SYNC))) {
+               char dv[PATH_MAX], dv_rep[PATH_MAX];
+               snprintf(dv, PATH_MAX, "/sys/dev/block/%d:%d",
+                       disks[d*2].major, disks[d*2].minor);
+               snprintf(dv_rep, PATH_MAX, "/sys/dev/block/%d:%d",
+                       disks[d*2+1].major, disks[d*2+1].minor);
+
+               if ((is_dev_alive(dv) && (disks[d*2].state & (1<<MD_DISK_SYNC))) ||
+                   (is_dev_alive(dv_rep) && (disks[d*2+1].state & (1<<MD_DISK_SYNC)))) {
                        avail_disks ++;
                        avail[d] = 1;
                } else
@@ -468,7 +484,9 @@ int Detail(char *dev, struct context *c)
                if (ioctl(fd, GET_BITMAP_FILE, &bmf) == 0 && bmf.pathname[0]) {
                        printf("     Intent Bitmap : %s\n", bmf.pathname);
                        printf("\n");
-               } else if (array.state & (1<<MD_SB_BITMAP_PRESENT))
+               } else if (array.state & (1<<MD_SB_CLUSTERED))
+                       printf("     Intent Bitmap : Internal(Clustered)\n\n");
+               else if (array.state & (1<<MD_SB_BITMAP_PRESENT))
                        printf("     Intent Bitmap : Internal\n\n");
                atime = array.utime;
                if (atime)
@@ -489,24 +507,45 @@ int Detail(char *dev, struct context *c)
                        if (array.state & (1 << MD_SB_CLEAN)) {
                                if ((array.level == 0) ||
                                    (array.level == LEVEL_LINEAR))
-                                       arrayst = map_num(sysfs_array_states,
-                                                         sra->array_state);
+                                       arrayst = map_num_s(sysfs_array_states,
+                                                              sra->array_state);
                                else
                                        arrayst = "clean";
-                       } else
+                       } else {
                                arrayst = "active";
+                               if (array.state & (1<<MD_SB_CLUSTERED)) {
+                                       for (d = 0; d < max_disks * 2; d++) {
+                                               char *dv;
+                                               mdu_disk_info_t disk = disks[d];
+
+                                               /* only check first valid disk in cluster env */
+                                               if ((disk.state & (MD_DISK_SYNC | MD_DISK_ACTIVE))
+                                                       && (disk.major | disk.minor)) {
+                                                       dv = map_dev_preferred(disk.major, disk.minor, 0,
+                                                                       c->prefer);
+                                                       if (!dv)
+                                                               continue;
+                                                       arrayst = IsBitmapDirty(dv) ? "active" : "clean";
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
 
-                       printf("             State : %s%s%s%s%s%s \n",
+                       printf("             State : %s%s%s%s%s%s%s \n",
                               arrayst, st,
                               (!e || (e->percent < 0 &&
                                       e->percent != RESYNC_PENDING &&
-                                      e->percent != RESYNC_DELAYED)) ?
+                                      e->percent != RESYNC_DELAYED &&
+                                      e->percent != RESYNC_REMOTE)) ?
                               "" : sync_action[e->resync],
                               larray_size ? "": ", Not Started",
                               (e && e->percent == RESYNC_DELAYED) ?
                               " (DELAYED)": "",
                               (e && e->percent == RESYNC_PENDING) ?
-                              " (PENDING)": "");
+                              " (PENDING)": "",
+                              (e && e->percent == RESYNC_REMOTE) ?
+                              " (REMOTE)": "");
                } else if (inactive && !is_container) {
                        printf("             State : inactive\n");
                }
@@ -517,7 +556,8 @@ int Detail(char *dev, struct context *c)
                               array.working_disks);
                if (array.raid_disks) {
                        printf("    Failed Devices : %d\n", array.failed_disks);
-                       printf("     Spare Devices : %d\n", array.spare_disks);
+                       if (!external)
+                               printf("     Spare Devices : %d\n", array.spare_disks);
                }
                printf("\n");
                if (array.level == 5) {
@@ -525,6 +565,11 @@ int Detail(char *dev, struct context *c)
                        printf("            Layout : %s\n",
                               str ? str : "-unknown-");
                }
+               if (array.level == 0 && array.layout) {
+                       str = map_num(r0layout, array.layout);
+                       printf("            Layout : %s\n",
+                              str ? str : "-unknown-");
+               }
                if (array.level == 6) {
                        str = map_num(r6layout, array.layout);
                        printf("            Layout : %s\n",
@@ -575,13 +620,6 @@ int Detail(char *dev, struct context *c)
                }
 
                if ((st && st->sb) && (info && info->reshape_active)) {
-#if 0
-This is pretty boring
-                       printf("     Reshape pos'n : %llu%s\n",
-                              (unsigned long long) info->reshape_progress << 9,
-                              human_size((unsigned long long)
-                                         info->reshape_progress << 9));
-#endif
                        if (info->delta_disks != 0)
                                printf("     Delta Devices : %d, (%d->%d)\n",
                                       info->delta_disks,
@@ -758,7 +796,8 @@ This is pretty boring
                                                       &max_devices, n_devices);
                        else
                                printf("   %s", dv);
-               }
+               } else if (disk.major | disk.minor)
+                       printf("   missing");
                if (!c->brief)
                        printf("\n");
        }
@@ -789,10 +828,12 @@ out:
        close(fd);
        free(subarray);
        free(avail);
-       for (d = 0; d < n_devices; d++)
-               free(devices[d]);
+       if (devices)
+               for (d = 0; d < n_devices; d++)
+                       free(devices[d]);
        free(devices);
        sysfs_free(sra);
+       free(st);
        return rv;
 }