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 ||
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++;
}
printf("\n");
}
if (sb->devflags) {
- printf(" Flags :");
+ printf(" Flags :");
if (sb->devflags & WriteMostly1)
printf(" write-mostly");
printf("\n");
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");
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;
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;
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;
} else
info->reshape_active = 0;
+ info->recovery_blocked = info->reshape_active;
+
+ if (map)
+ for (i=0; i<map_disks; i++)
+ map[i] = 0;
for (i = 0; i < __le32_to_cpu(sb->max_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;
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'.
*/
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)
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);
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) {
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, ':');
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));
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 */
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;
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;
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;
sb->dev_number = __cpu_to_le32(di->disk.number);
if (di->disk.state & (1<<MD_DISK_WRITEMOSTLY))
- sb->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) {
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) {
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;
return 0;
}
-static void free_super1(struct supertype *st);
-
static int load_super1(struct supertype *st, int fd, char *devname)
{
unsigned long long dsize;
free_super1(st);
- if (st->subarray[0])
- return 1;
-
if (st->ss == NULL || st->minor_version == -1) {
int bestvers = -1;
struct supertype tst;
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;
}
if (!st) return st;
memset(st, 0, sizeof(*st));
+ st->container_dev = NoMdDev;
st->ss = &super1;
st->max_devs = 384;
st->sb = NULL;
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 !!!
*/
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.
*/
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;
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;
}
}
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);
return 1;
}
-
static void locate_bitmap1(struct supertype *st, int fd)
{
unsigned long long offset;
int rv = 0;
int towrite, n;
- char *buf = (char*)(((long)(abuf+4096))&~4095UL);
+ char buf[4096];
locate_bitmap1(st, fd);
n = towrite;
if (n > 4096)
n = 4096;
- n = write(fd, buf, n);
+ n = awrite(fd, buf, n);
if (n > 0)
towrite -= n;
else
{
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)
{
fprintf(stderr, Name ": 1.x metadata does not support containers\n");
return 0;
}
+ if (chunk && *chunk == UnSet)
+ *chunk = DEFAULT_CHUNK;
+
if (!subdev)
return 1;
.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,