mdadm/mdadm-3.2.4-super1-fix-choice-of-data_offset.patch
Jes Sorensen aa53f3daa8 Fix mdadm-3.2.4 introduced bug where --add fails in common cases
Resolves: bz821717 (f17) bz821718 (f16) bz821719 (f15)

Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com>
2012-05-15 14:30:56 +02:00

93 lines
2.8 KiB
Diff

From d9751e06a601b5576b1b9e2c8126584083110ca5 Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Tue, 15 May 2012 09:51:03 +1000
Subject: [PATCH] super1: fix choice of data_offset.
While it is nice to set a high data_offset to leave plenty of head
room it is much more important to leave enough space to allow
of the data of the array.
So after we check that sb->size is still available, only reduce the
'reserved', don't increase it.
This fixes a bug where --adding a spare fails because it does not have
enough space in it.
Reported-by: nowhere <nowhere@hakkenden.ath.cx>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super1.c | 31 ++++++++++++++++---------------
1 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/super1.c b/super1.c
index be77c33..4f20cc3 100644
--- a/super1.c
+++ b/super1.c
@@ -1189,40 +1189,42 @@ static int write_init_super1(struct supertype *st)
case 1:
sb->super_offset = __cpu_to_le64(0);
reserved = bm_space + 4*2;
+ if (reserved < headroom)
+ reserved = headroom;
+ if (reserved + array_size > dsize)
+ reserved = dsize - array_size;
/* 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);
+ if (reserved > ONE_MEG)
+ reserved = (reserved/ONE_MEG) * ONE_MEG;
+
/* force 4K alignment */
reserved &= ~7ULL;
- if (reserved < headroom)
- reserved = headroom;
-
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)
+ if (4*2 + 4*2 + bm_space + array_size
> dsize)
- bm_space = dsize - __le64_to_cpu(sb->size)
+ bm_space = dsize - array_size
- 4*2 - 4*2;
reserved = bm_space + 4*2 + 4*2;
+ if (reserved < headroom)
+ reserved = headroom;
+ if (reserved + array_size > dsize)
+ reserved = dsize - array_size;
/* 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);
+ if (reserved > ONE_MEG)
+ reserved = (reserved/ONE_MEG) * ONE_MEG;
+
/* force 4K alignment */
reserved &= ~7ULL;
- if (reserved < headroom)
- reserved = headroom;
-
sb->data_offset = __cpu_to_le64(reserved);
sb->data_size = __cpu_to_le64(dsize - reserved);
break;
@@ -1234,7 +1236,6 @@ static int write_init_super1(struct supertype *st)
goto out;
}
-
sb->sb_csum = calc_sb_1_csum(sb);
rv = store_super1(st, di->fd);
if (rv == 0 && (__le32_to_cpu(sb->feature_map) & 1))
--
1.7.7.6