From 0308308138db260771bec109a4e9c1b0bb003b8d Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 9 May 2012 20:49:31 +1000 Subject: Add data_offset arg to ->init_super and use it in super1.c So if ->data_offset is already set, use that rather than computing one. Signed-off-by: NeilBrown --- Create.c | 2 +- Kill.c | 2 +- mdadm.h | 2 +- super-ddf.c | 14 +++++++---- super-intel.c | 13 +++++++--- super0.c | 7 +++++- super1.c | 76 +++++++++++++++++++++++++++++++++-------------------------- 7 files changed, 72 insertions(+), 44 deletions(-) diff --git a/Create.c b/Create.c index 0ad308f..6ba4383 100644 --- a/Create.c +++ b/Create.c @@ -692,7 +692,7 @@ int Create(struct supertype *st, char *mddev, name += 2; } } - if (!st->ss->init_super(st, &info.array, size, name, homehost, uuid)) + if (!st->ss->init_super(st, &info.array, size, name, homehost, uuid, -1LL)) goto abort_locked; total_slots = info.array.nr_disks; diff --git a/Kill.c b/Kill.c index bac4844..cd4f3d9 100644 --- a/Kill.c +++ b/Kill.c @@ -63,7 +63,7 @@ int Kill(char *dev, struct supertype *st, int force, int quiet, int noexcl) rv = st->ss->load_super(st, fd, dev); if (rv == 0 || (force && rv >= 2)) { st->ss->free_super(st); - st->ss->init_super(st, NULL, 0, "", NULL, NULL); + st->ss->init_super(st, NULL, 0, "", NULL, NULL, -1LL); if (st->ss->store_super(st, fd)) { if (!quiet) fprintf(stderr, Name ": Could not zero superblock on %s\n", diff --git a/mdadm.h b/mdadm.h index 0019a65..b3c9f53 100644 --- a/mdadm.h +++ b/mdadm.h @@ -681,7 +681,7 @@ extern struct superswitch { */ int (*init_super)(struct supertype *st, mdu_array_info_t *info, unsigned long long size, char *name, - char *homehost, int *uuid); + char *homehost, int *uuid, long long data_offset); /* update the metadata to include new device, either at create or * when hot-adding a spare. diff --git a/super-ddf.c b/super-ddf.c index a4144b7..6225a6f 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -1584,12 +1584,12 @@ static int init_super_ddf_bvd(struct supertype *st, mdu_array_info_t *info, unsigned long long size, char *name, char *homehost, - int *uuid); + int *uuid, long long data_offset); static int init_super_ddf(struct supertype *st, mdu_array_info_t *info, unsigned long long size, char *name, char *homehost, - int *uuid) + int *uuid, long long data_offset) { /* This is primarily called by Create when creating a new array. * We will then get add_to_super called for each component, and then @@ -1625,8 +1625,14 @@ static int init_super_ddf(struct supertype *st, struct phys_disk *pd; struct virtual_disk *vd; + if (data_offset >= 0) { + fprintf(stderr, Name ": data-offset not supported by DDF\n"); + return 0; + } + if (st->sb) - return init_super_ddf_bvd(st, info, size, name, homehost, uuid); + return init_super_ddf_bvd(st, info, size, name, homehost, uuid, + data_offset); if (posix_memalign((void**)&ddf, 512, sizeof(*ddf)) != 0) { fprintf(stderr, Name ": %s could not allocate superblock\n", __func__); @@ -1956,7 +1962,7 @@ static int init_super_ddf_bvd(struct supertype *st, mdu_array_info_t *info, unsigned long long size, char *name, char *homehost, - int *uuid) + int *uuid, long long data_offset) { /* We are creating a BVD inside a pre-existing container. * so st->sb is already set. diff --git a/super-intel.c b/super-intel.c index ea69094..d1dd705 100644 --- a/super-intel.c +++ b/super-intel.c @@ -4557,7 +4557,8 @@ static int check_name(struct intel_super *super, char *name, int quiet) static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, unsigned long long size, char *name, - char *homehost, int *uuid) + char *homehost, int *uuid, + long long data_offset) { /* We are creating a volume inside a pre-existing container. * so st->sb is already set. @@ -4726,7 +4727,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, static int init_super_imsm(struct supertype *st, mdu_array_info_t *info, unsigned long long size, char *name, - char *homehost, int *uuid) + char *homehost, int *uuid, long long data_offset) { /* This is primarily called by Create when creating a new array. * We will then get add_to_super called for each component, and then @@ -4741,8 +4742,14 @@ static int init_super_imsm(struct supertype *st, mdu_array_info_t *info, size_t mpb_size; char *version; + if (data_offset >= 0) { + fprintf(stderr, Name ": data-offset not supported by imsm\n"); + return 0; + } + if (st->sb) - return init_super_imsm_volume(st, info, size, name, homehost, uuid); + return init_super_imsm_volume(st, info, size, name, homehost, uuid, + data_offset); if (info) mpb_size = disks_to_mpb_size(info->nr_disks); diff --git a/super0.c b/super0.c index e0c5a55..ebebc49 100644 --- a/super0.c +++ b/super0.c @@ -601,11 +601,16 @@ static int update_super0(struct supertype *st, struct mdinfo *info, static int init_super0(struct supertype *st, mdu_array_info_t *info, unsigned long long size, char *ignored_name, char *homehost, - int *uuid) + int *uuid, long long data_offset) { mdp_super_t *sb; int spares; + if (data_offset >= 0) { + fprintf(stderr, Name ": data-offset not support for 0.90\n"); + return 0; + } + if (posix_memalign((void**)&sb, 4096, MD_SB_BYTES + ROUND_UP(sizeof(bitmap_super_t), 4096)) != 0) { fprintf(stderr, Name ": %s could not allocate superblock\n", __func__); diff --git a/super1.c b/super1.c index f8f3545..ee7b18b 100644 --- a/super1.c +++ b/super1.c @@ -862,7 +862,8 @@ static int update_super1(struct supertype *st, struct mdinfo *info, } static int init_super1(struct supertype *st, mdu_array_info_t *info, - unsigned long long size, char *name, char *homehost, int *uuid) + unsigned long long size, char *name, char *homehost, + int *uuid, long long data_offset) { struct mdp_superblock_1 *sb; int spares; @@ -926,7 +927,7 @@ static int init_super1(struct supertype *st, mdu_array_info_t *info, sb->chunksize = __cpu_to_le32(info->chunk_size>>9); sb->raid_disks = __cpu_to_le32(info->raid_disks); - sb->data_offset = __cpu_to_le64(0); + sb->data_offset = __cpu_to_le64(data_offset); sb->data_size = __cpu_to_le64(0); sb->super_offset = __cpu_to_le64(0); sb->recovery_offset = __cpu_to_le64(0); @@ -1095,6 +1096,7 @@ static int write_init_super1(struct supertype *st) struct devinfo *di; unsigned long long dsize, array_size; unsigned long long sb_offset, headroom; + long long data_offset; for (di = st->info; di && ! rv ; di = di->next) { if (di->disk.state == 1) @@ -1181,47 +1183,55 @@ static int write_init_super1(struct supertype *st) sb_offset -= 8*2; sb_offset &= ~(4*2-1); sb->super_offset = __cpu_to_le64(sb_offset); - sb->data_offset = __cpu_to_le64(0); + /* data_offset already set */ if (sb_offset < array_size + bm_space) bm_space = sb_offset - array_size; sb->data_size = __cpu_to_le64(sb_offset - bm_space); break; case 1: - sb->super_offset = __cpu_to_le64(0); - reserved = bm_space + 4*2; - /* Try for multiple of 1Meg so it is nicely aligned */ - #define ONE_MEG (2*1024) - reserved = ((reserved + ONE_MEG-1)/ONE_MEG) * ONE_MEG; - if (reserved + __le64_to_cpu(sb->size) > dsize) - reserved = dsize - __le64_to_cpu(sb->size); - /* force 4K alignment */ - reserved &= ~7ULL; - - if (reserved < headroom) - reserved = headroom; + data_offset = (long long)(int64_t)__le64_to_cpu(sb->data_offset); + if (data_offset < 0) { + sb->super_offset = __cpu_to_le64(0); + reserved = bm_space + 4*2; + /* Try for multiple of 1Meg so it is nicely aligned */ + #define ONE_MEG (2*1024) + reserved = ((reserved + ONE_MEG-1)/ONE_MEG) * ONE_MEG; + if (reserved + __le64_to_cpu(sb->size) > dsize) + reserved = dsize - __le64_to_cpu(sb->size); + /* force 4K alignment */ + reserved &= ~7ULL; + + if (reserved < headroom) + reserved = headroom; + } else + reserved = data_offset; sb->data_offset = __cpu_to_le64(reserved); sb->data_size = __cpu_to_le64(dsize - reserved); break; case 2: - sb_offset = 4*2; - sb->super_offset = __cpu_to_le64(4*2); - if (4*2 + 4*2 + bm_space + __le64_to_cpu(sb->size) - > dsize) - bm_space = dsize - __le64_to_cpu(sb->size) - - 4*2 - 4*2; - - reserved = bm_space + 4*2 + 4*2; - /* Try for multiple of 1Meg so it is nicely aligned */ - #define ONE_MEG (2*1024) - reserved = ((reserved + ONE_MEG-1)/ONE_MEG) * ONE_MEG; - if (reserved + __le64_to_cpu(sb->size) > dsize) - reserved = dsize - __le64_to_cpu(sb->size); - /* force 4K alignment */ - reserved &= ~7ULL; - - if (reserved < headroom) - reserved = headroom; + data_offset = (long long)(int64_t)__le64_to_cpu(sb->data_offset); + if (data_offset < 0) { + sb_offset = 4*2; + sb->super_offset = __cpu_to_le64(4*2); + if (4*2 + 4*2 + bm_space + __le64_to_cpu(sb->size) + > dsize) + bm_space = dsize - __le64_to_cpu(sb->size) + - 4*2 - 4*2; + + reserved = bm_space + 4*2 + 4*2; + /* Try for multiple of 1Meg so it is nicely aligned */ + #define ONE_MEG (2*1024) + reserved = ((reserved + ONE_MEG-1)/ONE_MEG) * ONE_MEG; + if (reserved + __le64_to_cpu(sb->size) > dsize) + reserved = dsize - __le64_to_cpu(sb->size); + /* force 4K alignment */ + reserved &= ~7ULL; + + if (reserved < headroom) + reserved = headroom; + } else + reserved = data_offset; sb->data_offset = __cpu_to_le64(reserved); sb->data_size = __cpu_to_le64(dsize - reserved); -- cgit v1.2.1