From 5dd497eecbb7dc453e6e1353e0e77bb4faeaeb3f Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Fri, 27 Jan 2006 06:21:06 +0000 Subject: [PATCH] Enable support for v.large raid1. clean up 'long long' usage for size of array, so that with v-1 superblocks a raid1 larger than 2TB is possible. Signed-off-by: Neil Brown --- Create.c | 20 +++++++-------- Kill.c | 2 +- mdadm.c | 4 +-- mdadm.h | 4 +-- super0.c | 6 +++-- super1.c | 77 ++++++++++++++++++++++++++++++++++++-------------------- 6 files changed, 69 insertions(+), 44 deletions(-) diff --git a/Create.c b/Create.c index 178d62e..7fbf9c0 100644 --- a/Create.c +++ b/Create.c @@ -32,7 +32,7 @@ #include "md_p.h" int Create(struct supertype *st, char *mddev, int mdfd, - int chunk, int level, int layout, unsigned long size, int raiddisks, int sparedisks, + int chunk, int level, int layout, unsigned long long size, int raiddisks, int sparedisks, char *name, int subdevs, mddev_dev_t devlist, int runstop, int verbose, int force, int assume_clean, @@ -74,7 +74,7 @@ int Create(struct supertype *st, char *mddev, int mdfd, mdu_array_info_t array; int major = BITMAP_MAJOR_HI; - memset(array, 0, sizeof(array)); + memset(&array, 0, sizeof(array)); vers = md_get_version(mdfd); if (vers < 9000) { @@ -231,7 +231,7 @@ int Create(struct supertype *st, char *mddev, int mdfd, if (size && freesize < size) { fprintf(stderr, Name ": %s is smaller that given size." - " %lluK < %luK + superblock\n", dname, freesize, size); + " %lluK < %lluK + superblock\n", dname, freesize, size); fail = 1; close(fd); continue; @@ -262,18 +262,18 @@ int Create(struct supertype *st, char *mddev, int mdfd, } if (level > 0 || level == LEVEL_MULTIPATH || level == LEVEL_FAULTY) { /* size is meaningful */ - if (minsize > 0x100000000ULL) { + if (minsize > 0x100000000ULL && st->ss->major == 0) { fprintf(stderr, Name ": devices too large for RAID level %d\n", level); return 1; } size = minsize; if (verbose > 0) - fprintf(stderr, Name ": size set to %luK\n", size); + fprintf(stderr, Name ": size set to %lluK\n", size); } } if (level > 0 && ((maxsize-size)*100 > maxsize)) { if (runstop != 1 || verbose >= 0) - fprintf(stderr, Name ": largest drive (%s) exceed size (%luK) by more than 1%%\n", + fprintf(stderr, Name ": largest drive (%s) exceed size (%lluK) by more than 1%%\n", maxdisc, size); warn = 1; } @@ -337,10 +337,10 @@ int Create(struct supertype *st, char *mddev, int mdfd, * .. but convert to sectors. */ int ncopies = (layout>>8) * (layout & 255); - bitmapsize = (unsigned long long)array.size * raiddisks / ncopies * 2; - printf("bms=%llu as=%d rd=%d nc=%d\n", bitmapsize, array.size, raiddisks, ncopies); + bitmapsize = (unsigned long long)size * raiddisks / ncopies * 2; +/* printf("bms=%llu as=%d rd=%d nc=%d\n", bitmapsize, size, raiddisks, ncopies);*/ } else - bitmapsize = (unsigned long long)array.size * 2; + bitmapsize = (unsigned long long)size * 2; /* There is lots of redundancy in these disk counts, * raid_disks is the most meaningful value @@ -368,7 +368,7 @@ int Create(struct supertype *st, char *mddev, int mdfd, array.chunk_size = chunk*1024; array.major_version = st->ss->major; - if (!st->ss->init_super(st, &super, &array, name)) + if (!st->ss->init_super(st, &super, &array, size, name)) return 1; if (bitmap_file && vers < 9003) { diff --git a/Kill.c b/Kill.c index 9f05e8b..95ab15c 100644 --- a/Kill.c +++ b/Kill.c @@ -63,7 +63,7 @@ int Kill(char *dev, int force) mdu_array_info_t info; info.major_version = -1; /* zero superblock */ free(super); - st->ss->init_super(st, &super, &info, ""); + st->ss->init_super(st, &super, &info, 0, ""); if (st->ss->store_super(st, fd, super)) { fprintf(stderr, Name ": Could not zero superblock on %s\n", dev); diff --git a/mdadm.c b/mdadm.c index 60e0c3e..64e895e 100644 --- a/mdadm.c +++ b/mdadm.c @@ -46,7 +46,7 @@ int main(int argc, char *argv[]) int i; int chunk = 0; - int size = -1; + long long size = -1; int level = UnSet; int layout = UnSet; int raiddisks = 0; @@ -347,7 +347,7 @@ int main(int argc, char *argv[]) if (strcmp(optarg, "max")==0) size = 0; else { - size = strtol(optarg, &c, 10); + size = strtoll(optarg, &c, 10); if (!optarg[0] || *c || size < 4) { fprintf(stderr, Name ": invalid size: %s\n", optarg); diff --git a/mdadm.h b/mdadm.h index b643ead..f03454d 100644 --- a/mdadm.h +++ b/mdadm.h @@ -186,7 +186,7 @@ extern struct superswitch { void (*getinfo_super)(struct mdinfo *info, mddev_ident_t ident, void *sbv); int (*update_super)(struct mdinfo *info, void *sbv, char *update, char *devname, int verbose); __u64 (*event_super)(void *sbv); - int (*init_super)(struct supertype *st, void **sbp, mdu_array_info_t *info, char *name); + int (*init_super)(struct supertype *st, void **sbp, mdu_array_info_t *info, unsigned long long size, char *name); void (*add_to_super)(void *sbv, mdu_disk_info_t *dinfo); int (*store_super)(struct supertype *st, int fd, void *sbv); int (*write_init_super)(struct supertype *st, void *sbv, mdu_disk_info_t *dinfo, char *devname); @@ -254,7 +254,7 @@ extern int Build(char *mddev, int mdfd, int chunk, int level, int layout, extern int Create(struct supertype *st, char *mddev, int mdfd, - int chunk, int level, int layout, unsigned long size, int raiddisks, int sparedisks, + int chunk, int level, int layout, unsigned long long size, int raiddisks, int sparedisks, char *name, int subdevs, mddev_dev_t devlist, int runstop, int verbose, int force, int assume_clean, diff --git a/super0.c b/super0.c index 2884855..aa7cdd9 100644 --- a/super0.c +++ b/super0.c @@ -378,7 +378,7 @@ static __u64 event_super0(void *sbv) -static int init_super0(struct supertype *st, void **sbp, mdu_array_info_t *info, char *ignored_name) +static int init_super0(struct supertype *st, void **sbp, mdu_array_info_t *info, unsigned long long size, char *ignored_name) { mdp_super_t *sb = malloc(MD_SB_BYTES + sizeof(bitmap_super_t)); int spares; @@ -407,6 +407,8 @@ static int init_super0(struct supertype *st, void **sbp, mdu_array_info_t *info, sb->set_uuid0 = random(); sb->ctime = time(0); sb->level = info->level; + if (size != info->size) + return 0; sb->size = info->size; sb->nr_disks = info->nr_disks; sb->raid_disks = info->raid_disks; @@ -466,7 +468,7 @@ static int store_super0(struct supertype *st, int fd, void *sbv) dsize = ((unsigned long long)size)<<9; } - if (dsize < MD_RESERVED_SECTORS*2) + if (dsize < MD_RESERVED_SECTORS*2*512) return 2; offset = MD_NEW_SIZE_SECTORS(dsize>>9); diff --git a/super1.c b/super1.c index bb98bb9..190ec60 100644 --- a/super1.c +++ b/super1.c @@ -409,7 +409,7 @@ static __u64 event_super1(void *sbv) return __le64_to_cpu(sb->events); } -static int init_super1(struct supertype *st, void **sbp, mdu_array_info_t *info, char *name) +static int init_super1(struct supertype *st, void **sbp, mdu_array_info_t *info, unsigned long long size, char *name) { struct mdp_superblock_1 *sb = malloc(1024 + sizeof(bitmap_super_t)); int spares; @@ -448,7 +448,7 @@ static int init_super1(struct supertype *st, void **sbp, mdu_array_info_t *info, sb->ctime = __cpu_to_le64((unsigned long long)time(0)); sb->level = __cpu_to_le32(info->level); sb->layout = __cpu_to_le32(info->layout); - sb->size = __cpu_to_le64(info->size*2ULL); + sb->size = __cpu_to_le64(size*2ULL); sb->chunksize = __cpu_to_le32(info->chunk_size>>9); sb->raid_disks = __cpu_to_le32(info->raid_disks); @@ -491,13 +491,21 @@ static int store_super1(struct supertype *st, int fd, void *sbv) struct mdp_superblock_1 *sb = sbv; unsigned long long sb_offset; int sbsize; - long size; + unsigned long size; + unsigned long long dsize; - if (ioctl(fd, BLKGETSIZE, &size)) - return 1; +#ifdef BLKGETSIZE64 + if (ioctl(fd, BLKGETSIZE64, &dsize) != 0) +#endif + { + if (ioctl(fd, BLKGETSIZE, &size)) + return 1; + else + dsize = (unsigned long long)size; + } else + dsize >>= 9; - - if (size < 24) + if (dsize < 24) return 2; /* @@ -510,7 +518,7 @@ static int store_super1(struct supertype *st, int fd, void *sbv) */ switch(st->minor_version) { case 0: - sb_offset = size; + sb_offset = dsize; sb_offset -= 8*2; sb_offset &= ~(4*2-1); break; @@ -556,7 +564,8 @@ static int write_init_super1(struct supertype *st, void *sbv, int rfd; int rv; - long size; + unsigned long size; + unsigned long long dsize; long long sb_offset; @@ -592,12 +601,18 @@ static int write_init_super1(struct supertype *st, void *sbv, free(refsb); } - if (ioctl(fd, BLKGETSIZE, &size)) { - close(fd); - return 1; - } +#ifdef BLKGETSIZE64 + if (ioctl(fd, BLKGETSIZE64, &dsize) != 0) +#endif + { + if (ioctl(fd, BLKGETSIZE, &size)) + return 1; + else + dsize = size; + } else + dsize >>= 9; - if (size < 24) { + if (dsize < 24) { close(fd); return 2; } @@ -613,7 +628,7 @@ static int write_init_super1(struct supertype *st, void *sbv, */ switch(st->minor_version) { case 0: - sb_offset = size; + sb_offset = dsize; sb_offset -= 8*2; sb_offset &= ~(4*2-1); sb->super_offset = __cpu_to_le64(sb_offset); @@ -623,13 +638,13 @@ static int write_init_super1(struct supertype *st, void *sbv, case 1: sb->super_offset = __cpu_to_le64(0); sb->data_offset = __cpu_to_le64(4*2); /* leave 4k for super and bitmap */ - sb->data_size = __cpu_to_le64(size - 4*2); + sb->data_size = __cpu_to_le64(dsize - 4*2); break; case 2: sb_offset = 4*2; sb->super_offset = __cpu_to_le64(sb_offset); sb->data_offset = __cpu_to_le64(sb_offset+4*2); - sb->data_size = __cpu_to_le64(size - 4*2 - 4*2); + sb->data_size = __cpu_to_le64(dsize - 4*2 - 4*2); break; default: return -EINVAL; @@ -686,6 +701,7 @@ static int compare_super1(void **firstp, void *secondv) static int load_super1(struct supertype *st, int fd, void **sbp, char *devname) { unsigned long size; + unsigned long long dsize; unsigned long long sb_offset; struct mdp_superblock_1 *super; @@ -723,17 +739,24 @@ static int load_super1(struct supertype *st, int fd, void **sbp, char *devname) st->ss = NULL; return 2; } - if (ioctl(fd, BLKGETSIZE, &size)) { - if (devname) - fprintf(stderr, Name ": cannot find device size for %s: %s\n", - devname, strerror(errno)); - return 1; - } +#ifdef BLKGETSIZE64 + if (ioctl(fd, BLKGETSIZE64, &dsize) != 0) +#endif + { + if (ioctl(fd, BLKGETSIZE, &size)) { + if (devname) + fprintf(stderr, Name ": cannot find device size for %s: %s\n", + devname, strerror(errno)); + return 1; + } + dsize = size; + } else + dsize >>= 9; - if (size < 24) { + if (dsize < 24) { if (devname) - fprintf(stderr, Name ": %s is too small for md: size is %lu sectors.\n", - devname, size); + fprintf(stderr, Name ": %s is too small for md: size is %llu sectors.\n", + devname, dsize); return 1; } @@ -747,7 +770,7 @@ static int load_super1(struct supertype *st, int fd, void **sbp, char *devname) */ switch(st->minor_version) { case 0: - sb_offset = size; + sb_offset = dsize; sb_offset -= 8*2; sb_offset &= ~(4*2-1); break;