/*
* mdadm - manage Linux "md" devices aka RAID arrays.
*
- * Copyright (C) 2001-2009 Neil Brown <neilb@suse.de>
+ * Copyright (C) 2001-2016 Neil Brown <neilb@suse.com>
*
*
* This program is free software; you can redistribute it and/or modify
|MD_FEATURE_JOURNAL \
)
+#ifndef MDASSEMBLE
static int role_from_sb(struct mdp_superblock_1 *sb)
{
unsigned int d;
role = MD_DISK_ROLE_SPARE;
return role;
}
+#endif
/* return how many bytes are needed for bitmap, for cluster-md each node
* should have it's own bitmap */
}
if (super.bblog_size != 0 &&
- __le32_to_cpu(super.bblog_size) <= 100 &&
+ __le16_to_cpu(super.bblog_size) <= 100 &&
super.bblog_offset != 0 &&
(super.feature_map & __le32_to_cpu(MD_FEATURE_BAD_BLOCKS))) {
/* There is a bad block log */
unsigned long long bb_offset = sb_offset;
- int bytes = __le32_to_cpu(super.bblog_size) * 512;
+ int bytes = __le16_to_cpu(super.bblog_size) * 512;
int written = 0;
struct align_fd afrom, ato;
__u64 *bbl, *bbp;
int i;
- if (!sb->bblog_size || __le32_to_cpu(sb->bblog_size) > 100
+ if (!sb->bblog_size || __le16_to_cpu(sb->bblog_size) > 100
|| !sb->bblog_offset){
printf("No bad-blocks list configured on %s\n", devname);
return 0;
return 0;
}
- size = __le32_to_cpu(sb->bblog_size)* 512;
+ size = __le16_to_cpu(sb->bblog_size)* 512;
if (posix_memalign((void**)&bbl, 4096, size) != 0) {
pr_err("could not allocate badblocks list\n");
return 0;
if (sb->bblog_offset && sb->bblog_size) {
unsigned long long bbend = super_offset;
bbend += (int32_t)__le32_to_cpu(sb->bblog_offset);
- bbend += __le32_to_cpu(sb->bblog_size);
+ bbend += __le16_to_cpu(sb->bblog_size);
if (bbend > earliest)
earliest = bbend;
}
}
} else if (strcmp(update, "linear-grow-new") == 0) {
unsigned int i;
- int rfd, fd;
+ int fd;
unsigned int max = __le32_to_cpu(sb->max_dev);
for (i=0 ; i < max ; 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 r[4] = {random(), random(), random(), random()};
- memcpy(sb->device_uuid, r, 16);
- }
- if (rfd >= 0)
- close(rfd);
+ random_uuid(sb->device_uuid);
sb->dev_roles[i] =
__cpu_to_le16(info->disk.raid_disk);
(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 (strcmp(update, "revert-reshape") == 0) {
+ } else if (strncmp(update, "revert-reshape", 14) == 0) {
rv = -2;
if (!(sb->feature_map & __cpu_to_le32(MD_FEATURE_RESHAPE_ACTIVE)))
pr_err("No active reshape to revert on %s\n",
unsigned long long reshape_sectors;
long reshape_chunk;
rv = 0;
+ /* If the reshape hasn't started, just stop it.
+ * It is conceivable that a stripe was modified but
+ * the metadata not updated. In that case the backup
+ * should have been used to get passed the critical stage.
+ * If that couldn't happen, the "-nobackup" version
+ * will be used.
+ */
+ if (strcmp(update, "revert-reshape-nobackup") == 0 &&
+ sb->reshape_position == 0 &&
+ (__le32_to_cpu(sb->delta_disks) > 0 ||
+ (__le32_to_cpu(sb->delta_disks) == 0 &&
+ !(sb->feature_map & __cpu_to_le32(MD_FEATURE_RESHAPE_BACKWARDS))))) {
+ sb->feature_map &= ~__cpu_to_le32(MD_FEATURE_RESHAPE_ACTIVE);
+ sb->raid_disks = __cpu_to_le32(__le32_to_cpu(sb->raid_disks) -
+ __le32_to_cpu(sb->delta_disks));
+ sb->delta_disks = 0;
+ goto done;
+ }
/* reshape_position is a little messy.
* Its value must be a multiple of the larger
* chunk size, and of the "after" data disks.
sb->new_offset = __cpu_to_le32(-offset_delta);
sb->data_size = __cpu_to_le64(__le64_to_cpu(sb->data_size) - offset_delta);
}
+ done:;
}
} else if (strcmp(update, "_reshape_progress")==0)
sb->reshape_position = __cpu_to_le64(info->reshape_progress);
{
struct mdp_superblock_1 *sb;
int spares;
- int rfd;
char defname[10];
int sbsize;
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 r[4] = {random(), random(), random(), random()};
- memcpy(sb->set_uuid, r, 16);
- }
- if (rfd >= 0) close(rfd);
- }
+ else
+ random_uuid(sb->set_uuid);;
if (name == NULL || *name == 0) {
sprintf(defname, "%d", info->md_minor);
}
#endif
-static int locate_bitmap1(struct supertype *st, int fd);
+static int locate_bitmap1(struct supertype *st, int fd, int node_num);
static int store_super1(struct supertype *st, int fd)
{
struct bitmap_super_s *bm = (struct bitmap_super_s*)
(((char*)sb)+MAX_SB_SIZE);
if (__le32_to_cpu(bm->magic) == BITMAP_MAGIC) {
- locate_bitmap1(st, fd);
+ locate_bitmap1(st, fd, 0);
if (awrite(&afd, bm, sizeof(*bm)) != sizeof(*bm))
return 5;
}
* NOTE: result must be multiple of 4K else bad things happen
* on 4K-sector devices.
*/
- if (devsize < 64*2) return 0;
+ 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)
#define META_BLOCK_SIZE 4096
__u32 crc32c_le(__u32 crc, unsigned char const *p, size_t len);
+#ifndef MDASSEMBLE
static int write_empty_r5l_meta_block(struct supertype *st, int fd)
{
struct r5l_meta_block *mb;
return 1;
}
-#ifndef MDASSEMBLE
static int write_init_super1(struct supertype *st)
{
struct mdp_superblock_1 *sb = st->sb;
struct supertype *refst;
- int rfd;
int rv = 0;
unsigned long long bm_space;
struct devinfo *di;
else
sb->devflags &= ~WriteMostly1;
- if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 ||
- read(rfd, sb->device_uuid, 16) != 16) {
- __u32 r[4] = {random(), random(), random(), random()};
- memcpy(sb->device_uuid, r, 16);
- }
- if (rfd >= 0)
- close(rfd);
+ random_uuid(sb->device_uuid);
if (!(di->disk.state & (1<<MD_DISK_JOURNAL)))
sb->events = 0;
}
if (rv == 0 && (__le32_to_cpu(sb->feature_map) & 1))
- rv = st->ss->write_bitmap(st, di->fd, NoUpdate);
+ rv = st->ss->write_bitmap(st, di->fd, NodeNumUpdate);
close(di->fd);
di->fd = -1;
if (rv)
return 1;
}
+ memset(super, 0, SUPER1_SIZE);
+
if (aread(&afd, super, MAX_SB_SIZE) != MAX_SB_SIZE) {
if (devname)
pr_err("Cannot read superblock on %s\n",
* valid. If it doesn't clear the bit. An --assemble --force
* should get that written out.
*/
- locate_bitmap1(st, fd);
+ locate_bitmap1(st, fd, 0);
if (aread(&afd, bsb, 512) != 512)
goto no_bitmap;
unsigned long long chunk = *chunkp;
int room = 0;
int creating = 0;
+ int len;
struct mdp_superblock_1 *sb = st->sb;
bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + MAX_SB_SIZE);
int uuid[4];
}
break;
default:
- return 0;
+ return -ENOSPC;
}
room -= bbl_size;
if (room <= 1)
/* No room for a bitmap */
- return 0;
+ return -ENOSPC;
max_bits = (room * 512 - sizeof(bitmap_super_t)) * 8;
if (chunk < 64*1024*1024)
chunk = 64*1024*1024;
} else if (chunk < min_chunk)
- return 0; /* chunk size too small */
+ return -EINVAL; /* chunk size too small */
if (chunk == 0) /* rounding problem */
- return 0;
+ return -EINVAL;
if (offset == 0) {
/* start bitmap on a 4K boundary with enough space for
if (st->nodes)
sb->feature_map = __cpu_to_le32(__le32_to_cpu(sb->feature_map)
| MD_FEATURE_BITMAP_VERSIONED);
- if (st->cluster_name)
- strncpy((char *)bms->cluster_name,
- st->cluster_name, strlen(st->cluster_name));
+ if (st->cluster_name) {
+ len = sizeof(bms->cluster_name);
+ strncpy((char *)bms->cluster_name, st->cluster_name, len);
+ bms->cluster_name[len - 1] = '\0';
+ }
*chunkp = chunk;
- return 1;
+ return 0;
}
-static int locate_bitmap1(struct supertype *st, int fd)
+static int locate_bitmap1(struct supertype *st, int fd, int node_num)
{
unsigned long long offset;
struct mdp_superblock_1 *sb;
else
ret = -1;
offset = __le64_to_cpu(sb->super_offset);
- offset += (int32_t) __le32_to_cpu(sb->bitmap_offset);
+ offset += (int32_t) __le32_to_cpu(sb->bitmap_offset) * (node_num + 1);
if (mustfree)
free(sb);
lseek64(fd, offset<<9, 0);
bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb)+MAX_SB_SIZE);
int rv = 0;
void *buf;
- int towrite, n;
+ int towrite, n, len;
struct align_fd afd;
unsigned int i = 0;
unsigned long long total_bm_space, bm_space_per_node;
case NameUpdate:
/* update cluster name */
if (st->cluster_name) {
- memset((char *)bms->cluster_name, 0, sizeof(bms->cluster_name));
- strncpy((char *)bms->cluster_name, st->cluster_name, 64);
+ len = sizeof(bms->cluster_name);
+ memset((char *)bms->cluster_name, 0, len);
+ strncpy((char *)bms->cluster_name,
+ st->cluster_name, len);
+ bms->cluster_name[len - 1] = '\0';
}
break;
case NodeNumUpdate:
/* cluster md only supports superblock 1.2 now */
- if (st->minor_version != 2) {
+ if (st->minor_version != 2 && bms->version == BITMAP_MAJOR_CLUSTERED) {
pr_err("Warning: cluster md only works with superblock 1.2\n");
return -EINVAL;
}
+ if (bms->version == BITMAP_MAJOR_CLUSTERED) {
+ 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)
+ /* --nodes is not specified */
+ break;
+ else if (__cpu_to_le32(st->nodes) < bms->nodes) {
+ /* Since the nodes num is not increased, no need to check the space
+ * is enough or not, just update bms->nodes */
+ bms->nodes = __cpu_to_le32(st->nodes);
+ break;
+ }
+ } else {
+ /* no need to change bms->nodes for other bitmap types */
+ if (st->nodes)
+ pr_err("Warning: --nodes option is only suitable for clustered bitmap\n");
+ break;
+ }
+
/* Each node has an independent bitmap, it is necessary to calculate the
* space is enough or not, first get how many bytes for the total bitmap */
bm_space_per_node = calc_bitmap_size(bms, 4096);
init_afd(&afd, fd);
- locate_bitmap1(st, fd);
+ locate_bitmap1(st, fd, 0);
if (posix_memalign(&buf, 4096, 4096))
return -ENOMEM;
void *ret;
struct mdp_superblock_1 *sb;
int i;
- int rfd;
unsigned long long offset;
if (posix_memalign(&ret, 4096, 1024) != 0)
sb->super_offset = __cpu_to_le64(offset);
//*(__u64*)(st->other + 128 + 8 + 8) = __cpu_to_le64(offset);
- if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 ||
- read(rfd, sb->device_uuid, 16) != 16) {
- __u32 r[4] = {random(), random(), random(), random()};
- memcpy(sb->device_uuid, r, 16);
- }
- if (rfd >= 0)
- close(rfd);
+ random_uuid(sb->device_uuid);
for (i = 0; i < MD_SB_DISKS; i++) {
int state = sb0->disks[i].state;