summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2008-05-15 16:47:41 +1000
committerNeil Brown <neilb@suse.de>2008-05-15 16:47:41 +1000
commit17f25ca6fb71221f4fa7891c0037f88d26dbc67c (patch)
treee233a0ca2461dbd4d27e0d69c90466b06ffc75ec
parent2270232245dc189807e6ca36835b44146377fc37 (diff)
downloadmdadm-17f25ca6fb71221f4fa7891c0037f88d26dbc67c.tar.gz
mdadm-17f25ca6fb71221f4fa7891c0037f88d26dbc67c.tar.xz
mdadm-17f25ca6fb71221f4fa7891c0037f88d26dbc67c.zip
Add 'container' level and ->validate_geometry method.
These will be used for ddf.
-rw-r--r--Create.c56
-rw-r--r--ReadMe.c1
-rw-r--r--mdadm.h7
-rw-r--r--super0.c38
-rw-r--r--super1.c32
5 files changed, 112 insertions, 22 deletions
diff --git a/Create.c b/Create.c
index 8407579..d423585 100644
--- a/Create.c
+++ b/Create.c
@@ -182,6 +182,7 @@ int Create(struct supertype *st, char *mddev, int mdfd,
case 1:
case LEVEL_FAULTY:
case LEVEL_MULTIPATH:
+ case LEVEL_CONTAINER:
if (chunk) {
chunk = 0;
if (verbose > 0)
@@ -193,13 +194,17 @@ int Create(struct supertype *st, char *mddev, int mdfd,
return 1;
}
+ if (st && ! st->ss->validate_geometry(st, level, layout, raiddisks,
+ chunk, size, NULL, NULL))
+ return 1;
+
/* now look at the subdevs */
info.array.active_disks = 0;
info.array.working_disks = 0;
dnum = 0;
for (dv=devlist; dv; dv=dv->next, dnum++) {
char *dname = dv->devname;
- unsigned long long ldsize, freesize;
+ unsigned long long freesize;
int fd;
if (strcasecmp(dname, "missing")==0) {
if (first_missing > dnum)
@@ -219,11 +224,6 @@ int Create(struct supertype *st, char *mddev, int mdfd,
fail=1;
continue;
}
- if (!get_dev_size(fd, dname, &ldsize)) {
- fail = 1;
- close(fd);
- continue;
- }
if (st == NULL) {
struct createinfo *ci = conf_get_create_info();
if (ci)
@@ -231,17 +231,22 @@ int Create(struct supertype *st, char *mddev, int mdfd,
}
if (st == NULL) {
/* Need to choose a default metadata, which is different
- * depending on the sizes of devices
+ * depending on geometry of array.
*/
int i;
char *name = "default";
- if (level >= 1 && ldsize > (0x7fffffffULL<<10))
- name = "default/large";
- for(i=0; !st && superlist[i]; i++)
+ for(i=0; !st && superlist[i]; i++) {
st = superlist[i]->match_metadata_desc(name);
+ if (st && !st->ss->validate_geometry
+ (st, level, layout, raiddisks,
+ chunk, size, dname, &freesize))
+ st = NULL;
+ }
if (!st) {
- fprintf(stderr, Name ": internal error - no default metadata style\n");
+ fprintf(stderr, Name ": device %s not suitable "
+ "for any style of array\n",
+ dname);
exit(2);
}
if (st->ss->major != 0 ||
@@ -250,14 +255,19 @@ int Create(struct supertype *st, char *mddev, int mdfd,
" %d.%d metadata\n",
st->ss->major,
st->minor_version);
- }
- freesize = st->ss->avail_size(st, ldsize >> 9);
- if (freesize == 0) {
- fprintf(stderr, Name ": %s is too small: %luK\n",
- dname, (unsigned long)(ldsize>>10));
- fail = 1;
- close(fd);
- continue;
+ } else {
+ if (!st->ss->validate_geometry(st, level, layout,
+ raiddisks,
+ chunk, size, dname,
+ &freesize)) {
+
+ fprintf(stderr,
+ Name ": %s is not suitable for "
+ "this array.\n",
+ dname);
+ fail = 1;
+ continue;
+ }
}
freesize /= 2; /* convert to K */
@@ -268,7 +278,8 @@ int Create(struct supertype *st, char *mddev, int mdfd,
if (size && freesize < size) {
fprintf(stderr, Name ": %s is smaller that given size."
- " %lluK < %lluK + superblock\n", dname, freesize, size);
+ " %lluK < %lluK + metadata\n",
+ dname, freesize, size);
fail = 1;
close(fd);
continue;
@@ -581,7 +592,10 @@ int Create(struct supertype *st, char *mddev, int mdfd,
st->ss->free_super(st);
/* param is not actually used */
- if (runstop == 1 || subdevs >= raiddisks) {
+ if (level == LEVEL_CONTAINER)
+ /* No need to start */
+ ;
+ else if (runstop == 1 || subdevs >= raiddisks) {
mdu_param_t param;
if (ioctl(mdfd, RUN_ARRAY, &param)) {
fprintf(stderr, Name ": RUN_ARRAY failed: %s\n",
diff --git a/ReadMe.c b/ReadMe.c
index 1b55395..a52f080 100644
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -610,6 +610,7 @@ mapping_t pers[] = {
{ "raid10", 10},
{ "10", 10},
{ "faulty", LEVEL_FAULTY},
+ { "container", LEVEL_CONTAINER},
{ NULL, 0}
};
diff --git a/mdadm.h b/mdadm.h
index 5c18d15..7b5a08e 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -358,6 +358,10 @@ extern struct superswitch {
void (*locate_bitmap)(struct supertype *st, int fd);
int (*write_bitmap)(struct supertype *st, int fd);
void (*free_super)(struct supertype *st);
+ int (*validate_geometry)(struct supertype *st, int level, int layout,
+ int raiddisks,
+ int chunk, unsigned long long size,
+ char *subdev, unsigned long long *freesize);
int major;
int swapuuid; /* true if uuid is bigending rather than hostendian */
} super0, super1, *superlist[];
@@ -531,6 +535,9 @@ extern int open_mddev_devnum(char *devname, int devnum, char *name,
#define LEVEL_LINEAR (-1)
#define LEVEL_FAULTY (-5)
+/* kernel module doesn't know about these */
+#define LEVEL_CONTAINER (-100)
+
/* faulty stuff */
diff --git a/super0.c b/super0.c
index 7e81482..a1c97f8 100644
--- a/super0.c
+++ b/super0.c
@@ -991,6 +991,43 @@ static void free_super0(struct supertype *st)
st->sb = NULL;
}
+static int validate_geometry0(struct supertype *st, int level,
+ int layout, int raiddisks,
+ int chunk, unsigned long long size,
+ char *subdev, unsigned long long *freesize)
+{
+ unsigned long long ldsize;
+ int fd;
+
+ if (level == LEVEL_CONTAINER)
+ return 0;
+ if (raiddisks > MD_SB_DISKS)
+ return 0;
+ if (size > (0x7fffffffULL<<10))
+ return 0;
+ if (!subdev)
+ return 1;
+
+ fd = open(subdev, O_RDONLY|O_EXCL, 0);
+ if (fd < 0) {
+ fprintf(stderr, Name ": Cannot open %s: %s\n",
+ subdev, strerror(errno));
+ return 0;
+ }
+ if (!get_dev_size(fd, subdev, &ldsize)) {
+ close(fd);
+ return 0;
+ }
+ close(fd);
+
+ if (ldsize < MD_RESERVED_SECTORS * 512)
+ return 0;
+ if (size > (0x7fffffffULL<<10))
+ return 0;
+ *freesize = MD_NEW_SIZE_SECTORS(ldsize >> 9);
+ return 1;
+}
+
struct superswitch super0 = {
#ifndef MDASSEMBLE
.examine_super = examine_super0,
@@ -1016,6 +1053,7 @@ struct superswitch super0 = {
.locate_bitmap = locate_bitmap0,
.write_bitmap = write_bitmap0,
.free_super = free_super0,
+ .validate_geometry = validate_geometry0,
.major = 0,
.swapuuid = 0,
};
diff --git a/super1.c b/super1.c
index fe915f8..c510899 100644
--- a/super1.c
+++ b/super1.c
@@ -1199,7 +1199,7 @@ static struct supertype *match_metadata_desc1(char *arg)
return st;
}
if (strcmp(arg, "1") == 0 ||
- strcmp(arg, "default/large") == 0) {
+ strcmp(arg, "default") == 0) {
st->minor_version = -1;
return st;
}
@@ -1416,6 +1416,35 @@ static void free_super1(struct supertype *st)
st->sb = NULL;
}
+static int validate_geometry1(struct supertype *st, int level,
+ int layout, int raiddisks,
+ int chunk, unsigned long long size,
+ char *subdev, unsigned long long *freesize)
+{
+ unsigned long long ldsize;
+ int fd;
+
+ if (level == LEVEL_CONTAINER)
+ return 0;
+ if (!subdev)
+ return 1;
+
+ fd = open(subdev, O_RDONLY|O_EXCL, 0);
+ if (fd < 0) {
+ fprintf(stderr, Name ": Cannot open %s: %s\n",
+ subdev, strerror(errno));
+ return 0;
+ }
+ if (!get_dev_size(fd, subdev, &ldsize)) {
+ close(fd);
+ return 0;
+ }
+ close(fd);
+
+ *freesize = avail_size1(st, ldsize >> 9);
+ return 1;
+}
+
struct superswitch super1 = {
#ifndef MDASSEMBLE
.examine_super = examine_super1,
@@ -1441,6 +1470,7 @@ struct superswitch super1 = {
.locate_bitmap = locate_bitmap1,
.write_bitmap = write_bitmap1,
.free_super = free_super1,
+ .validate_geometry = validate_geometry1,
.major = 1,
#if __BYTE_ORDER == BIG_ENDIAN
.swapuuid = 0,