summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2012-04-04 14:00:40 +1000
committerNeilBrown <neilb@suse.de>2012-04-04 14:04:28 +1000
commit508a7f16b242d6c3353e15aab46ac8ca8dc7cd08 (patch)
tree7c630e2b43593bd4c7be269a2e04655bda4b8c05
parentfbdef49811c9e2b54e2064d9af68cfffa77c6e77 (diff)
downloadmdadm-508a7f16b242d6c3353e15aab46ac8ca8dc7cd08.tar.gz
super1: leave more space in front of data by default.
The kernel is growing the ability to avoid the need for a backup file during reshape by being able to change the data offset. For this to be useful we need plenty of free space before the data so the data offset can be reduced. So for v1.1 and v1.2 metadata make the default data_offset much larger. Aim for 128Meg, but keep a power of 2 and don't use more than 0.1% of each device. Don't change v1.0 as that is used when the data_offset is required to be zero. Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r--super1.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/super1.c b/super1.c
index 2770a7f..36369d8 100644
--- a/super1.c
+++ b/super1.c
@@ -1094,7 +1094,7 @@ static int write_init_super1(struct supertype *st)
unsigned long long reserved;
struct devinfo *di;
unsigned long long dsize, array_size;
- unsigned long long sb_offset;
+ unsigned long long sb_offset, headroom;
for (di = st->info; di && ! rv ; di = di->next) {
if (di->disk.state == 1)
@@ -1167,6 +1167,14 @@ static int write_init_super1(struct supertype *st)
/* work out how much space we left for a bitmap */
bm_space = choose_bm_space(array_size);
+ /* We try to leave 0.1% at the start for reshape
+ * operations, but limit this to 128Meg (0.1% of 10Gig)
+ * which is plenty for efficient reshapes
+ */
+ headroom = 128 * 1024 * 2;
+ while (headroom << 10 > array_size)
+ headroom >>= 1;
+
switch(st->minor_version) {
case 0:
sb_offset = dsize;
@@ -1189,6 +1197,9 @@ static int write_init_super1(struct supertype *st)
/* 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;
@@ -1209,6 +1220,9 @@ static int write_init_super1(struct supertype *st)
/* 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;
@@ -1506,12 +1520,13 @@ static __u64 avail_size1(struct supertype *st, __u64 devsize)
st->minor_version = 2;
if (super == NULL && st->minor_version > 0) {
/* haven't committed to a size yet, so allow some
- * slack for alignment of data_offset.
- * We haven't access to device details so allow
- * 1 Meg if bigger than 1Gig
+ * slack for space for reshape.
+ * Limit slack to 128M, but aim for about 0.1%
*/
- if (devsize > 1024*1024*2)
- devsize -= 1024*2;
+ unsigned long long headroom = 128*1024*2;
+ while ((headroom << 10) > devsize)
+ headroom >>= 1;
+ devsize -= headroom;
}
switch(st->minor_version) {
case 0: