Skip site navigation (1)Skip section navigation (2)
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>