Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 26 Feb 2004 10:47:32 +0100
From:      "Poul-Henning Kamp" <phk@phk.freebsd.dk>
To:        Pawel Jakub Dawidek <pjd@freebsd.org>
Cc:        freebsd-geom@freebsd.org
Subject:   Re: GEOM stripe library. 
Message-ID:  <886.1077788852@critter.freebsd.dk>
In-Reply-To: Your message of "Wed, 25 Feb 2004 11:30:57 %2B0100." <20040225103057.GB5506@darkness.comp.waw.pl> 

next in thread | previous in thread | raw e-mail | index | archive | help
In message <20040225103057.GB5506@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@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.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?886.1077788852>