Author: mav
Date: Thu Jan 17 00:50:25 2013
New Revision: 245522
URL: http://svnweb.freebsd.org/changeset/base/245522

Log:
  For Promise/AMD metadata add support for disks with capacity above 2TiB
  and for volumes with sector size above 512 bytes.

Modified:
  head/sbin/geom/class/raid/graid.8
  head/sys/geom/raid/md_promise.c

Modified: head/sbin/geom/class/raid/graid.8
==============================================================================
--- head/sbin/geom/class/raid/graid.8   Thu Jan 17 00:42:30 2013        
(r245521)
+++ head/sbin/geom/class/raid/graid.8   Thu Jan 17 00:50:25 2013        
(r245522)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd September 13, 2012
+.Dd January 16, 2013
 .Dt GRAID 8
 .Os
 .Sh NAME
@@ -274,7 +274,6 @@ complete it there.
 Do not run GEOM RAID class on migrating volumes under pain of possible data
 corruption!
 .Sh 2TiB BARRIERS
-Promise metadata format does not support disks above 2TiB.
 NVIDIA metadata format does not support volumes above 2TiB.
 .Sh SYSCTL VARIABLES
 The following

Modified: head/sys/geom/raid/md_promise.c
==============================================================================
--- head/sys/geom/raid/md_promise.c     Thu Jan 17 00:42:30 2013        
(r245521)
+++ head/sys/geom/raid/md_promise.c     Thu Jan 17 00:50:25 2013        
(r245522)
@@ -84,7 +84,7 @@ struct promise_raid_conf {
        struct promise_raid_disk        disk;   /* This subdisk info. */
        uint32_t        disk_offset;            /* Subdisk offset. */
        uint32_t        disk_sectors;           /* Subdisk size */
-       uint32_t        rebuild_lba;            /* Rebuild position. */
+       uint32_t        disk_rebuild;           /* Rebuild position. */
        uint16_t        generation;             /* Generation number. */
        uint8_t         status;                 /* Volume status. */
 #define PROMISE_S_VALID                0x01
@@ -123,7 +123,17 @@ struct promise_raid_conf {
        uint32_t        magic_4;
        uint32_t        magic_5;
        uint32_t        total_sectors_high;
-       uint32_t        filler3[324];
+       uint8_t         magic_6;
+       uint8_t         sector_size;
+       uint16_t        magic_7;
+       uint32_t        magic_8[32];
+       uint16_t        magic_9;
+       uint32_t        disk_offset_high;
+       uint32_t        disk_sectors_high;
+       uint32_t        disk_rebuild_high;
+       uint16_t        magic_10;
+       uint32_t        magic_11[3];
+       uint32_t        filler3[284];
        uint32_t        checksum;
 } __packed;
 
@@ -191,7 +201,7 @@ g_raid_md_promise_print(struct promise_r
            meta->disk.device, meta->disk.id);
        printf("disk_offset         %u\n", meta->disk_offset);
        printf("disk_sectors        %u\n", meta->disk_sectors);
-       printf("rebuild_lba         %u\n", meta->rebuild_lba);
+       printf("disk_rebuild        %u\n", meta->disk_rebuild);
        printf("generation          %u\n", meta->generation);
        printf("status              0x%02x\n", meta->status);
        printf("type                %u\n", meta->type);
@@ -217,6 +227,10 @@ g_raid_md_promise_print(struct promise_r
        printf("magic_4             0x%08x\n", meta->magic_4);
        printf("magic_5             0x%08x\n", meta->magic_5);
        printf("total_sectors_high  0x%08x\n", meta->total_sectors_high);
+       printf("sector_size         %u\n", meta->sector_size);
+       printf("disk_offset_high    0x%08x\n", meta->disk_offset_high);
+       printf("disk_sectors_high   0x%08x\n", meta->disk_sectors_high);
+       printf("disk_rebuild_high   0x%08x\n", meta->disk_rebuild_high);
        printf("=================================================\n");
 }
 
@@ -244,9 +258,9 @@ promise_meta_find_disk(struct promise_ra
 
 static int
 promise_meta_unused_range(struct promise_raid_conf **metaarr, int nsd,
-    uint32_t sectors, uint32_t *off, uint32_t *size)
+    off_t sectors, off_t *off, off_t *size)
 {
-       uint32_t coff, csize;
+       off_t coff, csize, tmp;
        int i, j;
 
        sectors -= 131072;
@@ -257,10 +271,10 @@ promise_meta_unused_range(struct promise
        i = 0;
        while (1) {
                for (j = 0; j < nsd; j++) {
-                       if (metaarr[j]->disk_offset >= coff) {
-                               csize = MIN(csize,
-                                   metaarr[j]->disk_offset - coff);
-                       }
+                       tmp = ((off_t)metaarr[j]->disk_offset_high << 32) +
+                           metaarr[j]->disk_offset;
+                       if (tmp >= coff)
+                               csize = MIN(csize, tmp - coff);
                }
                if (csize > *size) {
                        *off = coff;
@@ -268,7 +282,10 @@ promise_meta_unused_range(struct promise
                }
                if (i >= nsd)
                        break;
-               coff = metaarr[i]->disk_offset + metaarr[i]->disk_sectors;
+               coff = ((off_t)metaarr[i]->disk_offset_high << 32) +
+                    metaarr[i]->disk_offset +
+                   ((off_t)metaarr[i]->disk_sectors_high << 32) +
+                    metaarr[i]->disk_sectors;
                csize = sectors - coff;
                i++;
        };
@@ -369,6 +386,25 @@ next:
                return (subdisks);
        }
 
+       /* Remove filler garbage from fields used in newer metadata. */
+       if (meta->disk_offset_high == 0x8b8c8d8e &&
+           meta->disk_sectors_high == 0x8788898a &&
+           meta->disk_rebuild_high == 0x83848586) {
+               meta->disk_offset_high = 0;
+               meta->disk_sectors_high = 0;
+               if (meta->disk_rebuild == UINT32_MAX)
+                       meta->disk_rebuild_high = UINT32_MAX;
+               else
+                       meta->disk_rebuild_high = 0;
+               if (meta->total_sectors_high == 0x15161718) {
+                       meta->total_sectors_high = 0;
+                       if (meta->rebuild_lba64 == 0x2122232425262728)
+                               meta->rebuild_lba64 = UINT64_MAX;
+               }
+       }
+       if (meta->sector_size < 1 || meta->sector_size > 8)
+               meta->sector_size = 1;
+
        /* Save this part and look for next. */
        *metaarr = meta;
        metaarr++;
@@ -386,8 +422,9 @@ promise_meta_write(struct g_consumer *cp
        struct g_provider *pp;
        struct promise_raid_conf *meta;
        char *buf;
+       off_t off, size;
        int error, i, subdisk, fake;
-       uint32_t checksum, *ptr, off, size;
+       uint32_t checksum, *ptr;
 
        pp = cp->provider;
        subdisk = 0;
@@ -409,9 +446,12 @@ next:
                meta->disk.flags = PROMISE_F_ONLINE | PROMISE_F_VALID;
                meta->disk.number = 0xff;
                arc4rand(&meta->disk.id, sizeof(meta->disk.id), 0);
-               meta->disk_offset = off;
-               meta->disk_sectors = size;
-               meta->rebuild_lba = UINT32_MAX;
+               meta->disk_offset_high = off >> 32;
+               meta->disk_offset = (uint32_t)off;
+               meta->disk_sectors_high = size >> 32;
+               meta->disk_sectors = (uint32_t)size;
+               meta->disk_rebuild_high = UINT32_MAX;
+               meta->disk_rebuild = UINT32_MAX;
                fake = 1;
        }
        if (meta != NULL) {
@@ -464,6 +504,7 @@ static int
 promise_meta_write_spare(struct g_consumer *cp)
 {
        struct promise_raid_conf *meta;
+       off_t tmp;
        int error;
 
        meta = malloc(sizeof(*meta), M_MD_PROMISE, M_WAITOK | M_ZERO);
@@ -473,9 +514,11 @@ promise_meta_write_spare(struct g_consum
        meta->disk.flags = PROMISE_F_SPARE | PROMISE_F_ONLINE | PROMISE_F_VALID;
        meta->disk.number = 0xff;
        arc4rand(&meta->disk.id, sizeof(meta->disk.id), 0);
-       meta->disk_sectors = cp->provider->mediasize / cp->provider->sectorsize;
-       meta->disk_sectors -= 131072;
-       meta->rebuild_lba = UINT32_MAX;
+       tmp = cp->provider->mediasize / cp->provider->sectorsize - 131072;
+       meta->disk_sectors_high = tmp >> 32;
+       meta->disk_sectors = (uint32_t)tmp;
+       meta->disk_rebuild_high = UINT32_MAX;
+       meta->disk_rebuild = UINT32_MAX;
        error = promise_meta_write(cp, &meta, 1);
        free(meta, M_MD_PROMISE);
        return (error);
@@ -617,9 +660,8 @@ g_raid_md_promise_start_disk(struct g_ra
        struct g_raid_md_promise_perdisk *pd;
        struct g_raid_md_promise_pervolume *pv;
        struct promise_raid_conf *meta;
-       off_t size;
+       off_t eoff, esize, size;
        int disk_pos, md_disk_pos, i, resurrection = 0;
-       uint32_t eoff, esize;
 
        sc = disk->d_softc;
        pd = (struct g_raid_md_promise_perdisk *)disk->d_md_data;
@@ -729,8 +771,10 @@ nofit:
                sd->sd_offset = (off_t)eoff * 512;
                sd->sd_size = (off_t)esize * 512;
        } else {
-               sd->sd_offset = (off_t)pd->pd_meta[sdn]->disk_offset * 512;
-               sd->sd_size = (off_t)pd->pd_meta[sdn]->disk_sectors * 512;
+               sd->sd_offset = (((off_t)pd->pd_meta[sdn]->disk_offset_high
+                   << 32) + pd->pd_meta[sdn]->disk_offset) * 512;
+               sd->sd_size = (((off_t)pd->pd_meta[sdn]->disk_sectors_high
+                   << 32) + pd->pd_meta[sdn]->disk_sectors) * 512;
        }
 
        if (resurrection) {
@@ -749,7 +793,8 @@ nofit:
                        sd->sd_rebuild_pos = 0;
                else {
                        sd->sd_rebuild_pos =
-                           (off_t)pd->pd_meta[sdn]->rebuild_lba * 512;
+                           (((off_t)pd->pd_meta[sdn]->disk_rebuild << 32) +
+                            pd->pd_meta[sdn]->disk_rebuild) * 512;
                }
        } else if (!(meta->disks[md_disk_pos].flags & PROMISE_F_ONLINE)) {
                /* Rebuilding disk. */
@@ -875,13 +920,15 @@ g_raid_md_promise_start(struct g_raid_vo
        vol->v_disks_count = meta->total_disks;
        vol->v_mediasize = (off_t)meta->total_sectors * 512; //ZZZ
        if (meta->total_sectors_high < 256) /* If value looks sane. */
-               vol->v_mediasize |=
+               vol->v_mediasize +=
                    ((off_t)meta->total_sectors_high << 32) * 512; //ZZZ
-       vol->v_sectorsize = 512; //ZZZ
+       vol->v_sectorsize = 512 * meta->sector_size;
        for (i = 0; i < vol->v_disks_count; i++) {
                sd = &vol->v_subdisks[i];
-               sd->sd_offset = (off_t)meta->disk_offset * 512; //ZZZ
-               sd->sd_size = (off_t)meta->disk_sectors * 512; //ZZZ
+               sd->sd_offset = (((off_t)meta->disk_offset_high << 32) +
+                   meta->disk_offset) * 512;
+               sd->sd_size = (((off_t)meta->disk_sectors_high << 32) +
+                   meta->disk_sectors) * 512;
        }
        g_raid_start_volume(vol);
 
@@ -1213,9 +1260,8 @@ g_raid_md_ctl_promise(struct g_raid_md_o
        const char *nodename, *verb, *volname, *levelname, *diskname;
        char *tmp;
        int *nargs, *force;
-       off_t size, sectorsize, strip;
+       off_t esize, offs[PROMISE_MAX_DISKS], size, sectorsize, strip;
        intmax_t *sizearg, *striparg;
-       uint32_t offs[PROMISE_MAX_DISKS], esize;
        int numdisks, i, len, level, qual;
        int error;
 
@@ -1323,13 +1369,6 @@ g_raid_md_ctl_promise(struct g_raid_md_o
                        cp->private = disk;
                        g_topology_unlock();
 
-                       if (pp->mediasize / pp->sectorsize > UINT32_MAX) {
-                               gctl_error(req,
-                                   "Disk '%s' is too big.", diskname);
-                               error = -8;
-                               break;
-                       }
-
                        g_raid_get_disk_info(disk);
 
                        /* Reserve some space for metadata. */
@@ -1394,10 +1433,6 @@ g_raid_md_ctl_promise(struct g_raid_md_o
                        gctl_error(req, "Size too small.");
                        return (-13);
                }
-               if (size > 0xffffffffllu * sectorsize) {
-                       gctl_error(req, "Size too big.");
-                       return (-14);
-               }
 
                /* We have all we need, create things: volume, ... */
                pv = malloc(sizeof(*pv), M_MD_PROMISE, M_WAITOK | M_ZERO);
@@ -1629,14 +1664,6 @@ g_raid_md_ctl_promise(struct g_raid_md_o
                        pp = cp->provider;
                        g_topology_unlock();
 
-                       if (pp->mediasize / pp->sectorsize > UINT32_MAX) {
-                               gctl_error(req,
-                                   "Disk '%s' is too big.", diskname);
-                               g_raid_kill_consumer(sc, cp);
-                               error = -8;
-                               break;
-                       }
-
                        pd = malloc(sizeof(*pd), M_MD_PROMISE, M_WAITOK | 
M_ZERO);
 
                        disk = g_raid_create_disk(sc);
@@ -1733,9 +1760,9 @@ g_raid_md_write_promise(struct g_raid_md
                    vol->v_raid_level == G_RAID_VOLUME_RL_RAID1E)
                        meta->array_width /= 2;
                meta->array_number = vol->v_global_id;
-               meta->total_sectors = vol->v_mediasize / vol->v_sectorsize;
-               meta->total_sectors_high =
-                   (vol->v_mediasize / vol->v_sectorsize) >> 32;
+               meta->total_sectors = vol->v_mediasize / 512;
+               meta->total_sectors_high = (vol->v_mediasize / 512) >> 32;
+               meta->sector_size = vol->v_sectorsize / 512;
                meta->cylinders = meta->total_sectors / (255 * 63) - 1;
                meta->heads = 254;
                meta->sectors = 63;
@@ -1828,15 +1855,24 @@ g_raid_md_write_promise(struct g_raid_md
                        pd->pd_meta[j] = promise_meta_copy(meta);
                        pd->pd_meta[j]->disk = meta->disks[pos];
                        pd->pd_meta[j]->disk.number = pos;
+                       pd->pd_meta[j]->disk_offset_high =
+                           (sd->sd_offset / 512) >> 32;
                        pd->pd_meta[j]->disk_offset = sd->sd_offset / 512;
+                       pd->pd_meta[j]->disk_sectors_high =
+                           (sd->sd_size / 512) >> 32;
                        pd->pd_meta[j]->disk_sectors = sd->sd_size / 512;
                        if (sd->sd_state == G_RAID_SUBDISK_S_REBUILD) {
-                               pd->pd_meta[j]->rebuild_lba =
+                               pd->pd_meta[j]->disk_rebuild_high =
+                                   (sd->sd_rebuild_pos / 512) >> 32;
+                               pd->pd_meta[j]->disk_rebuild =
                                    sd->sd_rebuild_pos / 512;
-                       } else if (sd->sd_state < G_RAID_SUBDISK_S_REBUILD)
-                               pd->pd_meta[j]->rebuild_lba = 0;
-                       else
-                               pd->pd_meta[j]->rebuild_lba = UINT32_MAX;
+                       } else if (sd->sd_state < G_RAID_SUBDISK_S_REBUILD) {
+                               pd->pd_meta[j]->disk_rebuild_high = 0;
+                               pd->pd_meta[j]->disk_rebuild = 0;
+                       } else {
+                               pd->pd_meta[j]->disk_rebuild_high = UINT32_MAX;
+                               pd->pd_meta[j]->disk_rebuild = UINT32_MAX;
+                       }
                        pd->pd_updated = 1;
                }
        }
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to