From f9c25f1d2af73f9494589afab42e07aa9ca2f740 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Tue, 22 Nov 2005 03:37:14 +0000 Subject: [PATCH] Support bitmaps with raid10 And a couple of other little things Signed-off-by: Neil Brown --- Build.c | 4 +++- ChangeLog | 6 ++++++ Create.c | 16 ++++++++++++++-- Grow.c | 11 +++++++++-- bitmap.c | 11 ++++++----- mdadm.8 | 4 ++-- mdadm.c | 2 +- mdadm.h | 3 ++- super0.c | 7 +++---- super1.c | 9 ++++----- 10 files changed, 50 insertions(+), 23 deletions(-) diff --git a/Build.c b/Build.c index 2fcc47e1..bb53a11c 100644 --- a/Build.c +++ b/Build.c @@ -58,6 +58,7 @@ int Build(char *mddev, int mdfd, int chunk, int level, int layout, mddev_dev_t dv; int bitmap_fd; unsigned long long size = ~0ULL; + unsigned long long bitmapsize; /* scan all devices, make sure they really are block devices */ for (dv = devlist; dv; dv=dv->next) { @@ -215,8 +216,9 @@ int Build(char *mddev, int mdfd, int chunk, int level, int layout, " between different architectured. Consider upgrading the Linux kernel.\n"); #endif } + bitmapsize = size>>9; /* FIXME wrong for RAID10 */ if (CreateBitmap(bitmap_file, 1, NULL, bitmap_chunk, - delay, write_behind, size>>9, major)) { + delay, write_behind, bitmapsize, major)) { return 1; } bitmap_fd = open(bitmap_file, O_RDWR); diff --git a/ChangeLog b/ChangeLog index cb66fc48..824400e9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,10 @@ Changes Prior to this release + - Assorted bug fixes + - Support write-intent-bitmaps on raid10 + - Support little-endian (Rather than hostendian) bitmaps. + - Return correct error code from 'mdadm -S' + +Changes Prior to 2.1 release - Fix assembling of raid10 array when devices are missing. mdadm now correctly detects if a array is workable or not depending on which devices are present, and so will correctly diff --git a/Create.c b/Create.c index 148ab0e7..0fd38a58 100644 --- a/Create.c +++ b/Create.c @@ -69,6 +69,7 @@ int Create(struct supertype *st, char *mddev, int mdfd, int vers; int rv; int bitmap_fd; + unsigned long long bitmapsize; mdu_array_info_t array; int major = BITMAP_MAJOR_HI; @@ -322,6 +323,17 @@ int Create(struct supertype *st, char *mddev, int mdfd, else array.state = 0; /* not clean, but no errors */ + if (level == 10) { + /* for raid10, the bitmap size is the capacity of the array, + * which is array.size * raid_disks / ncopies; + * .. 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); + } else + bitmapsize = (unsigned long long)array.size * 2; + /* There is lots of redundancy in these disk counts, * raid_disks is the most meaningful value * it describes the geometry of the array @@ -365,7 +377,7 @@ int Create(struct supertype *st, char *mddev, int mdfd, return 1; } if (!st->ss->add_internal_bitmap(st, super, bitmap_chunk, delay, write_behind, - &array.size, 1, major)) { + bitmapsize, 1, major)) { fprintf(stderr, Name ": Given bitmap chunk size not supported.\n"); return 1; } @@ -397,7 +409,7 @@ int Create(struct supertype *st, char *mddev, int mdfd, st->ss->uuid_from_super(uuid, super); if (CreateBitmap(bitmap_file, force, (char*)uuid, bitmap_chunk, delay, write_behind, - array.size*2ULL /* FIXME wrong for raid10 */, + bitmapsize, major)) { return 1; } diff --git a/Grow.c b/Grow.c index aa14638a..d669a4e2 100644 --- a/Grow.c +++ b/Grow.c @@ -208,6 +208,7 @@ int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int struct supertype *st; int major = BITMAP_MAJOR_HI; int vers = md_get_version(fd); + unsigned long long bitmapsize; if (vers < 9003) { major = BITMAP_MAJOR_HOSTENDIAN; @@ -254,6 +255,12 @@ int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int devname); return 1; } + bitmapsize = array.size * 2; + if (array.level == 10) { + int ncopies = (array.layout&255)*(array.layout>>8); + bitmapsize = bitmapsize * array.raid_disks / ncopies; + } + st = super_by_version(array.major_version, array.minor_version); if (!st) { fprintf(stderr, Name ": Cannot understand version %d.%d\n", @@ -285,7 +292,7 @@ int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int if (st->ss->load_super(st, fd2, &super, NULL)==0) { st->ss->add_internal_bitmap(st, super, chunk, delay, write_behind, - &array.size, 0, major); + bitmapsize, 0, major); st->ss->write_bitmap(st, fd2, super); } close(fd2); @@ -332,7 +339,7 @@ int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int return 1; } if (CreateBitmap(file, 0, (char*)uuid, chunk, - delay, write_behind, array.size*2ULL, major)) { + delay, write_behind, bitmapsize, major)) { return 1; } bitmap_fd = open(file, O_RDWR); diff --git a/bitmap.c b/bitmap.c index bc29768f..bdfd4055 100644 --- a/bitmap.c +++ b/bitmap.c @@ -126,7 +126,7 @@ bitmap_info_t *bitmap_fd_read(int fd, int brief) info = malloc(sizeof(*info)); if (info == NULL) { - fprintf(stderr, Name ": failed to allocate %d bytes\n", + fprintf(stderr, Name ": failed to allocate %zd bytes\n", sizeof(*info)); return NULL; } @@ -168,7 +168,8 @@ bitmap_info_t *bitmap_fd_read(int fd, int brief) if (read_bits < total_bits) { /* file truncated... */ fprintf(stderr, Name ": WARNING: bitmap file is not large " - "enough for array size %llu!\n\n", info->sb.sync_size); + "enough for array size %llu!\n\n", + (unsigned long long)info->sb.sync_size); total_bits = read_bits; } out: @@ -263,8 +264,8 @@ int ExamineBitmap(char *filename, int brief, struct supertype *st) *(__u32 *)(sb->uuid+8), *(__u32 *)(sb->uuid+12)); } - printf(" Events : %llu\n", sb->events); - printf(" Events Cleared : %llu\n", sb->events_cleared); + printf(" Events : %llu\n", (unsigned long long)sb->events); + printf(" Events Cleared : %llu\n", (unsigned long long)sb->events_cleared); printf(" State : %s\n", bitmap_state(sb->state)); printf(" Chunksize : %s\n", human_chunksize(sb->chunksize)); printf(" Daemon : %ds flush period\n", sb->daemon_sleep); @@ -273,7 +274,7 @@ int ExamineBitmap(char *filename, int brief, struct supertype *st) else sprintf(buf, "Normal"); printf(" Write Mode : %s\n", buf); - printf(" Sync Size : %llu%s\n", sb->sync_size/2, + printf(" Sync Size : %llu%s\n", (unsigned long long)sb->sync_size/2, human_size(sb->sync_size * 512)); if (brief) goto free_info; diff --git a/mdadm.8 b/mdadm.8 index aa39a236..45326f62 100644 --- a/mdadm.8 +++ b/mdadm.8 @@ -516,8 +516,8 @@ will not try to be so clever. Instruct mdadm to create the device file if needed, possibly allocating an unused minor number. "md" causes a non-partitionable array to be used. "mdp", "part" or "p" causes a partitionable array (2.6 and -later) to be used. "yes" requires the named md device to have a -'standard' format, and the type and minor number will be determined +later) to be used. "yes" requires the named md device to haveo +a 'standard' format, and the type and minor number will be determined from this. See DEVICE NAMES below. The argument can also come immediately after diff --git a/mdadm.c b/mdadm.c index ad3d1517..8af61e96 100644 --- a/mdadm.c +++ b/mdadm.c @@ -1059,7 +1059,7 @@ int main(int argc, char *argv[]) put_md_name(name); } } while (!last && err); - if (err) rv |= 1 + if (err) rv |= 1; } else { fprintf(stderr, Name ": No devices given.\n"); exit(2); diff --git a/mdadm.h b/mdadm.h index 85a853b6..2abb0f0c 100644 --- a/mdadm.h +++ b/mdadm.h @@ -190,7 +190,8 @@ extern struct superswitch { int (*load_super)(struct supertype *st, int fd, void **sbp, char *devname); struct supertype * (*match_metadata_desc)(char *arg); __u64 (*avail_size)(struct supertype *st, __u64 size); - int (*add_internal_bitmap)(struct supertype *st, void *sbv, int chunk, int delay, int write_behind, int *sizep, int may_change, int major); + int (*add_internal_bitmap)(struct supertype *st, void *sbv, int chunk, int delay, int write_behind, + unsigned long long size, int may_change, int major); void (*locate_bitmap)(struct supertype *st, int fd, void *sbv); int (*write_bitmap)(struct supertype *st, int fd, void *sbv); int major; diff --git a/super0.c b/super0.c index 4ab40af9..6b8c2081 100644 --- a/super0.c +++ b/super0.c @@ -657,7 +657,7 @@ static __u64 avail_size0(struct supertype *st, __u64 devsize) return MD_NEW_SIZE_SECTORS(devsize); } -static int add_internal_bitmap0(struct supertype *st, void *sbv, int chunk, int delay, int write_behind, int *sizep, int may_change, int major) +static int add_internal_bitmap0(struct supertype *st, void *sbv, int chunk, int delay, int write_behind, unsigned long long size, int may_change, int major) { /* * The bitmap comes immediately after the superblock and must be 60K in size @@ -665,7 +665,6 @@ static int add_internal_bitmap0(struct supertype *st, void *sbv, int chunk, int * * size is in K, chunk is in bytes !!! */ - unsigned long long size = *sizep; unsigned long long bits; unsigned long long max_bits = 60*1024*8; unsigned long long min_chunk; @@ -674,7 +673,7 @@ static int add_internal_bitmap0(struct supertype *st, void *sbv, int chunk, int min_chunk = 4096; /* sub-page chunks don't work yet.. */ - bits = (size * 1024)/ min_chunk +1; + bits = (size * 512)/ min_chunk +1; while (bits > max_bits) { min_chunk *= 2; bits = (bits+1)/2; @@ -692,7 +691,7 @@ static int add_internal_bitmap0(struct supertype *st, void *sbv, int chunk, int uuid_from_super0((int*)bms->uuid, sb); bms->chunksize = __cpu_to_le32(chunk); bms->daemon_sleep = __cpu_to_le32(delay); - bms->sync_size = __cpu_to_le64(size<<1); + bms->sync_size = __cpu_to_le64(size); bms->write_behind = __cpu_to_le32(write_behind); diff --git a/super1.c b/super1.c index 46ce82d9..a0a3a682 100644 --- a/super1.c +++ b/super1.c @@ -842,7 +842,7 @@ static __u64 avail_size1(struct supertype *st, __u64 devsize) static int add_internal_bitmap1(struct supertype *st, void *sbv, - int chunk, int delay, int write_behind, int *sizep, int may_change, int major) + int chunk, int delay, int write_behind, unsigned long long size, int may_change, int major) { /* * If not may_change, then this is a 'Grow', and the bitmap @@ -851,10 +851,9 @@ add_internal_bitmap1(struct supertype *st, void *sbv, * before the superblock if we like, or may move the start. * For now, just squeeze the bitmap into 3k and don't change anything. * - * size is in K, chunk is in bytes !!! + * size is in sectors, chunk is in bytes !!! */ - unsigned long long size = *sizep; unsigned long long bits; unsigned long long max_bits = (3*512 - sizeof(bitmap_super_t)) * 8; unsigned long long min_chunk; @@ -868,7 +867,7 @@ add_internal_bitmap1(struct supertype *st, void *sbv, min_chunk = 4096; /* sub-page chunks don't work yet.. */ - bits = (size*1024)/min_chunk +1; + bits = (size*512)/min_chunk +1; while (bits > max_bits) { min_chunk *= 2; bits = (bits+1)/2; @@ -887,7 +886,7 @@ add_internal_bitmap1(struct supertype *st, void *sbv, uuid_from_super1((int*)bms->uuid, sb); bms->chunksize = __cpu_to_le32(chunk); bms->daemon_sleep = __cpu_to_le32(delay); - bms->sync_size = __cpu_to_le64(size<<1); + bms->sync_size = __cpu_to_le64(size); bms->write_behind = __cpu_to_le32(write_behind); return 1; -- 2.39.2