Bring in the GEOM Virtualisation class, which allows to create huge GEOM
providers with limited physical storage and add physical storage as needed. Submitted by: Ivan Voras Sponsored by: Google Summer of Code 2006 Approved by: re (kensmith)
This commit is contained in:
parent
a95a61fc19
commit
f854db0bf5
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=172302
@ -174,6 +174,8 @@
|
|||||||
..
|
..
|
||||||
stripe
|
stripe
|
||||||
..
|
..
|
||||||
|
virstor
|
||||||
|
..
|
||||||
..
|
..
|
||||||
gnu
|
gnu
|
||||||
posix
|
posix
|
||||||
|
@ -49,7 +49,7 @@ LSUBDIRS= cam/scsi \
|
|||||||
fs/devfs fs/fdescfs fs/fifofs fs/msdosfs fs/ntfs fs/nullfs \
|
fs/devfs fs/fdescfs fs/fifofs fs/msdosfs fs/ntfs fs/nullfs \
|
||||||
${_fs_nwfs} fs/portalfs fs/procfs fs/smbfs fs/udf fs/unionfs \
|
${_fs_nwfs} fs/portalfs fs/procfs fs/smbfs fs/udf fs/unionfs \
|
||||||
geom/cache geom/concat geom/eli geom/gate geom/journal geom/label \
|
geom/cache geom/concat geom/eli geom/gate geom/journal geom/label \
|
||||||
geom/mirror geom/nop geom/raid3 geom/shsec geom/stripe \
|
geom/mirror geom/nop geom/raid3 geom/shsec geom/stripe geom/virstor \
|
||||||
netgraph/atm netgraph/netflow \
|
netgraph/atm netgraph/netflow \
|
||||||
security/audit \
|
security/audit \
|
||||||
security/mac_biba security/mac_bsdextended security/mac_lomac \
|
security/mac_biba security/mac_bsdextended security/mac_lomac \
|
||||||
|
@ -16,5 +16,6 @@ SUBDIR+=part
|
|||||||
SUBDIR+=raid3
|
SUBDIR+=raid3
|
||||||
SUBDIR+=shsec
|
SUBDIR+=shsec
|
||||||
SUBDIR+=stripe
|
SUBDIR+=stripe
|
||||||
|
SUBDIR+=virstor
|
||||||
|
|
||||||
.include <bsd.subdir.mk>
|
.include <bsd.subdir.mk>
|
||||||
|
13
sbin/geom/class/virstor/Makefile
Normal file
13
sbin/geom/class/virstor/Makefile
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# $FreeBSD$
|
||||||
|
|
||||||
|
.PATH: ${.CURDIR}/../../misc ${.CURDIR}/../../../../sys/geom/virstor
|
||||||
|
|
||||||
|
CLASS= virstor
|
||||||
|
|
||||||
|
SRCS+= binstream.c
|
||||||
|
SRCS+= g_virstor_md.c
|
||||||
|
|
||||||
|
DPADD= ${LIBMD}
|
||||||
|
LDADD= -lmd
|
||||||
|
|
||||||
|
.include <bsd.lib.mk>
|
578
sbin/geom/class/virstor/geom_virstor.c
Normal file
578
sbin/geom/class/virstor/geom_virstor.c
Normal file
@ -0,0 +1,578 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2005 Ivan Voras <ivoras@freebsd.org>
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <paths.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <libgeom.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <core/geom.h>
|
||||||
|
#include <misc/subr.h>
|
||||||
|
|
||||||
|
#include <geom/virstor/g_virstor_md.h>
|
||||||
|
#include <geom/virstor/g_virstor.h>
|
||||||
|
|
||||||
|
uint32_t lib_version = G_LIB_VERSION;
|
||||||
|
uint32_t version = G_VIRSTOR_VERSION;
|
||||||
|
static intmax_t chunk_size = 4 * 1024 * 1024; /* in kB (default: 4 MB) */
|
||||||
|
static intmax_t vir_size = 2ULL << 40; /* in MB (default: 2 TB) */
|
||||||
|
|
||||||
|
#if G_LIB_VERSION == 1
|
||||||
|
/* Support RELENG_6 */
|
||||||
|
#define G_TYPE_BOOL G_TYPE_NONE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* virstor_main gets called by the geom(8) utility
|
||||||
|
*/
|
||||||
|
static void virstor_main(struct gctl_req *req, unsigned flags);
|
||||||
|
|
||||||
|
struct g_command class_commands[] = {
|
||||||
|
{"clear", G_FLAG_VERBOSE, virstor_main, G_NULL_OPTS, NULL,
|
||||||
|
"[-v] prov ..."
|
||||||
|
},
|
||||||
|
{"dump", 0, virstor_main, G_NULL_OPTS, NULL,
|
||||||
|
"prov ..."
|
||||||
|
},
|
||||||
|
{"label", G_FLAG_VERBOSE | G_FLAG_LOADKLD, virstor_main,
|
||||||
|
{
|
||||||
|
{'h', "hardcode", NULL, G_TYPE_BOOL},
|
||||||
|
{'m', "chunk_size", &chunk_size, G_TYPE_NUMBER},
|
||||||
|
{'s', "vir_size", &vir_size, G_TYPE_NUMBER},
|
||||||
|
G_OPT_SENTINEL
|
||||||
|
},
|
||||||
|
NULL, "[-h] [-v] [-m chunk_size] [-s vir_size] name provider0 [provider1 ...]"
|
||||||
|
},
|
||||||
|
{"destroy", G_FLAG_VERBOSE, NULL,
|
||||||
|
{
|
||||||
|
{'f', "force", NULL, G_TYPE_BOOL},
|
||||||
|
G_OPT_SENTINEL
|
||||||
|
},
|
||||||
|
NULL, "[-fv] name ..."
|
||||||
|
},
|
||||||
|
{"stop", G_FLAG_VERBOSE, NULL,
|
||||||
|
{
|
||||||
|
{'f', "force", NULL, G_TYPE_BOOL},
|
||||||
|
G_OPT_SENTINEL
|
||||||
|
},
|
||||||
|
NULL, "[-fv] name ... (alias for \"destroy\")"
|
||||||
|
},
|
||||||
|
{"add", G_FLAG_VERBOSE, NULL,
|
||||||
|
{
|
||||||
|
{'h', "hardcode", NULL, G_TYPE_BOOL},
|
||||||
|
G_OPT_SENTINEL
|
||||||
|
},
|
||||||
|
NULL, "[-vh] name prov [prov ...]"
|
||||||
|
},
|
||||||
|
{"remove", G_FLAG_VERBOSE, NULL, G_NULL_OPTS, NULL,
|
||||||
|
"[-v] name ..."
|
||||||
|
},
|
||||||
|
G_CMD_SENTINEL
|
||||||
|
};
|
||||||
|
|
||||||
|
static int verbose = 0;
|
||||||
|
|
||||||
|
/* Helper functions' declarations */
|
||||||
|
static void virstor_clear(struct gctl_req *req);
|
||||||
|
static void virstor_dump(struct gctl_req *req);
|
||||||
|
static void virstor_label(struct gctl_req *req);
|
||||||
|
|
||||||
|
/* Dispatcher function (no real work done here, only verbose flag recorder) */
|
||||||
|
static void
|
||||||
|
virstor_main(struct gctl_req *req, unsigned flags)
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
if ((flags & G_FLAG_VERBOSE) != 0)
|
||||||
|
verbose = 1;
|
||||||
|
|
||||||
|
name = gctl_get_ascii(req, "verb");
|
||||||
|
if (name == NULL) {
|
||||||
|
gctl_error(req, "No '%s' argument.", "verb");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (strcmp(name, "label") == 0)
|
||||||
|
virstor_label(req);
|
||||||
|
else if (strcmp(name, "clear") == 0)
|
||||||
|
virstor_clear(req);
|
||||||
|
else if (strcmp(name, "dump") == 0)
|
||||||
|
virstor_dump(req);
|
||||||
|
else
|
||||||
|
gctl_error(req, "%s: Unknown command: %s.", __func__, name);
|
||||||
|
|
||||||
|
/* No CTASSERT in userland
|
||||||
|
CTASSERT(VIRSTOR_MAP_BLOCK_ENTRIES*VIRSTOR_MAP_ENTRY_SIZE == MAXPHYS);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pathgen(const char *name, char *path, size_t size)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (strncmp(name, _PATH_DEV, strlen(_PATH_DEV)) != 0)
|
||||||
|
snprintf(path, size, "%s%s", _PATH_DEV, name);
|
||||||
|
else
|
||||||
|
strlcpy(path, name, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
my_g_metadata_store(const char *name, u_char *md, size_t size)
|
||||||
|
{
|
||||||
|
char path[MAXPATHLEN];
|
||||||
|
unsigned sectorsize;
|
||||||
|
off_t mediasize;
|
||||||
|
u_char *sector;
|
||||||
|
int error, fd;
|
||||||
|
ssize_t abc;
|
||||||
|
|
||||||
|
pathgen(name, path, sizeof(path));
|
||||||
|
sector = NULL;
|
||||||
|
error = 0;
|
||||||
|
|
||||||
|
fd = open(path, O_RDWR);
|
||||||
|
if (fd == -1)
|
||||||
|
return (errno);
|
||||||
|
mediasize = g_get_mediasize(name);
|
||||||
|
if (mediasize == 0) {
|
||||||
|
error = errno;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
sectorsize = g_get_sectorsize(name);
|
||||||
|
if (sectorsize == 0) {
|
||||||
|
error = errno;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
assert(sectorsize >= size);
|
||||||
|
sector = malloc(sectorsize);
|
||||||
|
if (sector == NULL) {
|
||||||
|
error = ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
bcopy(md, sector, size);
|
||||||
|
if ((abc = pwrite(fd, sector, sectorsize, mediasize - sectorsize)) !=
|
||||||
|
(ssize_t)sectorsize) {
|
||||||
|
error = errno;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
if (sector != NULL)
|
||||||
|
free(sector);
|
||||||
|
close(fd);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Labels a new geom Meaning: parses and checks the parameters, calculates &
|
||||||
|
* writes metadata to the relevant providers so when the next round of
|
||||||
|
* "tasting" comes (which will be just after the provider(s) are closed) geom
|
||||||
|
* can be instantiated with the tasted metadata.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
virstor_label(struct gctl_req *req)
|
||||||
|
{
|
||||||
|
struct g_virstor_metadata md;
|
||||||
|
off_t msize;
|
||||||
|
unsigned char *sect;
|
||||||
|
unsigned int i;
|
||||||
|
size_t ssize, secsize;
|
||||||
|
const char *name;
|
||||||
|
char param[32];
|
||||||
|
int hardcode, nargs, error;
|
||||||
|
struct virstor_map_entry *map;
|
||||||
|
size_t total_chunks; /* We'll run out of memory if
|
||||||
|
this needs to be bigger. */
|
||||||
|
unsigned int map_chunks; /* Chunks needed by the map (map size). */
|
||||||
|
size_t map_size; /* In bytes. */
|
||||||
|
ssize_t written;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
nargs = gctl_get_int(req, "nargs");
|
||||||
|
if (nargs < 2) {
|
||||||
|
gctl_error(req, "Too few arguments (%d): expecting: name "
|
||||||
|
"provider0 [provider1 ...]", nargs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hardcode = gctl_get_int(req, "hardcode");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize constant parts of metadata: magic signature, version,
|
||||||
|
* name.
|
||||||
|
*/
|
||||||
|
bzero(&md, sizeof(md));
|
||||||
|
strlcpy(md.md_magic, G_VIRSTOR_MAGIC, sizeof(md.md_magic));
|
||||||
|
md.md_version = G_VIRSTOR_VERSION;
|
||||||
|
name = gctl_get_ascii(req, "arg0");
|
||||||
|
if (name == NULL) {
|
||||||
|
gctl_error(req, "No 'arg%u' argument.", 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
strlcpy(md.md_name, name, sizeof(md.md_name));
|
||||||
|
|
||||||
|
md.md_virsize = (off_t)gctl_get_intmax(req, "vir_size");
|
||||||
|
md.md_chunk_size = gctl_get_intmax(req, "chunk_size");
|
||||||
|
md.md_count = nargs - 1;
|
||||||
|
|
||||||
|
if (md.md_virsize == 0 || md.md_chunk_size == 0) {
|
||||||
|
gctl_error(req, "Virtual size and chunk size must be non-zero");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (md.md_chunk_size % MAXPHYS != 0) {
|
||||||
|
/* XXX: This is not strictly needed, but it's convenient to
|
||||||
|
* impose some limitations on it, so why not MAXPHYS. */
|
||||||
|
size_t new_size = (md.md_chunk_size / MAXPHYS) * MAXPHYS;
|
||||||
|
if (new_size < md.md_chunk_size)
|
||||||
|
new_size += MAXPHYS;
|
||||||
|
fprintf(stderr, "Resizing chunk size to be a multiple of "
|
||||||
|
"MAXPHYS (%d kB).\n", MAXPHYS / 1024);
|
||||||
|
fprintf(stderr, "New chunk size: %zu kB\n", new_size / 1024);
|
||||||
|
md.md_chunk_size = new_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (md.md_virsize % md.md_chunk_size != 0) {
|
||||||
|
off_t chunk_count = md.md_virsize / md.md_chunk_size;
|
||||||
|
md.md_virsize = chunk_count * md.md_chunk_size;
|
||||||
|
fprintf(stderr, "Resizing virtual size to be a multiple of "
|
||||||
|
"chunk size.\n");
|
||||||
|
fprintf(stderr, "New virtual size: %zu MB\n",
|
||||||
|
(size_t)(md.md_virsize/(1024 * 1024)));
|
||||||
|
}
|
||||||
|
|
||||||
|
msize = secsize = ssize = 0;
|
||||||
|
for (i = 1; i < (unsigned)nargs; i++) {
|
||||||
|
snprintf(param, sizeof(param), "arg%u", i);
|
||||||
|
name = gctl_get_ascii(req, param);
|
||||||
|
ssize = g_get_sectorsize(name);
|
||||||
|
if (ssize == 0)
|
||||||
|
fprintf(stderr, "%s for %s\n", strerror(errno), name);
|
||||||
|
msize += g_get_mediasize(name);
|
||||||
|
if (secsize == 0)
|
||||||
|
secsize = ssize;
|
||||||
|
else if (secsize != ssize) {
|
||||||
|
gctl_error(req, "Devices need to have same sector size "
|
||||||
|
"(%u on %s needs to be %u).",
|
||||||
|
(u_int)ssize, name, (u_int)secsize);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (md.md_chunk_size % secsize != 0) {
|
||||||
|
fprintf(stderr, "Error: chunk size is not a multiple of sector "
|
||||||
|
"size.");
|
||||||
|
gctl_error(req, "Chunk size (in bytes) must be multiple of %u.",
|
||||||
|
(unsigned int)secsize);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
total_chunks = md.md_virsize / md.md_chunk_size;
|
||||||
|
map_size = total_chunks * sizeof(*map);
|
||||||
|
assert(md.md_virsize % md.md_chunk_size == 0);
|
||||||
|
|
||||||
|
ssize = map_size % secsize;
|
||||||
|
if (ssize != 0) {
|
||||||
|
size_t add_chunks = (secsize - ssize) / sizeof(*map);
|
||||||
|
total_chunks += add_chunks;
|
||||||
|
md.md_virsize = (off_t)total_chunks * (off_t)md.md_chunk_size;
|
||||||
|
map_size = total_chunks * sizeof(*map);
|
||||||
|
fprintf(stderr, "Resizing virtual size to fit virstor "
|
||||||
|
"structures.\n");
|
||||||
|
fprintf(stderr, "New virtual size: %ju MB (%zu new chunks)\n",
|
||||||
|
(uintmax_t)(md.md_virsize / (1024 * 1024)), add_chunks);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
printf("Total virtual chunks: %zu (%zu MB each), %ju MB total "
|
||||||
|
"virtual size.\n",
|
||||||
|
total_chunks, (size_t)(md.md_chunk_size / (1024 * 1024)),
|
||||||
|
md.md_virsize/(1024 * 1024));
|
||||||
|
|
||||||
|
if ((off_t)md.md_virsize < msize)
|
||||||
|
fprintf(stderr, "WARNING: Virtual storage size < Physical "
|
||||||
|
"available storage (%ju < %ju)\n", md.md_virsize, msize);
|
||||||
|
|
||||||
|
/* Clear last sector first to spoil all components if device exists. */
|
||||||
|
if (verbose)
|
||||||
|
printf("Clearing metadata on");
|
||||||
|
|
||||||
|
for (i = 1; i < (unsigned)nargs; i++) {
|
||||||
|
snprintf(param, sizeof(param), "arg%u", i);
|
||||||
|
name = gctl_get_ascii(req, param);
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
printf(" %s", name);
|
||||||
|
|
||||||
|
msize = g_get_mediasize(name);
|
||||||
|
ssize = g_get_sectorsize(name);
|
||||||
|
if (msize == 0 || ssize == 0) {
|
||||||
|
gctl_error(req, "Can't retrieve information about "
|
||||||
|
"%s: %s.", name, strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (msize < MAX(md.md_chunk_size*4, map_size))
|
||||||
|
gctl_error(req, "Device %s is too small", name);
|
||||||
|
error = g_metadata_clear(name, NULL);
|
||||||
|
if (error != 0) {
|
||||||
|
gctl_error(req, "Can't clear metadata on %s: %s.", name,
|
||||||
|
strerror(error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Write allocation table to the first provider - this needs to be done
|
||||||
|
* before metadata is written because when kernel tastes it it's too
|
||||||
|
* late */
|
||||||
|
name = gctl_get_ascii(req, "arg1"); /* device with metadata */
|
||||||
|
if (verbose)
|
||||||
|
printf(".\nWriting allocation table to %s...", name);
|
||||||
|
|
||||||
|
/* How many chunks does the map occupy? */
|
||||||
|
map_chunks = map_size/md.md_chunk_size;
|
||||||
|
if (map_size % md.md_chunk_size != 0)
|
||||||
|
map_chunks++;
|
||||||
|
if (verbose) {
|
||||||
|
printf(" (%zu MB, %d chunks) ", map_size/(1024*1024), map_chunks);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncmp(name, _PATH_DEV, strlen(_PATH_DEV)) == 0)
|
||||||
|
fd = open(name, O_RDWR);
|
||||||
|
else {
|
||||||
|
sprintf(param, "%s%s", _PATH_DEV, name);
|
||||||
|
fd = open(param, O_RDWR);
|
||||||
|
}
|
||||||
|
if (fd < 0)
|
||||||
|
gctl_error(req, "Cannot open provider %s to write map", name);
|
||||||
|
|
||||||
|
/* Do it with calloc because there might be a need to set up chunk flags
|
||||||
|
* in the future */
|
||||||
|
map = calloc(total_chunks, sizeof(*map));
|
||||||
|
if (map == NULL) {
|
||||||
|
gctl_error(req,
|
||||||
|
"Out of memory (need %zu bytes for allocation map)",
|
||||||
|
map_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
written = pwrite(fd, map, map_size, 0);
|
||||||
|
free(map);
|
||||||
|
if ((size_t)written != map_size) {
|
||||||
|
if (verbose) {
|
||||||
|
fprintf(stderr, "\nTried to write %zu, written %zd (%s)\n",
|
||||||
|
map_size, written, strerror(errno));
|
||||||
|
}
|
||||||
|
gctl_error(req, "Error writing out allocation map!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
close (fd);
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
printf("\nStoring metadata on ");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ID is randomly generated, unique for a geom. This is used to
|
||||||
|
* recognize all providers belonging to one geom.
|
||||||
|
*/
|
||||||
|
md.md_id = arc4random();
|
||||||
|
|
||||||
|
/* Ok, store metadata. */
|
||||||
|
for (i = 1; i < (unsigned)nargs; i++) {
|
||||||
|
snprintf(param, sizeof(param), "arg%u", i);
|
||||||
|
name = gctl_get_ascii(req, param);
|
||||||
|
|
||||||
|
msize = g_get_mediasize(name);
|
||||||
|
ssize = g_get_sectorsize(name);
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
printf("%s ", name);
|
||||||
|
|
||||||
|
/* this provider's position/type in geom */
|
||||||
|
md.no = i - 1;
|
||||||
|
/* this provider's size */
|
||||||
|
md.provsize = msize;
|
||||||
|
/* chunk allocation info */
|
||||||
|
md.chunk_count = md.provsize / md.md_chunk_size;
|
||||||
|
if (verbose)
|
||||||
|
printf("(%u chunks) ", md.chunk_count);
|
||||||
|
/* Check to make sure last sector is unused */
|
||||||
|
if ((off_t)(md.chunk_count) * md.md_chunk_size > msize-ssize)
|
||||||
|
md.chunk_count--;
|
||||||
|
md.chunk_next = 0;
|
||||||
|
if (i != 1) {
|
||||||
|
md.chunk_reserved = 0;
|
||||||
|
md.flags = 0;
|
||||||
|
} else {
|
||||||
|
md.chunk_reserved = map_chunks * 2;
|
||||||
|
md.flags = VIRSTOR_PROVIDER_ALLOCATED |
|
||||||
|
VIRSTOR_PROVIDER_CURRENT;
|
||||||
|
md.chunk_next = md.chunk_reserved;
|
||||||
|
if (verbose)
|
||||||
|
printf("(%u reserved) ", md.chunk_reserved);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hardcode)
|
||||||
|
bzero(md.provider, sizeof(md.provider));
|
||||||
|
else {
|
||||||
|
/* convert "/dev/something" to "something" */
|
||||||
|
if (strncmp(name, _PATH_DEV, strlen(_PATH_DEV)) == 0) {
|
||||||
|
strlcpy(md.provider, name + strlen(_PATH_DEV),
|
||||||
|
sizeof(md.provider));
|
||||||
|
} else
|
||||||
|
strlcpy(md.provider, name, sizeof(md.provider));
|
||||||
|
}
|
||||||
|
sect = malloc(ssize);
|
||||||
|
bzero(sect, ssize);
|
||||||
|
if (sect == NULL)
|
||||||
|
err(1, "Cannot allocate sector of %zu bytes", ssize);
|
||||||
|
virstor_metadata_encode(&md, sect);
|
||||||
|
error = my_g_metadata_store(name, sect, ssize);
|
||||||
|
free(sect);
|
||||||
|
if (error != 0) {
|
||||||
|
if (verbose)
|
||||||
|
printf("\n");
|
||||||
|
fprintf(stderr, "Can't store metadata on %s: %s.\n",
|
||||||
|
name, strerror(error));
|
||||||
|
gctl_error(req,
|
||||||
|
"Not fully done (error storing metadata).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
if (verbose)
|
||||||
|
printf("\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clears metadata on given provider(s) IF it's owned by us */
|
||||||
|
static void
|
||||||
|
virstor_clear(struct gctl_req *req)
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
char param[32];
|
||||||
|
unsigned i;
|
||||||
|
int nargs, error;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
nargs = gctl_get_int(req, "nargs");
|
||||||
|
if (nargs < 1) {
|
||||||
|
gctl_error(req, "Too few arguments.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (i = 0; i < (unsigned)nargs; i++) {
|
||||||
|
snprintf(param, sizeof(param), "arg%u", i);
|
||||||
|
name = gctl_get_ascii(req, param);
|
||||||
|
|
||||||
|
error = g_metadata_clear(name, G_VIRSTOR_MAGIC);
|
||||||
|
if (error != 0) {
|
||||||
|
fprintf(stderr, "Can't clear metadata on %s: %s "
|
||||||
|
"(do I own it?)\n", name, strerror(error));
|
||||||
|
gctl_error(req,
|
||||||
|
"Not fully done (can't clear metadata).");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strncmp(name, _PATH_DEV, strlen(_PATH_DEV)) == 0)
|
||||||
|
fd = open(name, O_RDWR);
|
||||||
|
else {
|
||||||
|
sprintf(param, "%s%s", _PATH_DEV, name);
|
||||||
|
fd = open(param, O_RDWR);
|
||||||
|
}
|
||||||
|
if (fd < 0) {
|
||||||
|
gctl_error(req, "Cannot clear header sector for %s",
|
||||||
|
name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (verbose)
|
||||||
|
printf("Metadata cleared on %s.\n", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print some metadata information */
|
||||||
|
static void
|
||||||
|
virstor_metadata_dump(const struct g_virstor_metadata *md)
|
||||||
|
{
|
||||||
|
printf(" Magic string: %s\n", md->md_magic);
|
||||||
|
printf(" Metadata version: %u\n", (u_int) md->md_version);
|
||||||
|
printf(" Device name: %s\n", md->md_name);
|
||||||
|
printf(" Device ID: %u\n", (u_int) md->md_id);
|
||||||
|
printf(" Provider index: %u\n", (u_int) md->no);
|
||||||
|
printf(" Active providers: %u\n", (u_int) md->md_count);
|
||||||
|
printf(" Hardcoded provider: %s\n",
|
||||||
|
md->provider[0] != '\0' ? md->provider : "(not hardcoded)");
|
||||||
|
printf(" Virtual size: %u MB\n",
|
||||||
|
(unsigned int)(md->md_virsize/(1024 * 1024)));
|
||||||
|
printf(" Chunk size: %u kB\n", md->md_chunk_size / 1024);
|
||||||
|
printf(" Chunks on provider: %u\n", md->chunk_count);
|
||||||
|
printf(" Chunks free: %u\n", md->chunk_count - md->chunk_next);
|
||||||
|
printf(" Reserved chunks: %u\n", md->chunk_reserved);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called by geom(8) via gvirstor_main() to dump metadata information */
|
||||||
|
static void
|
||||||
|
virstor_dump(struct gctl_req *req)
|
||||||
|
{
|
||||||
|
struct g_virstor_metadata md;
|
||||||
|
u_char tmpmd[512]; /* temporary buffer */
|
||||||
|
const char *name;
|
||||||
|
char param[16];
|
||||||
|
int nargs, error, i;
|
||||||
|
|
||||||
|
assert(sizeof(tmpmd) >= sizeof(md));
|
||||||
|
|
||||||
|
nargs = gctl_get_int(req, "nargs");
|
||||||
|
if (nargs < 1) {
|
||||||
|
gctl_error(req, "Too few arguments.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (i = 0; i < nargs; i++) {
|
||||||
|
snprintf(param, sizeof(param), "arg%u", i);
|
||||||
|
name = gctl_get_ascii(req, param);
|
||||||
|
|
||||||
|
error = g_metadata_read(name, (u_char *) & tmpmd, sizeof(tmpmd),
|
||||||
|
G_VIRSTOR_MAGIC);
|
||||||
|
if (error != 0) {
|
||||||
|
fprintf(stderr, "Can't read metadata from %s: %s.\n",
|
||||||
|
name, strerror(error));
|
||||||
|
gctl_error(req,
|
||||||
|
"Not fully done (error reading metadata).");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
virstor_metadata_decode((u_char *) & tmpmd, &md);
|
||||||
|
printf("Metadata on %s:\n", name);
|
||||||
|
virstor_metadata_dump(&md);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
227
sbin/geom/class/virstor/gvirstor.8
Normal file
227
sbin/geom/class/virstor/gvirstor.8
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
.\" Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||||
|
.\" Copyright (c) 2005 Ivan Voras <ivoras@FreeBSD.org>
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||||
|
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" $FreeBSD$
|
||||||
|
.\"
|
||||||
|
.Dd July 8, 2006
|
||||||
|
.Dt GVIRSTOR 8
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm gvirstor
|
||||||
|
.Nd "provides virtual data storage geom"
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm
|
||||||
|
.Cm label
|
||||||
|
.Op Fl hv
|
||||||
|
.Op Fl s Ar virsize
|
||||||
|
.Op Fl m Ar chunksize
|
||||||
|
.Ar name
|
||||||
|
.Ar prov ...
|
||||||
|
.Nm
|
||||||
|
.Cm stop
|
||||||
|
.Op Fl fv
|
||||||
|
.Ar name ...
|
||||||
|
.Nm
|
||||||
|
.Cm add
|
||||||
|
.Op Fl vh
|
||||||
|
.Ar name prov ...
|
||||||
|
.Nm
|
||||||
|
.Cm remove
|
||||||
|
.Op Fl v
|
||||||
|
.Ar name prov ...
|
||||||
|
.Nm
|
||||||
|
.Cm clear
|
||||||
|
.Op Fl v
|
||||||
|
.Ar prov ...
|
||||||
|
.Nm
|
||||||
|
.Cm dump
|
||||||
|
.Ar prov ...
|
||||||
|
.Nm
|
||||||
|
.Cm list
|
||||||
|
.Nm
|
||||||
|
.Cm status
|
||||||
|
.Nm
|
||||||
|
.Cm load
|
||||||
|
.Nm
|
||||||
|
.Cm unload
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
utility is used for setting up a storage device of arbitrary large size (for example,
|
||||||
|
several TB), consisting of an arbitrary number of physical storage devices with
|
||||||
|
total size <= the virtual size. Data for the virtual devices will be allocated from
|
||||||
|
physical devices on demand. In short, this is the virtual storage functionality.
|
||||||
|
The first argument to
|
||||||
|
.Nm
|
||||||
|
indicates an action to be performed:
|
||||||
|
.Bl -tag -width ".Cm destroy"
|
||||||
|
.It Cm label
|
||||||
|
Set up a virtual device from the given components with the specified
|
||||||
|
.Ar name .
|
||||||
|
Metadata are stored in the last sector of every component.
|
||||||
|
Argument
|
||||||
|
.Ar virsize
|
||||||
|
is the size of new virtual device, with default being 2 TiB (2097152 MiB).
|
||||||
|
Argument
|
||||||
|
.Ar chunksize
|
||||||
|
is the chunk size, with default being 4 MiB (4096 KiB).
|
||||||
|
The default is thus "-s 2097152 -m 4096".
|
||||||
|
.It Cm stop
|
||||||
|
Turn off an existing virtual device by its
|
||||||
|
.Ar name .
|
||||||
|
This command does not touch on-disk metadata.
|
||||||
|
As with other GEOM classes, stopped geoms cannot be started manually.
|
||||||
|
.It Cm add
|
||||||
|
Adds new components to existing virtual device by its
|
||||||
|
.Ar name .
|
||||||
|
The specified virstor device must exist and be active (i.e.
|
||||||
|
module loaded, device present in /dev).
|
||||||
|
.It Cm remove
|
||||||
|
Removes components from existing virtual device by its
|
||||||
|
.Ar name .
|
||||||
|
Only unallocated providers can be removed.
|
||||||
|
.It Cm clear
|
||||||
|
Clear metadata on the given providers.
|
||||||
|
.It Cm dump
|
||||||
|
Dump metadata stored on the given providers.
|
||||||
|
.It Cm list
|
||||||
|
See
|
||||||
|
.Xr geom 8 .
|
||||||
|
.It Cm status
|
||||||
|
See
|
||||||
|
.Xr geom 8 .
|
||||||
|
.It Cm load
|
||||||
|
See
|
||||||
|
.Xr geom 8 .
|
||||||
|
.It Cm unload
|
||||||
|
See
|
||||||
|
.Xr geom 8 .
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
Additional options:
|
||||||
|
.Bl -tag -width ".Fl f"
|
||||||
|
.It Fl f
|
||||||
|
Force the removal of the specified virtual device.
|
||||||
|
.It Fl h
|
||||||
|
Hardcode providers' names in metadata.
|
||||||
|
.It Fl v
|
||||||
|
Be more verbose.
|
||||||
|
.El
|
||||||
|
.Sh EXIT STATUS
|
||||||
|
Exit status is 0 on success, and 1 if the command fails.
|
||||||
|
.Sh EXAMPLES
|
||||||
|
The following example shows how to create a virtual device of default size
|
||||||
|
(2 TiB), of default chunk (extent) size (4 MiB), with two physical devices for
|
||||||
|
backing storage.
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
gvirstor label -v mydata /dev/ad4 /dev/ad6
|
||||||
|
newfs /dev/virstor/mydata
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
From now on, the virtual device will be available via the
|
||||||
|
.Pa /dev/virstor/mydata
|
||||||
|
device entry.
|
||||||
|
To add a new physical device / provider to an active virstor device:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
gvirstor add mydata ad8
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
This will add physical storage (from ad8) to
|
||||||
|
.Pa /dev/virstor/mydata
|
||||||
|
device.
|
||||||
|
To see device status information (including how much physical storage
|
||||||
|
is still available for the virtual device), use:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
gvirstor list
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
All standard
|
||||||
|
.Xr geom 8
|
||||||
|
subcommands (e.g. "status", "help") are also supported.
|
||||||
|
.Sh SYSCTLs
|
||||||
|
.Nm
|
||||||
|
has several
|
||||||
|
.Xr sysctl 8
|
||||||
|
tunable variables.
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
.Pa int kern.geom.virstor.debug
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
This sysctl controls verbosity of the kernel module, in the range
|
||||||
|
1 to 15. Messages that are marked with higher verbosity levels than
|
||||||
|
this are supressed. Default value is 5 and it's not
|
||||||
|
recommented to set this tunable to less than 2, because level 1 messages
|
||||||
|
are error events, and level 2 messages are system warnings.
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
.Pa int kern.geom.virstor.chunk_watermark
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
Value in this sysctl sets warning watermark level for physical chunk usage
|
||||||
|
on a single component. The warning is issued when a virstor component
|
||||||
|
has less than this many free chunks (default 100).
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
.Pa int kern.geom.virstor.component_watermark
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
Value in this sysctl sets warning watermark level for component usage.
|
||||||
|
The warning is issed when there are less than this many unallocated
|
||||||
|
components (default is 1).
|
||||||
|
.Pp
|
||||||
|
All these sysctls are also available as
|
||||||
|
.Xr loader 8
|
||||||
|
tunables.
|
||||||
|
.Sh LOG MESSAGES
|
||||||
|
.Nm
|
||||||
|
kernel module issues log messages with prefixes in standardised format,
|
||||||
|
which is useful for log message filtering and dispatching. Each message
|
||||||
|
line begins with
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
.Pa GEOM_VIRSTOR[%d]:
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
The number (%d) is message verbosity / importance level, in the range
|
||||||
|
1 to 15. If a message filtering, dispatching or operator alert system is
|
||||||
|
used, it is recommended that messages with levels 1 and 2 be taken
|
||||||
|
seriously (for example, to catch out-of-space conditions as set by
|
||||||
|
watermark sysctls).
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr geom 4 ,
|
||||||
|
.Xr geom 8 ,
|
||||||
|
.Xr newfs 8 ,
|
||||||
|
.Xr fstab 5 ,
|
||||||
|
.Xr glabel 8
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
utility appeared in
|
||||||
|
.Fx 7.0 .
|
||||||
|
.Sh BUGS
|
||||||
|
Commands "add" and "remove" contain unavoidable critical sections
|
||||||
|
which may make the virstor device unusable if a power failure (or
|
||||||
|
other disruptive event) happens during their execution.
|
||||||
|
It's recommended to run them when the system is quiescent.
|
||||||
|
.Sh AUTHOR
|
||||||
|
.An Ivan Voras Aq ivoras@FreeBSD.org
|
||||||
|
Sponsored by Google Summer of Code 2006
|
@ -123,6 +123,8 @@ RAID3
|
|||||||
SHSEC
|
SHSEC
|
||||||
.It
|
.It
|
||||||
STRIPE
|
STRIPE
|
||||||
|
.It
|
||||||
|
VIRSTOR
|
||||||
.El
|
.El
|
||||||
.Sh ENVIRONMENT
|
.Sh ENVIRONMENT
|
||||||
The following environment variables affect the execution of
|
The following environment variables affect the execution of
|
||||||
@ -161,7 +163,8 @@ geom md unload
|
|||||||
.Xr gnop 8 ,
|
.Xr gnop 8 ,
|
||||||
.Xr graid3 8 ,
|
.Xr graid3 8 ,
|
||||||
.Xr gshsec 8 ,
|
.Xr gshsec 8 ,
|
||||||
.Xr gstripe 8
|
.Xr gstripe 8 ,
|
||||||
|
.Xr gvirstor 8
|
||||||
.Sh HISTORY
|
.Sh HISTORY
|
||||||
The
|
The
|
||||||
.Nm
|
.Nm
|
||||||
|
@ -154,6 +154,7 @@ options GEOM_SHSEC # Shared secret.
|
|||||||
options GEOM_STRIPE # Disk striping.
|
options GEOM_STRIPE # Disk striping.
|
||||||
options GEOM_SUNLABEL # Sun/Solaris partitioning
|
options GEOM_SUNLABEL # Sun/Solaris partitioning
|
||||||
options GEOM_UZIP # Read-only compressed disks
|
options GEOM_UZIP # Read-only compressed disks
|
||||||
|
options GEOM_VIRSTOR # Virtual storage.
|
||||||
options GEOM_VOL # Volume names from UFS superblock
|
options GEOM_VOL # Volume names from UFS superblock
|
||||||
options GEOM_ZERO # Performance testing helper.
|
options GEOM_ZERO # Performance testing helper.
|
||||||
|
|
||||||
|
@ -1301,6 +1301,9 @@ geom/raid3/g_raid3_ctl.c optional geom_raid3
|
|||||||
geom/shsec/g_shsec.c optional geom_shsec
|
geom/shsec/g_shsec.c optional geom_shsec
|
||||||
geom/stripe/g_stripe.c optional geom_stripe
|
geom/stripe/g_stripe.c optional geom_stripe
|
||||||
geom/uzip/g_uzip.c optional geom_uzip
|
geom/uzip/g_uzip.c optional geom_uzip
|
||||||
|
geom/virstor/binstream.c optional geom_virstor
|
||||||
|
geom/virstor/g_virstor.c optional geom_virstor
|
||||||
|
geom/virstor/g_virstor_md.c optional geom_virstor
|
||||||
geom/zero/g_zero.c optional geom_zero
|
geom/zero/g_zero.c optional geom_zero
|
||||||
gnu/fs/ext2fs/ext2_alloc.c optional ext2fs \
|
gnu/fs/ext2fs/ext2_alloc.c optional ext2fs \
|
||||||
warning "kernel contains GPL contaminated ext2fs filesystem"
|
warning "kernel contains GPL contaminated ext2fs filesystem"
|
||||||
|
@ -96,6 +96,7 @@ GEOM_SHSEC opt_geom.h
|
|||||||
GEOM_STRIPE opt_geom.h
|
GEOM_STRIPE opt_geom.h
|
||||||
GEOM_SUNLABEL opt_geom.h
|
GEOM_SUNLABEL opt_geom.h
|
||||||
GEOM_UZIP opt_geom.h
|
GEOM_UZIP opt_geom.h
|
||||||
|
GEOM_VIRSTOR opt_geom.h
|
||||||
GEOM_VOL opt_geom.h
|
GEOM_VOL opt_geom.h
|
||||||
GEOM_ZERO opt_geom.h
|
GEOM_ZERO opt_geom.h
|
||||||
KSE opt_global.h
|
KSE opt_global.h
|
||||||
|
185
sys/geom/virstor/binstream.c
Normal file
185
sys/geom/virstor/binstream.c
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2005 Ivan Voras <ivoras@gmail.com>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// $Id: binstream.c,v 1.1 2006/07/05 10:47:54 ivoras Exp $
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <sys/endian.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
#include <geom/virstor/binstream.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* "Open" a binary stream for reading */
|
||||||
|
void
|
||||||
|
bs_open(bin_stream_t * bs, void *data)
|
||||||
|
{
|
||||||
|
bs->data = (char *)data;
|
||||||
|
bs->pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* "Reset" position in binary stream to zero */
|
||||||
|
void
|
||||||
|
bs_reset(bin_stream_t * bs)
|
||||||
|
{
|
||||||
|
bs->pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write a zero-terminated string; return next position */
|
||||||
|
unsigned
|
||||||
|
bs_write_str(bin_stream_t * bs, char *data)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
do {
|
||||||
|
*(bs->data + bs->pos + len) = *data;
|
||||||
|
len++;
|
||||||
|
} while (*(data++) != '\0');
|
||||||
|
bs->pos += len;
|
||||||
|
return bs->pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Write an arbitrary buffer; return next position */
|
||||||
|
unsigned
|
||||||
|
bs_write_buf(bin_stream_t * bs, char *data, unsigned data_size)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < data_size; i++)
|
||||||
|
*(bs->data + bs->pos + i) = *(data + i);
|
||||||
|
bs->pos += data_size;
|
||||||
|
return bs->pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Write a 8bit uint; return next position. */
|
||||||
|
unsigned
|
||||||
|
bs_write_u8(bin_stream_t * bs, uint8_t data)
|
||||||
|
{
|
||||||
|
*((uint8_t *) (bs->data + bs->pos)) = data;
|
||||||
|
return ++(bs->pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Write a 16bit uint; return next position. */
|
||||||
|
unsigned
|
||||||
|
bs_write_u16(bin_stream_t * bs, uint16_t data)
|
||||||
|
{
|
||||||
|
le16enc(bs->data + bs->pos, data);
|
||||||
|
return (bs->pos += 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Write a 32bit uint; return next position. */
|
||||||
|
unsigned
|
||||||
|
bs_write_u32(bin_stream_t * bs, uint32_t data)
|
||||||
|
{
|
||||||
|
le32enc(bs->data + bs->pos, data);
|
||||||
|
return (bs->pos += 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Write a 64bit uint; return next position. */
|
||||||
|
unsigned
|
||||||
|
bs_write_u64(bin_stream_t * bs, uint64_t data)
|
||||||
|
{
|
||||||
|
le64enc(bs->data + bs->pos, data);
|
||||||
|
return (bs->pos += 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Read a 8bit uint & return it */
|
||||||
|
uint8_t
|
||||||
|
bs_read_u8(bin_stream_t * bs)
|
||||||
|
{
|
||||||
|
uint8_t data = *((uint8_t *) (bs->data + bs->pos));
|
||||||
|
bs->pos++;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read a null-terminated string from stream into a buffer; buf_size is size
|
||||||
|
* of the buffer, including the final \0. Returns buf pointer or NULL if
|
||||||
|
* garbage input.
|
||||||
|
*/
|
||||||
|
char*
|
||||||
|
bs_read_str(bin_stream_t * bs, char *buf, unsigned buf_size)
|
||||||
|
{
|
||||||
|
unsigned len = 0;
|
||||||
|
char *work_buf = buf;
|
||||||
|
if (buf == NULL || buf_size < 1)
|
||||||
|
return NULL;
|
||||||
|
do {
|
||||||
|
*work_buf = *(bs->data + bs->pos + len);
|
||||||
|
} while (len++ < buf_size - 1 && *(work_buf++) != '\0');
|
||||||
|
*(buf + buf_size - 1) = '\0';
|
||||||
|
bs->pos += len;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Read an arbitrary buffer. */
|
||||||
|
void
|
||||||
|
bs_read_buf(bin_stream_t * bs, char *buf, unsigned buf_size)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < buf_size; i++)
|
||||||
|
*(buf + i) = *(bs->data + bs->pos + i);
|
||||||
|
bs->pos += buf_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Read a 16bit uint & return it */
|
||||||
|
uint16_t
|
||||||
|
bs_read_u16(bin_stream_t * bs)
|
||||||
|
{
|
||||||
|
uint16_t data = le16dec(bs->data + bs->pos);
|
||||||
|
bs->pos += 2;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Read a 32bit uint & return it */
|
||||||
|
uint32_t
|
||||||
|
bs_read_u32(bin_stream_t * bs)
|
||||||
|
{
|
||||||
|
uint32_t data = le32dec(bs->data + bs->pos);
|
||||||
|
bs->pos += 4;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Read a 64bit uint & return it */
|
||||||
|
uint64_t
|
||||||
|
bs_read_u64(bin_stream_t * bs)
|
||||||
|
{
|
||||||
|
uint64_t data = le64dec(bs->data + bs->pos);
|
||||||
|
bs->pos += 8;
|
||||||
|
return data;
|
||||||
|
}
|
93
sys/geom/virstor/binstream.h
Normal file
93
sys/geom/virstor/binstream.h
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2005 Ivan Voras <ivoras@gmail.com>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $FreeBSD$
|
||||||
|
*/
|
||||||
|
|
||||||
|
// $Id: binstream.h,v 1.1 2006/07/05 10:47:54 ivoras Exp $
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _BIN_STREAM_
|
||||||
|
#define _BIN_STREAM_
|
||||||
|
|
||||||
|
#ifndef uint8_t
|
||||||
|
#define uint8_t unsigned char
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned char *data;
|
||||||
|
int pos;
|
||||||
|
} bin_stream_t;
|
||||||
|
|
||||||
|
|
||||||
|
/* "Open" a binary stream for reading */
|
||||||
|
void bs_open (bin_stream_t * bs, void *data);
|
||||||
|
|
||||||
|
/* "Reset" position in binary stream to zero */
|
||||||
|
void bs_reset (bin_stream_t * bs);
|
||||||
|
|
||||||
|
|
||||||
|
/* Write a zero-terminated string; return next position */
|
||||||
|
unsigned bs_write_str(bin_stream_t * bs, char *data);
|
||||||
|
|
||||||
|
/* Write an arbitrary buffer; return next position */
|
||||||
|
unsigned bs_write_buf(bin_stream_t * bs, char *data, unsigned data_size);
|
||||||
|
|
||||||
|
/* Write a 8bit uint; return next position. */
|
||||||
|
unsigned bs_write_u8(bin_stream_t * bs, uint8_t data);
|
||||||
|
|
||||||
|
/* Write a 16bit uint; return next position. */
|
||||||
|
unsigned bs_write_u16(bin_stream_t * bs, uint16_t data);
|
||||||
|
|
||||||
|
/* Write a 32bit uint; return next position. */
|
||||||
|
unsigned bs_write_u32(bin_stream_t * bs, uint32_t data);
|
||||||
|
|
||||||
|
/* Write a 64bit uint; return next position. */
|
||||||
|
unsigned bs_write_u64(bin_stream_t * bs, uint64_t data);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read a null-terminated string from stream into a buffer; buf_size is size
|
||||||
|
* of the buffer, including the final \0. Returns buf pointer or NULL if
|
||||||
|
* garbage input.
|
||||||
|
*/
|
||||||
|
char *bs_read_str(bin_stream_t * bs, char *buf, unsigned buf_size);
|
||||||
|
|
||||||
|
/* Read an arbitrary buffer. */
|
||||||
|
void bs_read_buf(bin_stream_t * bs, char *buf, unsigned buf_size);
|
||||||
|
|
||||||
|
/* Read a 8bit uint * return it */
|
||||||
|
uint8_t bs_read_u8(bin_stream_t * bs);
|
||||||
|
|
||||||
|
/* Read a 16bit uint * return it */
|
||||||
|
uint16_t bs_read_u16(bin_stream_t * bs);
|
||||||
|
|
||||||
|
/* Read a 8bit uint * return it */
|
||||||
|
uint32_t bs_read_u32(bin_stream_t * bs);
|
||||||
|
|
||||||
|
/* Read a 8bit uint * return it */
|
||||||
|
uint64_t bs_read_u64(bin_stream_t * bs);
|
||||||
|
|
||||||
|
#endif
|
1864
sys/geom/virstor/g_virstor.c
Normal file
1864
sys/geom/virstor/g_virstor.c
Normal file
File diff suppressed because it is too large
Load Diff
135
sys/geom/virstor/g_virstor.h
Normal file
135
sys/geom/virstor/g_virstor.h
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2006-2007 Ivan Voras <ivoras@freebsd.org>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $FreeBSD$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _G_VIRSTOR_H_
|
||||||
|
#define _G_VIRSTOR_H_
|
||||||
|
|
||||||
|
#define G_VIRSTOR_CLASS_NAME "VIRSTOR"
|
||||||
|
|
||||||
|
|
||||||
|
#define VIRSTOR_MAP_ALLOCATED 1
|
||||||
|
struct virstor_map_entry {
|
||||||
|
uint16_t flags;
|
||||||
|
uint16_t provider_no;
|
||||||
|
uint32_t provider_chunk;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define VIRSTOR_MAP_ENTRY_SIZE (sizeof(struct virstor_map_entry))
|
||||||
|
#define VIRSTOR_MAP_BLOCK_ENTRIES (MAXPHYS / VIRSTOR_MAP_ENTRY_SIZE)
|
||||||
|
/* Struct size is guarded by CTASSERT in main source */
|
||||||
|
|
||||||
|
#ifdef _KERNEL
|
||||||
|
|
||||||
|
#define LOG_MSG(lvl, ...) do { \
|
||||||
|
if (g_virstor_debug >= (lvl)) { \
|
||||||
|
printf("GEOM_" G_VIRSTOR_CLASS_NAME); \
|
||||||
|
if (lvl > 0) \
|
||||||
|
printf("[%u]", lvl); \
|
||||||
|
printf(": "); \
|
||||||
|
printf(__VA_ARGS__); \
|
||||||
|
printf("\n"); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#define LOG_MESSAGE LOG_MSG
|
||||||
|
|
||||||
|
#define LOG_REQ(lvl, bp, ...) do { \
|
||||||
|
if (g_virstor_debug >= (lvl)) { \
|
||||||
|
printf("GEOM_" G_VIRSTOR_CLASS_NAME); \
|
||||||
|
if (lvl > 0) \
|
||||||
|
printf("[%u]", lvl); \
|
||||||
|
printf(": "); \
|
||||||
|
printf(__VA_ARGS__); \
|
||||||
|
printf(" "); \
|
||||||
|
g_print_bio(bp); \
|
||||||
|
printf("\n"); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#define LOG_REQUEST LOG_REQ
|
||||||
|
|
||||||
|
/* "critical" system announcements (e.g. "geom is up") */
|
||||||
|
#define LVL_ANNOUNCE 0
|
||||||
|
/* errors */
|
||||||
|
#define LVL_ERROR 1
|
||||||
|
/* warnings */
|
||||||
|
#define LVL_WARNING 2
|
||||||
|
/* info, noncritical for system operation (user doesn't have to see it */
|
||||||
|
#define LVL_INFO 5
|
||||||
|
/* debug info */
|
||||||
|
#define LVL_DEBUG 10
|
||||||
|
/* more debug info */
|
||||||
|
#define LVL_DEBUG2 12
|
||||||
|
/* superfluous debug info (large volumes of data) */
|
||||||
|
#define LVL_MOREDEBUG 15
|
||||||
|
|
||||||
|
|
||||||
|
/* Component data */
|
||||||
|
struct g_virstor_component {
|
||||||
|
struct g_consumer *gcons;
|
||||||
|
struct g_virstor_softc *sc;
|
||||||
|
unsigned int index; /* Component index in array */
|
||||||
|
unsigned int chunk_count;
|
||||||
|
unsigned int chunk_next;
|
||||||
|
unsigned int chunk_reserved;
|
||||||
|
unsigned int flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Internal geom instance data */
|
||||||
|
struct g_virstor_softc {
|
||||||
|
struct g_geom *geom;
|
||||||
|
struct g_provider *provider;
|
||||||
|
struct g_virstor_component *components;
|
||||||
|
u_int n_components;
|
||||||
|
u_int curr_component; /* Component currently used */
|
||||||
|
uint32_t id; /* Unique ID of this geom */
|
||||||
|
off_t virsize; /* Total size of virstor */
|
||||||
|
off_t sectorsize;
|
||||||
|
size_t chunk_size;
|
||||||
|
size_t chunk_count; /* governs map_size */
|
||||||
|
struct virstor_map_entry *map;
|
||||||
|
size_t map_size; /* (in bytes) */
|
||||||
|
size_t map_sectors; /* Size of map in sectors */
|
||||||
|
size_t me_per_sector; /* # map entries in a sector */
|
||||||
|
STAILQ_HEAD(, g_virstor_bio_q) delayed_bio_q; /* Queue of delayed BIOs */
|
||||||
|
struct mtx delayed_bio_q_mtx;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* "delayed BIOs" Queue element */
|
||||||
|
struct g_virstor_bio_q {
|
||||||
|
struct bio *bio;
|
||||||
|
STAILQ_ENTRY(g_virstor_bio_q) linkage;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _KERNEL */
|
||||||
|
|
||||||
|
#ifndef _PATH_DEV
|
||||||
|
#define _PATH_DEV "/dev/"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* !_G_VIRSTOR_H_ */
|
91
sys/geom/virstor/g_virstor_md.c
Normal file
91
sys/geom/virstor/g_virstor_md.c
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2005 Ivan Voras <ivoras@freebsd.org>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/endian.h>
|
||||||
|
|
||||||
|
#include <geom/virstor/g_virstor_md.h>
|
||||||
|
#include <geom/virstor/binstream.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Encode data from g_virstor_metadata structure into a endian-independant
|
||||||
|
* byte stream.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
virstor_metadata_encode(struct g_virstor_metadata *md, unsigned char *data)
|
||||||
|
{
|
||||||
|
bin_stream_t bs;
|
||||||
|
|
||||||
|
bs_open(&bs, data);
|
||||||
|
|
||||||
|
bs_write_buf(&bs, md->md_magic, sizeof(md->md_magic));
|
||||||
|
bs_write_u32(&bs, md->md_version);
|
||||||
|
bs_write_buf(&bs, md->md_name, sizeof(md->md_name));
|
||||||
|
bs_write_u64(&bs, md->md_virsize);
|
||||||
|
bs_write_u32(&bs, md->md_chunk_size);
|
||||||
|
bs_write_u32(&bs, md->md_id);
|
||||||
|
bs_write_u16(&bs, md->md_count);
|
||||||
|
|
||||||
|
bs_write_buf(&bs, md->provider, sizeof(md->provider));
|
||||||
|
bs_write_u16(&bs, md->no);
|
||||||
|
bs_write_u64(&bs, md->provsize);
|
||||||
|
bs_write_u32(&bs, md->chunk_count);
|
||||||
|
bs_write_u32(&bs, md->chunk_next);
|
||||||
|
bs_write_u16(&bs, md->chunk_reserved);
|
||||||
|
bs_write_u16(&bs, md->flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decode data from endian-independant byte stream into g_virstor_metadata
|
||||||
|
* structure.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
virstor_metadata_decode(unsigned char *data, struct g_virstor_metadata *md)
|
||||||
|
{
|
||||||
|
bin_stream_t bs;
|
||||||
|
|
||||||
|
bs_open(&bs, (char *)(data));
|
||||||
|
|
||||||
|
bs_read_buf(&bs, md->md_magic, sizeof(md->md_magic));
|
||||||
|
md->md_version = bs_read_u32(&bs);
|
||||||
|
bs_read_buf(&bs, md->md_name, sizeof(md->md_name));
|
||||||
|
md->md_virsize = bs_read_u64(&bs);
|
||||||
|
md->md_chunk_size = bs_read_u32(&bs);
|
||||||
|
md->md_id = bs_read_u32(&bs);
|
||||||
|
md->md_count = bs_read_u16(&bs);
|
||||||
|
|
||||||
|
bs_read_buf(&bs, md->provider, sizeof(md->provider));
|
||||||
|
md->no = bs_read_u16(&bs);
|
||||||
|
md->provsize = bs_read_u64(&bs);
|
||||||
|
md->chunk_count = bs_read_u32(&bs);
|
||||||
|
md->chunk_next = bs_read_u32(&bs);
|
||||||
|
md->chunk_reserved = bs_read_u16(&bs);
|
||||||
|
md->flags = bs_read_u16(&bs);
|
||||||
|
}
|
69
sys/geom/virstor/g_virstor_md.h
Normal file
69
sys/geom/virstor/g_virstor_md.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2005 Ivan Voras <ivoras@gmail.com>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $FreeBSD$
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _G_VIRSTOR_MD_H_
|
||||||
|
#define _G_VIRSTOR_MD_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Metadata declaration
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define G_VIRSTOR_MAGIC "GEOM::VIRSTOR"
|
||||||
|
#define G_VIRSTOR_VERSION 1
|
||||||
|
|
||||||
|
/* flag: provider is allocated */
|
||||||
|
#define VIRSTOR_PROVIDER_ALLOCATED 1
|
||||||
|
/* flag: provider is currently being filled (usually it's the last
|
||||||
|
* provider with VIRSTOR_PROVIDER_ALLOCATED flag */
|
||||||
|
#define VIRSTOR_PROVIDER_CURRENT 2
|
||||||
|
|
||||||
|
struct g_virstor_metadata {
|
||||||
|
/* Data global to the virstor device */
|
||||||
|
char md_magic[16]; /* Magic value. */
|
||||||
|
uint32_t md_version; /* Version number. */
|
||||||
|
char md_name[16]; /* Device name (e.g. "mydata") */
|
||||||
|
uint32_t md_id; /* Unique ID. */
|
||||||
|
uint64_t md_virsize; /* Virtual device's size */
|
||||||
|
uint32_t md_chunk_size; /* Chunk size in bytes */
|
||||||
|
uint16_t md_count; /* Total number of providers */
|
||||||
|
|
||||||
|
/* Data local to this provider */
|
||||||
|
char provider[16]; /* Hardcoded provider name */
|
||||||
|
uint16_t no; /* Provider number/index */
|
||||||
|
uint64_t provsize; /* Provider's size */
|
||||||
|
uint32_t chunk_count; /* Number of chunks in this pr. */
|
||||||
|
uint32_t chunk_next; /* Next chunk to allocate */
|
||||||
|
uint16_t chunk_reserved; /* Count of "reserved" chunks */
|
||||||
|
uint16_t flags; /* Provider's flags */
|
||||||
|
};
|
||||||
|
|
||||||
|
void virstor_metadata_encode(struct g_virstor_metadata *md, unsigned char *data);
|
||||||
|
void virstor_metadata_decode(unsigned char *data, struct g_virstor_metadata *md);
|
||||||
|
|
||||||
|
#endif /* !_G_VIRSTOR_H_ */
|
8
sys/modules/geom/geom_virstor/Makefile
Normal file
8
sys/modules/geom/geom_virstor/Makefile
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# $FreeBSD$
|
||||||
|
|
||||||
|
.PATH: ${.CURDIR}/../../../geom/virstor
|
||||||
|
|
||||||
|
KMOD= geom_virstor
|
||||||
|
SRCS= g_virstor.c g_virstor_md.c binstream.c
|
||||||
|
|
||||||
|
.include <bsd.kmod.mk>
|
Loading…
Reference in New Issue
Block a user