Date: Wed, 26 Nov 2014 00:06:22 +0000 (UTC) From: Marcel Moolenaar <marcel@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r275090 - user/marcel/libvdsk/libvdsk Message-ID: <201411260006.sAQ06Muf071084@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: marcel Date: Wed Nov 26 00:06:21 2014 New Revision: 275090 URL: https://svnweb.freebsd.org/changeset/base/275090 Log: Rewrite the raw disk support as a file format. This involves: 1. Defining a structure to represent a file format, 2. Implement an ordered probe to match formats to opened files, 3. Move calls to preadv(2), pwritev(2) and fsync(2) in the API functions into the format-specific methods, 4. Change the API functions into thin wrappers around the methods. The ordered probe combines priority with capability. The priority is based on the presence and location of metadata. The capabilities are for writing and support for device special files. The intend is to have the raw format probe as a last resort as ithere's no metadata associated with the format. Added: user/marcel/libvdsk/libvdsk/raw.c (contents, props changed) Modified: user/marcel/libvdsk/libvdsk/Makefile user/marcel/libvdsk/libvdsk/vdsk.c user/marcel/libvdsk/libvdsk/vdsk_int.h Modified: user/marcel/libvdsk/libvdsk/Makefile ============================================================================== --- user/marcel/libvdsk/libvdsk/Makefile Tue Nov 25 23:01:01 2014 (r275089) +++ user/marcel/libvdsk/libvdsk/Makefile Wed Nov 26 00:06:21 2014 (r275090) @@ -6,6 +6,10 @@ SHLIB_MAJOR= 0 SRCS= vdsk.c INCS= vdsk.h +# List of formats to support +SRCS+= \ + raw.c + DEBUG_FLAGS=-O0 -gdwarf-2 .include <bsd.lib.mk> Added: user/marcel/libvdsk/libvdsk/raw.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/marcel/libvdsk/libvdsk/raw.c Wed Nov 26 00:06:21 2014 (r275090) @@ -0,0 +1,103 @@ +/*- + * Copyright (c) 2014 Marcel Moolenaar + * 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 AUTHOR 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 AUTHOR 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/disk.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <errno.h> +#include <fcntl.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <vdsk.h> + +#include "vdsk_int.h" + +static int +raw_probe(struct vdsk *vdsk __unused) +{ + + return (0); +} + +static int +raw_open(struct vdsk *vdsk __unused) +{ + + return (0); +} + +static int +raw_close(struct vdsk *vdsk __unused) +{ + + return (0); +} + +static int +raw_read(struct vdsk *vdsk, const struct iovec *iov, int iovcnt, off_t offset) +{ + ssize_t res; + + res = preadv(vdsk->fd, iov, iovcnt, offset); + return ((res == -1) ? errno : 0); +} + +static int +raw_write(struct vdsk *vdsk, const struct iovec *iov, int iovcnt, off_t offset) +{ + ssize_t res; + + res = pwritev(vdsk->fd, iov, iovcnt, offset); + return ((res == -1) ? errno : 0); +} + +static int +raw_flush(struct vdsk *vdsk) +{ + int res; + + res = fsync(vdsk->fd); + return ((res == -1) ? errno : 0); +} + +static struct vdsk_format raw_format = { + .name = "raw", + .description = "Raw Disk File or Device", + .flags = VDSKFMT_CAN_WRITE | VDSKFMT_DEVICE_OK | VDSKFMT_NO_METADATA, + .probe = raw_probe, + .open = raw_open, + .close = raw_close, + .read = raw_read, + .write = raw_write, + .flush = raw_flush, +}; +FORMAT_DEFINE(raw_format); + Modified: user/marcel/libvdsk/libvdsk/vdsk.c ============================================================================== --- user/marcel/libvdsk/libvdsk/vdsk.c Tue Nov 25 23:01:01 2014 (r275089) +++ user/marcel/libvdsk/libvdsk/vdsk.c Wed Nov 26 00:06:21 2014 (r275090) @@ -40,6 +40,13 @@ __FBSDID("$FreeBSD$"); #include "vdsk_int.h" +static inline int +vdsk_is_dev(struct vdsk *vdsk) +{ + + return ((S_ISCHR(vdsk->fsbuf.st_mode)) ? 1 : 0); +} + static struct vdsk * vdsk_deref(vdskctx ctx) { @@ -48,6 +55,34 @@ vdsk_deref(vdskctx ctx) return (vdsk - 1); } +static struct vdsk_format * +vdsk_probe(struct vdsk *vdsk) +{ + struct vdsk_format *f, *fmt, **f_iter; + int error, probe; + + fmt = NULL; + probe = VDSKFMT_HAS_HEADER | VDSKFMT_HAS_FOOTER; + probe |= (vdsk_is_dev(vdsk)) ? VDSKFMT_DEVICE_OK : 0; + probe |= (vdsk->fflags & FWRITE) ? VDSKFMT_CAN_WRITE : 0; + while (fmt == NULL && probe >= 0) { + SET_FOREACH(f_iter, libvdsk_formats) { + f = *f_iter; + if ((f->flags & probe) != probe) + continue; + error = f->probe(vdsk); + if (!error) { + fmt = f; + break; + } + } + probe -= VDSKFMT_HAS_FOOTER; + } + if (fmt == NULL) + errno = EFTYPE; + return (fmt); +} + vdskctx vdsk_open(const char *path, int flags, size_t size) { @@ -81,7 +116,7 @@ vdsk_open(const char *path, int flags, s if (fstat(vdsk->fd, &vdsk->fsbuf) == -1) break; - if (S_ISCHR(vdsk->fsbuf.st_mode)) { + if (vdsk_is_dev(vdsk)) { if (ioctl(vdsk->fd, DIOCGMEDIASIZE, &vdsk->capacity) < 0) break; @@ -93,10 +128,20 @@ vdsk_open(const char *path, int flags, s vdsk->sectorsize = DEV_BSIZE; } + vdsk->fmt = vdsk_probe(vdsk); + if (vdsk->fmt == NULL) + break; + lck = (vdsk->fflags & FWRITE) ? LOCK_EX : LOCK_SH; if (flock(vdsk->fd, lck | LOCK_NB) == -1) break; + errno = vdsk->fmt->open(vdsk); + if (errno != 0) { + flock(vdsk->fd, LOCK_UN); + break; + } + /* Complete... */ ctx = vdsk + 1; } while (0); @@ -119,6 +164,7 @@ vdsk_close(vdskctx ctx) { struct vdsk *vdsk = vdsk_deref(ctx); + vdsk->fmt->close(vdsk); flock(vdsk->fd, LOCK_UN); close(vdsk->fd); free(vdsk->filename); @@ -146,29 +192,27 @@ int vdsk_read(vdskctx ctx, const struct iovec *iov, int iovcnt, off_t offset) { struct vdsk *vdsk = vdsk_deref(ctx); - ssize_t res; - res = preadv(vdsk->fd, iov, iovcnt, offset); - return ((res == -1) ? errno : 0); + return (vdsk->fmt->read(vdsk, iov, iovcnt, offset)); } int vdsk_write(vdskctx ctx, const struct iovec *iov, int iovcnt, off_t offset) { struct vdsk *vdsk = vdsk_deref(ctx); - ssize_t res; - res = pwritev(vdsk->fd, iov, iovcnt, offset); - return ((res == -1) ? errno : 0); + if ((vdsk->fflags & FWRITE) == 0) + return (EROFS); + return (vdsk->fmt->write(vdsk, iov, iovcnt, offset)); } int vdsk_flush(vdskctx ctx) { struct vdsk *vdsk = vdsk_deref(ctx); - int res; - res = fsync(vdsk->fd); - return ((res == -1) ? errno : 0); + if ((vdsk->fflags & FWRITE) == 0) + return (0); + return (vdsk->fmt->flush(vdsk)); } Modified: user/marcel/libvdsk/libvdsk/vdsk_int.h ============================================================================== --- user/marcel/libvdsk/libvdsk/vdsk_int.h Tue Nov 25 23:01:01 2014 (r275089) +++ user/marcel/libvdsk/libvdsk/vdsk_int.h Wed Nov 26 00:06:21 2014 (r275090) @@ -29,7 +29,38 @@ #ifndef __VDSK_INT_H__ #define __VDSK_INT_H__ +#include <sys/linker_set.h> + +struct vdsk; + +/* + * The disk format registration structure. + */ +struct vdsk_format { + const char *name; + const char *description; + int flags; +#define VDSKFMT_DEVICE_OK 1 +#define VDSKFMT_CAN_WRITE 2 +#define VDSKFMT_NO_METADATA 0 +#define VDSKFMT_HAS_FOOTER 4 +#define VDSKFMT_HAS_HEADER 8 + int (*probe)(struct vdsk *); + int (*open)(struct vdsk *); + int (*close)(struct vdsk *); + int (*read)(struct vdsk *, const struct iovec *, int, off_t); + int (*write)(struct vdsk *, const struct iovec *, int, off_t); + int (*flush)(struct vdsk *); +}; + +SET_DECLARE(libvdsk_formats, struct vdsk_format); +#define FORMAT_DEFINE(nm) DATA_SET(libvdsk_formats, nm) + +/* + * The internal representation of a "disk". + */ struct vdsk { + struct vdsk_format *fmt; int fd; int fflags; char *filename;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201411260006.sAQ06Muf071084>