unsigned int disk_csum, csum;
unsigned long long newcsum;
int size = sizeof(*sb) + __le32_to_cpu(sb->max_dev)*2;
- unsigned int *isuper = (unsigned int*)sb;
+ unsigned int *isuper = (unsigned int *)sb;
/* 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 (; size>=4; size -= 4 ) {
+ for (; size >= 4; size -= 4) {
newcsum += __le32_to_cpu(*isuper);
isuper++;
}
static void examine_super1(struct supertype *st, char *homehost)
{
struct mdp_superblock_1 *sb = st->sb;
- bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb)+MAX_SB_SIZE);
+ bitmap_super_t *bms = (bitmap_super_t *)(((char *)sb) + MAX_SB_SIZE);
time_t atime;
unsigned int d;
int role;
int layout;
unsigned long long sb_offset;
struct mdinfo info;
+ int inconsistent = 0;
printf(" Magic : %08x\n", __le32_to_cpu(sb->magic));
printf(" Version : 1");
printf(".0\n");
printf(" Feature Map : 0x%x\n", __le32_to_cpu(sb->feature_map));
printf(" Array UUID : ");
- for (i=0; i<16; i++) {
- if ((i&3)==0 && i != 0) printf(":");
+ for (i = 0; i < 16; i++) {
+ if ((i & 3) == 0 && i != 0)
+ printf(":");
printf("%02x", sb->set_uuid[i]);
}
printf("\n");
st->ss->getinfo_super(st, &info, NULL);
if (info.space_after != 1 &&
- !(__le32_to_cpu(sb->feature_map) & MD_FEATURE_NEW_OFFSET))
- printf(" Unused Space : before=%llu sectors, after=%llu sectors\n",
- info.space_before, info.space_after);
-
- printf(" State : %s\n",
- (__le64_to_cpu(sb->resync_offset)+1)? "active":"clean");
+ !(__le32_to_cpu(sb->feature_map) & MD_FEATURE_NEW_OFFSET)) {
+ printf(" Unused Space : before=%llu sectors, ",
+ info.space_before);
+ if (info.space_after < INT64_MAX)
+ printf("after=%llu sectors\n", info.space_after);
+ else
+ printf("after=-%llu sectors DEVICE TOO SMALL\n",
+ UINT64_MAX - info.space_after);
+ }
+ printf(" State : %s%s\n",
+ (__le64_to_cpu(sb->resync_offset) + 1) ? "active":"clean",
+ (info.space_after > INT64_MAX) ? " TRUNCATED DEVICE" : "");
printf(" Device UUID : ");
- for (i=0; i<16; i++) {
- if ((i&3)==0 && i != 0)
+ for (i = 0; i < 16; i++) {
+ if ((i & 3)==0 && i != 0)
printf(":");
printf("%02x", sb->device_uuid[i]);
}
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]) != MD_DISK_ROLE_SPARE)
- break;
- for (d = 0; d < i; d++) {
- int role = __le16_to_cpu(sb->dev_roles[d]);
- if (d)
- printf(", ");
- if (role == MD_DISK_ROLE_SPARE)
- printf("empty");
- else
- if(role == MD_DISK_ROLE_FAULTY)
- printf("failed");
- else
- printf("%d", role);
- }
- printf(")\n");
-#endif
printf(" Device Role : ");
role = role_from_sb(sb);
if (role >= MD_DISK_ROLE_FAULTY)
if (role == d)
cnt++;
}
- if (cnt == 2)
+ if (cnt == 2 && __le32_to_cpu(sb->level) > 0)
printf("R");
else if (cnt == 1)
printf("A");
else if (cnt == 0)
printf(".");
- else
+ else {
printf("?");
+ inconsistent = 1;
+ }
}
-#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]);
- if (role == MD_DISK_ROLE_FAULTY)
- faulty++;
- }
- if (faulty)
- printf(" %d failed", faulty);
-#endif
printf(" ('A' == active, '.' == missing, 'R' == replacing)");
printf("\n");
+ for (d = 0; d < __le32_to_cpu(sb->max_dev); d++) {
+ unsigned int r = __le16_to_cpu(sb->dev_roles[d]);
+ if (r <= MD_DISK_ROLE_MAX &&
+ r > __le32_to_cpu(sb->raid_disks) + delta_extra)
+ inconsistent = 1;
+ }
+ if (inconsistent) {
+ printf("WARNING Array state is inconsistent - each number should appear only once\n");
+ for (d = 0; d < __le32_to_cpu(sb->max_dev); d++)
+ if (__le16_to_cpu(sb->dev_roles[d]) >=
+ MD_DISK_ROLE_FAULTY)
+ printf(" %d:-", d);
+ else
+ printf(" %d:%d", d,
+ __le16_to_cpu(sb->dev_roles[d]));
+ printf("\n");
+ }
}
static void brief_examine_super1(struct supertype *st, int verbose)
printf("ARRAY ");
if (nm) {
- printf("/dev/md/");
- print_escape(nm);
+ printf(DEV_MD_DIR "%s", nm);
putchar(' ');
}
if (verbose && c)
printf("num-devices=%d ", __le32_to_cpu(sb->raid_disks));
printf("UUID=");
for (i = 0; i < 16; i++) {
- if ((i&3)==0 && i != 0)
+ if ((i & 3)==0 && i != 0)
printf(":");
printf("%02x", sb->set_uuid[i]);
}
- if (sb->set_name[0]) {
- printf(" name=");
- print_quoted(sb->set_name);
- }
printf("\n");
}
int len = 32;
int layout;
- printf("MD_LEVEL=%s\n", map_num(pers, __le32_to_cpu(sb->level)));
+ printf("MD_LEVEL=%s\n", map_num_s(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') {
}
printf("MD_UUID=");
for (i = 0; i < 16; i++) {
- if ((i&3) == 0 && i != 0)
+ if ((i & 3) == 0 && i != 0)
printf(":");
printf("%02x", sb->set_uuid[i]);
}
__le64_to_cpu(sb->utime) & 0xFFFFFFFFFFULL);
printf("MD_DEV_UUID=");
for (i = 0; i < 16; i++) {
- if ((i&3) == 0 && i != 0)
+ if ((i & 3) == 0 && i != 0)
printf(":");
printf("%02x", sb->device_uuid[i]);
}
/* have the header, can calculate
* correct bitmap bytes */
bitmap_super_t *bms;
- bms = (void*)buf;
+ bms = (void *)buf;
bytes = calc_bitmap_size(bms, 512);
if (n > bytes)
n = bytes;
static void detail_super1(struct supertype *st, char *homehost, char *subarray)
{
struct mdp_superblock_1 *sb = st->sb;
- bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + MAX_SB_SIZE);
+ bitmap_super_t *bms = (bitmap_super_t *)(((char *)sb) + MAX_SB_SIZE);
int i;
int l = homehost ? strlen(homehost) : 0;
printf("\n Cluster Name : %-64s", bms->cluster_name);
printf("\n UUID : ");
for (i = 0; i < 16; i++) {
- if ((i&3) == 0 && i != 0)
+ if ((i & 3) == 0 && i != 0)
printf(":");
printf("%02x", sb->set_uuid[i]);
}
struct mdp_superblock_1 *sb = st->sb;
int i;
- if (sb->set_name[0]) {
- printf(" name=");
- print_quoted(sb->set_name);
- }
printf(" UUID=");
for (i = 0; i < 16; i++) {
if ((i & 3) == 0 && i != 0)
}
size = __le16_to_cpu(sb->bblog_size)* 512;
- if (posix_memalign((void**)&bbl, 4096, size) != 0) {
+ if (posix_memalign((void **)&bbl, 4096, size) != 0) {
pr_err("could not allocate badblocks list\n");
return 0;
}
static void uuid_from_super1(struct supertype *st, int uuid[4])
{
struct mdp_superblock_1 *super = st->sb;
- char *cuuid = (char*)uuid;
+ char *cuuid = (char *)uuid;
int i;
for (i = 0; i < 16; i++)
cuuid[i] = super->set_uuid[i];
static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map)
{
struct mdp_superblock_1 *sb = st->sb;
- struct bitmap_super_s *bsb = (void*)(((char*)sb)+MAX_SB_SIZE);
+ struct bitmap_super_s *bsb = (void *)(((char *)sb) + MAX_SB_SIZE);
struct misc_dev_info *misc =
- (void*)(((char*)sb)+MAX_SB_SIZE+BM_SUPER_SIZE);
+ (void *)(((char *)sb) + MAX_SB_SIZE+BM_SUPER_SIZE);
int working = 0;
unsigned int i;
unsigned int role;
info->recovery_blocked = info->reshape_active;
if (map)
- for (i=0; i<map_disks; i++)
+ 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]);
}
static int update_super1(struct supertype *st, struct mdinfo *info,
- char *update, char *devname, int verbose,
+ enum update_opt update, char *devname, int verbose,
int uuid_set, char *homehost)
{
/* NOTE: for 'assemble' and 'force' we need to return non-zero
*/
int rv = 0;
struct mdp_superblock_1 *sb = st->sb;
- bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + MAX_SB_SIZE);
+ bitmap_super_t *bms = (bitmap_super_t *)(((char *)sb) + MAX_SB_SIZE);
- if (strcmp(update, "homehost") == 0 &&
- homehost) {
- /* Note that 'homehost' is special as it is really
+ if (update == UOPT_HOMEHOST && homehost) {
+ /*
+ * Note that 'homehost' is special as it is really
* a "name" update.
*/
char *c;
- update = "name";
+ update = UOPT_NAME;
c = strchr(sb->set_name, ':');
if (c)
- strncpy(info->name, c+1, 31 - (c-sb->set_name));
+ snprintf(info->name, sizeof(info->name), "%s", c + 1);
else
- strncpy(info->name, sb->set_name, 32);
- info->name[32] = 0;
+ snprintf(info->name, sizeof(info->name), "%s",
+ sb->set_name);
}
- if (strcmp(update, "force-one")==0) {
+ switch (update) {
+ case UOPT_NAME: {
+ int namelen;
+
+ if (!info->name[0])
+ snprintf(info->name, sizeof(info->name), "%d", info->array.md_minor);
+ memset(sb->set_name, 0, sizeof(sb->set_name));
+
+ namelen = strnlen(homehost, MD_NAME_MAX) + 1 + strnlen(info->name, MD_NAME_MAX);
+ if (homehost &&
+ strchr(info->name, ':') == NULL &&
+ namelen < MD_NAME_MAX) {
+ strcpy(sb->set_name, homehost);
+ strcat(sb->set_name, ":");
+ strcat(sb->set_name, info->name);
+ } else {
+ namelen = min((int)strnlen(info->name, MD_NAME_MAX),
+ (int)sizeof(sb->set_name) - 1);
+ memcpy(sb->set_name, info->name, namelen);
+ memset(&sb->set_name[namelen], '\0',
+ sizeof(sb->set_name) - namelen);
+ }
+ break;
+ }
+ case UOPT_SPEC_FORCE_ONE:
/* Not enough devices for a working array,
* so bring this one up-to-date
*/
if (sb->events != __cpu_to_le64(info->events))
rv = 1;
sb->events = __cpu_to_le64(info->events);
- } else if (strcmp(update, "force-array")==0) {
+ break;
+ case UOPT_SPEC_FORCE_ARRAY:
/* Degraded array and 'force' requests to
* maybe need to mark it 'clean'.
*/
rv = 1;
sb->resync_offset = MaxSector;
}
- } else if (strcmp(update, "assemble")==0) {
+ break;
+ case UOPT_SPEC_ASSEMBLE: {
int d = info->disk.number;
int want;
if (info->disk.state & (1<<MD_DISK_ACTIVE))
__cpu_to_le64(info->reshape_progress);
rv = 1;
}
- } else if (strcmp(update, "linear-grow-new") == 0) {
- unsigned int i;
+ break;
+ }
+ case UOPT_SPEC_LINEAR_GROW_NEW: {
+ int i;
int fd;
- unsigned int max = __le32_to_cpu(sb->max_dev);
+ int max = __le32_to_cpu(sb->max_dev);
+
+ if (max > MAX_DEVS)
+ return -2;
for (i = 0; i < max; i++)
if (__le16_to_cpu(sb->dev_roles[i]) >=
MD_DISK_ROLE_FAULTY)
break;
+ if (i != info->disk.number)
+ return -2;
sb->dev_number = __cpu_to_le32(i);
- info->disk.number = i;
- if (i >= max) {
- sb->max_dev = __cpu_to_le32(max+1);
- }
+
+ if (i == max)
+ sb->max_dev = __cpu_to_le32(max + 1);
+ if (i > max)
+ return -2;
random_uuid(sb->device_uuid);
sb->data_size = __cpu_to_le64(
ds - __le64_to_cpu(sb->data_offset));
} else {
- ds -= 8*2;
- ds &= ~(unsigned long long)(4*2-1);
+ 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));
}
}
- } else if (strcmp(update, "linear-grow-update") == 0) {
+ break;
+ }
+ case UOPT_SPEC_LINEAR_GROW_UPDATE: {
int max = __le32_to_cpu(sb->max_dev);
+ int i = info->disk.number;
+ if (max > MAX_DEVS || i > MAX_DEVS)
+ return -2;
+ if (i > max)
+ return -2;
+ if (i == max)
+ sb->max_dev = __cpu_to_le32(max + 1);
sb->raid_disks = __cpu_to_le32(info->array.raid_disks);
- if (info->array.raid_disks > max) {
- sb->max_dev = __cpu_to_le32(max+1);
- }
sb->dev_roles[info->disk.number] =
__cpu_to_le16(info->disk.raid_disk);
- } else if (strcmp(update, "resync") == 0) {
+ break;
+ }
+ case UOPT_RESYNC:
/* make sure resync happens */
- sb->resync_offset = 0ULL;
- } else if (strcmp(update, "uuid") == 0) {
+ sb->resync_offset = 0;
+ break;
+ case UOPT_UUID:
copy_uuid(sb->set_uuid, info->uuid, super1.swapuuid);
if (__le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET)
memcpy(bms->uuid, sb->set_uuid, 16);
- } else if (strcmp(update, "no-bitmap") == 0) {
+ break;
+ case UOPT_NO_BITMAP:
sb->feature_map &= ~__cpu_to_le32(MD_FEATURE_BITMAP_OFFSET);
- } else if (strcmp(update, "bbl") == 0) {
+ if (bms->version == BITMAP_MAJOR_CLUSTERED && !IsBitmapDirty(devname))
+ sb->resync_offset = MaxSector;
+ break;
+ case UOPT_BBL: {
/* only possible if there is room after the bitmap, or if
* there is no bitmap
*/
bb_offset = bitmap_offset + bm_sectors;
while (bb_offset < (long)sb_offset + 8 + 32*2 &&
bb_offset + 8+8 <= (long)data_offset)
- /* too close to bitmap, and room to grow */
bb_offset += 8;
if (bb_offset + 8 <= (long)data_offset) {
sb->bblog_size = __cpu_to_le16(8);
sb->bblog_offset = __cpu_to_le32(bb_offset);
}
} else {
- /* 1.0 - Put bbl just before super block */
if (bm_sectors && bitmap_offset < 0)
space = -bitmap_offset - bm_sectors;
else
sb->bblog_offset = __cpu_to_le32((unsigned)-8);
}
}
- } else if (strcmp(update, "no-bbl") == 0) {
+ break;
+ }
+ case UOPT_NO_BBL:
if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BAD_BLOCKS))
pr_err("Cannot remove active bbl from %s\n",devname);
else {
sb->bblog_shift = 0;
sb->bblog_offset = 0;
}
- } else if (strcmp(update, "force-no-bbl") == 0) {
+ break;
+ case UOPT_FORCE_NO_BBL:
sb->feature_map &= ~ __cpu_to_le32(MD_FEATURE_BAD_BLOCKS);
sb->bblog_size = 0;
sb->bblog_shift = 0;
sb->bblog_offset = 0;
- } else if (strcmp(update, "ppl") == 0) {
+ break;
+ case UOPT_PPL: {
unsigned long long sb_offset = __le64_to_cpu(sb->super_offset);
unsigned long long data_offset = __le64_to_cpu(sb->data_offset);
unsigned long long data_size = __le64_to_cpu(sb->data_size);
sb->ppl.offset = __cpu_to_le16(offset);
sb->ppl.size = __cpu_to_le16(space);
sb->feature_map |= __cpu_to_le32(MD_FEATURE_PPL);
- } else if (strcmp(update, "no-ppl") == 0) {
+ break;
+ }
+ case UOPT_NO_PPL:
sb->feature_map &= ~__cpu_to_le32(MD_FEATURE_PPL |
MD_FEATURE_MUTLIPLE_PPLS);
- } 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));
- if (homehost &&
- strchr(info->name, ':') == NULL &&
- strlen(homehost)+1+strlen(info->name) < 32) {
- strcpy(sb->set_name, homehost);
- strcat(sb->set_name, ":");
- strcat(sb->set_name, info->name);
- } else {
- int namelen;
-
- namelen = min((int)strlen(info->name),
- (int)sizeof(sb->set_name) - 1);
- memcpy(sb->set_name, info->name, namelen);
- memset(&sb->set_name[namelen], '\0',
- sizeof(sb->set_name) - namelen);
- }
- } 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 */
+ break;
+ case UOPT_DEVICESIZE:
+ if (__le64_to_cpu(sb->super_offset) >=
+ __le64_to_cpu(sb->data_offset))
+ break;
+ /*
+ * set data_size to device size less data_offset
+ */
struct misc_dev_info *misc = (struct misc_dev_info*)
(st->sb + MAX_SB_SIZE + BM_SUPER_SIZE);
sb->data_size = __cpu_to_le64(
misc->device_size - __le64_to_cpu(sb->data_offset));
- } else if (strncmp(update, "revert-reshape", 14) == 0) {
+ break;
+ case UOPT_SPEC_REVERT_RESHAPE_NOBACKUP:
+ case UOPT_REVERT_RESHAPE:
rv = -2;
if (!(sb->feature_map &
__cpu_to_le32(MD_FEATURE_RESHAPE_ACTIVE)))
* If that couldn't happen, the "-nobackup" version
* will be used.
*/
- if (strcmp(update, "revert-reshape-nobackup") == 0 &&
+ if (update == UOPT_SPEC_REVERT_RESHAPE_NOBACKUP &&
sb->reshape_position == 0 &&
(__le32_to_cpu(sb->delta_disks) > 0 ||
(__le32_to_cpu(sb->delta_disks) == 0 &&
* So we reject a revert-reshape unless the
* alignment is good.
*/
- if (__le32_to_cpu(sb->level) >= 4 &&
- __le32_to_cpu(sb->level) <= 6) {
+ if (is_level456(__le32_to_cpu(sb->level))) {
reshape_sectors =
__le64_to_cpu(sb->reshape_position);
reshape_chunk = __le32_to_cpu(sb->new_chunk);
}
done:;
}
- } else if (strcmp(update, "_reshape_progress") == 0)
+ break;
+ case UOPT_SPEC__RESHAPE_PROGRESS:
sb->reshape_position = __cpu_to_le64(info->reshape_progress);
- else if (strcmp(update, "writemostly") == 0)
+ break;
+ case UOPT_SPEC_WRITEMOSTLY:
sb->devflags |= WriteMostly1;
- else if (strcmp(update, "readwrite") == 0)
+ break;
+ case UOPT_SPEC_READWRITE:
sb->devflags &= ~WriteMostly1;
- else if (strcmp(update, "failfast") == 0)
+ break;
+ case UOPT_SPEC_FAILFAST:
sb->devflags |= FailFast1;
- else if (strcmp(update, "nofailfast") == 0)
+ break;
+ case UOPT_SPEC_NOFAILFAST:
sb->devflags &= ~FailFast1;
- else
+ break;
+ case UOPT_LAYOUT_ORIGINAL:
+ case UOPT_LAYOUT_ALTERNATE:
+ case UOPT_LAYOUT_UNSPECIFIED:
+ if (__le32_to_cpu(sb->level) != 0) {
+ pr_err("%s: %s only supported for RAID0\n",
+ devname ?: "", map_num(update_options, update));
+ rv = -1;
+ } else if (update == UOPT_LAYOUT_UNSPECIFIED) {
+ sb->feature_map &= ~__cpu_to_le32(MD_FEATURE_RAID0_LAYOUT);
+ sb->layout = 0;
+ } else {
+ sb->feature_map |= __cpu_to_le32(MD_FEATURE_RAID0_LAYOUT);
+ sb->layout = __cpu_to_le32(update == UOPT_LAYOUT_ORIGINAL ? 1 : 2);
+ }
+ break;
+ default:
rv = -1;
+ }
sb->sb_csum = calc_sb_1_csum(sb);
char defname[10];
int sbsize;
- if (posix_memalign((void**)&sb, 4096, SUPER1_SIZE) != 0) {
+ if (posix_memalign((void **)&sb, 4096, SUPER1_SIZE) != 0) {
pr_err("could not allocate superblock\n");
return 0;
}
name = defname;
}
if (homehost &&
- strchr(name, ':')== NULL &&
- strlen(homehost)+1+strlen(name) < 32) {
+ strchr(name, ':') == NULL &&
+ strlen(homehost) + 1 + strlen(name) < 32) {
strcpy(sb->set_name, homehost);
strcat(sb->set_name, ":");
strcat(sb->set_name, name);
if (dk->number >= (int)__le32_to_cpu(sb->max_dev) &&
__le32_to_cpu(sb->max_dev) < MAX_DEVS)
- sb->max_dev = __cpu_to_le32(dk->number+1);
+ 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 */
di->devname = devname;
di->disk = *dk;
di->data_offset = data_offset;
- get_dev_size(fd, NULL, &di->dev_size);
+
+ if (is_fd_valid(fd))
+ get_dev_size(fd, NULL, &di->dev_size);
+
di->next = NULL;
*dip = di;
return 4;
if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) {
- struct bitmap_super_s *bm = (struct bitmap_super_s*)
- (((char*)sb)+MAX_SB_SIZE);
+ struct bitmap_super_s *bm;
+ bm = (struct bitmap_super_s *)(((char *)sb) + MAX_SB_SIZE);
if (__le32_to_cpu(bm->magic) == BITMAP_MAGIC) {
locate_bitmap1(st, fd, 0);
if (awrite(&afd, bm, sizeof(*bm)) != sizeof(*bm))
init_afd(&afd, fd);
- if (posix_memalign((void**)&mb, 4096, META_BLOCK_SIZE) != 0) {
+ if (posix_memalign((void **)&mb, 4096, META_BLOCK_SIZE) != 0) {
pr_err("Could not allocate memory for the meta block.\n");
return 1;
}
return 1;
}
+static bool has_raid0_layout(struct mdp_superblock_1 *sb)
+{
+ if (sb->level == 0 && sb->layout != 0)
+ return true;
+ else
+ return false;
+}
+
static int write_init_super1(struct supertype *st)
{
struct mdp_superblock_1 *sb = st->sb;
unsigned long long sb_offset;
unsigned long long data_offset;
long bm_offset;
- int raid0_need_layout = 0;
+ bool raid0_need_layout = false;
+
+ /* Since linux kernel v5.4, raid0 always has a layout */
+ if (has_raid0_layout(sb) && get_linux_version() >= 5004000)
+ raid0_need_layout = true;
for (di = st->info; di; di = di->next) {
if (di->disk.state & (1 << MD_DISK_JOURNAL))
sb->feature_map |= __cpu_to_le32(MD_FEATURE_JOURNAL);
- if (sb->level == 0 && sb->layout != 0) {
+ if (has_raid0_layout(sb) && !raid0_need_layout) {
+
struct devinfo *di2 = st->info;
unsigned long long s1, s2;
s1 = di->dev_size;
s2 -= di2->data_offset;
s2 /= __le32_to_cpu(sb->chunksize);
if (s1 != s2)
- raid0_need_layout = 1;
+ raid0_need_layout = true;
}
}
/* same array, so preserve events and
* dev_number */
sb->events = refsb->events;
- /* bugs in 2.6.17 and earlier mean the
- * dev_number chosen in Manage must be preserved
- */
- if (get_linux_version() >= 2006018)
- sb->dev_number = refsb->dev_number;
}
free_super1(refst);
}
return rv;
}
-static int compare_super1(struct supertype *st, struct supertype *tst)
+static int compare_super1(struct supertype *st, struct supertype *tst,
+ int verbose)
{
/*
* return:
return 1;
if (!first) {
- if (posix_memalign((void**)&first, 4096, SUPER1_SIZE) != 0) {
+ if (posix_memalign((void **)&first, 4096, SUPER1_SIZE) != 0) {
pr_err("could not allocate superblock\n");
return 1;
}
tst.ss = &super1;
for (tst.minor_version = 0; tst.minor_version <= 2;
tst.minor_version++) {
+ tst.ignore_hw_compat = st->ignore_hw_compat;
switch(load_super1(&tst, fd, devname)) {
case 0: super = tst.sb;
if (bestvers == -1 ||
return 1;
}
- if (posix_memalign((void**)&super, 4096, SUPER1_SIZE) != 0) {
+ if (posix_memalign((void **)&super, 4096, SUPER1_SIZE) != 0) {
pr_err("could not allocate superblock\n");
return 1;
}
free(super);
return 2;
}
- st->sb = super;
- bsb = (struct bitmap_super_s *)(((char*)super)+MAX_SB_SIZE);
+ bsb = (struct bitmap_super_s *)(((char *)super) + MAX_SB_SIZE);
misc = (struct misc_dev_info*)
- (((char*)super)+MAX_SB_SIZE+BM_SUPER_SIZE);
+ (((char *)super) + MAX_SB_SIZE+BM_SUPER_SIZE);
misc->device_size = dsize;
if (st->data_offset == INVALID_SECTORS)
st->data_offset = __le64_to_cpu(super->data_offset);
+ if (st->minor_version >= 1 &&
+ st->ignore_hw_compat == 0 &&
+ ((role_from_sb(super) != MD_DISK_ROLE_JOURNAL &&
+ dsize < (__le64_to_cpu(super->data_offset) +
+ __le64_to_cpu(super->size))) ||
+ dsize < (__le64_to_cpu(super->data_offset) +
+ __le64_to_cpu(super->data_size)))) {
+ if (devname)
+ pr_err("Device %s is not large enough for data described in superblock\n",
+ devname);
+ free(super);
+ return 2;
+ }
+ st->sb = super;
+
/* Now check on the bitmap superblock */
if ((__le32_to_cpu(super->feature_map)&MD_FEATURE_BITMAP_OFFSET) == 0)
return 0;
return 0;
no_bitmap:
- super->feature_map = __cpu_to_le32(__le32_to_cpu(super->feature_map)
- & ~MD_FEATURE_BITMAP_OFFSET);
+ super->feature_map = __cpu_to_le32(__le32_to_cpu(super->feature_map) &
+ ~MD_FEATURE_BITMAP_OFFSET);
return 0;
}
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)+MAX_SB_SIZE);
+ bsb = (struct bitmap_super_s *)(((char *)super) + MAX_SB_SIZE);
bmspace = calc_bitmap_size(bsb, 4096) >> 9;
} else if (md_feature_any_ppl_on(super->feature_map)) {
bmspace = __le16_to_cpu(super->ppl.size);
int creating = 0;
int len;
struct mdp_superblock_1 *sb = st->sb;
- bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + MAX_SB_SIZE);
+ bitmap_super_t *bms = (bitmap_super_t *)(((char *)sb) + MAX_SB_SIZE);
int uuid[4];
if (__le64_to_cpu(sb->data_size) == 0)
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;
+ bits = (size * 512) / min_chunk + 1;
while (bits > max_bits) {
min_chunk *= 2;
- bits = (bits+1)/2;
+ bits = (bits + 1) / 2;
}
if (chunk == UnSet) {
/* For practical purpose, 64Meg is a good
/* start bitmap on a 4K boundary with enough space for
* the bitmap
*/
- bits = (size*512) / chunk + 1;
- room = ((bits+7)/8 + sizeof(bitmap_super_t) +4095)/4096;
+ bits = (size * 512) / chunk + 1;
+ room = ((bits + 7) / 8 + sizeof(bitmap_super_t) + 4095) / 4096;
room *= 8; /* convert 4K blocks to sectors */
offset = -room - bbl_size;
}
static int locate_bitmap1(struct supertype *st, int fd, int node_num)
{
- unsigned long long offset;
+ unsigned long long offset, bm_sectors_per_node;
struct mdp_superblock_1 *sb;
+ bitmap_super_t *bms;
int mustfree = 0;
int ret;
ret = 0;
else
ret = -1;
- offset = __le64_to_cpu(sb->super_offset);
- offset += (int32_t) __le32_to_cpu(sb->bitmap_offset) * (node_num + 1);
+
+ offset = __le64_to_cpu(sb->super_offset) + (int32_t)__le32_to_cpu(sb->bitmap_offset);
+ if (node_num) {
+ bms = (bitmap_super_t *)(((char *)sb) + MAX_SB_SIZE);
+ bm_sectors_per_node = calc_bitmap_size(bms, 4096) >> 9;
+ offset += bm_sectors_per_node * node_num;
+ }
if (mustfree)
free(sb);
lseek64(fd, offset<<9, 0);
static int write_bitmap1(struct supertype *st, int fd, enum bitmap_update update)
{
struct mdp_superblock_1 *sb = st->sb;
- bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb)+MAX_SB_SIZE);
+ bitmap_super_t *bms = (bitmap_super_t *)(((char *)sb) + MAX_SB_SIZE);
int rv = 0;
void *buf;
int towrite, n, len;
}
if (bms->version == BITMAP_MAJOR_CLUSTERED) {
- if (__cpu_to_le32(st->nodes) < bms->nodes) {
+ if (st->nodes == 1) {
+ /* the parameter for nodes is not valid */
+ pr_err("Warning: cluster-md at least needs two nodes\n");
+ return -EINVAL;
+ } else if (st->nodes == 0) {
+ /*
+ * parameter "--nodes" is not specified, (eg, add a disk to
+ * clustered raid)
+ */
+ break;
+ } else if (__cpu_to_le32(st->nodes) < bms->nodes) {
/*
* Since the nodes num is not increased, no
* need to check the space enough or not,
init_afd(&afd, fd);
- locate_bitmap1(st, fd, 0);
+ if (locate_bitmap1(st, fd, 0) < 0) {
+ pr_err("Error: Invalid bitmap\n");
+ return -EINVAL;
+ }
if (posix_memalign(&buf, 4096, 4096))
return -ENOMEM;
unsigned long long ldsize, devsize;
int bmspace;
unsigned long long headroom;
+ unsigned long long overhead;
int fd;
- if (level == LEVEL_CONTAINER) {
+ if (is_container(level)) {
if (verbose)
pr_err("1.x metadata does not support containers\n");
return 0;
close(fd);
devsize = ldsize >> 9;
- if (devsize < 24) {
- *freesize = 0;
- return 0;
- }
/* creating: allow suitable space for bitmap or PPL */
if (consistency_policy == CONSISTENCY_POLICY_PPL)
case 0: /* metadata at end. Round down and subtract space to reserve */
devsize = (devsize & ~(4ULL*2-1));
/* space for metadata, bblog, bitmap/ppl */
- devsize -= 8*2 + 8 + bmspace;
+ overhead = 8*2 + 8 + bmspace;
+ if (devsize < overhead) /* detect underflow */
+ goto dev_too_small_err;
+ devsize -= overhead;
break;
case 1:
case 2:
+ if (devsize < data_offset) /* detect underflow */
+ goto dev_too_small_err;
devsize -= data_offset;
break;
}
*freesize = devsize;
return 1;
+
+/* Error condition, device cannot even hold the overhead. */
+dev_too_small_err:
+ fprintf(stderr, "device %s is too small (%lluK) for "
+ "required metadata!\n", subdev, devsize>>1);
+ *freesize = 0;
+ return 0;
}
void *super1_make_v0(struct supertype *st, struct mdinfo *info, mdp_super_t *sb0)
copy_uuid(sb->set_uuid, info->uuid, super1.swapuuid);
sprintf(sb->set_name, "%d", sb0->md_minor);
- sb->ctime = __cpu_to_le32(info->array.ctime+1);
+ sb->ctime = __cpu_to_le32(info->array.ctime + 1);
sb->level = __cpu_to_le32(info->array.level);
sb->layout = __cpu_to_le32(info->array.layout);
sb->size = __cpu_to_le64(info->component_size);
- sb->chunksize = __cpu_to_le32(info->array.chunk_size/512);
+ sb->chunksize = __cpu_to_le32(info->array.chunk_size / 512);
sb->raid_disks = __cpu_to_le32(info->array.raid_disks);
if (info->array.level > 0)
sb->data_size = sb->size;
else
- sb->data_size = st->ss->avail_size(st, st->devsize/512, 0);
+ sb->data_size = st->ss->avail_size(st, st->devsize / 512, 0);
sb->resync_offset = MaxSector;
sb->max_dev = __cpu_to_le32(MD_SB_DISKS);
sb->dev_number = __cpu_to_le32(info->disk.number);