__u16 dev_roles[0]; /* role in array, or 0xffff for a spare, or 0xfffe for faulty */
};
+#ifndef offsetof
#define offsetof(t,f) ((int)&(((t*)0)->f))
+#endif
static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb)
{
unsigned int disk_csum, csum;
struct mdp_superblock_1 *sb = sbv;
time_t atime;
int d;
- int spares, faulty;
+ int faulty;
int i;
char *c;
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", sb->data_size, human_size(sb->data_size<<9));
+ printf(" Device Size : %llu%s\n", (unsigned long long)sb->data_size, human_size(sb->data_size<<9));
if (sb->data_offset)
- printf(" Data Offset : %llu sectors\n", __le64_to_cpu(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", __le64_to_cpu(sb->super_offset));
+ printf(" Super Offset : %llu sectors\n", (unsigned long long)__le64_to_cpu(sb->super_offset));
+ printf(" State : %s\n", (__le64_to_cpu(sb->resync_offset)+1)? "active":"clean");
printf(" Device UUID : ");
for (i=0; i<16; i++) {
printf("%02x", sb->set_uuid[i]);
else
printf(" Checksum : %x - expected %x\n", __le32_to_cpu(sb->sb_csum),
__le32_to_cpu(calc_sb_1_csum(sb)));
- printf(" Events : %llu\n", __le64_to_cpu(sb->events));
+ printf(" Events : %llu\n", (unsigned long long)__le64_to_cpu(sb->events));
printf("\n");
if (__le32_to_cpu(sb->level) == 5) {
c = map_num(r5layout, __le32_to_cpu(sb->layout));
else if (cnt == 1) printf("u");
else printf ("_");
}
- spares = faulty = 0;
+ faulty = 0;
for (i=0; i< __le32_to_cpu(sb->max_dev); i++) {
int role = __le16_to_cpu(sb->dev_roles[i]);
- switch (role) {
- case 0xFFFF: spares++; break;
- case 0xFFFE: faulty++;
- }
+ if (role == 0xFFFE)
+ faulty++;
}
- if (spares) printf(" %d spares", spares);
if (faulty) printf(" %d failed", faulty);
printf("\n");
}
printf("%02x", sb->set_uuid[i]);
if ((i&3)==0 && i != 0) printf(":");
}
- printf("\n Events : %llu\n\n", __le64_to_cpu(sb->events));
+ printf("\n Events : %llu\n\n", (unsigned long long)__le64_to_cpu(sb->events));
}
static void brief_detail_super1(void *sbv)
return __le64_to_cpu(sb->events);
}
-static int init_super1(void **sbp, mdu_array_info_t *info)
+static int init_super1(struct supertype *st, void **sbp, mdu_array_info_t *info)
{
struct mdp_superblock_1 *sb = malloc(1024);
int spares;
sb->ctime = __cpu_to_le64((unsigned long long)time(0));
sb->level = __cpu_to_le32(info->level);
- sb->layout = __cpu_to_le32(info->level);
+ sb->layout = __cpu_to_le32(info->layout);
sb->size = __cpu_to_le64(info->size*2ULL);
sb->chunksize = __cpu_to_le32(info->chunk_size>>9);
sb->raid_disks = __cpu_to_le32(info->raid_disks);
sb->utime = sb->ctime;
sb->events = __cpu_to_le64(1);
- if (info->state & MD_SB_CLEAN)
+ if (info->state & (1<<MD_SB_CLEAN))
sb->resync_offset = ~0ULL;
else
sb->resync_offset = 0;
__u16 *rp = sb->dev_roles + dk->number;
if (dk->state == 6) /* active, sync */
*rp = __cpu_to_le16(dk->raid_disk);
- else if (dk->state == 2) /* active -> spare */
+ else if ((dk->state & ~2) == 0) /* active or idle -> spare */
*rp = 0xffff;
else
*rp = 0xfffe;
}
-static int store_super1(int fd, void *sbv)
+static int store_super1(struct supertype *st, int fd, void *sbv)
{
struct mdp_superblock_1 *sb = sbv;
- long long sb_offset;
+ unsigned long long sb_offset;
int sbsize;
+ long size;
+
+ if (ioctl(fd, BLKGETSIZE, &size))
+ return 1;
+
+
+ if (size < 24)
+ return 2;
+
+ /*
+ * Calculate the position of the superblock.
+ * It is always aligned to a 4K boundary and
+ * depending on minor_version, it can be:
+ * 0: At least 8K, but less than 12K, from end of device
+ * 1: At start of device
+ * 2: 4K from start of device.
+ */
+ switch(st->minor_version) {
+ case 0:
+ sb_offset = size;
+ sb_offset -= 8*2;
+ sb_offset &= ~(4*2-1);
+ break;
+ case 1:
+ sb_offset = 0;
+ break;
+ case 2:
+ sb_offset = 4*2;
+ break;
+ default:
+ return -EINVAL;
+ }
+
- sb_offset = __le64_to_cpu(sb->super_offset) << 9;
+ if (sb_offset != __le64_to_cpu(sb->super_offset) &&
+ 0 != __le64_to_cpu(sb->super_offset)
+ ) {
+ fprintf(stderr, Name ": internal error - sb_offset is wrong\n");
+ abort();
+ }
- if (lseek64(fd, sb_offset, 0)< 0LL)
+ if (lseek64(fd, sb_offset << 9, 0)< 0LL)
return 3;
sbsize = sizeof(*sb) + 2 * __le32_to_cpu(sb->max_dev);
if (write(fd, sb, sbsize) != sbsize)
return 4;
+ fsync(fd);
return 0;
}
+static int load_super1(struct supertype *st, int fd, void **sbp, char *devname);
+
static int write_init_super1(struct supertype *st, void *sbv, mdu_disk_info_t *dinfo, char *devname)
{
struct mdp_superblock_1 *sb = sbv;
- int fd = open(devname, O_RDWR, O_EXCL);
+ struct mdp_superblock_1 *refsb = NULL;
+ int fd = open(devname, O_RDWR | O_EXCL);
+ int rfd;
int rv;
long size;
}
sb->dev_number = __cpu_to_le32(dinfo->number);
- *(__u32*)(sb->device_uuid) = random();
- *(__u32*)(sb->device_uuid+4) = random();
- *(__u32*)(sb->device_uuid+8) = random();
- *(__u32*)(sb->device_uuid+12) = random();
+ 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();
+ }
+ if (rfd >= 0) close(rfd);
+ sb->events = 0;
+
+ if (load_super1(st, fd, (void**)&refsb, NULL)==0) {
+ memcpy(sb->device_uuid, refsb->device_uuid, 16);
+ if (memcmp(sb->set_uuid, refsb->set_uuid, 16)==0) {
+ /* same array, so preserve events and dev_number */
+ sb->events = refsb->events;
+ sb->dev_number = refsb->dev_number;
+ }
+ free(refsb);
+ }
- if (ioctl(fd, BLKGETSIZE, &size))
+ if (ioctl(fd, BLKGETSIZE, &size)) {
+ close(fd);
return 1;
+ }
- if (size < 24)
+ if (size < 24) {
+ close(fd);
return 2;
+ }
/*
sb->sb_csum = calc_sb_1_csum(sb);
- rv = store_super1(fd, sb);
+ rv = store_super1(st, fd, sb);
if (rv)
fprintf(stderr, Name ": failed to write superblock to %s\n", devname);
+ close(fd);
return rv;
}
if (st->ss == NULL) {
- /* guess... */
+ int bestvers = -1;
+ __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: return 0; /* good */
+ case 0: super = *sbp;
+ if (bestvers == -1 ||
+ bestctime < __le64_to_cpu(super->ctime)) {
+ bestvers = st->minor_version;
+ bestctime = __le64_to_cpu(super->ctime);
+ }
+ free(super);
+ *sbp = NULL;
+ break;
case 1: st->ss = NULL; 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;
+ return rv;
+ }
st->ss = NULL;
return 2;
}
if (!st) return st;
st->ss = &super1;
+ st->max_devs = 384;
if (strcmp(arg, "1") == 0 ||
strcmp(arg, "1.0") == 0) {
st->minor_version = 0;