return __cpu_to_le32(csum);
}
+static char abuf[4096+4096];
+static int aread(int fd, void *buf, int len)
+{
+ /* aligned read.
+ * On devices with a 4K sector size, we need to read
+ * the full sector and copy relevant bits into
+ * the buffer
+ */
+ int bsize;
+ char *b;
+ int n;
+ if (ioctl(fd, BLKSSZGET, &bsize) != 0 ||
+ bsize <= len)
+ return read(fd, buf, len);
+ if (bsize > 4096)
+ return -1;
+ b = (char*)(((long)(abuf+4096))&~4095UL);
+
+ n = read(fd, b, bsize);
+ if (n <= 0)
+ return n;
+ lseek(fd, len - n, 1);
+ if (n > len)
+ n = len;
+ memcpy(buf, b, n);
+ return n;
+}
+
+static int awrite(int fd, void *buf, int len)
+{
+ /* aligned write.
+ * On devices with a 4K sector size, we need to write
+ * the full sector. We pre-read if the sector is larger
+ * than the write.
+ * The address must be sector-aligned.
+ */
+ int bsize;
+ char *b;
+ int n;
+ if (ioctl(fd, BLKSSZGET, &bsize) != 0 ||
+ bsize <= len)
+ return write(fd, buf, len);
+ if (bsize > 4096)
+ return -1;
+ b = (char*)(((long)(abuf+4096))&~4095UL);
+
+ n = read(fd, b, bsize);
+ if (n <= 0)
+ return n;
+ lseek(fd, -n, 1);
+ memcpy(b, buf, len);
+ n = write(fd, b, bsize);
+ if (n <= 0)
+ return n;
+ lseek(fd, len - n, 1);
+ return len;
+}
+
#ifndef MDASSEMBLE
static void examine_super1(struct supertype *st, char *homehost)
{
struct mdp_superblock_1 *sb = st->sb;
time_t atime;
int d;
- int faulty;
+ int role;
int i;
char *c;
int l = homehost ? strlen(homehost) : 0;
printf(" New Layout : %s\n", c?c:"-unknown-");
}
if (__le32_to_cpu(sb->level) == 10) {
- printf(" New Layout : near=%d, %s=%d\n",
- __le32_to_cpu(sb->new_layout)&255,
- (__le32_to_cpu(sb->new_layout)&0x10000)?"offset":"far",
- (__le32_to_cpu(sb->new_layout)>>8)&255);
+ printf(" New Layout :");
+ print_r10_layout(__le32_to_cpu(sb->new_layout));
+ printf("\n");
}
}
if (__le32_to_cpu(sb->new_chunk) != __le32_to_cpu(sb->chunksize))
}
if (__le32_to_cpu(sb->level) == 10) {
int lo = __le32_to_cpu(sb->layout);
- printf(" Layout : near=%d, %s=%d\n",
- lo&255,
- (lo&0x10000)?"offset":"far",
- (lo>>8)&255);
+ printf(" Layout :");
+ print_r10_layout(lo);
+ printf("\n");
}
switch(__le32_to_cpu(sb->level)) {
case 0:
default: break;
}
printf("\n");
+#if 0
+ /* This turns out to just be confusing */
printf(" Array Slot : %d (", __le32_to_cpu(sb->dev_number));
for (i= __le32_to_cpu(sb->max_dev); i> 0 ; i--)
if (__le16_to_cpu(sb->dev_roles[i-1]) != 0xffff)
else printf("%d", role);
}
printf(")\n");
+#endif
+ printf(" Device Role : ");
+ d = __le32_to_cpu(sb->dev_number);
+ if (d < sb->raid_disks)
+ role = __le16_to_cpu(sb->dev_roles[d]);
+ else
+ role = 0xFFFF;
+ if (role >= 0xFFFE)
+ printf("spare\n");
+ else
+ printf("Active device %d\n", role);
+
printf(" Array State : ");
for (d=0; d<__le32_to_cpu(sb->raid_disks); d++) {
int cnt = 0;
}
}
if (cnt > 1) printf("?");
- else if (cnt == 1 && me) printf("U");
- else if (cnt == 1) printf("u");
- else printf ("_");
+ else if (cnt == 1) printf("A");
+ else printf (".");
}
+#if 0
+ /* This is confusing too */
faulty = 0;
for (i=0; i< __le32_to_cpu(sb->max_dev); i++) {
int role = __le16_to_cpu(sb->dev_roles[i]);
faulty++;
}
if (faulty) printf(" %d failed", faulty);
+#endif
+ printf(" ('A' == active, '.' == missing)");
printf("\n");
}
else if (sb->set_name[0])
nm = sb->set_name;
else
- nm = "??";
+ nm = NULL;
- printf("ARRAY /dev/md/%s level=%s ", nm, c?c:"-unknown-");
+ printf("ARRAY%s%s level=%s ",
+ nm ? " /dev/md/":"", nm,
+ c?c:"-unknown-");
sb_offset = __le64_to_cpu(sb->super_offset);
if (sb_offset <= 4)
printf("metadata=1.1 ");
}
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
}
info->events = __le64_to_cpu(sb->events);
sprintf(info->text_version, "1.%d", st->minor_version);
+ info->safe_mode_delay = 200;
memcpy(info->uuid, sb->set_uuid, 16);
}
if (strcmp(update, "linear-grow-new") == 0) {
int i;
- int rfd;
+ int rfd, fd;
int max = __le32_to_cpu(sb->max_dev);
for (i=0 ; i < max ; i++)
sb->dev_roles[i] =
__cpu_to_le16(info->disk.raid_disk);
+
+ fd = open(devname, O_RDONLY);
+ if (fd >= 0) {
+ unsigned long long ds;
+ get_dev_size(fd, devname, &ds);
+ close(fd);
+ ds >>= 9;
+ if (__le64_to_cpu(sb->super_offset) <
+ __le64_to_cpu(sb->data_offset)) {
+ sb->data_size = __cpu_to_le64(
+ ds - __le64_to_cpu(sb->data_offset));
+ } else {
+ ds -= 8*2;
+ ds &= ~(unsigned long long)(4*2-1);
+ sb->super_offset = __cpu_to_le64(ds);
+ sb->data_size = __cpu_to_le64(
+ ds - __le64_to_cpu(sb->data_offset));
+ }
+ }
}
if (strcmp(update, "linear-grow-update") == 0) {
sb->raid_disks = __cpu_to_le32(info->array.raid_disks);
int rfd;
char defname[10];
- posix_memalign((void**)&sb, 512, (1024 + 512 +
- sizeof(struct misc_dev_info)));
+ if (posix_memalign((void**)&sb, 512, (1024 + 512 +
+ sizeof(struct misc_dev_info))) != 0) {
+ fprintf(stderr, Name
+ ": %s could not allocate superblock\n", __func__);
+ return 0;
+ }
memset(sb, 0, 1024);
st->sb = sb;
mdu_disk_info_t disk;
struct devinfo *next;
};
+#ifndef MDASSEMBLE
/* Add a device to the superblock being created */
-static void add_to_super1(struct supertype *st, mdu_disk_info_t *dk,
+static int add_to_super1(struct supertype *st, mdu_disk_info_t *dk,
int fd, char *devname)
{
struct mdp_superblock_1 *sb = st->sb;
else
*rp = 0xfffe;
+ if (dk->number >= __le32_to_cpu(sb->max_dev) &&
+ __le32_to_cpu(sb->max_dev) < 384)
+ sb->max_dev = __cpu_to_le32(dk->number+1);
+
sb->dev_number = __cpu_to_le32(dk->number);
sb->sb_csum = calc_sb_1_csum(sb);
di->disk = *dk;
di->next = NULL;
*dip = di;
+
+ return 0;
}
+#endif
static void locate_bitmap1(struct supertype *st, int fd);
sbsize = sizeof(*sb) + 2 * __le32_to_cpu(sb->max_dev);
sbsize = (sbsize+511)&(~511UL);
- if (write(fd, sb, sbsize) != sbsize)
+ if (awrite(fd, sb, sbsize) != sbsize)
return 4;
if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) {
(((char*)sb)+1024);
if (__le32_to_cpu(bm->magic) == BITMAP_MAGIC) {
locate_bitmap1(st, fd);
- if (write(fd, bm, ROUND_UP(sizeof(*bm),512)) !=
- ROUND_UP(sizeof(*bm),512))
+ if (awrite(fd, bm, sizeof(*bm)) !=
+ sizeof(*bm))
return 5;
}
}
return 1;
if (!first) {
- posix_memalign((void**)&first, 512,
+ if (posix_memalign((void**)&first, 512,
1024 + 512 +
- sizeof(struct misc_dev_info));
+ sizeof(struct misc_dev_info)) != 0) {
+ fprintf(stderr, Name
+ ": %s could not allocate superblock\n", __func__);
+ return 1;
+ }
memcpy(first, second, 1024 + 512 +
sizeof(struct misc_dev_info));
st->sb = first;
return 1;
}
- posix_memalign((void**)&super, 512,
+ if (posix_memalign((void**)&super, 512,
1024 + 512 +
- sizeof(struct misc_dev_info));
+ sizeof(struct misc_dev_info)) != 0) {
+ fprintf(stderr, Name ": %s could not allocate superblock\n",
+ __func__);
+ return 1;
+ }
- if (read(fd, super, 1024) != 1024) {
+ if (aread(fd, super, 1024) != 1024) {
if (devname)
fprintf(stderr, Name ": Cannot read superblock on %s\n",
devname);
* should get that written out.
*/
locate_bitmap1(st, fd);
- if (read(fd, ((char*)super)+1024, 512)
+ if (aread(fd, ((char*)super)+1024, 512)
!= 512)
goto no_bitmap;
st->ss = &super1;
st->max_devs = 384;
st->sb = NULL;
- if (strcmp(arg, "1.0") == 0) {
+ /* leading zeros can be safely ignored. --detail generates them. */
+ while (*arg == '0')
+ arg++;
+ if (strcmp(arg, "1.0") == 0 ||
+ strcmp(arg, "1.00") == 0) {
st->minor_version = 0;
return st;
}
- if (strcmp(arg, "1.1") == 0) {
+ if (strcmp(arg, "1.1") == 0 ||
+ strcmp(arg, "1.01") == 0) {
st->minor_version = 1;
return st;
}
- if (strcmp(arg, "1.2") == 0) {
+ if (strcmp(arg, "1.2") == 0 ||
+ strcmp(arg, "1.02") == 0) {
st->minor_version = 2;
return st;
}
*/
static __u64 avail_size1(struct supertype *st, __u64 devsize)
{
+ struct mdp_superblock_1 *super = st->sb;
if (devsize < 24)
return 0;
- devsize -= choose_bm_space(devsize);
+ if (super == NULL)
+ /* creating: allow suitable space for bitmap */
+ devsize -= choose_bm_space(devsize);
+#ifndef MDASSEMBLE
+ else if (__le32_to_cpu(super->feature_map)&MD_FEATURE_BITMAP_OFFSET) {
+ /* hot-add. allow for actual size of bitmap */
+ struct bitmap_super_s *bsb;
+ bsb = (struct bitmap_super_s *)(((char*)super)+1024);
+ devsize -= bitmap_sectors(bsb);
+ }
+#endif
switch(st->minor_version) {
case -1: /* no specified. Now time to set default */
int rv = 0;
int towrite, n;
- char abuf[4096+512];
- char *buf = (char*)(((long)(abuf+512))&~511UL);
+ char *buf = (char*)(((long)(abuf+4096))&~4095UL);
locate_bitmap1(st, fd);
st->sb = NULL;
}
+#ifndef MDASSEMBLE
static int validate_geometry1(struct supertype *st, int level,
int layout, int raiddisks,
int chunk, unsigned long long size,
- char *subdev, unsigned long long *freesize)
+ char *subdev, unsigned long long *freesize,
+ int verbose)
{
unsigned long long ldsize;
int fd;
fd = open(subdev, O_RDONLY|O_EXCL, 0);
if (fd < 0) {
- fprintf(stderr, Name ": Cannot open %s: %s\n",
- subdev, strerror(errno));
+ if (verbose)
+ fprintf(stderr, Name ": super1.x cannot open %s: %s\n",
+ subdev, strerror(errno));
return 0;
}
+
if (!get_dev_size(fd, subdev, &ldsize)) {
close(fd);
return 0;
*freesize = avail_size1(st, ldsize >> 9);
return 1;
}
+#endif /* MDASSEMBLE */
struct superswitch super1 = {
#ifndef MDASSEMBLE
.brief_detail_super = brief_detail_super1,
.export_detail_super = export_detail_super1,
.write_init_super = write_init_super1,
+ .validate_geometry = validate_geometry1,
+ .add_to_super = add_to_super1,
#endif
.match_home = match_home1,
.uuid_from_super = uuid_from_super1,
.getinfo_super = getinfo_super1,
.update_super = update_super1,
.init_super = init_super1,
- .add_to_super = add_to_super1,
.store_super = store_super1,
.compare_super = compare_super1,
.load_super = load_super1,
.locate_bitmap = locate_bitmap1,
.write_bitmap = write_bitmap1,
.free_super = free_super1,
- .validate_geometry = validate_geometry1,
#if __BYTE_ORDER == BIG_ENDIAN
.swapuuid = 0,
#else
.swapuuid = 1,
#endif
+ .name = "1.0",
};