summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog2
-rw-r--r--mdadm.817
-rw-r--r--mdadm.c6
-rw-r--r--super1.c34
4 files changed, 52 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index 6ea0c3b..1c359f8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,8 @@ Changes Prior to this release
missing devices (which is needed else if won't assemble.
Without this fix it would only assemble if one or zero
missing devices.
+ - Support --update=devicesize for cases where the underlying device
+ can change size.
Changes Prior to 2.5.6 release
- Fix bug which meant "bitmap=xxx" in mdadm.conf was not handled
diff --git a/mdadm.8 b/mdadm.8
index 2e92ec9..f761853 100644
--- a/mdadm.8
+++ b/mdadm.8
@@ -712,6 +712,7 @@ argument given to this flag can be one of
.BR homehost ,
.BR resync ,
.BR byteorder ,
+.BR devicesize ,
or
.BR super-minor .
@@ -789,6 +790,22 @@ The
option will correct the summaries in the superblock. That is the
counts of total, working, active, failed, and spare devices.
+The
+.B devicesize
+will rarely be of use. It applies to version 1.1 and 1.2 metadata
+only (where the metadata is at the start of the device) and is only
+useful when the component device has changed size (typically become
+larger). The version 1 metadata records the amount of the device that
+can be used to store data, so if a device in a version 1.1 or 1.2
+array becomes larger, the metadata will still be visible, but the
+extra space will not. In this case it might be useful to assemble the
+array with
+.BR --update=devicesize .
+This will cause
+.I mdadm
+to determine the maximum usable amount of space on each device and
+update the relevant field in the metadata.
+
.TP
.B --auto-update-homehost
This flag is only meaning with auto-assembly (see discussion below).
diff --git a/mdadm.c b/mdadm.c
index 286df30..41360c4 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -582,6 +582,8 @@ int main(int argc, char *argv[])
continue;
if (strcmp(update, "homehost")==0)
continue;
+ if (strcmp(update, "devicesize")==0)
+ continue;
if (strcmp(update, "byteorder")==0) {
if (ss) {
fprintf(stderr, Name ": must not set metadata type with --update=byteorder.\n");
@@ -601,8 +603,8 @@ int main(int argc, char *argv[])
else
fprintf(stderr, Name ": '--update=%s' is invalid. ", update);
fprintf(stderr, "Valid --update options are:\n"
- " 'sparc2.2', 'super-minor', 'uuid', 'name', 'resync',\n"
- " 'summaries', 'homehost', 'byteorder'.\n");
+ " 'sparc2.2', 'super-minor', 'uuid', 'name', 'resync',\n"
+ " 'summaries', 'homehost', 'byteorder', 'devicesize'.\n");
exit(2);
case O(ASSEMBLE,NoDegraded): /* --no-degraded */
diff --git a/super1.c b/super1.c
index 7aa324f..368d9bc 100644
--- a/super1.c
+++ b/super1.c
@@ -94,6 +94,10 @@ struct mdp_superblock_1 {
__u16 dev_roles[0]; /* role in array, or 0xffff for a spare, or 0xfffe for faulty */
};
+struct misc_dev_info {
+ __u64 device_size;
+};
+
/* feature_map bits */
#define MD_FEATURE_BITMAP_OFFSET 1
#define MD_FEATURE_RECOVERY_OFFSET 2 /* recovery_offset is present and
@@ -558,6 +562,17 @@ static int update_super1(struct mdinfo *info, void *sbv, char *update,
} else
strcpy(sb->set_name, info->name);
}
+ if (strcmp(update, "devicesize") == 0 &&
+ __le64_to_cpu(sb->super_offset) <
+ __le64_to_cpu(sb->data_offset)) {
+ /* set data_size to device size less data_offset */
+ struct misc_dev_info *misc = (struct misc_dev_info*)
+ (sbv + 1024 + sizeof(struct bitmap_super_s));
+ printf("Size was %llu\n", __le64_to_cpu(sb->data_size));
+ sb->data_size = __cpu_to_le64(
+ misc->device_size - __le64_to_cpu(sb->data_offset));
+ printf("Size is %llu\n", __le64_to_cpu(sb->data_size));
+ }
if (strcmp(update, "_reshape_progress")==0)
sb->reshape_position = __cpu_to_le64(info->reshape_progress);
@@ -568,7 +583,8 @@ static int update_super1(struct mdinfo *info, void *sbv, char *update,
static int init_super1(struct supertype *st, void **sbp, mdu_array_info_t *info,
unsigned long long size, char *name, char *homehost)
{
- struct mdp_superblock_1 *sb = malloc(1024 + sizeof(bitmap_super_t));
+ struct mdp_superblock_1 *sb = malloc(1024 + sizeof(bitmap_super_t) +
+ sizeof(struct misc_dev_info));
int spares;
int rfd;
char defname[10];
@@ -882,8 +898,10 @@ static int compare_super1(void **firstp, void *secondv)
return 1;
if (!first) {
- first = malloc(1024+sizeof(bitmap_super_t));
- memcpy(first, second, 1024+sizeof(bitmap_super_t));
+ first = malloc(1024+sizeof(bitmap_super_t) +
+ sizeof(struct misc_dev_info));
+ memcpy(first, second, 1024+sizeof(bitmap_super_t) +
+ sizeof(struct misc_dev_info));
*firstp = first;
return 0;
}
@@ -908,6 +926,7 @@ static int load_super1(struct supertype *st, int fd, void **sbp, char *devname)
struct mdp_superblock_1 *super;
int uuid[4];
struct bitmap_super_s *bsb;
+ struct misc_dev_info *misc;
if (st->ss == NULL) {
@@ -997,7 +1016,8 @@ static int load_super1(struct supertype *st, int fd, void **sbp, char *devname)
return 1;
}
- super = malloc(1024 + sizeof(bitmap_super_t));
+ super = malloc(1024 + sizeof(bitmap_super_t) +
+ sizeof(struct misc_dev_info));
if (read(fd, super, 1024) != 1024) {
if (devname)
@@ -1031,6 +1051,11 @@ static int load_super1(struct supertype *st, int fd, void **sbp, char *devname)
}
*sbp = super;
+ bsb = (struct bitmap_super_s *)(((char*)super)+1024);
+
+ misc = (struct misc_dev_info*) (bsb+1);
+ misc->device_size = dsize;
+
/* Now check on the bitmap superblock */
if ((__le32_to_cpu(super->feature_map)&MD_FEATURE_BITMAP_OFFSET) == 0)
return 0;
@@ -1044,7 +1069,6 @@ static int load_super1(struct supertype *st, int fd, void **sbp, char *devname)
goto no_bitmap;
uuid_from_super1(uuid, super);
- bsb = (struct bitmap_super_s *)(((char*)super)+1024);
if (__le32_to_cpu(bsb->magic) != BITMAP_MAGIC ||
memcmp(bsb->uuid, uuid, 16) != 0)
goto no_bitmap;