Remove the multiple super_switchs for ddf.

It is simpler if there is just one, and the methods
make decisions as appropriate.
This commit is contained in:
Neil Brown 2008-07-12 20:27:39 +10:00
parent ba7eb04f71
commit 78e449282e
2 changed files with 87 additions and 152 deletions

View File

@ -501,6 +501,15 @@ extern struct superswitch {
void (*locate_bitmap)(struct supertype *st, int fd); void (*locate_bitmap)(struct supertype *st, int fd);
int (*write_bitmap)(struct supertype *st, int fd); int (*write_bitmap)(struct supertype *st, int fd);
void (*free_super)(struct supertype *st); void (*free_super)(struct supertype *st);
/* validate_geometry is called with an st returned by
* match_metadata_desc.
* It should check that the geometry described in compatible with
* the metadata type. It will be called repeatedly as devices
* added to validate changing size and new devices. If there are
* inter-device dependencies, it should record sufficient details
* so these can be validated.
*/
int (*validate_geometry)(struct supertype *st, int level, int layout, int (*validate_geometry)(struct supertype *st, int level, int layout,
int raiddisks, int raiddisks,
int chunk, unsigned long long size, int chunk, unsigned long long size,

View File

@ -427,7 +427,6 @@ struct ddf_super {
#define offsetof(t,f) ((size_t)&(((t*)0)->f)) #define offsetof(t,f) ((size_t)&(((t*)0)->f))
#endif #endif
static struct superswitch super_ddf_container, super_ddf_bvd, super_ddf_svd;
static int calc_crc(void *buf, int len) static int calc_crc(void *buf, int len)
{ {
@ -852,40 +851,6 @@ static struct supertype *match_metadata_desc_ddf(char *arg)
return st; return st;
} }
static struct supertype *match_metadata_desc_ddf_bvd(char *arg)
{
struct supertype *st;
if (strcmp(arg, "ddf/bvd") != 0 &&
strcmp(arg, "bvd") != 0 &&
strcmp(arg, "default") != 0
)
return NULL;
st = malloc(sizeof(*st));
memset(st, 0, sizeof(*st));
st->ss = &super_ddf_bvd;
st->max_devs = 512;
st->minor_version = 0;
st->sb = NULL;
return st;
}
static struct supertype *match_metadata_desc_ddf_svd(char *arg)
{
struct supertype *st;
if (strcmp(arg, "ddf/svd") != 0 &&
strcmp(arg, "svd") != 0 &&
strcmp(arg, "default") != 0
)
return NULL;
st = malloc(sizeof(*st));
memset(st, 0, sizeof(*st));
st->ss = &super_ddf_svd;
st->max_devs = 512;
st->minor_version = 0;
st->sb = NULL;
return st;
}
#ifndef MDASSEMBLE #ifndef MDASSEMBLE
@ -1229,10 +1194,17 @@ static void uuid_from_super_ddf(struct supertype *st, int uuid[4])
} }
} }
static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info);
static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info) static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info)
{ {
struct ddf_super *ddf = st->sb; struct ddf_super *ddf = st->sb;
if (ddf->currentconf) {
getinfo_super_ddf_bvd(st, info);
return;
}
info->array.raid_disks = __be16_to_cpu(ddf->phys->used_pdes); info->array.raid_disks = __be16_to_cpu(ddf->phys->used_pdes);
info->array.level = LEVEL_CONTAINER; info->array.level = LEVEL_CONTAINER;
info->array.layout = 0; info->array.layout = 0;
@ -1416,6 +1388,12 @@ static void make_header_guid(char *guid)
if (rfd >= 0) close(rfd); if (rfd >= 0) close(rfd);
} }
static int init_super_ddf_bvd(struct supertype *st,
mdu_array_info_t *info,
unsigned long long size,
char *name, char *homehost,
int *uuid);
static int init_super_ddf(struct supertype *st, static int init_super_ddf(struct supertype *st,
mdu_array_info_t *info, mdu_array_info_t *info,
unsigned long long size, char *name, char *homehost, unsigned long long size, char *name, char *homehost,
@ -1459,6 +1437,9 @@ static int init_super_ddf(struct supertype *st,
st->sb = NULL; st->sb = NULL;
return 0; return 0;
} }
if (st->sb)
return init_super_ddf_bvd(st, info, size, name, homehost,
uuid);
ddf = malloc(sizeof(*ddf)); ddf = malloc(sizeof(*ddf));
memset(ddf, 0, sizeof(*ddf)); memset(ddf, 0, sizeof(*ddf));
@ -1717,7 +1698,7 @@ static int rlq_to_layout(int rlq, int prl, int raiddisks)
struct extent { struct extent {
unsigned long long start, size; unsigned long long start, size;
}; };
int cmp_extent(const void *av, const void *bv) static int cmp_extent(const void *av, const void *bv)
{ {
const struct extent *a = av; const struct extent *a = av;
const struct extent *b = bv; const struct extent *b = bv;
@ -1728,7 +1709,7 @@ int cmp_extent(const void *av, const void *bv)
return 0; return 0;
} }
struct extent *get_extents(struct ddf_super *ddf, struct dl *dl) static struct extent *get_extents(struct ddf_super *ddf, struct dl *dl)
{ {
/* find a list of used extents on the give physical device /* find a list of used extents on the give physical device
* (dnum) of the given ddf. * (dnum) of the given ddf.
@ -1979,6 +1960,11 @@ static void add_to_super_ddf(struct supertype *st,
int n, i; int n, i;
struct stat stb; struct stat stb;
if (ddf->currentconf) {
add_to_super_ddf_bvd(st, dk, fd, devname);
return;
}
/* This is device numbered dk->number. We need to create /* This is device numbered dk->number. We need to create
* a phys_disk entry and a more detailed disk_data entry. * a phys_disk entry and a more detailed disk_data entry.
*/ */
@ -2150,7 +2136,17 @@ static __u64 avail_size_ddf(struct supertype *st, __u64 devsize)
} }
#ifndef MDASSEMBLE #ifndef MDASSEMBLE
int validate_geometry_ddf(struct supertype *st, static int validate_geometry_ddf_container(struct supertype *st,
int level, int layout, int raiddisks,
int chunk, unsigned long long size,
char *dev, unsigned long long *freesize);
static int validate_geometry_ddf_bvd(struct supertype *st,
int level, int layout, int raiddisks,
int chunk, unsigned long long size,
char *dev, unsigned long long *freesize);
static int validate_geometry_ddf(struct supertype *st,
int level, int layout, int raiddisks, int level, int layout, int raiddisks,
int chunk, unsigned long long size, int chunk, unsigned long long size,
char *dev, unsigned long long *freesize) char *dev, unsigned long long *freesize)
@ -2167,53 +2163,50 @@ int validate_geometry_ddf(struct supertype *st,
*/ */
if (level == LEVEL_CONTAINER) { if (level == LEVEL_CONTAINER) {
st->ss = &super_ddf_container; /* Must be a fresh device to add to a container */
if (dev) { return validate_geometry_ddf_container(st, level, layout,
int rv =st->ss->validate_geometry(st, level, layout, raiddisks,
raiddisks, chunk, chunk, size, dev, freesize);
size,
NULL, freesize);
if (rv)
return rv;
}
return st->ss->validate_geometry(st, level, layout, raiddisks,
chunk, size, dev, freesize);
} }
if (st->sb) { if (st->sb) {
/* creating in a given container */ /* A container has already been opened, so we are
st->ss = &super_ddf_bvd; * creating in there. Maybe a BVD, maybe an SVD.
if (dev) { * Should make a distinction one day.
int rv =st->ss->validate_geometry(st, level, layout, */
raiddisks, chunk, return validate_geometry_ddf_bvd(st, level, layout, raiddisks,
size,
NULL, freesize);
if (rv)
return rv;
}
return st->ss->validate_geometry(st, level, layout, raiddisks,
chunk, size, dev, freesize); chunk, size, dev, freesize);
} }
/* FIXME should exclude MULTIPATH, or more appropriately, allow if (!dev) {
* only known levels. /* Initial sanity check. Exclude illegal levels. */
*/ int i;
if (!dev) for (i=0; ddf_level_num[i].num1 != MAXINT; i++)
if (ddf_level_num[i].num2 == level)
break;
if (ddf_level_num[i].num1 == MAXINT)
return 0;
/* Should check layout? etc */
return 1; return 1;
}
/* This device needs to be either a device in a 'ddf' container, /* This is the first device for the array.
* or it needs to be a 'ddf-bvd' array. * If it is a container, we read it in and do automagic allocations,
* no other devices should be given.
* Otherwise it must be a member device of a container, and we
* do manual allocation.
* Later we should check for a BVD and make an SVD.
*/ */
fd = open(dev, O_RDONLY|O_EXCL, 0); fd = open(dev, O_RDONLY|O_EXCL, 0);
if (fd >= 0) { if (fd >= 0) {
sra = sysfs_read(fd, 0, GET_VERSION); sra = sysfs_read(fd, 0, GET_VERSION);
close(fd); close(fd);
if (sra && sra->array.major_version == -1 && if (sra && sra->array.major_version == -1 &&
strcmp(sra->text_version, "ddf-bvd") == 0) { strcmp(sra->text_version, "ddf") == 0) {
st->ss = &super_ddf_svd;
return st->ss->validate_geometry(st, level, layout, /* load super */
raiddisks, chunk, size, /* find space for 'n' devices. */
dev, freesize); /* remember the devices */
/* Somehow return the fact that we have enough */
} }
fprintf(stderr, fprintf(stderr,
@ -2242,12 +2235,11 @@ int validate_geometry_ddf(struct supertype *st,
* and try to create a bvd * and try to create a bvd
*/ */
struct ddf_super *ddf; struct ddf_super *ddf;
st->ss = &super_ddf_bvd;
if (load_super_ddf_all(st, cfd, (void **)&ddf, NULL, 1) == 0) { if (load_super_ddf_all(st, cfd, (void **)&ddf, NULL, 1) == 0) {
st->sb = ddf; st->sb = ddf;
st->container_dev = fd2devnum(cfd); st->container_dev = fd2devnum(cfd);
close(cfd); close(cfd);
return st->ss->validate_geometry(st, level, layout, return validate_geometry_ddf_bvd(st, level, layout,
raiddisks, chunk, size, raiddisks, chunk, size,
dev, freesize); dev, freesize);
} }
@ -2258,10 +2250,10 @@ int validate_geometry_ddf(struct supertype *st,
return 1; return 1;
} }
int validate_geometry_ddf_container(struct supertype *st, static int validate_geometry_ddf_container(struct supertype *st,
int level, int layout, int raiddisks, int level, int layout, int raiddisks,
int chunk, unsigned long long size, int chunk, unsigned long long size,
char *dev, unsigned long long *freesize) char *dev, unsigned long long *freesize)
{ {
int fd; int fd;
unsigned long long ldsize; unsigned long long ldsize;
@ -2288,10 +2280,10 @@ int validate_geometry_ddf_container(struct supertype *st,
return 1; return 1;
} }
int validate_geometry_ddf_bvd(struct supertype *st, static int validate_geometry_ddf_bvd(struct supertype *st,
int level, int layout, int raiddisks, int level, int layout, int raiddisks,
int chunk, unsigned long long size, int chunk, unsigned long long size,
char *dev, unsigned long long *freesize) char *dev, unsigned long long *freesize)
{ {
struct stat stb; struct stat stb;
struct ddf_super *ddf = st->sb; struct ddf_super *ddf = st->sb;
@ -2375,19 +2367,6 @@ int validate_geometry_ddf_bvd(struct supertype *st,
return 1; return 1;
} }
int validate_geometry_ddf_svd(struct supertype *st,
int level, int layout, int raiddisks,
int chunk, unsigned long long size,
char *dev, unsigned long long *freesize)
{
/* dd/svd only supports striped, mirrored, concat, spanned... */
if (level != LEVEL_LINEAR &&
level != 0 &&
level != 1)
return 0;
return 1;
}
static int load_super_ddf_all(struct supertype *st, int fd, static int load_super_ddf_all(struct supertype *st, int fd,
void **sbp, char *devname, int keep_fd) void **sbp, char *devname, int keep_fd)
{ {
@ -2461,7 +2440,7 @@ static int load_super_ddf_all(struct supertype *st, int fd,
} }
*sbp = super; *sbp = super;
if (st->ss == NULL) { if (st->ss == NULL) {
st->ss = &super_ddf_container; st->ss = &super_ddf;
st->minor_version = 0; st->minor_version = 0;
st->max_devs = 512; st->max_devs = 512;
st->container_dev = fd2devnum(fd); st->container_dev = fd2devnum(fd);
@ -3100,6 +3079,7 @@ struct superswitch super_ddf = {
.detail_super = detail_super_ddf, .detail_super = detail_super_ddf,
.brief_detail_super = brief_detail_super_ddf, .brief_detail_super = brief_detail_super_ddf,
.validate_geometry = validate_geometry_ddf, .validate_geometry = validate_geometry_ddf,
.write_init_super = write_init_super_ddf,
#endif #endif
.match_home = match_home_ddf, .match_home = match_home_ddf,
.uuid_from_super= uuid_from_super_ddf, .uuid_from_super= uuid_from_super_ddf,
@ -3115,6 +3095,8 @@ struct superswitch super_ddf = {
.store_super = store_zero_ddf, .store_super = store_zero_ddf,
.free_super = free_super_ddf, .free_super = free_super_ddf,
.match_metadata_desc = match_metadata_desc_ddf, .match_metadata_desc = match_metadata_desc_ddf,
.add_to_super = add_to_super_ddf,
.container_content = container_content_ddf,
.external = 1, .external = 1,
@ -3127,59 +3109,3 @@ struct superswitch super_ddf = {
.activate_spare = ddf_activate_spare, .activate_spare = ddf_activate_spare,
}; };
/* Super_ddf_container is set by validate_geometry_ddf when given a
* device that is not part of any array
*/
static struct superswitch super_ddf_container = {
#ifndef MDASSEMBLE
.validate_geometry = validate_geometry_ddf_container,
.write_init_super = write_init_super_ddf,
#endif
.load_super = load_super_ddf,
.init_super = init_super_ddf,
.add_to_super = add_to_super_ddf,
.getinfo_super = getinfo_super_ddf,
.free_super = free_super_ddf,
.container_content = container_content_ddf,
.external = 1,
};
static struct superswitch super_ddf_bvd = {
#ifndef MDASSEMBLE
// .detail_super = detail_super_ddf_bvd,
// .brief_detail_super = brief_detail_super_ddf_bvd,
.validate_geometry = validate_geometry_ddf_bvd,
.write_init_super = write_init_super_ddf,
#endif
.update_super = update_super_ddf,
.init_super = init_super_ddf_bvd,
.add_to_super = add_to_super_ddf_bvd,
.getinfo_super = getinfo_super_ddf_bvd,
.load_super = load_super_ddf,
.free_super = free_super_ddf,
.match_metadata_desc = match_metadata_desc_ddf_bvd,
.external = 2,
};
static struct superswitch super_ddf_svd = {
#ifndef MDASSEMBLE
// .detail_super = detail_super_ddf_svd,
// .brief_detail_super = brief_detail_super_ddf_svd,
.validate_geometry = validate_geometry_ddf_svd,
#endif
.update_super = update_super_ddf,
.init_super = init_super_ddf,
.load_super = load_super_ddf,
.free_super = free_super_ddf,
.match_metadata_desc = match_metadata_desc_ddf_svd,
.external = 2,
};