NeilBrown: super1: fix choice of data_offset.

Michael Tokarev mjt at alioth.debian.org
Fri May 25 18:01:37 UTC 2012


Module: mdadm
Branch: master
Commit: d9751e06a601b5576b1b9e2c8126584083110ca5
URL:    http://git.debian.org/?p=pkg-mdadm/mdadm.git;a=commit;h=d9751e06a601b5576b1b9e2c8126584083110ca5

Author: NeilBrown <neilb at suse.de>
Date:   Tue May 15 09:51:03 2012 +1000

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 at hakkenden.ath.cx>
Signed-off-by: NeilBrown <neilb at 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))




More information about the pkg-mdadm-commits mailing list