__u16 dev_roles[0]; /* role in array, or 0xffff for a spare, or 0xfffe for faulty */
};
+struct misc_dev_info {
+ __u64 device_size;
+};
+
/* feature_map bits */
#define MD_FEATURE_BITMAP_OFFSET 1
#define MD_FEATURE_RECOVERY_OFFSET 2 /* recovery_offset is present and
}
#ifndef MDASSEMBLE
-static void examine_super1(void *sbv, char *homehost)
+static void examine_super1(struct supertype *st, char *homehost)
{
- struct mdp_superblock_1 *sb = sbv;
+ struct mdp_superblock_1 *sb = st->sb;
time_t atime;
int d;
int faulty;
char *c;
int l = homehost ? strlen(homehost) : 0;
int layout;
+ unsigned long long sb_offset;
printf(" Magic : %08x\n", __le32_to_cpu(sb->magic));
- printf(" Version : %02d\n", 1);
+ printf(" Version : 1");
+ sb_offset = __le64_to_cpu(sb->super_offset);
+ if (sb_offset <= 4)
+ printf(".1\n");
+ else if (sb_offset <= 8)
+ printf(".2\n");
+ else
+ printf(".0\n");
printf(" Feature Map : 0x%x\n", __le32_to_cpu(sb->feature_map));
printf(" Array UUID : ");
for (i=0; i<16; i++) {
printf(" Raid Level : %s\n", c?c:"-unknown-");
printf(" Raid Devices : %d\n", __le32_to_cpu(sb->raid_disks));
printf("\n");
- printf(" Device Size : %llu%s\n", (unsigned long long)sb->data_size, human_size(sb->data_size<<9));
+ printf(" Avail Dev Size : %llu%s\n",
+ (unsigned long long)__le64_to_cpu(sb->data_size),
+ human_size(__le64_to_cpu(sb->data_size)<<9));
if (__le32_to_cpu(sb->level) >= 0) {
int ddsks=0;
switch(__le32_to_cpu(sb->level)) {
ddsks*(unsigned long long)__le64_to_cpu(sb->size),
human_size(ddsks*__le64_to_cpu(sb->size)<<9));
if (sb->size != sb->data_size)
- printf(" Used Size : %llu%s\n",
+ printf(" Used Dev Size : %llu%s\n",
(unsigned long long)__le64_to_cpu(sb->size),
human_size(__le64_to_cpu(sb->size)<<9));
}
if (sb->data_offset)
- printf(" Data Offset : %llu sectors\n", (unsigned long long)__le64_to_cpu(sb->data_offset));
- if (sb->super_offset)
- printf(" Super Offset : %llu sectors\n", (unsigned long long)__le64_to_cpu(sb->super_offset));
+ printf(" Data Offset : %llu sectors\n",
+ (unsigned long long)__le64_to_cpu(sb->data_offset));
+ printf(" Super Offset : %llu sectors\n",
+ (unsigned long long)__le64_to_cpu(sb->super_offset));
if (__le32_to_cpu(sb->feature_map) & MD_FEATURE_RECOVERY_OFFSET)
printf("Recovery Offset : %llu sectors\n", (unsigned long long)__le64_to_cpu(sb->recovery_offset));
printf(" State : %s\n", (__le64_to_cpu(sb->resync_offset)+1)? "active":"clean");
printf("\n");
if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) {
printf("Internal Bitmap : %ld sectors from superblock\n",
- (long)__le32_to_cpu(sb->bitmap_offset));
+ (long)(int32_t)__le32_to_cpu(sb->bitmap_offset));
}
if (sb->feature_map & __le32_to_cpu(MD_FEATURE_RESHAPE_ACTIVE)) {
printf(" Reshape pos'n : %llu%s\n", (unsigned long long)__le64_to_cpu(sb->reshape_position)/2,
}
-static void brief_examine_super1(void *sbv)
+static void brief_examine_super1(struct supertype *st)
{
- struct mdp_superblock_1 *sb = sbv;
+ struct mdp_superblock_1 *sb = st->sb;
int i;
+ unsigned long long sb_offset;
char *nm;
char *c=map_num(pers, __le32_to_cpu(sb->level));
else
nm = "??";
- printf("ARRAY /dev/md/%s level=%s metadata=1 num-devices=%d UUID=",
- nm,
- c?c:"-unknown-", __le32_to_cpu(sb->raid_disks));
+ printf("ARRAY /dev/md/%s level=%s ", nm, c?c:"-unknown-");
+ sb_offset = __le64_to_cpu(sb->super_offset);
+ if (sb_offset <= 4)
+ printf("metadata=1.1 ");
+ else if (sb_offset <= 8)
+ printf("metadata=1.2 ");
+ else
+ printf("metadata=1.0 ");
+ printf("num-devices=%d UUID=", __le32_to_cpu(sb->raid_disks));
for (i=0; i<16; i++) {
if ((i&3)==0 && i != 0) printf(":");
printf("%02x", sb->set_uuid[i]);
printf("\n");
}
-static void detail_super1(void *sbv, char *homehost)
+static void export_examine_super1(struct supertype *st)
{
- struct mdp_superblock_1 *sb = sbv;
+ struct mdp_superblock_1 *sb = st->sb;
+ int i;
+ int len = 32;
+
+ printf("MD_LEVEL=%s\n", map_num(pers, __le32_to_cpu(sb->level)));
+ printf("MD_DEVICES=%d\n", __le32_to_cpu(sb->raid_disks));
+ for (i=0; i<32; i++)
+ if (sb->set_name[i] == '\n' ||
+ sb->set_name[i] == '\0') {
+ len = i;
+ break;
+ }
+ if (len)
+ printf("MD_NAME=%.*s\n", len, sb->set_name);
+ printf("MD_UUID=");
+ for (i=0; i<16; i++) {
+ if ((i&3)==0 && i != 0) printf(":");
+ printf("%02x", sb->set_uuid[i]);
+ }
+ printf("\n");
+ printf("MD_UPDATE_TIME=%llu\n",
+ __le64_to_cpu(sb->utime) & 0xFFFFFFFFFFULL);
+ printf("MD_DEV_UUID=");
+ for (i=0; i<16; i++) {
+ if ((i&3)==0 && i != 0) printf(":");
+ printf("%02x", sb->device_uuid[i]);
+ }
+ printf("\n");
+ printf("MD_EVENTS=%llu\n",
+ (unsigned long long)__le64_to_cpu(sb->events));
+}
+
+static void detail_super1(struct supertype *st, char *homehost)
+{
+ struct mdp_superblock_1 *sb = st->sb;
int i;
int l = homehost ? strlen(homehost) : 0;
printf("\n Events : %llu\n\n", (unsigned long long)__le64_to_cpu(sb->events));
}
-static void brief_detail_super1(void *sbv)
+static void brief_detail_super1(struct supertype *st)
{
- struct mdp_superblock_1 *sb = sbv;
+ struct mdp_superblock_1 *sb = st->sb;
int i;
if (sb->set_name[0])
}
}
+static void export_detail_super1(struct supertype *st)
+{
+ struct mdp_superblock_1 *sb = st->sb;
+ int i;
+ int len = 32;
+
+ for (i=0; i<32; i++)
+ if (sb->set_name[i] == '\n' ||
+ sb->set_name[i] == '\0') {
+ len = i;
+ break;
+ }
+ if (len)
+ printf("MD_NAME=%.*s\n", len, sb->set_name);
+ printf("MD_UUID=");
+ for (i=0; i<16; i++) {
+ if ((i&3)==0 && i != 0) printf(":");
+ printf("%02x", sb->set_uuid[i]);
+ }
+ printf("\n");
+}
+
#endif
-static int match_home1(void *sbv, char *homehost)
+static int match_home1(struct supertype *st, char *homehost)
{
- struct mdp_superblock_1 *sb = sbv;
+ struct mdp_superblock_1 *sb = st->sb;
int l = homehost ? strlen(homehost) : 0;
return (l > 0 && l < 32 &&
strncmp(sb->set_name, homehost, l) == 0);
}
-static void uuid_from_super1(int uuid[4], void * sbv)
+static void uuid_from_super1(struct supertype *st, int uuid[4])
{
- struct mdp_superblock_1 *super = sbv;
+ struct mdp_superblock_1 *super = st->sb;
char *cuuid = (char*)uuid;
int i;
for (i=0; i<16; i++)
cuuid[i] = super->set_uuid[i];
}
-static void getinfo_super1(struct mdinfo *info, void *sbv)
+static void getinfo_super1(struct supertype *st, struct mdinfo *info)
{
- struct mdp_superblock_1 *sb = sbv;
+ struct mdp_superblock_1 *sb = st->sb;
int working = 0;
int i;
int role;
info->array.ctime = __le64_to_cpu(sb->ctime);
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))
+ ? 1 : 0;
info->data_offset = __le64_to_cpu(sb->data_offset);
info->component_size = __le64_to_cpu(sb->size);
info->array.working_disks = working;
}
-static int update_super1(struct mdinfo *info, void *sbv, char *update,
+static int update_super1(struct supertype *st, struct mdinfo *info,
+ char *update,
char *devname, int verbose,
int uuid_set, char *homehost)
{
* For others, the return value is ignored.
*/
int rv = 0;
- struct mdp_superblock_1 *sb = sbv;
+ struct mdp_superblock_1 *sb = st->sb;
if (strcmp(update, "force-one")==0) {
/* Not enough devices for a working array,
rv = 1;
}
}
-#if 0
- if (strcmp(update, "newdev") == 0) {
- int d = info->disk.number;
- memset(&sb->disks[d], 0, sizeof(sb->disks[d]));
- sb->disks[d].number = d;
- sb->disks[d].major = info->disk.major;
- sb->disks[d].minor = info->disk.minor;
- sb->disks[d].raid_disk = info->disk.raid_disk;
- sb->disks[d].state = info->disk.state;
- sb->this_disk = sb->disks[d];
+ if (strcmp(update, "linear-grow-new") == 0) {
+ int i;
+ int rfd;
+ int max = __le32_to_cpu(sb->max_dev);
+
+ for (i=0 ; i < max ; i++)
+ if (__le16_to_cpu(sb->dev_roles[i]) >= 0xfffe)
+ break;
+ sb->dev_number = __cpu_to_le32(i);
+ info->disk.number = i;
+ if (max >= __le32_to_cpu(sb->max_dev))
+ sb->max_dev = __cpu_to_le32(max+1);
+
+ if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 ||
+ read(rfd, sb->device_uuid, 16) != 16) {
+ *(__u32*)(sb->device_uuid) = random();
+ *(__u32*)(sb->device_uuid+4) = random();
+ *(__u32*)(sb->device_uuid+8) = random();
+ *(__u32*)(sb->device_uuid+12) = random();
+ }
+
+ sb->dev_roles[i] =
+ __cpu_to_le16(info->disk.raid_disk);
}
-#endif
- if (strcmp(update, "grow") == 0) {
+ if (strcmp(update, "linear-grow-update") == 0) {
sb->raid_disks = __cpu_to_le32(info->array.raid_disks);
- /* FIXME */
+ sb->dev_roles[info->disk.number] =
+ __cpu_to_le16(info->disk.raid_disk);
}
if (strcmp(update, "resync") == 0) {
/* make sure resync happens */
sb->resync_offset = 0ULL;
}
if (strcmp(update, "uuid") == 0) {
- memcpy(sb->set_uuid, info->uuid, 16);
+ copy_uuid(sb->set_uuid, info->uuid, super1.swapuuid);
+
if (__le32_to_cpu(sb->feature_map)&MD_FEATURE_BITMAP_OFFSET) {
struct bitmap_super_s *bm;
- bm = (struct bitmap_super_s*)(sbv+1024);
- memcpy(bm->uuid, info->uuid, 16);
+ bm = (struct bitmap_super_s*)(st->sb+1024);
+ memcpy(bm->uuid, sb->set_uuid, 16);
}
}
if (strcmp(update, "homehost") == 0 &&
} else
strcpy(sb->set_name, info->name);
}
+ 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 */
+ struct misc_dev_info *misc = (struct misc_dev_info*)
+ (st->sb + 1024 + sizeof(struct bitmap_super_s));
+ printf("Size was %llu\n", (unsigned long long)
+ __le64_to_cpu(sb->data_size));
+ sb->data_size = __cpu_to_le64(
+ 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)
sb->reshape_position = __cpu_to_le64(info->reshape_progress);
return rv;
}
-
-static __u64 event_super1(void *sbv)
+static int init_super1(struct supertype *st, mdu_array_info_t *info,
+ unsigned long long size, char *name, char *homehost, int *uuid)
{
- struct mdp_superblock_1 *sb = sbv;
- return __le64_to_cpu(sb->events);
-}
-
-static int init_super1(struct supertype *st, void **sbp, mdu_array_info_t *info,
- unsigned long long size, char *name, char *homehost)
-{
- struct mdp_superblock_1 *sb = malloc(1024 + sizeof(bitmap_super_t));
+ struct mdp_superblock_1 *sb = malloc(1024 + sizeof(bitmap_super_t) +
+ sizeof(struct misc_dev_info));
int spares;
int rfd;
char defname[10];
memset(sb, 0, 1024);
+ st->sb = sb;
if (info->major_version == -1) {
/* zeroing superblock */
- *sbp = sb;
return 0;
}
sb->feature_map = 0;
sb->pad0 = 0;
- if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 ||
- read(rfd, sb->set_uuid, 16) != 16) {
- *(__u32*)(sb->set_uuid) = random();
- *(__u32*)(sb->set_uuid+4) = random();
- *(__u32*)(sb->set_uuid+8) = random();
- *(__u32*)(sb->set_uuid+12) = random();
+ if (uuid)
+ copy_uuid(sb->set_uuid, uuid, super1.swapuuid);
+ else {
+ if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 ||
+ read(rfd, sb->set_uuid, 16) != 16) {
+ *(__u32*)(sb->set_uuid) = random();
+ *(__u32*)(sb->set_uuid+4) = random();
+ *(__u32*)(sb->set_uuid+8) = random();
+ *(__u32*)(sb->set_uuid+12) = random();
+ }
+ if (rfd >= 0) close(rfd);
}
- if (rfd >= 0) close(rfd);
if (name == NULL || *name == 0) {
sprintf(defname, "%d", info->md_minor);
memset(sb->dev_roles, 0xff, 1024 - sizeof(struct mdp_superblock_1));
- *sbp = sb;
return 1;
}
/* Add a device to the superblock being created */
-static void add_to_super1(void *sbv, mdu_disk_info_t *dk)
+static void add_to_super1(struct supertype *st, mdu_disk_info_t *dk)
{
- struct mdp_superblock_1 *sb = sbv;
+ struct mdp_superblock_1 *sb = st->sb;
__u16 *rp = sb->dev_roles + dk->number;
if ((dk->state & 6) == 6) /* active, sync */
*rp = __cpu_to_le16(dk->raid_disk);
*rp = 0xfffe;
}
-static void locate_bitmap1(struct supertype *st, int fd, void *sbv);
+static void locate_bitmap1(struct supertype *st, int fd);
-static int store_super1(struct supertype *st, int fd, void *sbv)
+static int store_super1(struct supertype *st, int fd)
{
- struct mdp_superblock_1 *sb = sbv;
+ struct mdp_superblock_1 *sb = st->sb;
unsigned long long sb_offset;
int sbsize;
- unsigned long size;
unsigned long long dsize;
-#ifdef BLKGETSIZE64
- if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
-#endif
- {
- if (ioctl(fd, BLKGETSIZE, &size))
- return 1;
- else
- dsize = (unsigned long long)size;
- } else
- dsize >>= 9;
+ if (!get_dev_size(fd, NULL, &dsize))
+ return 1;
+
+ dsize >>= 9;
if (dsize < 24)
return 2;
struct bitmap_super_s *bm = (struct bitmap_super_s*)
(((char*)sb)+1024);
if (__le32_to_cpu(bm->magic) == BITMAP_MAGIC) {
- locate_bitmap1(st, fd, sbv);
+ locate_bitmap1(st, fd);
if (write(fd, bm, sizeof(*bm)) != sizeof(*bm))
return 5;
}
return 0;
}
-static int load_super1(struct supertype *st, int fd, void **sbp, char *devname);
+static int load_super1(struct supertype *st, int fd, char *devname);
-static int write_init_super1(struct supertype *st, void *sbv,
+static unsigned long choose_bm_space(unsigned long devsize)
+{
+ /* if the device is bigger than 8Gig, save 64k for bitmap usage,
+ * if bigger than 200Gig, save 128k
+ */
+ if (devsize < 64*2) return 0;
+ if (devsize - 64*2 >= 200*1024*1024*2)
+ return 128*2;
+ if (devsize - 4*2 > 8*1024*1024*2)
+ return 64*2;
+ return 4*2;
+}
+
+static int write_init_super1(struct supertype *st,
mdu_disk_info_t *dinfo, char *devname)
{
- struct mdp_superblock_1 *sb = sbv;
- void *refsbv = NULL;
+ struct mdp_superblock_1 *sb = st->sb;
+ struct supertype refst;
int fd = open(devname, O_RDWR | O_EXCL);
int rfd;
int rv;
+ int bm_space;
- unsigned long size, space;
unsigned long long dsize, array_size;
long long sb_offset;
if (rfd >= 0) close(rfd);
sb->events = 0;
- if (load_super1(st, fd, &refsbv, NULL)==0) {
- struct mdp_superblock_1 *refsb = refsbv;
+ refst =*st;
+ refst.sb = NULL;
+ if (load_super1(&refst, 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) {
free(refsb);
}
-#ifdef BLKGETSIZE64
- if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
-#endif
- {
- if (ioctl(fd, BLKGETSIZE, &size))
- return 1;
- else
- dsize = size;
- } else
- dsize >>= 9;
+ if (!get_dev_size(fd, NULL, &dsize))
+ return 1;
+ dsize >>= 9;
if (dsize < 24) {
close(fd);
* for a bitmap.
*/
array_size = __le64_to_cpu(sb->size);
+ /* work out how much space we left for a bitmap */
+ bm_space = choose_bm_space(array_size);
+
switch(st->minor_version) {
case 0:
sb_offset = dsize;
sb_offset &= ~(4*2-1);
sb->super_offset = __cpu_to_le64(sb_offset);
sb->data_offset = __cpu_to_le64(0);
- if (sb_offset-64*2 >= array_size && array_size > 8*1024*1024*2)
- sb->data_size = __cpu_to_le64(sb_offset-64*2);
- else
- sb->data_size = __cpu_to_le64(sb_offset);
+ if (sb_offset - bm_space < array_size)
+ bm_space = sb_offset - array_size;
+ sb->data_size = __cpu_to_le64(sb_offset - bm_space);
break;
case 1:
sb->super_offset = __cpu_to_le64(0);
- if (dsize - 64*2 >= array_size && array_size > 8*1024*1024*2)
- space = 64*2;
- else
- space = 4*2;
- sb->data_offset = __cpu_to_le64(space); /* leave space for super and bitmap */
- sb->data_size = __cpu_to_le64(dsize - space);
+ if (4*2 + bm_space + __le64_to_cpu(sb->size) > dsize)
+ bm_space = dsize - __le64_to_cpu(sb->size) - 4*2;
+ sb->data_offset = __cpu_to_le64(bm_space + 4*2);
+ sb->data_size = __cpu_to_le64(dsize - bm_space - 4*2);
break;
case 2:
sb_offset = 4*2;
- if (dsize - 4*2 - 64*2 >= array_size && array_size > 8*1024*1024*2)
- space = 64*2;
- else
- space = 4*2;
- sb->super_offset = __cpu_to_le64(sb_offset);
- sb->data_offset = __cpu_to_le64(sb_offset+space);
- sb->data_size = __cpu_to_le64(dsize - 4*2 - space);
+ sb->super_offset = __cpu_to_le64(4*2);
+ if (4*2 + 4*2 + bm_space + __le64_to_cpu(sb->size) > dsize)
+ bm_space = dsize - __le64_to_cpu(sb->size) - 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 - bm_space );
break;
default:
return -EINVAL;
sb->sb_csum = calc_sb_1_csum(sb);
- rv = store_super1(st, fd, sb);
+ rv = store_super1(st, fd);
if (rv)
fprintf(stderr, Name ": failed to write superblock to %s\n", devname);
if (rv == 0 && (__le32_to_cpu(sb->feature_map) & 1))
- rv = st->ss->write_bitmap(st, fd, sbv);
+ rv = st->ss->write_bitmap(st, fd);
close(fd);
return rv;
}
-static int compare_super1(void **firstp, void *secondv)
+static int compare_super1(struct supertype *st, struct supertype *tst)
{
/*
* return:
* 2 wrong uuid
* 3 wrong other info
*/
- struct mdp_superblock_1 *first = *firstp;
- struct mdp_superblock_1 *second = secondv;
+ struct mdp_superblock_1 *first = st->sb;
+ struct mdp_superblock_1 *second = tst->sb;
if (second->magic != __cpu_to_le32(MD_SB_MAGIC))
return 1;
return 1;
if (!first) {
- first = malloc(1024+sizeof(bitmap_super_t));
- memcpy(first, second, 1024+sizeof(bitmap_super_t));
- *firstp = first;
+ first = malloc(1024+sizeof(bitmap_super_t) +
+ sizeof(struct misc_dev_info));
+ memcpy(first, second, 1024+sizeof(bitmap_super_t) +
+ sizeof(struct misc_dev_info));
+ st->sb = first;
return 0;
}
if (memcmp(first->set_uuid, second->set_uuid, 16)!= 0)
return 0;
}
-static int load_super1(struct supertype *st, int fd, void **sbp, char *devname)
+static void free_super1(struct supertype *st);
+
+static int load_super1(struct supertype *st, int fd, char *devname)
{
- unsigned long size;
unsigned long long dsize;
unsigned long long sb_offset;
struct mdp_superblock_1 *super;
int uuid[4];
struct bitmap_super_s *bsb;
+ struct misc_dev_info *misc;
+ free_super1(st);
- if (st->ss == NULL) {
+ if (st->ss == NULL || st->minor_version == -1) {
int bestvers = -1;
+ struct supertype tst;
__u64 bestctime = 0;
/* guess... choose latest ctime */
- st->ss = &super1;
- for (st->minor_version = 0; st->minor_version <= 2 ; st->minor_version++) {
- switch(load_super1(st, fd, sbp, devname)) {
- case 0: super = *sbp;
+ tst.ss = &super1;
+ tst.sb = NULL;
+ for (tst.minor_version = 0; tst.minor_version <= 2 ; tst.minor_version++) {
+ switch(load_super1(&tst, fd, devname)) {
+ case 0: super = tst.sb;
if (bestvers == -1 ||
bestctime < __le64_to_cpu(super->ctime)) {
- bestvers = st->minor_version;
+ bestvers = tst.minor_version;
bestctime = __le64_to_cpu(super->ctime);
}
free(super);
- *sbp = NULL;
+ tst.sb = NULL;
break;
- case 1: st->ss = NULL; return 1; /*bad device */
+ case 1: return 1; /*bad device */
case 2: break; /* bad, try next */
}
}
if (bestvers != -1) {
int rv;
- st->minor_version = bestvers;
- st->ss = &super1;
- st->max_devs = 384;
- rv = load_super1(st, fd, sbp, devname);
- if (rv) st->ss = NULL;
+ tst.minor_version = bestvers;
+ tst.ss = &super1;
+ tst.max_devs = 384;
+ rv = load_super1(&tst, fd, devname);
+ if (rv == 0)
+ *st = tst;
return rv;
}
- st->ss = NULL;
return 2;
}
-#ifdef BLKGETSIZE64
- if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
-#endif
- {
- if (ioctl(fd, BLKGETSIZE, &size)) {
- if (devname)
- fprintf(stderr, Name ": cannot find device size for %s: %s\n",
- devname, strerror(errno));
- return 1;
- }
- dsize = size;
- } else
- dsize >>= 9;
+ if (!get_dev_size(fd, devname, &dsize))
+ return 1;
+ dsize >>= 9;
if (dsize < 24) {
if (devname)
return 1;
}
- super = malloc(1024 + sizeof(bitmap_super_t));
+ super = malloc(1024 + sizeof(bitmap_super_t) +
+ sizeof(struct misc_dev_info));
if (read(fd, super, 1024) != 1024) {
if (devname)
free(super);
return 2;
}
- *sbp = super;
+ st->sb = super;
+
+ bsb = (struct bitmap_super_s *)(((char*)super)+1024);
+
+ misc = (struct misc_dev_info*) (bsb+1);
+ misc->device_size = dsize;
/* Now check on the bitmap superblock */
if ((__le32_to_cpu(super->feature_map)&MD_FEATURE_BITMAP_OFFSET) == 0)
* valid. If it doesn't clear the bit. An --assemble --force
* should get that written out.
*/
- locate_bitmap1(st, fd, super);
+ locate_bitmap1(st, fd);
if (read(fd, ((char*)super)+1024, sizeof(struct bitmap_super_s))
!= sizeof(struct bitmap_super_s))
goto no_bitmap;
- uuid_from_super1(uuid, super);
- bsb = (struct bitmap_super_s *)(((char*)super)+1024);
+ uuid_from_super1(st, uuid);
if (__le32_to_cpu(bsb->magic) != BITMAP_MAGIC ||
memcmp(bsb->uuid, uuid, 16) != 0)
goto no_bitmap;
st->ss = &super1;
st->max_devs = 384;
- if (strcmp(arg, "1") == 0 ||
- strcmp(arg, "1.0") == 0 ||
- strcmp(arg, "default/large") == 0) {
+ st->sb = NULL;
+ if (strcmp(arg, "1.0") == 0) {
st->minor_version = 0;
return st;
}
st->minor_version = 2;
return st;
}
+ if (strcmp(arg, "1") == 0 ||
+ strcmp(arg, "default/large") == 0) {
+ st->minor_version = -1;
+ return st;
+ }
free(st);
return NULL;
if (devsize < 24)
return 0;
- /* if the device is bigger than 8Gig, save 64k for bitmap usage,
- * if biffer than 200Gig, save 128k
- */
- if (devsize > 200*1024*1024*2)
- devsize -= 128*2;
- else if (devsize > 8*1024*1024*2)
- devsize -= 64*2;
+ devsize -= choose_bm_space(devsize);
switch(st->minor_version) {
+ case -1: /* no specified. Now time to set default */
+ st->minor_version = 0;
+ /* FALL THROUGH */
case 0:
/* at end */
return ((devsize - 8*2 ) & ~(4*2-1));
}
static int
-add_internal_bitmap1(struct supertype *st, void *sbv,
- int chunk, int delay, int write_behind, unsigned long long size,
+add_internal_bitmap1(struct supertype *st,
+ int *chunkp, int delay, int write_behind,
+ unsigned long long size,
int may_change, int major)
{
/*
* 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.
- * For now, just squeeze the bitmap into 3k and don't change anything.
+ * If !may_change, the bitmap MUST live at offset of 1K, until
+ * we get a sysfs interface.
*
* size is in sectors, chunk is in bytes !!!
*/
unsigned long long bits;
- unsigned long long max_bits = (6*512 - sizeof(bitmap_super_t)) * 8;
+ unsigned long long max_bits;
unsigned long long min_chunk;
- struct mdp_superblock_1 *sb = sbv;
+ long offset;
+ int chunk = *chunkp;
+ int room = 0;
+ struct mdp_superblock_1 *sb = st->sb;
bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + 1024);
- if (st->minor_version && !may_change &&
- __le64_to_cpu(sb->data_offset) - __le64_to_cpu(sb->super_offset) < 8)
- return 0; /* doesn't fit */
+ switch(st->minor_version) {
+ case 0:
+ /* either 3K after the superblock, or some amount of space
+ * before.
+ */
+ if (may_change) {
+ /* We are creating array, so we *know* how much room has
+ * been left.
+ */
+ offset = 0;
+ room = choose_bm_space(__le64_to_cpu(sb->size));
+ if (room == 4*2) {
+ /* make it 3K after the superblock */
+ room = 3*2;
+ offset = 2;
+ }
+ } else {
+ 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 &&
+ __le32_to_cpu(sb->max_dev) <= 384)) {
+ room = 3*2;
+ offset = 1*2;
+ } else {
+ offset = 0; /* means movable offset */
+ }
+ }
+ break;
+ case 1:
+ case 2: /* between superblock and data */
+ if (may_change) {
+ 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;
+ offset = 2;
+ } else {
+ room -= 4*2;
+ offset = 4*2;
+ }
+ }
+ break;
+ default:
+ return 0;
+ }
+ if (chunk == UnSet && room > 128*2)
+ /* Limit to 128K of bitmap when chunk size not requested */
+ room = 128*2;
+ max_bits = (room * 512 - sizeof(bitmap_super_t)) * 8;
min_chunk = 4096; /* sub-page chunks don't work yet.. */
bits = (size*512)/min_chunk +1;
if (chunk == 0) /* rounding problem */
return 0;
- sb->bitmap_offset = __cpu_to_le32(2);
+ if (offset == 0) {
+ bits = (size*512) / chunk + 1;
+ room = ((bits+7)/8 + sizeof(bitmap_super_t) +511)/512;
+ offset = -room;
+ }
+
+ sb->bitmap_offset = __cpu_to_le32(offset);
sb->feature_map = __cpu_to_le32(__le32_to_cpu(sb->feature_map) | 1);
memset(bms, 0, sizeof(*bms));
bms->magic = __cpu_to_le32(BITMAP_MAGIC);
bms->version = __cpu_to_le32(major);
- uuid_from_super1((int*)bms->uuid, sb);
+ uuid_from_super1(st, (int*)bms->uuid);
bms->chunksize = __cpu_to_le32(chunk);
bms->daemon_sleep = __cpu_to_le32(delay);
bms->sync_size = __cpu_to_le64(size);
bms->write_behind = __cpu_to_le32(write_behind);
+ *chunkp = chunk;
return 1;
}
-static void locate_bitmap1(struct supertype *st, int fd, void *sbv)
+static void locate_bitmap1(struct supertype *st, int fd)
{
unsigned long long offset;
struct mdp_superblock_1 *sb;
int mustfree = 0;
- if (!sbv) {
- if (st->ss->load_super(st, fd, &sbv, NULL))
+ if (!st->sb) {
+ if (st->ss->load_super(st, fd, NULL))
return; /* no error I hope... */
mustfree = 1;
}
- sb = sbv;
+ sb = st->sb;
offset = __le64_to_cpu(sb->super_offset);
- offset += (long) __le32_to_cpu(sb->bitmap_offset);
+ offset += (int32_t) __le32_to_cpu(sb->bitmap_offset);
if (mustfree)
free(sb);
lseek64(fd, offset<<9, 0);
}
-static int write_bitmap1(struct supertype *st, int fd, void *sbv)
+static int write_bitmap1(struct supertype *st, int fd)
{
- struct mdp_superblock_1 *sb = sbv;
+ struct mdp_superblock_1 *sb = st->sb;
bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb)+1024);
int rv = 0;
int towrite, n;
char buf[4096];
- locate_bitmap1(st, fd, sbv);
+ locate_bitmap1(st, fd);
if (write(fd, ((char*)sb)+1024, sizeof(bitmap_super_t)) !=
sizeof(bitmap_super_t))
return rv;
}
+static void free_super1(struct supertype *st)
+{
+ if (st->sb)
+ free(st->sb);
+ st->sb = NULL;
+}
+
struct superswitch super1 = {
#ifndef MDASSEMBLE
.examine_super = examine_super1,
.brief_examine_super = brief_examine_super1,
+ .export_examine_super = export_examine_super1,
.detail_super = detail_super1,
.brief_detail_super = brief_detail_super1,
+ .export_detail_super = export_detail_super1,
#endif
.match_home = match_home1,
.uuid_from_super = uuid_from_super1,
.getinfo_super = getinfo_super1,
.update_super = update_super1,
- .event_super = event_super1,
.init_super = init_super1,
.add_to_super = add_to_super1,
.store_super = store_super1,
.add_internal_bitmap = add_internal_bitmap1,
.locate_bitmap = locate_bitmap1,
.write_bitmap = write_bitmap1,
+ .free_super = free_super1,
.major = 1,
#if __BYTE_ORDER == BIG_ENDIAN
.swapuuid = 0,