more ddf stuff
Create a BVD in a DDF Do not actually assemble it yet...
This commit is contained in:
parent
a322f70c41
commit
5f8097beb9
53
Create.c
53
Create.c
|
@ -70,6 +70,7 @@ int Create(struct supertype *st, char *mddev, int mdfd,
|
|||
int vers;
|
||||
int rv;
|
||||
int bitmap_fd;
|
||||
int have_container = 0;
|
||||
unsigned long long bitmapsize;
|
||||
struct mdinfo *sra;
|
||||
struct mdinfo info;
|
||||
|
@ -125,11 +126,47 @@ int Create(struct supertype *st, char *mddev, int mdfd,
|
|||
Name ": This level does not support spare devices\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (subdevs == 1 && strcmp(devlist->devname, "missing") != 0) {
|
||||
/* If given a single device, it might be a container, and we can
|
||||
* extract a device list from there
|
||||
*/
|
||||
mdu_array_info_t inf;
|
||||
int fd;
|
||||
|
||||
memset(&inf, 0, sizeof(inf));
|
||||
fd = open(devlist->devname, O_RDONLY, 0);
|
||||
if (fd >= 0 &&
|
||||
ioctl(fd, GET_ARRAY_INFO, &inf) == 0 &&
|
||||
inf.raid_disks == 0) {
|
||||
/* yep, looks like a container */
|
||||
if (st) {
|
||||
rv = st->ss->load_super(st, fd,
|
||||
devlist->devname);
|
||||
if (rv == 0)
|
||||
have_container = 1;
|
||||
} else {
|
||||
st = guess_super(fd);
|
||||
if (st && !(rv = st->ss->
|
||||
load_super(st, fd,
|
||||
devlist->devname)))
|
||||
have_container = 1;
|
||||
else
|
||||
st = NULL;
|
||||
}
|
||||
}
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
if (have_container) {
|
||||
subdevs = 0;
|
||||
devlist = NULL;
|
||||
}
|
||||
}
|
||||
if (subdevs > raiddisks+sparedisks) {
|
||||
fprintf(stderr, Name ": You have listed more devices (%d) than are in the array(%d)!\n", subdevs, raiddisks+sparedisks);
|
||||
return 1;
|
||||
}
|
||||
if (subdevs < raiddisks+sparedisks) {
|
||||
if (!have_container && subdevs < raiddisks+sparedisks) {
|
||||
fprintf(stderr, Name ": You haven't given enough devices (real or missing) to create this array\n");
|
||||
return 1;
|
||||
}
|
||||
|
@ -311,11 +348,13 @@ int Create(struct supertype *st, char *mddev, int mdfd,
|
|||
return 1;
|
||||
}
|
||||
if (size == 0) {
|
||||
if (mindisc == NULL) {
|
||||
if (mindisc == NULL && !have_container) {
|
||||
fprintf(stderr, Name ": no size and no drives given - aborting create.\n");
|
||||
return 1;
|
||||
}
|
||||
if (level > 0 || level == LEVEL_MULTIPATH || level == LEVEL_FAULTY) {
|
||||
if (level > 0 || level == LEVEL_MULTIPATH
|
||||
|| level == LEVEL_FAULTY
|
||||
|| (st && st->ss->external) ) {
|
||||
/* size is meaningful */
|
||||
if (minsize > 0x100000000ULL && st->ss->major == 0) {
|
||||
fprintf(stderr, Name ": devices too large for RAID level %d\n", level);
|
||||
|
@ -375,7 +414,7 @@ int Create(struct supertype *st, char *mddev, int mdfd,
|
|||
missing_disks++;
|
||||
}
|
||||
|
||||
if (level <= 0 && first_missing != subdevs * 2) {
|
||||
if (level <= 0 && first_missing < subdevs * 2) {
|
||||
fprintf(stderr,
|
||||
Name ": This level does not support missing devices\n");
|
||||
return 1;
|
||||
|
@ -571,7 +610,11 @@ int Create(struct supertype *st, char *mddev, int mdfd,
|
|||
strcasecmp(dv->devname, "missing")==0)
|
||||
continue;
|
||||
|
||||
fd = open(dv->devname, O_RDWR|O_EXCL, 0);
|
||||
if (st->ss->external == 2)
|
||||
fd = open(dv->devname, O_RDWR, 0);
|
||||
else
|
||||
fd = open(dv->devname, O_RDWR|O_EXCL,0);
|
||||
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, Name ": failed to open %s "
|
||||
"after earlier success - aborting\n",
|
||||
|
|
2
mdadm.h
2
mdadm.h
|
@ -530,6 +530,8 @@ extern int enough(int level, int raid_disks, int layout, int clean,
|
|||
extern int ask(char *mesg);
|
||||
extern unsigned long long get_component_size(int fd);
|
||||
extern void remove_partitions(int fd);
|
||||
extern unsigned long long calc_array_size(int level, int raid_disks, int layout,
|
||||
int chunksize, unsigned long long devsize);
|
||||
|
||||
|
||||
extern char *human_size(long long bytes);
|
||||
|
|
410
super-ddf.c
410
super-ddf.c
|
@ -1279,6 +1279,30 @@ static int update_super_ddf(struct supertype *st, struct mdinfo *info,
|
|||
return rv;
|
||||
}
|
||||
|
||||
static void make_header_guid(char *guid)
|
||||
{
|
||||
__u32 stamp;
|
||||
int rfd;
|
||||
/* Create a DDF Header of Virtual Disk GUID */
|
||||
|
||||
/* 24 bytes of fiction required.
|
||||
* first 8 are a 'vendor-id' - "Linux-MD"
|
||||
* next 8 are controller type.. how about 0X DEAD BEEF 0000 0000
|
||||
* Remaining 8 random number plus timestamp
|
||||
*/
|
||||
memcpy(guid, T10, sizeof(T10));
|
||||
stamp = __cpu_to_be32(0xdeadbeef);
|
||||
memcpy(guid+8, &stamp, 4);
|
||||
stamp = __cpu_to_be32(0);
|
||||
memcpy(guid+12, &stamp, 4);
|
||||
stamp = __cpu_to_be32(time(0) - DECADE);
|
||||
memcpy(guid+16, &stamp, 4);
|
||||
rfd = open("/dev/urandom", O_RDONLY);
|
||||
if (rfd < 0 || read(rfd, &stamp, 4) != 4)
|
||||
stamp = random();
|
||||
memcpy(guid+20, &stamp, 4);
|
||||
if (rfd >= 0) close(rfd);
|
||||
}
|
||||
static int init_super_ddf(struct supertype *st,
|
||||
mdu_array_info_t *info,
|
||||
unsigned long long size, char *name, char *homehost,
|
||||
|
@ -1310,8 +1334,6 @@ static int init_super_ddf(struct supertype *st,
|
|||
struct ddf_super *ddf;
|
||||
char hostname[17];
|
||||
int hostlen;
|
||||
__u32 stamp;
|
||||
int rfd;
|
||||
int max_phys_disks, max_virt_disks;
|
||||
unsigned long long sector;
|
||||
int clen;
|
||||
|
@ -1333,23 +1355,7 @@ static int init_super_ddf(struct supertype *st,
|
|||
*/
|
||||
|
||||
ddf->anchor.magic = DDF_HEADER_MAGIC;
|
||||
/* 24 bytes of fiction required.
|
||||
* first 8 are a 'vendor-id' - "Linux-MD"
|
||||
* next 8 are controller type.. how about 0X DEAD BEEF 0000 0000
|
||||
* Remaining 16 are serial number.... maybe a hostname would do?
|
||||
*/
|
||||
memcpy(ddf->anchor.guid, T10, sizeof(T10));
|
||||
stamp = __cpu_to_be32(0xdeadbeef);
|
||||
memcpy(ddf->anchor.guid+8, &stamp, 4);
|
||||
stamp = __cpu_to_be32(0);
|
||||
memcpy(ddf->anchor.guid+12, &stamp, 4);
|
||||
stamp = __cpu_to_be32(time(0) - DECADE);
|
||||
memcpy(ddf->anchor.guid+16, &stamp, 4);
|
||||
rfd = open("/dev/urandom", O_RDONLY);
|
||||
if (rfd < 0 || read(rfd, &stamp, 4) != 4)
|
||||
stamp = random();
|
||||
memcpy(ddf->anchor.guid+20, &stamp, 4);
|
||||
if (rfd >= 0) close(rfd);
|
||||
make_header_guid(ddf->anchor.guid);
|
||||
|
||||
memcpy(ddf->anchor.revision, DDF_REVISION, 8);
|
||||
ddf->anchor.seq = __cpu_to_be32(1);
|
||||
|
@ -1479,10 +1485,212 @@ static int init_super_ddf(struct supertype *st,
|
|||
vd->max_vdes = __cpu_to_be16(max_virt_disks);
|
||||
memset(vd->pad, 0xff, 52);
|
||||
|
||||
for (i=0; i<max_virt_disks; i++)
|
||||
memset(&vd->entries[i], 0xff, sizeof(struct virtual_entry));
|
||||
|
||||
st->sb = ddf;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int all_ff(char *guid)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < DDF_GUID_LEN; i++)
|
||||
if (guid[i] != (char)0xff)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
static int chunk_to_shift(int chunksize)
|
||||
{
|
||||
return ffs(chunksize/512)-1;
|
||||
}
|
||||
|
||||
static int level_to_prl(int level)
|
||||
{
|
||||
switch (level) {
|
||||
case LEVEL_LINEAR: return DDF_CONCAT;
|
||||
case 0: return DDF_RAID0;
|
||||
case 1: return DDF_RAID1;
|
||||
case 4: return DDF_RAID4;
|
||||
case 5: return DDF_RAID5;
|
||||
case 6: return DDF_RAID6;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
static int layout_to_rlq(int level, int layout, int raiddisks)
|
||||
{
|
||||
switch(level) {
|
||||
case 0:
|
||||
return DDF_RAID0_SIMPLE;
|
||||
case 1:
|
||||
switch(raiddisks) {
|
||||
case 2: return DDF_RAID1_SIMPLE;
|
||||
case 3: return DDF_RAID1_MULTI;
|
||||
default: return -1;
|
||||
}
|
||||
case 4:
|
||||
switch(layout) {
|
||||
case 0: return DDF_RAID4_N;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
switch(layout) {
|
||||
case ALGORITHM_LEFT_ASYMMETRIC:
|
||||
return DDF_RAID5_N_RESTART;
|
||||
case ALGORITHM_RIGHT_ASYMMETRIC:
|
||||
return DDF_RAID5_0_RESTART;
|
||||
case ALGORITHM_LEFT_SYMMETRIC:
|
||||
return DDF_RAID5_N_CONTINUE;
|
||||
case ALGORITHM_RIGHT_SYMMETRIC:
|
||||
return -1; /* not mentioned in standard */
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int init_super_ddf_bvd(struct supertype *st,
|
||||
mdu_array_info_t *info,
|
||||
unsigned long long size,
|
||||
char *name, char *homehost,
|
||||
int *uuid)
|
||||
{
|
||||
/* We are creating a BVD inside a pre-existing container.
|
||||
* so st->sb is already set.
|
||||
* We need to create a new vd_config and a new virtual_entry
|
||||
*/
|
||||
struct ddf_super *ddf = st->sb;
|
||||
int venum;
|
||||
struct virtual_entry *ve;
|
||||
struct vcl *vcl;
|
||||
struct vd_config *vc;
|
||||
int mppe;
|
||||
int conflen;
|
||||
|
||||
if (__be16_to_cpu(ddf->virt->populated_vdes)
|
||||
>= __be16_to_cpu(ddf->virt->max_vdes)) {
|
||||
fprintf(stderr, Name": This ddf already has the "
|
||||
"maximum of %d virtual devices\n",
|
||||
__be16_to_cpu(ddf->virt->max_vdes));
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (venum = 0; venum < __be16_to_cpu(ddf->virt->max_vdes); venum++)
|
||||
if (all_ff(ddf->virt->entries[venum].guid))
|
||||
break;
|
||||
if (venum == __be16_to_cpu(ddf->virt->max_vdes)) {
|
||||
fprintf(stderr, Name ": Cannot find spare slot for "
|
||||
"virtual disk - DDF is corrupt\n");
|
||||
return 0;
|
||||
}
|
||||
ve = &ddf->virt->entries[venum];
|
||||
|
||||
/* A Virtual Disk GUID contains the T10 Vendor ID, controller type,
|
||||
* timestamp, random number
|
||||
*/
|
||||
make_header_guid(ve->guid);
|
||||
ve->unit = __cpu_to_be16(info->md_minor);
|
||||
ve->pad0 = 0xFFFF;
|
||||
ve->guid_crc = crc32(0, (unsigned char*)ddf->anchor.guid, DDF_GUID_LEN);
|
||||
ve->type = 0;
|
||||
ve->state = 0;
|
||||
ve->init_state = 0;
|
||||
if (!(info->state & 1))
|
||||
ve->init_state = DDF_state_inconsistent;
|
||||
memset(ve->pad1, 0xff, 14);
|
||||
memset(ve->name, ' ', 16);
|
||||
if (name)
|
||||
strncpy(ve->name, name, 16);
|
||||
ddf->virt->populated_vdes =
|
||||
__cpu_to_be16(__be16_to_cpu(ddf->virt->populated_vdes)+1);
|
||||
|
||||
/* Now create a new vd_config */
|
||||
conflen = __be16_to_cpu(ddf->active->config_record_len);
|
||||
vcl = malloc(offsetof(struct vcl, conf) + conflen * 512);
|
||||
vcl->lba_offset = (__u64*) &vcl->conf.phys_refnum[ddf->max_part+1];
|
||||
|
||||
vc = &vcl->conf;
|
||||
|
||||
vc->magic = DDF_VD_CONF_MAGIC;
|
||||
memcpy(vc->guid, ve->guid, DDF_GUID_LEN);
|
||||
vc->timestamp = __cpu_to_be32(time(0)-DECADE);
|
||||
vc->seqnum = __cpu_to_be32(1);
|
||||
memset(vc->pad0, 0xff, 24);
|
||||
vc->prim_elmnt_count = __cpu_to_be16(info->raid_disks);
|
||||
vc->chunk_shift = chunk_to_shift(info->chunk_size);
|
||||
vc->prl = level_to_prl(info->level);
|
||||
vc->rlq = layout_to_rlq(info->level, info->layout, info->raid_disks);
|
||||
vc->sec_elmnt_count = 1;
|
||||
vc->sec_elmnt_seq = 0;
|
||||
vc->srl = 0;
|
||||
vc->blocks = __cpu_to_be64(info->size * 2);
|
||||
vc->array_blocks = __cpu_to_be64(
|
||||
calc_array_size(info->level, info->raid_disks, info->layout,
|
||||
info->chunk_size, info->size*2));
|
||||
memset(vc->pad1, 0xff, 8);
|
||||
vc->spare_refs[0] = 0xffffffff;
|
||||
vc->spare_refs[1] = 0xffffffff;
|
||||
vc->spare_refs[2] = 0xffffffff;
|
||||
vc->spare_refs[3] = 0xffffffff;
|
||||
vc->spare_refs[4] = 0xffffffff;
|
||||
vc->spare_refs[5] = 0xffffffff;
|
||||
vc->spare_refs[6] = 0xffffffff;
|
||||
vc->spare_refs[7] = 0xffffffff;
|
||||
memset(vc->cache_pol, 0, 8);
|
||||
vc->bg_rate = 0x80;
|
||||
memset(vc->pad2, 0xff, 3);
|
||||
memset(vc->pad3, 0xff, 52);
|
||||
memset(vc->pad4, 0xff, 192);
|
||||
memset(vc->v0, 0xff, 32);
|
||||
memset(vc->v1, 0xff, 32);
|
||||
memset(vc->v2, 0xff, 16);
|
||||
memset(vc->v3, 0xff, 16);
|
||||
memset(vc->vendor, 0xff, 32);
|
||||
mppe = __be16_to_cpu(ddf->anchor.max_primary_element_entries);
|
||||
memset(vc->phys_refnum, 0xff, 4*mppe);
|
||||
memset(vc->phys_refnum+mppe, 0x00, 8*mppe);
|
||||
|
||||
vcl->next = ddf->conflist;
|
||||
ddf->conflist = vcl;
|
||||
ddf->newconf = vcl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void add_to_super_ddf_bvd(struct supertype *st,
|
||||
mdu_disk_info_t *dk, int fd, char *devname)
|
||||
{
|
||||
/* fd and devname identify a device with-in the ddf container (st).
|
||||
* dk identifies a location in the new BVD.
|
||||
* We need to find suitable free space in that device and update
|
||||
* the phys_refnum and lba_offset for the newly created vd_config.
|
||||
* We might also want to update the type in the phys_disk
|
||||
* section. FIXME
|
||||
*/
|
||||
struct dl *dl;
|
||||
struct ddf_super *ddf = st->sb;
|
||||
struct vd_config *vc;
|
||||
__u64 *lba_offset;
|
||||
int mppe;
|
||||
|
||||
for (dl = ddf->dlist; dl ; dl = dl->next)
|
||||
if (dl->major == dk->major &&
|
||||
dl->minor == dk->minor)
|
||||
break;
|
||||
if (!dl || ! (dk->state & (1<<MD_DISK_SYNC)))
|
||||
return;
|
||||
|
||||
vc = &ddf->newconf->conf;
|
||||
vc->phys_refnum[dk->raid_disk] = dl->disk.refnum;
|
||||
mppe = __be16_to_cpu(ddf->anchor.max_primary_element_entries);
|
||||
lba_offset = (__u64*)(vc->phys_refnum + mppe);
|
||||
lba_offset[dk->raid_disk] = 0; /* FIXME */
|
||||
|
||||
dl->vlist[0] =ddf->newconf; /* FIXME */
|
||||
|
||||
dl->fd = fd;
|
||||
dl->devname = devname;
|
||||
}
|
||||
|
||||
/* add a device to a container, either while creating it or while
|
||||
* expanding a pre-existing container
|
||||
*/
|
||||
|
@ -1517,7 +1725,7 @@ static void add_to_super_ddf(struct supertype *st,
|
|||
*(__u32*)(dd->disk.guid + 16) = random();
|
||||
*(__u32*)(dd->disk.guid + 20) = random();
|
||||
|
||||
dd->disk.refnum = random(); /* and hope for the best */
|
||||
dd->disk.refnum = random(); /* and hope for the best FIXME check this is unique!!*/
|
||||
dd->disk.forced_ref = 1;
|
||||
dd->disk.forced_guid = 1;
|
||||
memset(dd->disk.vendor, ' ', 32);
|
||||
|
@ -1664,14 +1872,40 @@ int validate_geometry_ddf(struct supertype *st,
|
|||
|
||||
if (level == LEVEL_CONTAINER) {
|
||||
st->ss = &super_ddf_container;
|
||||
if (dev) {
|
||||
int rv =st->ss->validate_geometry(st, level, layout,
|
||||
raiddisks, chunk,
|
||||
size,
|
||||
NULL, freesize);
|
||||
if (rv)
|
||||
return rv;
|
||||
}
|
||||
return st->ss->validate_geometry(st, level, layout, raiddisks,
|
||||
chunk, size, dev, freesize);
|
||||
}
|
||||
|
||||
if (st->sb) {
|
||||
/* creating in a given container */
|
||||
st->ss = &super_ddf_bvd;
|
||||
if (dev) {
|
||||
int rv =st->ss->validate_geometry(st, level, layout,
|
||||
raiddisks, chunk,
|
||||
size,
|
||||
NULL, freesize);
|
||||
if (rv)
|
||||
return rv;
|
||||
}
|
||||
return st->ss->validate_geometry(st, level, layout, raiddisks,
|
||||
chunk, size, dev, freesize);
|
||||
}
|
||||
/* FIXME should exclude MULTIPATH, or more appropriately, allow
|
||||
* only known levels.
|
||||
*/
|
||||
if (!dev)
|
||||
return 1;
|
||||
|
||||
/* This device needs to be either a device in a 'ddf' container,
|
||||
* or it needs to be a 'ddf-bvd' array. Test the first first.
|
||||
* or it needs to be a 'ddf-bvd' array.
|
||||
*/
|
||||
|
||||
fd = open(dev, O_RDONLY|O_EXCL, 0);
|
||||
|
@ -1714,7 +1948,7 @@ int validate_geometry_ddf(struct supertype *st,
|
|||
struct ddf_super *ddf;
|
||||
st->ss = &super_ddf_bvd;
|
||||
if (load_super_ddf_all(st, cfd, (void **)&ddf, NULL, 1) == 0) {
|
||||
st->info = ddf;
|
||||
st->sb = ddf;
|
||||
close(cfd);
|
||||
return st->ss->validate_geometry(st, level, layout,
|
||||
raiddisks, chunk, size,
|
||||
|
@ -1757,6 +1991,67 @@ int validate_geometry_ddf_container(struct supertype *st,
|
|||
return 1;
|
||||
}
|
||||
|
||||
struct extent {
|
||||
unsigned long long start, size;
|
||||
};
|
||||
int cmp_extent(const void *av, const void *bv)
|
||||
{
|
||||
const struct extent *a = av;
|
||||
const struct extent *b = bv;
|
||||
if (a->start < b->start)
|
||||
return -1;
|
||||
if (a->start > b->start)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct extent *get_extents(struct ddf_super *ddf, struct dl *dl)
|
||||
{
|
||||
/* find a list of used extents on the give physical device
|
||||
* (dnum) or the given ddf.
|
||||
* Return a malloced array of 'struct extent'
|
||||
|
||||
FIXME ignore DDF_Legacy devices?
|
||||
|
||||
*/
|
||||
struct extent *rv;
|
||||
int n = 0;
|
||||
int dnum;
|
||||
int i, j;
|
||||
|
||||
for (dnum = 0; dnum < ddf->phys->used_pdes; dnum++)
|
||||
if (memcmp(dl->disk.guid,
|
||||
ddf->phys->entries[dnum].guid,
|
||||
DDF_GUID_LEN) == 0)
|
||||
break;
|
||||
|
||||
if (dnum == ddf->phys->used_pdes)
|
||||
return NULL;
|
||||
|
||||
rv = malloc(sizeof(struct extent) * (ddf->max_part + 2));
|
||||
if (!rv)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < ddf->max_part+1; i++) {
|
||||
struct vcl *v = dl->vlist[i];
|
||||
if (v == NULL)
|
||||
continue;
|
||||
for (j=0; j < v->conf.prim_elmnt_count; j++)
|
||||
if (v->conf.phys_refnum[j] == dl->disk.refnum) {
|
||||
/* This device plays role 'j' in 'v'. */
|
||||
rv[n].start = __be64_to_cpu(v->lba_offset[j]);
|
||||
rv[n].size = __be64_to_cpu(v->conf.blocks);
|
||||
n++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
qsort(rv, n, sizeof(*rv), cmp_extent);
|
||||
|
||||
rv[n].start = __be64_to_cpu(ddf->phys->entries[dnum].config_size);
|
||||
rv[n].size = 0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
int validate_geometry_ddf_bvd(struct supertype *st,
|
||||
int level, int layout, int raiddisks,
|
||||
int chunk, unsigned long long size,
|
||||
|
@ -1765,6 +2060,10 @@ int validate_geometry_ddf_bvd(struct supertype *st,
|
|||
struct stat stb;
|
||||
struct ddf_super *ddf = st->sb;
|
||||
struct dl *dl;
|
||||
unsigned long long pos = 0;
|
||||
unsigned long long maxsize;
|
||||
struct extent *e;
|
||||
int i;
|
||||
/* ddf/bvd supports lots of things, but not containers */
|
||||
if (level == LEVEL_CONTAINER)
|
||||
return 0;
|
||||
|
@ -1772,6 +2071,41 @@ int validate_geometry_ddf_bvd(struct supertype *st,
|
|||
if (!ddf)
|
||||
return 0;
|
||||
|
||||
if (!dev) {
|
||||
/* General test: make sure there is space for
|
||||
* 'raiddisks' device extents of size 'size'.
|
||||
*/
|
||||
unsigned long long minsize = size;
|
||||
int dcnt = 0;
|
||||
if (minsize == 0)
|
||||
minsize = 8;
|
||||
for (dl = ddf->dlist; dl ; dl = dl->next)
|
||||
{
|
||||
int found = 0;
|
||||
|
||||
i = 0;
|
||||
e = get_extents(ddf, dl);
|
||||
if (!e) continue;
|
||||
do {
|
||||
unsigned long long esize;
|
||||
esize = e[i].start - pos;
|
||||
if (esize >= minsize)
|
||||
found = 1;
|
||||
pos = e[i].start + e[i].size;
|
||||
i++;
|
||||
} while (e[i-1].size);
|
||||
if (found)
|
||||
dcnt++;
|
||||
free(e);
|
||||
}
|
||||
if (dcnt < raiddisks) {
|
||||
fprintf(stderr, Name ": Not enough devices with space "
|
||||
"for this array (%d < %d)\n",
|
||||
dcnt, raiddisks);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/* This device must be a member of the set */
|
||||
if (stat(dev, &stb) < 0)
|
||||
return 0;
|
||||
|
@ -1782,6 +2116,23 @@ int validate_geometry_ddf_bvd(struct supertype *st,
|
|||
dl->minor == minor(stb.st_rdev))
|
||||
break;
|
||||
}
|
||||
if (!dl) {
|
||||
fprintf(stderr, Name ": %s is not in the same DDF set\n",
|
||||
dev);
|
||||
return 0;
|
||||
}
|
||||
e = get_extents(ddf, dl);
|
||||
maxsize = 0;
|
||||
i = 0;
|
||||
if (e) do {
|
||||
unsigned long long esize;
|
||||
esize = e[i].start - pos;
|
||||
if (esize >= maxsize)
|
||||
maxsize = esize;
|
||||
pos = e[i].start + e[i].size;
|
||||
i++;
|
||||
} while (e[i-1].size);
|
||||
*freesize = maxsize;
|
||||
// FIXME here I am
|
||||
|
||||
return 1;
|
||||
|
@ -1855,11 +2206,11 @@ static int load_super_ddf_all(struct supertype *st, int fd,
|
|||
/* Now we need the device-local bits */
|
||||
for (sd = sra->devs ; sd ; sd = sd->next) {
|
||||
sprintf(nm, "%d:%d", sd->disk.major, sd->disk.minor);
|
||||
dfd = dev_open(nm, O_RDONLY);
|
||||
dfd = dev_open(nm, keep_fd? O_RDWR : O_RDONLY);
|
||||
if (!dfd)
|
||||
return 2;
|
||||
seq = load_ddf_local(dfd, super, NULL, keep_fd);
|
||||
close(dfd);
|
||||
if (!keep_fd) close(dfd);
|
||||
}
|
||||
*sbp = super;
|
||||
if (st->ss == NULL) {
|
||||
|
@ -1950,9 +2301,11 @@ struct superswitch super_ddf_bvd = {
|
|||
// .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,
|
||||
.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,
|
||||
|
@ -1962,7 +2315,7 @@ struct superswitch super_ddf_bvd = {
|
|||
|
||||
.major = 1001,
|
||||
.swapuuid = 0,
|
||||
.external = 1,
|
||||
.external = 2,
|
||||
.text_version = "ddf",
|
||||
};
|
||||
|
||||
|
@ -1970,7 +2323,7 @@ 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_bvd,
|
||||
.validate_geometry = validate_geometry_ddf_svd,
|
||||
#endif
|
||||
.update_super = update_super_ddf,
|
||||
.init_super = init_super_ddf,
|
||||
|
@ -1979,9 +2332,8 @@ struct superswitch super_ddf_svd = {
|
|||
.free_super = free_super_ddf,
|
||||
.match_metadata_desc = match_metadata_desc_ddf_svd,
|
||||
|
||||
|
||||
.major = 1002,
|
||||
.swapuuid = 0,
|
||||
.external = 1,
|
||||
.external = 2,
|
||||
.text_version = "ddf",
|
||||
};
|
||||
|
|
17
util.c
17
util.c
|
@ -609,6 +609,23 @@ char *human_size_brief(long long bytes)
|
|||
}
|
||||
#endif
|
||||
|
||||
unsigned long long calc_array_size(int level, int raid_disks, int layout,
|
||||
int chunksize, unsigned long long devsize)
|
||||
{
|
||||
int data_disks = 0;
|
||||
switch (level) {
|
||||
case 0: data_disks = raid_disks; break;
|
||||
case 1: data_disks = 1; break;
|
||||
case 4:
|
||||
case 5: data_disks = raid_disks - 1; break;
|
||||
case 6: data_disks = raid_disks - 2; break;
|
||||
case 10: data_disks = raid_disks / (layout & 255) / ((layout>>8)&255);
|
||||
break;
|
||||
}
|
||||
devsize &= ~(unsigned long long)((chunksize>>9)-1);
|
||||
return data_disks * devsize;
|
||||
}
|
||||
|
||||
#if !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO)
|
||||
int get_mdp_major(void)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue