/*
* 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 */
strncmp(sb->set_name, homehost, l) == 0)
printf(" (local to host %s)", homehost);
printf("\n");
- if (bms->nodes > 0)
+ if (bms->nodes > 0 && (__le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET))
printf(" Cluster Name : %-64s\n", bms->cluster_name);
atime = __le64_to_cpu(sb->ctime) & 0xFFFFFFFFFFULL;
printf(" Creation Time : %.24s\n", ctime(&atime));
}
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;
sb->set_name[l] == ':' &&
strncmp(sb->set_name, homehost, l) == 0)
printf(" (local to host %s)", homehost);
- if (bms->nodes > 0)
+ if (bms->nodes > 0 && (__le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET))
printf("\n Cluster Name : %-64s", bms->cluster_name);
printf("\n UUID : ");
for (i=0; i<16; i++) {
__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;
size /= 512;
bmend += size;
if (bmend > earliest)
- bmend = earliest;
+ earliest = bmend;
}
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;
}
int rv = 0;
int lockid;
struct mdp_superblock_1 *sb = st->sb;
+ bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + MAX_SB_SIZE);
- if (is_clustered(st)) {
- rv = cluster_get_dlmlock(st, &lockid);
+ if (bms->version == BITMAP_MAJOR_CLUSTERED && dlm_funs_ready()) {
+ rv = cluster_get_dlmlock(&lockid);
if (rv) {
pr_err("Cannot get dlmlock in %s return %d\n", __func__, rv);
- cluster_release_dlmlock(st, lockid);
+ cluster_release_dlmlock(lockid);
return rv;
}
}
sb->bblog_shift = 0;
sb->bblog_offset = 0;
}
+ } else if (strcmp(update, "force-no-bbl") == 0) {
+ 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, "name") == 0) {
if (info->name[0] == 0)
sprintf(info->name, "%d", info->array.md_minor);
(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);
rv = -1;
sb->sb_csum = calc_sb_1_csum(sb);
- if (is_clustered(st))
- cluster_release_dlmlock(st, lockid);
+ if (bms->version == BITMAP_MAJOR_CLUSTERED && dlm_funs_ready())
+ cluster_release_dlmlock(lockid);
return rv;
}
struct mdp_superblock_1 *sb = st->sb;
__u16 *rp = sb->dev_roles + dk->number;
struct devinfo *di, **dip;
+ bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + MAX_SB_SIZE);
int rv, lockid;
- if (is_clustered(st)) {
- rv = cluster_get_dlmlock(st, &lockid);
+ if (bms->version == BITMAP_MAJOR_CLUSTERED && dlm_funs_ready()) {
+ rv = cluster_get_dlmlock(&lockid);
if (rv) {
pr_err("Cannot get dlmlock in %s return %d\n", __func__, rv);
- cluster_release_dlmlock(st, lockid);
+ cluster_release_dlmlock(lockid);
return rv;
}
}
di->next = NULL;
*dip = di;
- if (is_clustered(st))
- cluster_release_dlmlock(st, lockid);
+ if (bms->version == BITMAP_MAJOR_CLUSTERED && dlm_funs_ready())
+ cluster_release_dlmlock(lockid);
return 0;
}
#endif
-static void 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 align_fd afd;
int sbsize;
unsigned long long dsize;
+ bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + MAX_SB_SIZE);
int rv, lockid;
- if (is_clustered(st)) {
- rv = cluster_get_dlmlock(st, &lockid);
+ if (bms->version == BITMAP_MAJOR_CLUSTERED && dlm_funs_ready()) {
+ rv = cluster_get_dlmlock(&lockid);
if (rv) {
pr_err("Cannot get dlmlock in %s return %d\n", __func__, rv);
- cluster_release_dlmlock(st, lockid);
+ cluster_release_dlmlock(lockid);
return rv;
}
}
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;
}
}
fsync(fd);
- if (is_clustered(st))
- cluster_release_dlmlock(st, lockid);
+ if (bms->version == BITMAP_MAJOR_CLUSTERED && dlm_funs_ready())
+ cluster_release_dlmlock(lockid);
return 0;
}
* 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;
if (rfd >= 0)
close(rfd);
- sb->events = 0;
+ if (!(di->disk.state & (1<<MD_DISK_JOURNAL)))
+ sb->events = 0;
refst = dup_super(st);
if (load_super1(refst, di->fd, NULL)==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 void 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;
int mustfree = 0;
+ int ret;
if (!st->sb) {
if (st->ss->load_super(st, fd, NULL))
- return; /* no error I hope... */
+ return -1; /* no error I hope... */
mustfree = 1;
}
sb = st->sb;
+ if ((__le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET))
+ ret = 0;
+ 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);
+ return ret;
}
static int write_bitmap1(struct supertype *st, int fd, enum bitmap_update update)
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;
static void free_super1(struct supertype *st)
{
- int rv, lockid;
- if (is_clustered(st)) {
- rv = cluster_get_dlmlock(st, &lockid);
- if (rv) {
- pr_err("Cannot get dlmlock in %s return %d\n", __func__, rv);
- cluster_release_dlmlock(st, lockid);
- return;
- }
- }
if (st->sb)
free(st->sb);
free(di);
}
st->sb = NULL;
- if (is_clustered(st))
- cluster_release_dlmlock(st, lockid);
}
#ifndef MDASSEMBLE