super1: encourage data alignment on 1Meg boundary

For 1.1 and 1.2 metadata where data_offset is not zero,
it is important to align the data_offset to underlying
block size.

We don't currently have access to the particular device
in avail_size so just try to force to a 1Meg boundary.

Also default 1.x metadata to 1.2 as documented.

Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
NeilBrown 2010-03-03 15:22:56 +11:00
parent d1d3482b56
commit a380e2751e
1 changed files with 40 additions and 12 deletions

View File

@ -994,6 +994,8 @@ static unsigned long choose_bm_space(unsigned long devsize)
{ {
/* if the device is bigger than 8Gig, save 64k for bitmap usage, /* if the device is bigger than 8Gig, save 64k for bitmap usage,
* if bigger than 200Gig, save 128k * if bigger than 200Gig, save 128k
* NOTE: result must be multiple of 4K else bad things happen
* on 4K-sector devices.
*/ */
if (devsize < 64*2) return 0; if (devsize < 64*2) return 0;
if (devsize - 64*2 >= 200*1024*1024*2) if (devsize - 64*2 >= 200*1024*1024*2)
@ -1011,6 +1013,7 @@ static int write_init_super1(struct supertype *st)
int rfd; int rfd;
int rv = 0; int rv = 0;
int bm_space; int bm_space;
unsigned long long reserved;
struct devinfo *di; struct devinfo *di;
unsigned long long dsize, array_size; unsigned long long dsize, array_size;
long long sb_offset; long long sb_offset;
@ -1094,10 +1097,17 @@ static int write_init_super1(struct supertype *st)
break; break;
case 1: case 1:
sb->super_offset = __cpu_to_le64(0); sb->super_offset = __cpu_to_le64(0);
if (4*2 + bm_space + __le64_to_cpu(sb->size) > dsize) reserved = bm_space + 4*2;
bm_space = dsize - __le64_to_cpu(sb->size) -4*2; /* Try for multiple of 1Meg so it is nicely aligned */
sb->data_offset = __cpu_to_le64(bm_space + 4*2); #define ONE_MEG (2*1024)
sb->data_size = __cpu_to_le64(dsize - bm_space - 4*2); reserved = ((reserved + ONE_MEG-1)/ONE_MEG) * ONE_MEG;
if (reserved + __le64_to_cpu(sb->size) > dsize)
reserved = dsize - __le64_to_cpu(sb->size);
/* force 4K alignment */
reserved &= ~7ULL;
sb->data_offset = __cpu_to_le64(reserved);
sb->data_size = __cpu_to_le64(dsize - reserved);
break; break;
case 2: case 2:
sb_offset = 4*2; sb_offset = 4*2;
@ -1106,9 +1116,18 @@ static int write_init_super1(struct supertype *st)
> dsize) > dsize)
bm_space = dsize - __le64_to_cpu(sb->size) bm_space = dsize - __le64_to_cpu(sb->size)
- 4*2 - 4*2; - 4*2 - 4*2;
sb->data_offset = __cpu_to_le64(4*2 + 4*2 + bm_space);
sb->data_size = __cpu_to_le64(dsize - 4*2 - 4*2 reserved = bm_space + 4*2 + 4*2;
- bm_space ); /* 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);
/* force 4K alignment */
reserved &= ~7ULL;
sb->data_offset = __cpu_to_le64(reserved);
sb->data_size = __cpu_to_le64(dsize - reserved);
break; break;
default: default:
return -EINVAL; return -EINVAL;
@ -1400,10 +1419,19 @@ static __u64 avail_size1(struct supertype *st, __u64 devsize)
} }
#endif #endif
if (st->minor_version < 0)
/* not specified, so time to set default */
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
*/
if (devsize > 1024*1024*2)
devsize -= 1024*2;
}
switch(st->minor_version) { switch(st->minor_version) {
case -1: /* no specified. Now time to set default */
st->minor_version = 0;
/* FALL THROUGH */
case 0: case 0:
/* at end */ /* at end */
return ((devsize - 8*2 ) & ~(4*2-1)); return ((devsize - 8*2 ) & ~(4*2-1));