GEOM stripe library.
Poul-Henning Kamp
phk at phk.freebsd.dk
Thu Feb 26 11:29:12 PST 2004
In message <20040225103057.GB5506 at darkness.comp.waw.pl>, Pawel Jakub Dawidek wr
ites:
> * This disk have two slice:
> *
> * d_slices[0].s_offset =3D 1024
> * d_slices[0].s_length =3D 2048
> * d_slices[0].s_virt_offset =3D 0
> * d_slices[0].s_virt_end =3D 2048 (s_virt_offset + s_length)
I can't really see what we need s_virt_end for. If you need it for
implementation, then please calculate it as part of setup so that
the users of this library will not even see it.
>/*
> * Structure g_stripe_group describes group of disks that are used
> * on given offset. This allows to create stripe on disks with different
> * sizes.
> *
> * disk 0 disk 1 disk 2 START_DISK START_OFFSET
> * +-------+ +-------+ +-------+ 0 0
> * |0000000| |0000000| |0000000|
> * |0000000| |0000000| |0000000|
> * + - - - + +-------+ + - - - + 1024 0 + 1024 * 3 =3D 3072
> * |1111111| |1111111|
> * |1111111| |1111111|
> * |1111111| |1111111|
> * +-------+ + - - - + 2560 3072 + 1536 * 2 =3D 6144
> * |2222222|
> * +-------+ 3072 6144 + 512 * 1 =3D 6656
> *
> * sc_groups[0].g_ndisks =3D 3
> * sc_groups[0].g_disks =3D { 0, 1, 2 }
> * sc_groups[0].g_start_offset =3D 0
> * sc_groups[0].g_end_offset =3D 3072
> * sc_groups[0].g_start_disk =3D 0
Where is the actual stripe-width ? Shouldn't that be a parameter here ?
> * sc_groups[1].g_ndisks =3D 2
> * sc_groups[1].g_disks =3D { 0, 2 }
> * sc_groups[1].g_start_offset =3D 3072
> * sc_groups[1].g_end_offset =3D 6144
> * sc_groups[1].g_start_disk =3D 2560
s/2560/1024/ ?
> * sc_groups[2].g_ndisks =3D 1
> * sc_groups[2].g_disks =3D { 2 }
> * sc_groups[2].g_start_offset =3D 6144
> * sc_groups[2].g_end_offset =3D 6656
> * sc_groups[2].g_start_disk =3D 3072
s/3072/2560/ ?
I have been thinking a bit more about this, and I can see a number of
in-use striping geometries you cannot handle with this, in particular
non-uniform striping (64k from disk0, 128k from disk1, 64k from disk0,
128k from disk1, ...) There are also some underspecified parameters
and some overspecified ones.
I think it would be much more compact in the client code and just as
efficient for the library code to describe just the actual layout:
struct g_slicecomponent {
off_t offset;
off_t bite;
/* private members for the library */
...
};
struct g_slicepart {
off_t stripes;
struct g_slicecomponent *components;
/* private members for the library */
...
};
struct stripe {
int nconsumer;
struct g_consumer *consumer;
int nparts;
struct g_slicepart *slicepart;
/* private members for the library */
...
};
Simply striping two 1 megabyte disks with 8k stripes, preserving
the first 63 sectors for metadata would look like this in not-quite-C:
struct stripe {
.nconsumer = 2;
.consumer = [ ptr1; ptr2; ];
.nparts = 1;
.slicepart = [
{
.stripes = (1M - 63*512) / 8192;
.components = [
{
.offset = 63;
.bite = 8k / 2;
};
{
.offset = 63;
.bite = 8k / 2;
};
]
};
]
};
And setting this up in class code could look like this:
struct stripe *sp;
sp = g_stripe_new(/* consumers */ 2, /* parts */ 1);
sp->consumer[0] = c0;
sp->consumer[1] = c1;
sp->slicepart[0].stripes = (size - magic) / stripewidth;
sp->slicepart[0].components[0].offset = magic;
sp->slicepart[0].components[0].bite = stripewidth / 2;
sp->slicepart[0].components[1].offset = magic;
sp->slicepart[0].components[1].bite = stripewidth / 2;
error = g_stripe_calculate(sp);
A geometry somewhat like yours and with all parameters filled in
would then look like this in not-quite-C:
struct stripe {
.nconsumer = 3;
.consumer = [ ptr1; ptr2; ptr3; ];
.nparts = 3;
.slicepart = [
{
.stripes = 1024;
.components = [
{
.offset = 1024;
.bite = 1024;
};
{
.offset = 1024;
.bite = 1024;
};
{
.offset = 1024;
.bite = 1024;
};
]
};
{
.stripes = 3072;
.components = [
{
.offset = 1024 + 1024 * 1024;
.bite = 512;
};
{
.offset = 0;
.bite = 0;
};
{
.offset = 1024 + 1024 * 1024;
.bite = 512;
};
]
};
{
.stripes = 256;
.components = [
{
.offset = 0;
.bite = 0;
};
{
.offset = 0;
.bite = 0;
};
{
.consumer = 2;
.offset = 1024 + 1024 * 1024 + 3072 * 512;
.bite = 2048;
};
]
};
]
};
And would look like this in C code:
struct stripe *sp;
sp = g_stripe_new(/* consumers */ 3, /* parts */ 3);
sp->consumer[0] = c0;
sp->consumer[1] = c1;
sp->consumer[2] = c2;
sp->slicepart[0].stripes = 1024;
for (i = 0; i < 3; i++) {
sp->slicepart[0].components[i].offset = 1024;
sp->slicepart[0].components[i].bite = 1024;
}
sp->slicepart[1].stripes = 3072;
sp->slicepart[1].components[0].offset = -1; /* autocalculate */
sp->slicepart[1].components[0].bite = 512;
sp->slicepart[1].components[2].offset = -1; /* autocalculate */
sp->slicepart[1].components[2].bite = 512;
sp->slicepart[1].stripes = 256;
sp->slicepart[1].components[2].offset = -1; /* autocalculate */
sp->slicepart[1].components[2].bite = 2048;
error = g_stripe_calculate(sp);
Setting offset to -1 means "continue wherever we got to".
--
Poul-Henning Kamp | UNIX since Zilog Zeus 3.20
phk at FreeBSD.ORG | TCP/IP since RFC 956
FreeBSD committer | BSD since 4.3-tahoe
Never attribute to malice what can adequately be explained by incompetence.
More information about the freebsd-geom
mailing list