diff options
author | pjd <pjd@FreeBSD.org> | 2007-05-06 01:17:46 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2007-05-06 01:17:46 +0000 |
commit | 06c3c94d09a055f50fea693c717aab29967eecfa (patch) | |
tree | 412b3c67aac60058064ece4d329e452193280558 | |
parent | 50b649402941efe6db99339a648cacd28c4e67bc (diff) | |
download | FreeBSD-src-06c3c94d09a055f50fea693c717aab29967eecfa.zip FreeBSD-src-06c3c94d09a055f50fea693c717aab29967eecfa.tar.gz |
Implement and document some utility functions that can be used to communicate
with GEOM providers.
OK'ed by: phk
-rw-r--r-- | lib/libgeom/Makefile | 12 | ||||
-rw-r--r-- | lib/libgeom/geom_util.c | 236 | ||||
-rw-r--r-- | lib/libgeom/libgeom.3 | 104 | ||||
-rw-r--r-- | lib/libgeom/libgeom.h | 11 |
4 files changed, 360 insertions, 3 deletions
diff --git a/lib/libgeom/Makefile b/lib/libgeom/Makefile index c64ce50..7535e1e 100644 --- a/lib/libgeom/Makefile +++ b/lib/libgeom/Makefile @@ -6,6 +6,7 @@ SRCS+= geom_getxml.c SRCS+= geom_stats.c SRCS+= geom_xml2tree.c SRCS+= geom_ctl.c +SRCS+= geom_util.c INCS= libgeom.h CFLAGS += -I${.CURDIR} @@ -31,6 +32,15 @@ MLINKS+= \ libgeom.3 gctl_rw_param.3 \ libgeom.3 gctl_issue.3 \ libgeom.3 gctl_free.3 \ - libgeom.3 gctl_dump.3 + libgeom.3 gctl_dump.3 \ + libgeom.3 g_close.3 \ + libgeom.3 g_delete.3 \ + libgeom.3 g_flush.3 \ + libgeom.3 g_get_ident.3 \ + libgeom.3 g_get_name.3 \ + libgeom.3 g_mediasize.3 \ + libgeom.3 g_open.3 \ + libgeom.3 g_open_by_ident.3 \ + libgeom.3 g_sectorsize.3 .include <bsd.lib.mk> diff --git a/lib/libgeom/geom_util.c b/lib/libgeom/geom_util.c new file mode 100644 index 0000000..fa7d89a --- /dev/null +++ b/lib/libgeom/geom_util.c @@ -0,0 +1,236 @@ +/*- + * Copyright (c) 2007 Pawel Jakub Dawidek <pjd@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/disk.h> +#include <sys/stat.h> + +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <stdint.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <paths.h> + +#include <libgeom.h> + +/* + * Open the given provider and at least check if this is a block device. + */ +int +g_open(const char *name, int write) +{ + char path[MAXPATHLEN]; + int fd; + + if (name[0] == '/') + strlcpy(path, name, sizeof(path)); + else + snprintf(path, sizeof(path), "%s%s", _PATH_DEV, name); + + fd = open(path, write ? O_RDWR : O_RDONLY); + if (fd == -1) + return (-1); + /* Let try to get sectorsize, which will prove it is a GEOM provider. */ + if (g_sectorsize(fd) == -1) { + close(fd); + errno = EFTYPE; + return (-1); + } + return (fd); +} + +int +g_close(int fd) +{ + + return (close(fd)); +} + +static int +g_ioctl_arg(int fd, unsigned long cmd, void *arg) +{ + int ret; + + if (arg != NULL) + ret = ioctl(fd, cmd, arg); + else + ret = ioctl(fd, cmd); + return (ret >= 0 ? 0 : -1); +} + +static int +g_ioctl(int fd, unsigned long cmd) +{ + + return (g_ioctl_arg(fd, cmd, NULL)); +} + +/* + * Return media size of the given provider. + */ +off_t +g_mediasize(int fd) +{ + off_t mediasize; + + if (g_ioctl_arg(fd, DIOCGMEDIASIZE, &mediasize) == -1) + mediasize = -1; + return (mediasize); +} + +/* + * Return sector size of the given provider. + */ +ssize_t +g_sectorsize(int fd) +{ + u_int sectorsize; + + if (g_ioctl_arg(fd, DIOCGSECTORSIZE, §orsize) == -1) + return (-1); + return ((ssize_t)sectorsize); +} + +/* + * Call BIO_FLUSH for the given provider. + */ +int +g_flush(int fd) +{ + + return (g_ioctl(fd, DIOCGFLUSH)); +} + +/* + * Call BIO_DELETE for the given range. + */ +int +g_delete(int fd, off_t offset, off_t length) +{ + off_t arg[2]; + + arg[0] = offset; + arg[1] = length; + return (g_ioctl_arg(fd, DIOCGDELETE, arg)); +} + +/* + * Return ID of the given provider. + */ +int +g_get_ident(int fd, char *ident, size_t size) +{ + char lident[DISK_IDENT_SIZE]; + + if (g_ioctl_arg(fd, DIOCGIDENT, lident) == -1) + return (-1); + if (lident[0] == '\0') { + errno = ENOENT; + return (-1); + } + if (strlcpy(ident, lident, size) >= size) { + errno = ENAMETOOLONG; + return (-1); + } + return (0); +} + +/* + * Return name of the provider, which has the given ID. + */ +int +g_get_name(const char *ident, char *name, size_t size) +{ + int fd; + + fd = g_open_by_ident(ident, 0, name, size); + if (fd == -1) + return (-1); + g_close(fd); + return (0); +} + +/* + * Find provider name by the given ID. + */ +int +g_open_by_ident(const char *ident, int write, char *name, size_t size) +{ + char lident[DISK_IDENT_SIZE]; + struct gmesh mesh; + struct gclass *mp; + struct ggeom *gp; + struct gprovider *pp; + int error, fd; + + error = geom_gettree(&mesh); + if (error != 0) { + errno = error; + return (-1); + } + + error = ENOENT; + fd = -1; + + LIST_FOREACH(mp, &mesh.lg_class, lg_class) { + LIST_FOREACH(gp, &mp->lg_geom, lg_geom) { + LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { + fd = g_open(pp->lg_name, write); + if (fd == -1) + continue; + if (g_get_ident(fd, lident, + sizeof(lident)) == -1) { + g_close(fd); + continue; + } + if (strcmp(ident, lident) != 0) { + g_close(fd); + continue; + } + error = 0; + if (name != NULL && strlcpy(name, pp->lg_name, + size) >= size) { + error = ENAMETOOLONG; + g_close(fd); + } + goto end; + } + } + } +end: + geom_deletetree(&mesh); + if (error != 0) { + errno = error; + return (-1); + } + return (fd); +} diff --git a/lib/libgeom/libgeom.3 b/lib/libgeom/libgeom.3 index 9172a00..bb67105 100644 --- a/lib/libgeom/libgeom.3 +++ b/lib/libgeom/libgeom.3 @@ -1,4 +1,5 @@ .\" Copyright (c) 2003 Poul-Henning Kamp +.\" Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org> .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -27,7 +28,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 7, 2004 +.Dd May 6, 2007 .Dt LIBGEOM 3 .Os .Sh NAME @@ -44,7 +45,16 @@ .Nm gctl_rw_param , .Nm gctl_issue , .Nm gctl_free , -.Nm gctl_dump +.Nm gctl_dump , +.Nm g_open , +.Nm g_close , +.Nm g_mediasize , +.Nm g_sectorsize , +.Nm g_flush , +.Nm g_delete , +.Nm g_get_ident , +.Nm g_get_name , +.Nm g_open_by_ident .Nd userland API library for kernel GEOM subsystem .Sh LIBRARY .Lb libgeom @@ -80,6 +90,25 @@ .Fn gctl_free "struct gctl_req *req" .Ft void .Fn gctl_dump "struct gctl_req *req" "FILE *f" +.Ss "Utility Functions" +.Ft int +.Fn g_open "const char *name" "int write" +.Ft int +.Fn g_close "int fd" +.Ft off_t +.Fn g_mediasize "int fd" +.Ft ssize_t +.Fn g_sectorsize "int fd" +.Ft int +.Fn g_flush "int fd" +.Ft int +.Fn g_delete "int fd" "off_t offset" "off_t length" +.Ft int +.Fn g_get_ident "int fd" "char *ident" "size_t size" +.Ft int +.Fn g_get_name "const char *ident" "char *name" "size_t size" +.Ft int +.Fn g_open_by_ident "const char *ident" "int write" "char *name" "size_t size" .Sh DESCRIPTION The .Nm geom @@ -232,6 +261,76 @@ which returns .Dv NULL on success, or an error message corresponding to the first error which happened. +.Ss "Utility Functions" +The +.Fn g_* +functions are used to communicate with GEOM providers. +.Pp +The +.Fn g_open +function opens the given provider and returns file descriptor number, which can +be used with other functions. +The +.Fa write +argument indicates if operations that modify the provider (like +.Fn g_flush +or +.Fn g_delete ) +are going to be called. +.Pp +The +.Fn g_close +function closes the provider. +.Pp +The +.Fn g_mediasize +function returns size of the given provider. +.Pp +The +.Fn g_sectorsize +function returns sector size of the given provider. +.Pp +The +.Fn g_flush +function sends +.Dv BIO_FLUSH +request to flush write cache of the provider. +.Pp +The +.Fn g_delete +function tells the provider that the given data range is no longer used. +.Pp +The +.Fn g_get_ident +function returns provider's fixed and unique identifier. +The +.Fa ident +argument should be at least +.Dv DISK_IDENT_SIZE +big. +.Pp +The +.Fn g_get_name +function returns name of the provider, which identifier is equal to the +.Fa ident +string. +.Pp +The +.Fn g_open_by_ident +function opens provider using its ident, unlike +.Fn g_open +which uses provider's name. +If the +.Fa name +argument is not +.Dv NULL , +the function will store provider's name there. +.Pp +All functions return value greater than or equal to +.Va 0 +on success or +.Va -1 +on failure. .Sh EXAMPLES Create a request that is to be sent to the CCD class, and tell it to destroy a specific geom: @@ -256,3 +355,4 @@ library appeared in .Sh AUTHORS .An Poul-Henning Kamp Aq phk@FreeBSD.org .An Lukas Ertl Aq le@FreeBSD.org +.An Pawel Jakub Dawidek pjd@FreeBSD.org diff --git a/lib/libgeom/libgeom.h b/lib/libgeom/libgeom.h index 2cdb037..dc4bbba 100644 --- a/lib/libgeom/libgeom.h +++ b/lib/libgeom/libgeom.h @@ -144,6 +144,17 @@ const char *gctl_issue(struct gctl_req *req); void gctl_ro_param(struct gctl_req *req, const char *name, int len, const void* val); void gctl_rw_param(struct gctl_req *req, const char *name, int len, void* val); +/* geom_util.c */ +int g_open(const char *name, int write); +int g_close(int fd); +off_t g_mediasize(int fd); +ssize_t g_sectorsize(int fd); +int g_flush(int fd); +int g_delete(int fd, off_t offset, off_t length); +int g_get_ident(int fd, char *ident, size_t size); +int g_get_name(const char *ident, char *name, size_t size); +int g_open_by_ident(const char *ident, int write, char *name, size_t size); + __END_DECLS #endif /* _LIBGEOM_H_ */ |