summaryrefslogtreecommitdiffstats
path: root/super1.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2008-10-15 14:34:18 +1100
committerNeilBrown <neilb@suse.de>2008-10-15 14:34:18 +1100
commit1c6cb603fa60d3425f4d4b76e721b485bb006fcb (patch)
treeea7f7d00936e31e51f0016d4b72f7dc69ebc952c /super1.c
parente4965ef8461b3d0db6e94939f07d814d819f86c2 (diff)
downloadmdadm-1c6cb603fa60d3425f4d4b76e721b485bb006fcb.tar.gz
mdadm-1c6cb603fa60d3425f4d4b76e721b485bb006fcb.tar.xz
mdadm-1c6cb603fa60d3425f4d4b76e721b485bb006fcb.zip
Grow: Fix linear-growth when devices are not all the same size.
If we add a device to a linear array which is a difference size to the other devices in the array then, for v1.x metadata, we need to make sure the size is correctly reflected in the superblock.
Diffstat (limited to 'super1.c')
-rw-r--r--super1.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/super1.c b/super1.c
index bec0c5e..62a3ab9 100644
--- a/super1.c
+++ b/super1.c
@@ -599,7 +599,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
}
if (strcmp(update, "linear-grow-new") == 0) {
int i;
- int rfd;
+ int rfd, fd;
int max = __le32_to_cpu(sb->max_dev);
for (i=0 ; i < max ; i++)
@@ -620,6 +620,25 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
sb->dev_roles[i] =
__cpu_to_le16(info->disk.raid_disk);
+
+ fd = open(devname, O_RDONLY);
+ if (fd >= 0) {
+ unsigned long long ds;
+ get_dev_size(fd, devname, &ds);
+ close(fd);
+ ds >>= 9;
+ if (__le64_to_cpu(sb->super_offset) <
+ __le64_to_cpu(sb->data_offset)) {
+ sb->data_size = __cpu_to_le64(
+ ds - __le64_to_cpu(sb->data_offset));
+ } else {
+ ds -= 8*2;
+ ds &= ~(unsigned long long)(4*2-1);
+ sb->super_offset = __cpu_to_le64(ds);
+ sb->data_size = __cpu_to_le64(
+ ds - __le64_to_cpu(sb->data_offset));
+ }
+ }
}
if (strcmp(update, "linear-grow-update") == 0) {
sb->raid_disks = __cpu_to_le32(info->array.raid_disks);