Grow/bitmap: support adding bitmap via sysfs.
Adding a bitmap via ioctl can only add it at a fixed location. That location is not suitable for 4K-block devices. So allow setting the bitmap location via sysfs if kernel supports it and aim to always use 4K alignments. Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
parent
b6db6fab11
commit
c0c1acd691
24
Grow.c
24
Grow.c
|
@ -375,12 +375,18 @@ int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int
|
|||
return 1;
|
||||
}
|
||||
if (strcmp(file, "internal") == 0) {
|
||||
int rv;
|
||||
int d;
|
||||
int offset_setable = 0;
|
||||
struct mdinfo *mdi;
|
||||
if (st->ss->add_internal_bitmap == NULL) {
|
||||
fprintf(stderr, Name ": Internal bitmaps not supported "
|
||||
"with %s metadata\n", st->ss->name);
|
||||
return 1;
|
||||
}
|
||||
mdi = sysfs_read(fd, -1, GET_BITMAP_LOCATION);
|
||||
if (mdi)
|
||||
offset_setable = 1;
|
||||
for (d=0; d< st->max_devs; d++) {
|
||||
mdu_disk_info_t disk;
|
||||
char *dv;
|
||||
|
@ -401,11 +407,13 @@ int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int
|
|||
if (st->ss->add_internal_bitmap(
|
||||
st,
|
||||
&chunk, delay, write_behind,
|
||||
bitmapsize, 0, major)
|
||||
bitmapsize, offset_setable,
|
||||
major)
|
||||
)
|
||||
st->ss->write_bitmap(st, fd2);
|
||||
else {
|
||||
fprintf(stderr, Name ": failed to create internal bitmap - chunksize problem.\n");
|
||||
fprintf(stderr, Name ": failed "
|
||||
"to create internal bitmap - chunksize problem.\n");
|
||||
close(fd2);
|
||||
return 1;
|
||||
}
|
||||
|
@ -413,8 +421,16 @@ int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int
|
|||
close(fd2);
|
||||
}
|
||||
}
|
||||
array.state |= (1<<MD_SB_BITMAP_PRESENT);
|
||||
if (ioctl(fd, SET_ARRAY_INFO, &array)!= 0) {
|
||||
if (offset_setable) {
|
||||
st->ss->getinfo_super(st, mdi, NULL);
|
||||
sysfs_init(mdi, fd, -1);
|
||||
rv = sysfs_set_num(mdi, NULL, "bitmap/location",
|
||||
mdi->bitmap_offset);
|
||||
} else {
|
||||
array.state |= (1<<MD_SB_BITMAP_PRESENT);
|
||||
rv = ioctl(fd, SET_ARRAY_INFO, &array);
|
||||
}
|
||||
if (rv < 0) {
|
||||
if (errno == EBUSY)
|
||||
fprintf(stderr, Name
|
||||
": Cannot add bitmap while array is"
|
||||
|
|
13
mdadm.h
13
mdadm.h
|
@ -211,6 +211,7 @@ struct mdinfo {
|
|||
unsigned long long recovery_start; /* per-device rebuild position */
|
||||
#define MaxSector (~0ULL) /* resync/recovery complete position */
|
||||
};
|
||||
unsigned long bitmap_offset; /* 0 == none, 1 == a file */
|
||||
unsigned long safe_mode_delay; /* ms delay to mark clean */
|
||||
int new_level, delta_disks, new_layout, new_chunk;
|
||||
int errors;
|
||||
|
@ -448,11 +449,13 @@ enum sysfs_read_flags {
|
|||
GET_DISKS = (1 << 7),
|
||||
GET_DEGRADED = (1 << 8),
|
||||
GET_SAFEMODE = (1 << 9),
|
||||
GET_DEVS = (1 << 10), /* gets role, major, minor */
|
||||
GET_OFFSET = (1 << 11),
|
||||
GET_SIZE = (1 << 12),
|
||||
GET_STATE = (1 << 13),
|
||||
GET_ERROR = (1 << 14),
|
||||
GET_BITMAP_LOCATION = (1 << 10),
|
||||
|
||||
GET_DEVS = (1 << 20), /* gets role, major, minor */
|
||||
GET_OFFSET = (1 << 21),
|
||||
GET_SIZE = (1 << 22),
|
||||
GET_STATE = (1 << 23),
|
||||
GET_ERROR = (1 << 24),
|
||||
};
|
||||
|
||||
/* If fd >= 0, get the array it is open on,
|
||||
|
|
3
super0.c
3
super0.c
|
@ -360,6 +360,9 @@ static void getinfo_super0(struct supertype *st, struct mdinfo *info, char *map)
|
|||
info->array.state = sb->state;
|
||||
info->component_size = sb->size*2;
|
||||
|
||||
if (sb->state & (1<<MD_SB_BITMAP_PRESENT))
|
||||
info->bitmap_offset = 8;
|
||||
|
||||
info->disk.state = sb->this_disk.state;
|
||||
info->disk.major = sb->this_disk.major;
|
||||
info->disk.minor = sb->this_disk.minor;
|
||||
|
|
37
super1.c
37
super1.c
|
@ -578,6 +578,8 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map)
|
|||
|
||||
info->data_offset = __le64_to_cpu(sb->data_offset);
|
||||
info->component_size = __le64_to_cpu(sb->size);
|
||||
if (sb->feature_map & __le32_to_cpu(MD_FEATURE_BITMAP_OFFSET))
|
||||
info->bitmap_offset = __le32_to_cpu(sb->bitmap_offset);
|
||||
|
||||
info->disk.major = 0;
|
||||
info->disk.minor = 0;
|
||||
|
@ -1384,7 +1386,8 @@ static int load_super1(struct supertype *st, int fd, char *devname)
|
|||
return 0;
|
||||
|
||||
no_bitmap:
|
||||
super->feature_map = __cpu_to_le32(__le32_to_cpu(super->feature_map) & ~1);
|
||||
super->feature_map = __cpu_to_le32(__le32_to_cpu(super->feature_map)
|
||||
& ~MD_FEATURE_BITMAP_OFFSET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1486,12 +1489,10 @@ add_internal_bitmap1(struct supertype *st,
|
|||
int may_change, int major)
|
||||
{
|
||||
/*
|
||||
* If not may_change, then this is a 'Grow', and the bitmap
|
||||
* must fit after the superblock.
|
||||
* If may_change, then this is create, and we can put the bitmap
|
||||
* before the superblock if we like, or may move the start.
|
||||
* If !may_change, the bitmap MUST live at offset of 1K, until
|
||||
* we get a sysfs interface.
|
||||
* If not may_change, then this is a 'Grow' without sysfs support for
|
||||
* bitmaps, and the bitmap must fit after the superblock at 1K offset.
|
||||
* If may_change, then this is create or a Grow with sysfs syupport,
|
||||
* and we can put the bitmap wherever we like.
|
||||
*
|
||||
* size is in sectors, chunk is in bytes !!!
|
||||
*/
|
||||
|
@ -1502,16 +1503,20 @@ add_internal_bitmap1(struct supertype *st,
|
|||
long offset;
|
||||
unsigned long long chunk = *chunkp;
|
||||
int room = 0;
|
||||
int creating = 0;
|
||||
struct mdp_superblock_1 *sb = st->sb;
|
||||
bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + 1024);
|
||||
int uuid[4];
|
||||
|
||||
if (__le64_to_cpu(sb->data_size) == 0)
|
||||
/* Must be creating the array, else data_size would be non-zero */
|
||||
creating = 1;
|
||||
switch(st->minor_version) {
|
||||
case 0:
|
||||
/* either 3K after the superblock (when hot-add),
|
||||
* or some amount of space before.
|
||||
*/
|
||||
if (may_change) {
|
||||
if (creating) {
|
||||
/* We are creating array, so we *know* how much room has
|
||||
* been left.
|
||||
*/
|
||||
|
@ -1521,8 +1526,8 @@ add_internal_bitmap1(struct supertype *st,
|
|||
room = __le64_to_cpu(sb->super_offset)
|
||||
- __le64_to_cpu(sb->data_offset)
|
||||
- __le64_to_cpu(sb->data_size);
|
||||
/* remove '1 ||' when we can set offset via sysfs */
|
||||
if (1 || (room < 3*2 &&
|
||||
|
||||
if (!may_change || (room < 3*2 &&
|
||||
__le32_to_cpu(sb->max_dev) <= 384)) {
|
||||
room = 3*2;
|
||||
offset = 1*2;
|
||||
|
@ -1533,17 +1538,17 @@ add_internal_bitmap1(struct supertype *st,
|
|||
break;
|
||||
case 1:
|
||||
case 2: /* between superblock and data */
|
||||
if (may_change) {
|
||||
if (creating) {
|
||||
offset = 4*2;
|
||||
room = choose_bm_space(__le64_to_cpu(sb->size));
|
||||
} else {
|
||||
room = __le64_to_cpu(sb->data_offset)
|
||||
- __le64_to_cpu(sb->super_offset);
|
||||
if (1 || __le32_to_cpu(sb->max_dev) <= 384) {
|
||||
room -= 2;
|
||||
if (!may_change) {
|
||||
room -= 2; /* Leave 1K for superblock */
|
||||
offset = 2;
|
||||
} else {
|
||||
room -= 4*2;
|
||||
room -= 4*2; /* leave 4K for superblock */
|
||||
offset = 4*2;
|
||||
}
|
||||
}
|
||||
|
@ -1588,7 +1593,8 @@ add_internal_bitmap1(struct supertype *st,
|
|||
|
||||
sb->bitmap_offset = __cpu_to_le32(offset);
|
||||
|
||||
sb->feature_map = __cpu_to_le32(__le32_to_cpu(sb->feature_map) | 1);
|
||||
sb->feature_map = __cpu_to_le32(__le32_to_cpu(sb->feature_map)
|
||||
| MD_FEATURE_BITMAP_OFFSET);
|
||||
memset(bms, 0, sizeof(*bms));
|
||||
bms->magic = __cpu_to_le32(BITMAP_MAGIC);
|
||||
bms->version = __cpu_to_le32(major);
|
||||
|
@ -1603,7 +1609,6 @@ add_internal_bitmap1(struct supertype *st,
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void locate_bitmap1(struct supertype *st, int fd)
|
||||
{
|
||||
unsigned long long offset;
|
||||
|
|
13
sysfs.c
13
sysfs.c
|
@ -217,6 +217,19 @@ struct mdinfo *sysfs_read(int fd, int devnum, unsigned long options)
|
|||
msec = (msec * 1000) / scale;
|
||||
sra->safe_mode_delay = msec;
|
||||
}
|
||||
if (options & GET_BITMAP_LOCATION) {
|
||||
strcpy(base, "bitmap/location");
|
||||
if (load_sys(fname, buf))
|
||||
goto abort;
|
||||
if (strncmp(buf, "file", 4) == 0)
|
||||
sra->bitmap_offset = 1;
|
||||
else if (strncmp(buf, "none", 4) == 0)
|
||||
sra->bitmap_offset = 0;
|
||||
else if (buf[0] == '+')
|
||||
sra->bitmap_offset = strtoul(buf+1, NULL, 10);
|
||||
else
|
||||
goto abort;
|
||||
}
|
||||
|
||||
if (! (options & GET_DEVS))
|
||||
return sra;
|
||||
|
|
Loading…
Reference in New Issue