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->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;
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->super_offset = __cpu_to_le64(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) << 9 ) &&
+ 0 != (__le64_to_cpu(sb->super_offset) << 9 )
+ ) {
+ fprintf(stderr, Name ": internal error - sb_offset is wrong\n");
+ abort();
+ }
if (lseek64(fd, sb_offset, 0)< 0LL)
return 3;
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);