summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Detail.c6
-rw-r--r--Manage.c16
-rw-r--r--bitmap.c9
-rw-r--r--mdadm.811
-rw-r--r--mdadm.h4
-rw-r--r--super0.c7
-rw-r--r--super1.c48
-rw-r--r--util.c17
8 files changed, 86 insertions, 32 deletions
diff --git a/Detail.c b/Detail.c
index 4647360..dc11102 100644
--- a/Detail.c
+++ b/Detail.c
@@ -300,9 +300,9 @@ int Detail(char *dev, int brief, int export, int test, char *homehost)
printf(" Layout : %s\n", c?c:"-unknown-");
}
if (array.level == 10) {
- printf(" Layout : near=%d, %s=%d\n",
- array.layout&255, (array.layout&0x10000)?"offset":"far",
- (array.layout>>8)&255);
+ printf(" Layout :");
+ print_r10_layout(array.layout);
+ printf("\n");
}
switch (array.level) {
case 0:
diff --git a/Manage.c b/Manage.c
index a6e1072..0018d8d 100644
--- a/Manage.c
+++ b/Manage.c
@@ -446,13 +446,6 @@ int Manage_subdevs(char *devname, int fd,
}
if (array.not_persistent == 0 || tst->ss->external) {
- /* Make sure device is large enough */
- if (tst->ss->avail_size(tst, ldsize/512) <
- array_size) {
- fprintf(stderr, Name ": %s not large enough to join array\n",
- dv->devname);
- return 1;
- }
/* need to find a sample superblock to copy, and
* a spare slot to use.
@@ -488,6 +481,15 @@ int Manage_subdevs(char *devname, int fd,
fprintf(stderr, Name ": cannot find valid superblock in this array - HELP\n");
return 1;
}
+
+ /* Make sure device is large enough */
+ if (tst->ss->avail_size(tst, ldsize/512) <
+ array_size) {
+ fprintf(stderr, Name ": %s not large enough to join array\n",
+ dv->devname);
+ return 1;
+ }
+
/* Possibly this device was recently part of the array
* and was temporarily removed, and is now being re-added.
* If so, we can simply re-add it.
diff --git a/bitmap.c b/bitmap.c
index 0f8a265..1810166 100644
--- a/bitmap.c
+++ b/bitmap.c
@@ -115,6 +115,15 @@ unsigned long long bitmap_bits(unsigned long long array_size,
return (array_size * 512 + chunksize - 1) / chunksize;
}
+unsigned long bitmap_sectors(struct bitmap_super_s *bsb)
+{
+ unsigned long long bits = bitmap_bits(__le64_to_cpu(bsb->sync_size),
+ __le32_to_cpu(bsb->chunksize));
+ int bits_per_sector = 8*512;
+ return (bits + bits_per_sector - 1) / bits_per_sector;
+}
+
+
bitmap_info_t *bitmap_fd_read(int fd, int brief)
{
/* Note: fd might be open O_DIRECT, so we must be
diff --git a/mdadm.8 b/mdadm.8
index 41486e6..88aa6f7 100644
--- a/mdadm.8
+++ b/mdadm.8
@@ -2138,11 +2138,8 @@ configuration file at all.
.SH SEE ALSO
For further information on mdadm usage, MD and the various levels of
RAID, see:
-
.IP
-.UR http://linux-raid.osdl.org/
-http://linux\-raid.osdl.org/
-.UE
+.B http://linux\-raid.osdl.org/
.PP
(based upon Jakob \(/Ostergaard's Software\-RAID.HOWTO)
.\".PP
@@ -2163,9 +2160,9 @@ The latest version of
.I mdadm
should always be available from
.IP
-.UR http://www.kernel.org/pub/linux/utils/raid/mdadm/
-http://www.kernel.org/pub/linux/utils/raid/mdadm/
-.UE
+.B http://www.kernel.org/pub/linux/utils/raid/mdadm/
+.PP
+Related man pages:
.PP
.IR mdadm.conf (5),
.IR md (4).
diff --git a/mdadm.h b/mdadm.h
index aea7228..ed0c115 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -739,6 +739,7 @@ extern int CreateBitmap(char *filename, int force, char uuid[16],
int major);
extern int ExamineBitmap(char *filename, int brief, struct supertype *st);
extern int bitmap_update_uuid(int fd, int *uuid, int swap);
+extern unsigned long bitmap_sectors(struct bitmap_super_s *bsb);
extern int md_get_version(int fd);
extern int get_linux_version(void);
@@ -788,7 +789,8 @@ extern int add_disk(int mdfd, struct supertype *st,
extern int set_array_info(int mdfd, struct supertype *st, struct mdinfo *info);
extern char *human_size(long long bytes);
-char *human_size_brief(long long bytes);
+extern char *human_size_brief(long long bytes);
+extern void print_r10_layout(int layout);
#define NoMdDev (1<<23)
extern int find_free_devnum(int use_partitions);
diff --git a/super0.c b/super0.c
index 291ccdd..924d75d 100644
--- a/super0.c
+++ b/super0.c
@@ -188,10 +188,9 @@ static void examine_super0(struct supertype *st, char *homehost)
printf(" Layout : %s\n", c?c:"-unknown-");
}
if (sb->level == 10) {
- printf(" Layout : near=%d, %s=%d\n",
- sb->layout&255,
- (sb->layout&0x10000)?"offset":"far",
- (sb->layout>>8)&255);
+ printf(" Layout :");
+ print_r10_layout(sb->layout);
+ printf("\n");
}
switch(sb->level) {
case 0:
diff --git a/super1.c b/super1.c
index a392cf6..4cfd786 100644
--- a/super1.c
+++ b/super1.c
@@ -248,10 +248,9 @@ static void examine_super1(struct supertype *st, char *homehost)
printf(" New Layout : %s\n", c?c:"-unknown-");
}
if (__le32_to_cpu(sb->level) == 10) {
- printf(" New Layout : near=%d, %s=%d\n",
- __le32_to_cpu(sb->new_layout)&255,
- (__le32_to_cpu(sb->new_layout)&0x10000)?"offset":"far",
- (__le32_to_cpu(sb->new_layout)>>8)&255);
+ printf(" New Layout :");
+ print_r10_layout(__le32_to_cpu(sb->new_layout));
+ printf("\n");
}
}
if (__le32_to_cpu(sb->new_chunk) != __le32_to_cpu(sb->chunksize))
@@ -281,10 +280,9 @@ static void examine_super1(struct supertype *st, char *homehost)
}
if (__le32_to_cpu(sb->level) == 10) {
int lo = __le32_to_cpu(sb->layout);
- printf(" Layout : near=%d, %s=%d\n",
- lo&255,
- (lo&0x10000)?"offset":"far",
- (lo>>8)&255);
+ printf(" Layout :");
+ print_r10_layout(lo);
+ printf("\n");
}
switch(__le32_to_cpu(sb->level)) {
case 0:
@@ -597,7 +595,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
}
if (strcmp(update, "linear-grow-new") == 0) {
int i;
- int rfd;
+ int rfd, fd;
int max = __le32_to_cpu(sb->max_dev);
for (i=0 ; i < max ; i++)
@@ -618,6 +616,25 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
sb->dev_roles[i] =
__cpu_to_le16(info->disk.raid_disk);
+
+ fd = open(devname, O_RDONLY);
+ if (fd >= 0) {
+ unsigned long long ds;
+ get_dev_size(fd, devname, &ds);
+ close(fd);
+ ds >>= 9;
+ if (__le64_to_cpu(sb->super_offset) <
+ __le64_to_cpu(sb->data_offset)) {
+ sb->data_size = __cpu_to_le64(
+ ds - __le64_to_cpu(sb->data_offset));
+ } else {
+ 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));
+ }
+ }
}
if (strcmp(update, "linear-grow-update") == 0) {
sb->raid_disks = __cpu_to_le32(info->array.raid_disks);
@@ -1272,10 +1289,21 @@ static struct supertype *match_metadata_desc1(char *arg)
*/
static __u64 avail_size1(struct supertype *st, __u64 devsize)
{
+ struct mdp_superblock_1 *super = st->sb;
if (devsize < 24)
return 0;
- devsize -= choose_bm_space(devsize);
+ if (super == NULL)
+ /* creating: allow suitable space for bitmap */
+ devsize -= choose_bm_space(devsize);
+#ifndef MDASSEMBLE
+ else 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)+1024);
+ devsize -= bitmap_sectors(bsb);
+ }
+#endif
switch(st->minor_version) {
case -1: /* no specified. Now time to set default */
diff --git a/util.c b/util.c
index f6e4dd0..379403d 100644
--- a/util.c
+++ b/util.c
@@ -640,6 +640,23 @@ char *human_size_brief(long long bytes)
);
return buf;
}
+
+void print_r10_layout(int layout)
+{
+ int near = layout & 255;
+ int far = (layout >> 8) & 255;
+ int offset = (layout&0x10000);
+ char *sep = "";
+
+ if (near != 1) {
+ printf("%s near=%d", sep, near);
+ sep = ",";
+ }
+ if (far != 1)
+ printf("%s %s=%d", sep, offset?"offset":"far", far);
+ if (near*far == 1)
+ printf("NO REDUNDANCY");
+}
#endif
unsigned long long calc_array_size(int level, int raid_disks, int layout,