]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super-intel.c
imsm: Change the way of printing nvme drives in detail-platform.
[thirdparty/mdadm.git] / super-intel.c
index 4fd5e84d0bc785e8cca476be2b8083000e0b0367..5c1f759f24a64df2b01321ec406bd59df8f3d4bf 100644 (file)
                                                   * mutliple PPL area
                                                   */
 
+/*
+ * This macro let's us ensure that no-one accidentally
+ * changes the size of a struct
+ */
+#define ASSERT_SIZE(_struct, size) \
+static inline void __assert_size_##_struct(void)       \
+{                                                      \
+       switch (0) {                                    \
+       case 0: break;                                  \
+       case (sizeof(struct _struct) == size): break;   \
+       }                                               \
+}
+
 /* Disk configuration info. */
 #define IMSM_MAX_DEVICES 255
 struct imsm_disk {
@@ -112,6 +125,7 @@ struct imsm_disk {
 #define        IMSM_DISK_FILLERS       3
        __u32 filler[IMSM_DISK_FILLERS]; /* 0xF5 - 0x107 MPB_DISK_FILLERS for future expansion */
 };
+ASSERT_SIZE(imsm_disk, 48)
 
 /* map selector for map managment
  */
@@ -146,7 +160,8 @@ struct imsm_map {
        __u32 disk_ord_tbl[1];  /* disk_ord_tbl[num_members],
                                 * top byte contains some flags
                                 */
-} __attribute__ ((packed));
+};
+ASSERT_SIZE(imsm_map, 52)
 
 struct imsm_vol {
        __u32 curr_migr_unit;
@@ -169,7 +184,8 @@ struct imsm_vol {
        __u32 filler[4];
        struct imsm_map map[1];
        /* here comes another one if migr_state */
-} __attribute__ ((packed));
+};
+ASSERT_SIZE(imsm_vol, 84)
 
 struct imsm_dev {
        __u8  volume[MAX_RAID_SERIAL_LEN];
@@ -220,7 +236,8 @@ struct imsm_dev {
 #define IMSM_DEV_FILLERS 3
        __u32 filler[IMSM_DEV_FILLERS];
        struct imsm_vol vol;
-} __attribute__ ((packed));
+};
+ASSERT_SIZE(imsm_dev, 164)
 
 struct imsm_super {
        __u8 sig[MAX_SIGNATURE_LENGTH]; /* 0x00 - 0x1F */
@@ -248,7 +265,8 @@ struct imsm_super {
        struct imsm_disk disk[1];       /* 0xD8 diskTbl[numDisks] */
        /* here comes imsm_dev[num_raid_devs] */
        /* here comes BBM logs */
-} __attribute__ ((packed));
+};
+ASSERT_SIZE(imsm_super, 264)
 
 #define BBM_LOG_MAX_ENTRIES 254
 #define BBM_LOG_MAX_LBA_ENTRY_VAL 256          /* Represents 256 LBAs */
@@ -269,7 +287,8 @@ struct bbm_log {
        __u32 signature; /* 0xABADB10C */
        __u32 entry_count;
        struct bbm_log_entry marked_block_entries[BBM_LOG_MAX_ENTRIES];
-} __attribute__ ((__packed__));
+};
+ASSERT_SIZE(bbm_log, 2040)
 
 static char *map_state_str[] = { "normal", "uninitialized", "degraded", "failed" };
 
@@ -323,7 +342,8 @@ struct migr_record {
                                       * destination - high order 32 bits */
        __u32 num_migr_units_hi;      /* Total num migration units-of-op
                                       * high order 32 bits */
-} __attribute__ ((__packed__));
+};
+ASSERT_SIZE(migr_record, 64)
 
 struct md_list {
        /* usage marker:
@@ -1165,12 +1185,12 @@ static int count_memberships(struct dl *dl, struct intel_super *super)
 
 static __u32 imsm_min_reserved_sectors(struct intel_super *super);
 
-static int split_ull(unsigned long long n, __u32 *lo, __u32 *hi)
+static int split_ull(unsigned long long n, void *lo, void *hi)
 {
        if (lo == 0 || hi == 0)
                return 1;
-       *lo = __le32_to_cpu((unsigned)n);
-       *hi = __le32_to_cpu((unsigned)(n >> 32));
+       __put_unaligned32(__cpu_to_le32((__u32)n), lo);
+       __put_unaligned32(__cpu_to_le32((n >> 32)), hi);
        return 0;
 }
 
@@ -2163,26 +2183,43 @@ err:
        return 1;
 }
 
-static void detail_super_imsm(struct supertype *st, char *homehost)
+static void detail_super_imsm(struct supertype *st, char *homehost,
+                             char *subarray)
 {
        struct mdinfo info;
        char nbuf[64];
+       struct intel_super *super = st->sb;
+       int temp_vol = super->current_vol;
+
+       if (subarray)
+               super->current_vol = strtoul(subarray, NULL, 10);
 
        getinfo_super_imsm(st, &info, NULL);
        fname_from_uuid(st, &info, nbuf, ':');
        printf("\n              UUID : %s\n", nbuf + 5);
+
+       super->current_vol = temp_vol;
 }
 
-static void brief_detail_super_imsm(struct supertype *st)
+static void brief_detail_super_imsm(struct supertype *st, char *subarray)
 {
        struct mdinfo info;
        char nbuf[64];
+       struct intel_super *super = st->sb;
+       int temp_vol = super->current_vol;
+
+       if (subarray)
+               super->current_vol = strtoul(subarray, NULL, 10);
+
        getinfo_super_imsm(st, &info, NULL);
        fname_from_uuid(st, &info, nbuf, ':');
        printf(" UUID=%s", nbuf + 5);
+
+       super->current_vol = temp_vol;
 }
 
-static int imsm_read_serial(int fd, char *devname, __u8 *serial);
+static int imsm_read_serial(int fd, char *devname, __u8 *serial,
+                           size_t serial_buf_len);
 static void fd2devname(int fd, char *name);
 
 static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_base, int verbose)
@@ -2328,8 +2365,9 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
                else {
                        fd2devname(fd, buf);
                        printf("          Port%d : %s", port, buf);
-                       if (imsm_read_serial(fd, NULL, (__u8 *) buf) == 0)
-                               printf(" (%.*s)\n", MAX_RAID_SERIAL_LEN, buf);
+                       if (imsm_read_serial(fd, NULL, (__u8 *)buf,
+                                            sizeof(buf)) == 0)
+                               printf(" (%s)\n", buf);
                        else
                                printf(" ()\n");
                        close(fd);
@@ -2352,52 +2390,45 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
        return err;
 }
 
-static int print_vmd_attached_devs(struct sys_dev *hba)
+static int print_nvme_info(struct sys_dev *hba)
 {
+       char buf[1024];
        struct dirent *ent;
        DIR *dir;
-       char path[292];
-       char link[256];
-       char *c, *rp;
-
-       if (hba->type != SYS_DEV_VMD)
-               return 1;
+       char *rp;
+       int fd;
 
-       /* scroll through /sys/dev/block looking for devices attached to
-        * this hba
-        */
-       dir = opendir("/sys/bus/pci/drivers/nvme");
+       dir = opendir("/sys/block/");
        if (!dir)
                return 1;
 
        for (ent = readdir(dir); ent; ent = readdir(dir)) {
-               int n;
-
-               /* is 'ent' a device? check that the 'subsystem' link exists and
-                * that its target matches 'bus'
-                */
-               sprintf(path, "/sys/bus/pci/drivers/nvme/%s/subsystem",
-                       ent->d_name);
-               n = readlink(path, link, sizeof(link));
-               if (n < 0 || n >= (int)sizeof(link))
-                       continue;
-               link[n] = '\0';
-               c = strrchr(link, '/');
-               if (!c)
-                       continue;
-               if (strncmp("pci", c+1, strlen("pci")) != 0)
-                       continue;
-
-               sprintf(path, "/sys/bus/pci/drivers/nvme/%s", ent->d_name);
-
-               rp = realpath(path, NULL);
-               if (!rp)
-                       continue;
+               if (strstr(ent->d_name, "nvme")) {
+                       sprintf(buf, "/sys/block/%s", ent->d_name);
+                       rp = realpath(buf, NULL);
+                       if (!rp)
+                               continue;
+                       if (path_attached_to_hba(rp, hba->path)) {
+                               fd = open_dev(ent->d_name);
+                               if (fd < 0) {
+                                       free(rp);
+                                       continue;
+                               }
 
-               if (path_attached_to_hba(rp, hba->path)) {
-                       printf(" NVMe under VMD : %s\n", rp);
+                               fd2devname(fd, buf);
+                               if (hba->type == SYS_DEV_VMD)
+                                       printf(" NVMe under VMD : %s", buf);
+                               else if (hba->type == SYS_DEV_NVME)
+                                       printf("    NVMe Device : %s", buf);
+                               if (!imsm_read_serial(fd, NULL, (__u8 *)buf,
+                                                     sizeof(buf)))
+                                       printf(" (%s)\n", buf);
+                               else
+                                       printf("()\n");
+                               close(fd);
+                       }
+                       free(rp);
                }
-               free(rp);
        }
 
        closedir(dir);
@@ -2612,7 +2643,7 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle
                                        char buf[PATH_MAX];
                                        printf(" I/O Controller : %s (%s)\n",
                                                vmd_domain_to_controller(hba, buf), get_sys_dev_type(hba->type));
-                                       if (print_vmd_attached_devs(hba)) {
+                                       if (print_nvme_info(hba)) {
                                                if (verbose > 0)
                                                        pr_err("failed to get devices attached to VMD domain.\n");
                                                result |= 2;
@@ -2627,7 +2658,7 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle
                if (entry->type == SYS_DEV_NVME) {
                        for (hba = list; hba; hba = hba->next) {
                                if (hba->type == SYS_DEV_NVME)
-                                       printf("    NVMe Device : %s\n", hba->path);
+                                       print_nvme_info(hba);
                        }
                        printf("\n");
                        continue;
@@ -2875,7 +2906,7 @@ static unsigned long long calc_component_size(struct imsm_map *map,
 {
        unsigned long long component_size;
        unsigned long long dev_size = imsm_dev_size(dev);
-       unsigned long long calc_dev_size = 0;
+       long long calc_dev_size = 0;
        unsigned int member_disks = imsm_num_data_members(map);
 
        if (member_disks == 0)
@@ -2889,7 +2920,7 @@ static unsigned long long calc_component_size(struct imsm_map *map,
         * 2048 blocks per each device. If the difference is higher it means
         * that array size was expanded and num_data_stripes was not updated.
         */
-       if ((unsigned int)abs(calc_dev_size - dev_size) >
+       if (llabs(calc_dev_size - (long long)dev_size) >
            (1 << SECT_PER_MB_SHIFT) * member_disks) {
                component_size = dev_size / member_disks;
                dprintf("Invalid num_data_stripes in metadata; expected=%llu, found=%llu\n",
@@ -3992,11 +4023,11 @@ static int nvme_get_serial(int fd, void *buf, size_t buf_len)
 extern int scsi_get_serial(int fd, void *buf, size_t buf_len);
 
 static int imsm_read_serial(int fd, char *devname,
-                           __u8 serial[MAX_RAID_SERIAL_LEN])
+                           __u8 *serial, size_t serial_buf_len)
 {
        char buf[50];
        int rv;
-       int len;
+       size_t len;
        char *dest;
        char *src;
        unsigned int i;
@@ -4039,13 +4070,13 @@ static int imsm_read_serial(int fd, char *devname,
        len = dest - buf;
        dest = buf;
 
-       /* truncate leading characters */
-       if (len > MAX_RAID_SERIAL_LEN) {
-               dest += len - MAX_RAID_SERIAL_LEN;
-               len = MAX_RAID_SERIAL_LEN;
+       if (len > serial_buf_len) {
+               /* truncate leading characters */
+               dest += len - serial_buf_len;
+               len = serial_buf_len;
        }
 
-       memset(serial, 0, MAX_RAID_SERIAL_LEN);
+       memset(serial, 0, serial_buf_len);
        memcpy(serial, dest, len);
 
        return 0;
@@ -4100,7 +4131,7 @@ load_imsm_disk(int fd, struct intel_super *super, char *devname, int keep_fd)
        char name[40];
        __u8 serial[MAX_RAID_SERIAL_LEN];
 
-       rv = imsm_read_serial(fd, devname, serial);
+       rv = imsm_read_serial(fd, devname, serial, MAX_RAID_SERIAL_LEN);
 
        if (rv != 0)
                return 2;
@@ -5808,7 +5839,7 @@ int mark_spare(struct dl *disk)
                return ret_val;
 
        ret_val = 0;
-       if (!imsm_read_serial(disk->fd, NULL, serial)) {
+       if (!imsm_read_serial(disk->fd, NULL, serial, MAX_RAID_SERIAL_LEN)) {
                /* Restore disk serial number, because takeover marks disk
                 * as failed and adds to serial ':0' before it becomes
                 * a spare disk.
@@ -5859,7 +5890,7 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
        dd->fd = fd;
        dd->e = NULL;
        dd->action = DISK_ADD;
-       rv = imsm_read_serial(fd, devname, dd->serial);
+       rv = imsm_read_serial(fd, devname, dd->serial, MAX_RAID_SERIAL_LEN);
        if (rv) {
                pr_err("failed to retrieve scsi serial, aborting\n");
                if (dd->devname)
@@ -7298,11 +7329,8 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
 
        maxsize = merge_extents(super, i);
 
-       if (!check_env("IMSM_NO_PLATFORM") &&
-           mpb->num_raid_devs > 0 && size && size != maxsize) {
-               pr_err("attempting to create a second volume with size less then remaining space. Aborting...\n");
-               return 0;
-       }
+       if (mpb->num_raid_devs > 0 && size && size != maxsize)
+               pr_err("attempting to create a second volume with size less then remaining space.\n");
 
        if (maxsize < size || maxsize == 0) {
                if (verbose) {
@@ -7393,11 +7421,8 @@ static int imsm_get_free_size(struct supertype *st, int raiddisks,
                }
                maxsize = size;
        }
-       if (!check_env("IMSM_NO_PLATFORM") &&
-           mpb->num_raid_devs > 0 && size && size != maxsize) {
-               pr_err("attempting to create a second volume with size less then remaining space. Aborting...\n");
-               return 0;
-       }
+       if (mpb->num_raid_devs > 0 && size && size != maxsize)
+               pr_err("attempting to create a second volume with size less then remaining space.\n");
        cnt = 0;
        for (dl = super->disks; dl; dl = dl->next)
                if (dl->e)
@@ -7826,6 +7851,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
        int sb_errors = 0;
        struct dl *d;
        int spare_disks = 0;
+       int current_vol = super->current_vol;
 
        /* do not assemble arrays when not all attributes are supported */
        if (imsm_check_attributes(mpb->attributes) == 0) {
@@ -7993,6 +8019,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
                rest = this;
        }
 
+       super->current_vol = current_vol;
        return rest;
 }
 
@@ -9200,6 +9227,9 @@ static int add_remove_disk_update(struct intel_super *super)
                                        remove_disk_super(super,
                                                          disk_cfg->major,
                                                          disk_cfg->minor);
+                               } else {
+                                       disk_cfg->fd = disk->fd;
+                                       disk->fd = -1;
                                }
                        }
                        /* release allocate disk structure */