X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=super1.c;h=d23d6e8e5464ebd734c35a884066ea482b2d8650;hb=d59770567cc6078f555663cbc1929ddffdcc2f2e;hp=e8f59c6a1132afaf4dfa90a9975d2f4cf2cba619;hpb=d43494fc3c074fc589d928aaf227806437ef530b;p=thirdparty%2Fmdadm.git diff --git a/super1.c b/super1.c index e8f59c6a..d23d6e8e 100644 --- a/super1.c +++ b/super1.c @@ -111,7 +111,6 @@ static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb) unsigned long long newcsum; int size = sizeof(*sb) + __le32_to_cpu(sb->max_dev)*2; unsigned int *isuper = (unsigned int*)sb; - int i; /* make sure I can count... */ if (offsetof(struct mdp_superblock_1,data_offset) != 128 || @@ -123,7 +122,7 @@ static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb) disk_csum = sb->sb_csum; sb->sb_csum = 0; newcsum = 0; - for (i=0; size>=4; size -= 4 ) { + for (; size>=4; size -= 4 ) { newcsum += __le32_to_cpu(*isuper); isuper++; } @@ -314,7 +313,7 @@ static void examine_super1(struct supertype *st, char *homehost) printf("\n"); } if (sb->devflags) { - printf(" Flags :"); + printf(" Flags :"); if (sb->devflags & WriteMostly1) printf(" write-mostly"); printf("\n"); @@ -387,15 +386,11 @@ static void examine_super1(struct supertype *st, char *homehost) printf(" Array State : "); for (d=0; d<__le32_to_cpu(sb->raid_disks) + delta_extra; d++) { int cnt = 0; - int me = 0; unsigned int i; for (i=0; i< __le32_to_cpu(sb->max_dev); i++) { unsigned int role = __le16_to_cpu(sb->dev_roles[i]); - if (role == d) { - if (i == __le32_to_cpu(sb->dev_number)) - me = 1; + if (role == d) cnt++; - } } if (cnt > 1) printf("?"); else if (cnt == 1) printf("A"); @@ -558,13 +553,15 @@ static void uuid_from_super1(struct supertype *st, int uuid[4]) cuuid[i] = super->set_uuid[i]; } -static void getinfo_super1(struct supertype *st, struct mdinfo *info) +static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map) { struct mdp_superblock_1 *sb = st->sb; int working = 0; unsigned int i; - int role; + unsigned int role; + unsigned int map_disks = info->array.raid_disks; + memset(info, 0, sizeof(*info)); info->array.major_version = 1; info->array.minor_version = st->minor_version; info->array.patch_version = 0; @@ -576,11 +573,13 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info) info->array.utime = __le64_to_cpu(sb->utime); info->array.chunk_size = __le32_to_cpu(sb->chunksize)*512; info->array.state = - (__le64_to_cpu(sb->resync_offset) >= __le64_to_cpu(sb->size)) + (__le64_to_cpu(sb->resync_offset) == MaxSector) ? 1 : 0; 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; @@ -603,6 +602,8 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info) info->disk.state = 6; /* active and in sync */ info->disk.raid_disk = role; } + if (sb->devflags & WriteMostly1) + info->disk.state |= (1 << MD_DISK_WRITEMOSTLY); info->events = __le64_to_cpu(sb->events); sprintf(info->text_version, "1.%d", st->minor_version); info->safe_mode_delay = 200; @@ -629,22 +630,43 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info) } else info->reshape_active = 0; + info->recovery_blocked = info->reshape_active; + + if (map) + for (i=0; imax_dev); i++) { role = __le16_to_cpu(sb->dev_roles[i]); - if (/*role == 0xFFFF || */role < info->array.raid_disks) + if (/*role == 0xFFFF || */role < (unsigned) info->array.raid_disks) { working++; + if (map && role < map_disks) + map[role] = 1; + } } info->array.working_disks = working; } +static struct mdinfo *container_content1(struct supertype *st, char *subarray) +{ + struct mdinfo *info; + + if (subarray) + return NULL; + + info = malloc(sizeof(*info)); + getinfo_super1(st, info, NULL); + return info; +} + static int update_super1(struct supertype *st, struct mdinfo *info, char *update, char *devname, int verbose, int uuid_set, char *homehost) { - /* NOTE: for 'assemble' and 'force' we need to return non-zero if any change was made. - * For others, the return value is ignored. + /* NOTE: for 'assemble' and 'force' we need to return non-zero + * if any change was made. For others, the return value is + * ignored. */ int rv = 0; struct mdp_superblock_1 *sb = st->sb; @@ -656,8 +678,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info, if (sb->events != __cpu_to_le64(info->events)) rv = 1; sb->events = __cpu_to_le64(info->events); - } - if (strcmp(update, "force-array")==0) { + } else if (strcmp(update, "force-array")==0) { /* Degraded array and 'force' requests to * maybe need to mark it 'clean'. */ @@ -668,8 +689,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info, rv = 1; sb->resync_offset = MaxSector; } - } - if (strcmp(update, "assemble")==0) { + } else if (strcmp(update, "assemble")==0) { int d = info->disk.number; int want; if (info->disk.state == 6) @@ -694,8 +714,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info, sb->reshape_position = __cpu_to_le64(info->reshape_progress); rv = 1; } - } - if (strcmp(update, "linear-grow-new") == 0) { + } else if (strcmp(update, "linear-grow-new") == 0) { unsigned int i; int rfd, fd; unsigned int max = __le32_to_cpu(sb->max_dev); @@ -737,17 +756,14 @@ static int update_super1(struct supertype *st, struct mdinfo *info, ds - __le64_to_cpu(sb->data_offset)); } } - } - if (strcmp(update, "linear-grow-update") == 0) { + } else if (strcmp(update, "linear-grow-update") == 0) { sb->raid_disks = __cpu_to_le32(info->array.raid_disks); sb->dev_roles[info->disk.number] = __cpu_to_le16(info->disk.raid_disk); - } - if (strcmp(update, "resync") == 0) { + } else if (strcmp(update, "resync") == 0) { /* make sure resync happens */ sb->resync_offset = 0ULL; - } - if (strcmp(update, "uuid") == 0) { + } else if (strcmp(update, "uuid") == 0) { copy_uuid(sb->set_uuid, info->uuid, super1.swapuuid); if (__le32_to_cpu(sb->feature_map)&MD_FEATURE_BITMAP_OFFSET) { @@ -755,9 +771,10 @@ static int update_super1(struct supertype *st, struct mdinfo *info, bm = (struct bitmap_super_s*)(st->sb+1024); memcpy(bm->uuid, sb->set_uuid, 16); } - } - if (strcmp(update, "homehost") == 0 && - homehost) { + } else if (strcmp(update, "no-bitmap") == 0) { + sb->feature_map &= ~__cpu_to_le32(MD_FEATURE_BITMAP_OFFSET); + } else if (strcmp(update, "homehost") == 0 && + homehost) { char *c; update = "name"; c = strchr(sb->set_name, ':'); @@ -766,8 +783,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info, else strncpy(info->name, sb->set_name, 32); info->name[32] = 0; - } - if (strcmp(update, "name") == 0) { + } else if (strcmp(update, "name") == 0) { if (info->name[0] == 0) sprintf(info->name, "%d", info->array.md_minor); memset(sb->set_name, 0, sizeof(sb->set_name)); @@ -779,8 +795,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info, strcat(sb->set_name, info->name); } else strcpy(sb->set_name, info->name); - } - if (strcmp(update, "devicesize") == 0 && + } else if (strcmp(update, "devicesize") == 0 && __le64_to_cpu(sb->super_offset) < __le64_to_cpu(sb->data_offset)) { /* set data_size to device size less data_offset */ @@ -792,9 +807,14 @@ static int update_super1(struct supertype *st, struct mdinfo *info, misc->device_size - __le64_to_cpu(sb->data_offset)); printf("Size is %llu\n", (unsigned long long) __le64_to_cpu(sb->data_size)); - } - if (strcmp(update, "_reshape_progress")==0) + } else if (strcmp(update, "_reshape_progress")==0) sb->reshape_position = __cpu_to_le64(info->reshape_progress); + else if (strcmp(update, "writemostly")==0) + sb->devflags |= WriteMostly1; + else if (strcmp(update, "readwrite")==0) + sb->devflags &= ~WriteMostly1; + else + rv = -1; sb->sb_csum = calc_sb_1_csum(sb); return rv; @@ -913,6 +933,7 @@ static int add_to_super1(struct supertype *st, mdu_disk_info_t *dk, sb->max_dev = __cpu_to_le32(dk->number+1); sb->dev_number = __cpu_to_le32(dk->number); + sb->devflags = 0; /* don't copy another disks flags */ sb->sb_csum = calc_sb_1_csum(sb); dip = (struct devinfo **)&st->info; @@ -1019,11 +1040,13 @@ static unsigned long choose_bm_space(unsigned long devsize) return 4*2; } +static void free_super1(struct supertype *st); + #ifndef MDASSEMBLE static int write_init_super1(struct supertype *st) { struct mdp_superblock_1 *sb = st->sb; - struct supertype refst; + struct supertype *refst; int rfd; int rv = 0; unsigned long long bm_space; @@ -1043,7 +1066,9 @@ static int write_init_super1(struct supertype *st) sb->dev_number = __cpu_to_le32(di->disk.number); if (di->disk.state & (1<devflags |= __cpu_to_le32(WriteMostly1); + sb->devflags |= WriteMostly1; + else + sb->devflags &= ~WriteMostly1; if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 || read(rfd, sb->device_uuid, 16) != 16) { @@ -1055,10 +1080,9 @@ static int write_init_super1(struct supertype *st) sb->events = 0; - refst =*st; - refst.sb = NULL; - if (load_super1(&refst, di->fd, NULL)==0) { - struct mdp_superblock_1 *refsb = refst.sb; + refst = dup_super(st); + if (load_super1(refst, di->fd, NULL)==0) { + struct mdp_superblock_1 *refsb = refst->sb; memcpy(sb->device_uuid, refsb->device_uuid, 16); if (memcmp(sb->set_uuid, refsb->set_uuid, 16)==0) { @@ -1071,8 +1095,9 @@ static int write_init_super1(struct supertype *st) if (get_linux_version() >= 2006018) sb->dev_number = refsb->dev_number; } - free(refsb); + free_super1(refst); } + free(refst); if (!get_dev_size(di->fd, NULL, &dsize)) return 1; @@ -1207,8 +1232,6 @@ static int compare_super1(struct supertype *st, struct supertype *tst) return 0; } -static void free_super1(struct supertype *st); - static int load_super1(struct supertype *st, int fd, char *devname) { unsigned long long dsize; @@ -1220,9 +1243,6 @@ static int load_super1(struct supertype *st, int fd, char *devname) free_super1(st); - if (st->subarray[0]) - return 1; - if (st->ss == NULL || st->minor_version == -1) { int bestvers = -1; struct supertype tst; @@ -1366,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; } @@ -1377,6 +1398,7 @@ static struct supertype *match_metadata_desc1(char *arg) if (!st) return st; memset(st, 0, sizeof(*st)); + st->container_dev = NoMdDev; st->ss = &super1; st->max_devs = 384; st->sb = NULL; @@ -1467,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 !!! */ @@ -1483,15 +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. */ @@ -1501,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; @@ -1513,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; } } @@ -1568,11 +1593,13 @@ 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); - uuid_from_super1(st, (int*)bms->uuid); + uuid_from_super1(st, uuid); + memcpy(bms->uuid, uuid, 16); bms->chunksize = __cpu_to_le32(chunk); bms->daemon_sleep = __cpu_to_le32(delay); bms->sync_size = __cpu_to_le64(size); @@ -1582,7 +1609,6 @@ add_internal_bitmap1(struct supertype *st, return 1; } - static void locate_bitmap1(struct supertype *st, int fd) { unsigned long long offset; @@ -1610,7 +1636,7 @@ static int write_bitmap1(struct supertype *st, int fd) int rv = 0; int towrite, n; - char *buf = (char*)(((long)(abuf+4096))&~4095UL); + char buf[4096]; locate_bitmap1(st, fd); @@ -1625,7 +1651,7 @@ static int write_bitmap1(struct supertype *st, int fd) n = towrite; if (n > 4096) n = 4096; - n = write(fd, buf, n); + n = awrite(fd, buf, n); if (n > 0) towrite -= n; else @@ -1643,13 +1669,20 @@ static void free_super1(struct supertype *st) { if (st->sb) free(st->sb); + while (st->info) { + struct devinfo *di = st->info; + st->info = di->next; + if (di->fd >= 0) + close(di->fd); + free(di); + } st->sb = NULL; } #ifndef MDASSEMBLE static int validate_geometry1(struct supertype *st, int level, int layout, int raiddisks, - int chunk, unsigned long long size, + int *chunk, unsigned long long size, char *subdev, unsigned long long *freesize, int verbose) { @@ -1661,6 +1694,9 @@ static int validate_geometry1(struct supertype *st, int level, fprintf(stderr, Name ": 1.x metadata does not support containers\n"); return 0; } + if (chunk && *chunk == UnSet) + *chunk = DEFAULT_CHUNK; + if (!subdev) return 1; @@ -1698,6 +1734,7 @@ struct superswitch super1 = { .match_home = match_home1, .uuid_from_super = uuid_from_super1, .getinfo_super = getinfo_super1, + .container_content = container_content1, .update_super = update_super1, .init_super = init_super1, .store_super = store_super1,