summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2005-08-25 04:31:44 +0000
committerNeil Brown <neilb@suse.de>2005-08-25 04:31:44 +0000
commit34163fc7cfa4346ca7f2ca08039e0c5a3cf901ab (patch)
treed435caab2002739a704d35fe70ede2ab7afd1321
parenteb3b43aa2a44e590e3cb3129d1e29df45d18a22a (diff)
downloadmdadm-34163fc7cfa4346ca7f2ca08039e0c5a3cf901ab.tar.gz
mdadm-34163fc7cfa4346ca7f2ca08039e0c5a3cf901ab.tar.xz
mdadm-34163fc7cfa4346ca7f2ca08039e0c5a3cf901ab.zip
Support internal bitmaps with format-1 superblocks.
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
-rw-r--r--Create.c6
-rw-r--r--Grow.c2
-rw-r--r--Manage.c2
-rw-r--r--bitmap.c27
-rw-r--r--mdadm.h6
-rw-r--r--super0.c7
-rw-r--r--super1.c216
-rw-r--r--test11
-rw-r--r--tests/03r0assem2
9 files changed, 236 insertions, 43 deletions
diff --git a/Create.c b/Create.c
index 86b9dff..d8fcdfe 100644
--- a/Create.c
+++ b/Create.c
@@ -210,7 +210,7 @@ int Create(struct supertype *st, char *mddev, int mdfd,
ldsize = dsize;
ldsize <<= 9;
}
- freesize = st->ss->avail_size(ldsize >> 9);
+ freesize = st->ss->avail_size(st, ldsize >> 9, 64*2);
if (freesize == 0) {
fprintf(stderr, Name ": %s is too small: %luK\n",
dname, (unsigned long)(ldsize>>10));
@@ -355,7 +355,7 @@ int Create(struct supertype *st, char *mddev, int mdfd,
fprintf(stderr, Name ": internal bitmaps not supported by this kernel.\n");
return 1;
}
- if (!st->ss->add_internal_bitmap(super, bitmap_chunk, delay, write_behind,
+ if (!st->ss->add_internal_bitmap(st, super, bitmap_chunk, delay, write_behind,
size ? size : maxsize)) {
fprintf(stderr, Name ": Given bitmap chunk size not supported.\n");
return 1;
@@ -451,7 +451,7 @@ int Create(struct supertype *st, char *mddev, int mdfd,
break;
case 2:
if (disk.state == 1) break;
- st->ss->write_init_super(st, super, &disk, dv->devname);
+ st->ss->write_init_super(st, super, &disk, dv->devname, 64*2);
if (ioctl(mdfd, ADD_NEW_DISK, &disk)) {
fprintf(stderr, Name ": ADD_NEW_DISK for %s failed: %s\n",
diff --git a/Grow.c b/Grow.c
index 6157261..623daf3 100644
--- a/Grow.c
+++ b/Grow.c
@@ -273,7 +273,7 @@ int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int
if (fd2 < 0)
continue;
if (st->ss->load_super(st, fd2, &super, NULL)==0) {
- st->ss->add_internal_bitmap(super,
+ st->ss->add_internal_bitmap(st, super,
chunk, delay, write_behind,
array.size);
st->ss->write_bitmap(st, fd2, super);
diff --git a/Manage.c b/Manage.c
index 4cf40e1..8cc977f 100644
--- a/Manage.c
+++ b/Manage.c
@@ -311,7 +311,7 @@ int Manage_subdevs(char *devname, int fd,
if (dv->writemostly)
disc.state |= 1 << MD_DISK_WRITEMOSTLY;
st->ss->add_to_super(dsuper, &disc);
- if (st->ss->write_init_super(st, dsuper, &disc, dv->devname))
+ if (st->ss->write_init_super(st, dsuper, &disc, dv->devname, 0 /* FIXME */))
return 1;
} else if (dv->re_add) {
/* this had better be raid1.
diff --git a/bitmap.c b/bitmap.c
index 0a2ed5d..36ecd95 100644
--- a/bitmap.c
+++ b/bitmap.c
@@ -177,11 +177,12 @@ out:
return info;
}
-bitmap_info_t *bitmap_file_read(char *filename, int brief, struct supertype *st)
+bitmap_info_t *bitmap_file_read(char *filename, int brief, struct supertype **stp)
{
int fd;
bitmap_info_t *info;
struct stat stb;
+ struct supertype *st = *stp;
fd = open(filename, O_RDONLY);
if (fd < 0) {
@@ -199,6 +200,8 @@ bitmap_info_t *bitmap_file_read(char *filename, int brief, struct supertype *st)
} else {
st->ss->locate_bitmap(st, fd);
}
+ ioctl(fd, BLKFLSBUF, 0); /* make sure we read current data */
+ *stp = st;
}
info = bitmap_fd_read(fd, brief);
@@ -206,6 +209,18 @@ bitmap_info_t *bitmap_file_read(char *filename, int brief, struct supertype *st)
return info;
}
+__u32 swapl(__u32 l)
+{
+ char *c = (char*)&l;
+ char t= c[0];
+ c[0] = c[3];
+ c[3] = t;
+
+ t = c[1];
+ c[1] = c[2];
+ c[2] = t;
+ return l;
+}
int ExamineBitmap(char *filename, int brief, struct supertype *st)
{
/*
@@ -217,7 +232,7 @@ int ExamineBitmap(char *filename, int brief, struct supertype *st)
int rv = 1;
char buf[64];
- info = bitmap_file_read(filename, brief, st);
+ info = bitmap_file_read(filename, brief, &st);
if (!info)
return rv;
@@ -234,11 +249,19 @@ int ExamineBitmap(char *filename, int brief, struct supertype *st)
}
rv = 0;
+ if (st && st->ss->swapuuid) {
+ printf(" UUID : %08x.%08x.%08x.%08x\n",
+ swapl(*(__u32 *)(sb->uuid+0)),
+ swapl(*(__u32 *)(sb->uuid+4)),
+ swapl(*(__u32 *)(sb->uuid+8)),
+ swapl(*(__u32 *)(sb->uuid+12)));
+ } else {
printf(" UUID : %08x.%08x.%08x.%08x\n",
*(__u32 *)(sb->uuid+0),
*(__u32 *)(sb->uuid+4),
*(__u32 *)(sb->uuid+8),
*(__u32 *)(sb->uuid+12));
+ }
printf(" Events : %llu\n", sb->events);
printf(" Events Cleared : %llu\n", sb->events_cleared);
printf(" State : %s\n", bitmap_state(sb->state));
diff --git a/mdadm.h b/mdadm.h
index 547519c..06dd114 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -185,12 +185,12 @@ extern struct superswitch {
int (*init_super)(struct supertype *st, void **sbp, mdu_array_info_t *info, char *name);
void (*add_to_super)(void *sbv, mdu_disk_info_t *dinfo);
int (*store_super)(struct supertype *st, int fd, void *sbv);
- int (*write_init_super)(struct supertype *st, void *sbv, mdu_disk_info_t *dinfo, char *devname);
+ int (*write_init_super)(struct supertype *st, void *sbv, mdu_disk_info_t *dinfo, char *devname, int reserve);
int (*compare_super)(void **firstp, void *secondv);
int (*load_super)(struct supertype *st, int fd, void **sbp, char *devname);
struct supertype * (*match_metadata_desc)(char *arg);
- __u64 (*avail_size)(__u64 size);
- int (*add_internal_bitmap)(void *sbv, int chunk, int delay, int write_behind, unsigned long long size);
+ __u64 (*avail_size)(struct supertype *st, __u64 size, int reserve);
+ int (*add_internal_bitmap)(struct supertype *st, void *sbv, int chunk, int delay, int write_behind, unsigned long long size);
void (*locate_bitmap)(struct supertype *st, int fd);
int (*write_bitmap)(struct supertype *st, int fd, void *sbv);
int major;
diff --git a/super0.c b/super0.c
index b028cff..496e3bb 100644
--- a/super0.c
+++ b/super0.c
@@ -472,7 +472,7 @@ static int store_super0(struct supertype *st, int fd, void *sbv)
return 0;
}
-static int write_init_super0(struct supertype *st, void *sbv, mdu_disk_info_t *dinfo, char *devname)
+static int write_init_super0(struct supertype *st, void *sbv, mdu_disk_info_t *dinfo, char *devname, int reserve)
{
mdp_super_t *sb = sbv;
int fd = open(devname, O_RDWR|O_EXCL);
@@ -664,14 +664,15 @@ static struct supertype *match_metadata_desc0(char *arg)
return NULL;
}
-static __u64 avail_size0(__u64 devsize)
+static __u64 avail_size0(struct supertype *st, __u64 devsize, int reserve)
{
if (devsize < MD_RESERVED_SECTORS*2)
return 0ULL;
+ if (reserve > 64*2) return 0ULL;
return MD_NEW_SIZE_SECTORS(devsize);
}
-static int add_internal_bitmap0(void *sbv, int chunk, int delay, int write_behind, unsigned long long size)
+static int add_internal_bitmap0(struct supertype *st, void *sbv, int chunk, int delay, int write_behind, unsigned long long size)
{
/*
* The bitmap comes immediately after the superblock and must be 60K in size
diff --git a/super1.c b/super1.c
index e25d005..d4e4f76 100644
--- a/super1.c
+++ b/super1.c
@@ -54,7 +54,11 @@ struct mdp_superblock_1 {
__u32 chunksize; /* in 512byte sectors */
__u32 raid_disks;
- __u8 pad1[128-96]; /* set to 0 when written */
+ __u32 bitmap_offset; /* sectors after start of superblock that bitmap starts
+ * NOTE: signed, so bitmap can be before superblock
+ * only meaningful of feature_map[0] is set.
+ */
+ __u8 pad1[128-100]; /* set to 0 when written */
/* constant this-device information - 64 bytes */
__u64 data_offset; /* sector start of data, often 0 */
@@ -131,8 +135,8 @@ static void examine_super1(void *sbv)
printf(" Version : %02d.%02d\n", 1, __le32_to_cpu(sb->feature_map));
printf(" Array UUID : ");
for (i=0; i<16; i++) {
- printf("%02x", sb->set_uuid[i]);
if ((i&3)==0 && i != 0) printf(":");
+ printf("%02x", sb->set_uuid[i]);
}
printf("\n");
printf(" Name : %.32s\n", sb->set_name);
@@ -151,13 +155,13 @@ static void examine_super1(void *sbv)
printf(" State : %s\n", (__le64_to_cpu(sb->resync_offset)+1)? "active":"clean");
printf(" Device UUID : ");
for (i=0; i<16; i++) {
- printf("%02x", sb->set_uuid[i]);
if ((i&3)==0 && i != 0) printf(":");
+ printf("%02x", sb->device_uuid[i]);
}
printf("\n");
if (sb->devflags) {
printf(" Flags :");
- if (sb->devflags & WriteMostly1)
+ if (sb->devflags & WriteMostly1)
printf(" write-mostly");
printf("\n");
}
@@ -243,8 +247,8 @@ static void detail_super1(void *sbv)
printf(" Name : %.32s\n", sb->set_name);
printf(" UUID : ");
for (i=0; i<16; i++) {
- printf("%02x", sb->set_uuid[i]);
if ((i&3)==0 && i != 0) printf(":");
+ printf("%02x", sb->set_uuid[i]);
}
printf("\n Events : %llu\n\n", (unsigned long long)__le64_to_cpu(sb->events));
}
@@ -258,8 +262,8 @@ static void brief_detail_super1(void *sbv)
printf(" name=%.32s", sb->set_name);
printf(" UUID=");
for (i=0; i<16; i++) {
- printf("%02x", sb->set_uuid[i]);
if ((i&3)==0 && i != 0) printf(":");
+ printf("%02x", sb->set_uuid[i]);
}
}
@@ -385,8 +389,9 @@ static __u64 event_super1(void *sbv)
static int init_super1(struct supertype *st, void **sbp, mdu_array_info_t *info, char *name)
{
- struct mdp_superblock_1 *sb = malloc(1024);
+ struct mdp_superblock_1 *sb = malloc(1024 + sizeof(bitmap_super_t));
int spares;
+ int rfd;
memset(sb, 0, 1024);
if (info->major_version == -1)
@@ -405,10 +410,15 @@ static int init_super1(struct supertype *st, void **sbp, mdu_array_info_t *info,
sb->major_version = __cpu_to_le32(1);
sb->feature_map = 0;
sb->pad0 = 0;
- *(__u32*)(sb->set_uuid) = random();
- *(__u32*)(sb->set_uuid+4) = random();
- *(__u32*)(sb->set_uuid+8) = random();
- *(__u32*)(sb->set_uuid+12) = random();
+
+ if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 ||
+ read(rfd, sb->set_uuid, 16) != 16) {
+ *(__u32*)(sb->set_uuid) = random();
+ *(__u32*)(sb->set_uuid+4) = random();
+ *(__u32*)(sb->set_uuid+8) = random();
+ *(__u32*)(sb->set_uuid+12) = random();
+ }
+ if (rfd >= 0) close(rfd);
memset(sb->set_name, 0, 32);
strcpy(sb->set_name, name);
@@ -431,7 +441,7 @@ static int init_super1(struct supertype *st, void **sbp, mdu_array_info_t *info,
sb->resync_offset = ~0ULL;
else
sb->resync_offset = 0;
- sb->max_dev = __cpu_to_le32((1024- sizeof(struct mdp_superblock_1))/
+ sb->max_dev = __cpu_to_le32((1024- sizeof(struct mdp_superblock_1))/
sizeof(sb->dev_roles[0]));
memset(sb->pad3, 0, sizeof(sb->pad3));
@@ -450,7 +460,7 @@ static void add_to_super1(void *sbv, mdu_disk_info_t *dk)
*rp = __cpu_to_le16(dk->raid_disk);
else if ((dk->state & ~2) == 0) /* active or idle -> spare */
*rp = 0xffff;
- else
+ else
*rp = 0xfffe;
}
@@ -493,7 +503,7 @@ static int store_super1(struct supertype *st, int fd, void *sbv)
}
-
+
if (sb_offset != __le64_to_cpu(sb->super_offset) &&
0 != __le64_to_cpu(sb->super_offset)
) {
@@ -515,7 +525,9 @@ static int store_super1(struct supertype *st, int fd, void *sbv)
static int load_super1(struct supertype *st, int fd, void **sbp, char *devname);
-static int write_init_super1(struct supertype *st, void *sbv, mdu_disk_info_t *dinfo, char *devname)
+static int write_init_super1(struct supertype *st, void *sbv,
+ mdu_disk_info_t *dinfo, char *devname,
+ int reserve)
{
struct mdp_superblock_1 *sb = sbv;
struct mdp_superblock_1 *refsb = NULL;
@@ -534,7 +546,7 @@ static int write_init_super1(struct supertype *st, void *sbv, mdu_disk_info_t *d
}
sb->dev_number = __cpu_to_le32(dinfo->number);
- if (dinfo->state & (1<<MD_DISK_WRITEMOSTLY))
+ if (dinfo->state & (1<<MD_DISK_WRITEMOSTLY))
sb->devflags |= WriteMostly1;
if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 ||
@@ -556,7 +568,7 @@ static int write_init_super1(struct supertype *st, void *sbv, mdu_disk_info_t *d
}
free(refsb);
}
-
+
if (ioctl(fd, BLKGETSIZE, &size)) {
close(fd);
return 1;
@@ -583,18 +595,18 @@ static int write_init_super1(struct supertype *st, void *sbv, mdu_disk_info_t *d
sb_offset &= ~(4*2-1);
sb->super_offset = __cpu_to_le64(sb_offset);
sb->data_offset = __cpu_to_le64(0);
- sb->data_size = sb->super_offset;
+ sb->data_size = __cpu_to_le64(sb_offset - reserve);
break;
case 1:
sb->super_offset = __cpu_to_le64(0);
- sb->data_offset = __cpu_to_le64(2);
- sb->data_size = __cpu_to_le64(size - 2);
+ sb->data_offset = __cpu_to_le64(2 + reserve);
+ sb->data_size = __cpu_to_le64(size - 2 - reserve);
break;
case 2:
sb_offset = 4*2;
sb->super_offset = __cpu_to_le64(sb_offset);
- sb->data_offset = __cpu_to_le64(sb_offset+2);
- sb->data_size = __cpu_to_le64(size - 4*2 - 2);
+ sb->data_offset = __cpu_to_le64(sb_offset+2 + reserve);
+ sb->data_size = __cpu_to_le64(size - 4*2 - 2 - reserve);
break;
default:
return -EINVAL;
@@ -605,6 +617,30 @@ static int write_init_super1(struct supertype *st, void *sbv, mdu_disk_info_t *d
rv = store_super1(st, fd, sb);
if (rv)
fprintf(stderr, Name ": failed to write superblock to %s\n", devname);
+
+ if (__le32_to_cpu(sb->feature_map) & 1) {
+ /* write the bitmap */
+ int towrite, n;
+ char buf[4096];
+
+ st->ss->locate_bitmap(st, fd);
+ write(fd, ((char*)sb)+1024, sizeof(bitmap_super_t));
+ towrite = 62*1024;
+ memset(buf, 0xff, sizeof(buf));
+ while (towrite > 0) {
+ n=towrite;
+ if (n > sizeof(buf))
+ n = sizeof(buf);
+ n = write(fd, buf, n);
+ if (n > 0)
+ towrite -= n;
+ else
+ break;
+ }
+ if (towrite)
+ rv = -2;
+ }
+ fsync(fd);
close(fd);
return rv;
}
@@ -686,7 +722,7 @@ static int load_super1(struct supertype *st, int fd, void **sbp, char *devname)
return 2;
}
if (ioctl(fd, BLKGETSIZE, &size)) {
- if (devname)
+ if (devname)
fprintf(stderr, Name ": cannot find device size for %s: %s\n",
devname, strerror(errno));
return 1;
@@ -733,7 +769,7 @@ static int load_super1(struct supertype *st, int fd, void **sbp, char *devname)
return 1;
}
- super = malloc(1024);
+ super = malloc(1024 + sizeof(bitmap_super_t));
if (read(fd, super, 1024) != 1024) {
if (devname)
@@ -795,12 +831,137 @@ static struct supertype *match_metadata_desc1(char *arg)
return NULL;
}
-static __u64 avail_size1(__u64 devsize)
+/* find available size on device with this devsize, using
+ * superblock type st, and reserving 'reserve' sectors for
+ * a possible bitmap
+ */
+static __u64 avail_size1(struct supertype *st, __u64 devsize, int reserve)
{
if (devsize < 24)
return 0;
- return (devsize - 8*2 ) & ~(4*2-1);
+ switch(st->minor_version) {
+ case 0:
+ /* at end, with reserve before it */
+ return ((devsize - 8*2 ) & ~(4*2-1)) - reserve;
+ case 1:
+ /* at start, 1K for superblock */
+ return devsize - 2 - reserve;
+ case 2:
+ /* 4k from start, 1K for superblock */
+ return devsize - (4+1)*2 - reserve;
+ }
+ return 0;
+}
+
+static int add_internal_bitmap1(struct supertype *st, void *sbv, int chunk, int delay, int write_behind, unsigned long long size)
+{
+ /*
+ * The bitmap comes immediately before of after the superblock and must be 62K in size
+ * at most. The default size is between 31K and 62K
+ *
+ * size is in K, chunk is in bytes !!!
+ */
+
+ unsigned long long bits = size;
+ unsigned long long max_bits = 62*1024*8;
+ unsigned long long min_chunk;
+ struct mdp_superblock_1 *sb = sbv;
+ bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + 1024);
+
+
+ min_chunk = 4096; /* sub-page chunks don't work yet.. */
+ while (bits > max_bits) {
+ min_chunk *= 2;
+ bits = (bits+1)/2;
+ }
+ if (chunk == UnSet)
+ chunk = min_chunk;
+ else if (chunk < min_chunk)
+ return 0; /* chunk size too small */
+
+ if (st->minor_version == 0)
+ sb->bitmap_offset = __cpu_to_le32(-64*2);
+ else
+ sb->bitmap_offset = __cpu_to_le32(2);
+
+ sb->feature_map = __cpu_to_le32(__le32_to_cpu(sb->feature_map) | 1);
+ memset(bms, sizeof(*bms), 0);
+ bms->magic = __cpu_to_le32(BITMAP_MAGIC);
+ bms->version = __cpu_to_le32(BITMAP_MAJOR);
+ uuid_from_super1((int*)bms->uuid, sb);
+ bms->chunksize = __cpu_to_le32(chunk);
+ bms->daemon_sleep = __cpu_to_le32(delay);
+ bms->sync_size = __cpu_to_le64(size);
+ bms->write_behind = __cpu_to_le32(write_behind);
+
+
+
+ return 1;
+}
+
+
+void locate_bitmap1(struct supertype *st, int fd)
+{
+ unsigned long long dsize;
+ unsigned long size;
+ unsigned long long offset;
+
+ switch(st->minor_version){
+ case 0:
+#ifdef BLKGETSIZE64
+ if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
+#endif
+ {
+ if (ioctl(fd, BLKGETSIZE, &size))
+ return;
+ else
+ dsize = ((unsigned long long)size)<<9;
+ }
+
+ offset = (dsize - 8192) & ~4095ULL;
+
+ offset -= 65536;
+ break;
+
+ case 1:
+ offset = 1024;
+ break;
+ case 2:
+ offset = 4096+1024;
+ }
+ lseek64(fd, offset, 0);
+}
+
+int write_bitmap1(struct supertype *st, int fd, void *sbv)
+{
+ struct mdp_superblock_1 *sb = sbv;
+
+ int rv = 0;
+
+ int towrite, n;
+ char buf[4096];
+
+ locate_bitmap1(st, fd);
+
+ write(fd, ((char*)sb)+1024, sizeof(bitmap_super_t));
+ towrite = 62*1024 - sizeof(bitmap_super_t);
+ memset(buf, 0xff, sizeof(buf));
+ while (towrite > 0) {
+ n = towrite;
+ if (n > sizeof(buf))
+ n = sizeof(buf);
+ n = write(fd, buf, n);
+ if (n > 0)
+ towrite -= n;
+ else
+ break;
+ }
+ fsync(fd);
+ if (towrite)
+ rv = -2;
+
+ return rv;
}
struct superswitch super1 = {
@@ -822,6 +983,9 @@ struct superswitch super1 = {
.load_super = load_super1,
.match_metadata_desc = match_metadata_desc1,
.avail_size = avail_size1,
+ .add_internal_bitmap = add_internal_bitmap1,
+ .locate_bitmap = locate_bitmap1,
+ .write_bitmap = write_bitmap1,
.major = 1,
#if __BYTE_ORDER == BIG_ENDIAN
.swapuuid = 0,
diff --git a/test b/test
index dadca13..b505fa9 100644
--- a/test
+++ b/test
@@ -27,7 +27,9 @@ md0=/dev/md0 md1=/dev/md1 md2=/dev/md2
targetdir=/tmp
size=20000
mdsize0=19904
-mdsize1=19992
+mdsize1=19928
+mdsize11=19935
+mdsize12=19931
cleanup() {
$mdadm -Ss
@@ -96,7 +98,7 @@ check() {
bitmap )
grep -s bitmap > /dev/null /proc/mdstat || {
- echo >&2 ERROR no bitmap ; cat /proc/mdstat ; exist 1; }
+ echo >&2 ERROR no bitmap ; cat /proc/mdstat ; exit 1; }
;;
nobitmap )
if grep -s "bitmap" > /dev/null /proc/mdstat
@@ -134,8 +136,10 @@ rotest() {
-for script in tests/$prefix*[^~]
+for script in tests/$prefix tests/$prefix*[^~]
do
+ if [ -f "$script" ]
+ then
# source script in a subshell, so it has access to our
# namespace, but cannot change it.
if ( set -ex ; . $script ) 2> $targetdir/log
@@ -144,5 +148,6 @@ do
echo "$script failed"
exit 1
fi
+ fi
done
exit 0
diff --git a/tests/03r0assem b/tests/03r0assem
index 0d53901..6428cc0 100644
--- a/tests/03r0assem
+++ b/tests/03r0assem
@@ -84,7 +84,7 @@ mdadm -A $md2 -u $uuid $devlist
$tst
mdadm -S $md2
-# version 1 has now super-minor
+# version 1 has no super-minor
# mdadm --assemble $md2 --super-minor=2 $devlist #
# $tst
# mdadm -S $md2