diff options
-rw-r--r-- | Grow.c | 24 | ||||
-rw-r--r-- | mdadm.h | 13 | ||||
-rw-r--r-- | super0.c | 3 | ||||
-rw-r--r-- | super1.c | 37 | ||||
-rw-r--r-- | sysfs.c | 13 |
5 files changed, 65 insertions, 25 deletions
@@ -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" @@ -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, @@ -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; @@ -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; @@ -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; |