Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/vndcompress Abstract handling of the cloop2 offset t...



details:   https://anonhg.NetBSD.org/src/rev/5be4ee53f924
branches:  trunk
changeset: 326193:5be4ee53f924
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Wed Jan 22 06:14:46 2014 +0000

description:
Abstract handling of the cloop2 offset table.

Preparation for converting it to use a fixed-size window.

diffstat:

 usr.bin/vndcompress/Makefile        |    2 +-
 usr.bin/vndcompress/offtab.c        |  284 ++++++++++++++++++++++++++++++++++++
 usr.bin/vndcompress/offtab.h        |   72 +++++++++
 usr.bin/vndcompress/vndcompress.c   |  132 ++++++----------
 usr.bin/vndcompress/vnduncompress.c |   58 ++++--
 5 files changed, 441 insertions(+), 107 deletions(-)

diffs (truncated from 789 to 300 lines):

diff -r bbf20c8d6d00 -r 5be4ee53f924 usr.bin/vndcompress/Makefile
--- a/usr.bin/vndcompress/Makefile      Wed Jan 22 06:14:28 2014 +0000
+++ b/usr.bin/vndcompress/Makefile      Wed Jan 22 06:14:46 2014 +0000
@@ -1,5 +1,5 @@
 PROG=  vndcompress
-SRCS=  main.c utils.c vndcompress.c vnduncompress.c
+SRCS=  main.c offtab.c utils.c vndcompress.c vnduncompress.c
 
 LINKS= ${BINDIR}/vndcompress ${BINDIR}/vnduncompress
 MLINKS=        vndcompress.1 vnduncompress.1
diff -r bbf20c8d6d00 -r 5be4ee53f924 usr.bin/vndcompress/offtab.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/usr.bin/vndcompress/offtab.c      Wed Jan 22 06:14:46 2014 +0000
@@ -0,0 +1,284 @@
+/*     $NetBSD: offtab.c,v 1.1 2014/01/22 06:14:46 riastradh Exp $     */
+
+/*-
+ * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Taylor R. Campbell.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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>
+__RCSID("$NetBSD");
+
+#include <sys/types.h>
+#include <sys/endian.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "utils.h"
+
+#include "offtab.h"
+
+static void __printflike(1,2)
+offtab_bug(const char *fmt, ...)
+{
+
+       errx(1, "bug in offtab, please report");
+}
+
+static void __printflike(1,2)
+offtab_bugx(const char *fmt, ...)
+{
+
+       errx(1, "bug in offtab, please report");
+}
+
+/*
+ * Initialize an offtab to support the specified number of offsets read
+ * to or written from fd at byte position fdpos.
+ */
+void
+offtab_init(struct offtab *offtab, uint32_t n_offsets, int fd, off_t fdpos)
+{
+
+       assert(offtab != NULL);
+       assert(0 < n_offsets);
+       assert(0 <= fd);
+       assert(0 <= fdpos);
+
+       offtab->ot_n_offsets = n_offsets;
+       __CTASSERT(MAX_N_OFFSETS <= (SIZE_MAX / sizeof(uint64_t)));
+       offtab->ot_offsets = malloc(n_offsets * sizeof(uint64_t));
+       if (offtab->ot_offsets == NULL)
+               err(1, "malloc offset table");
+       offtab->ot_blkno = (uint32_t)-1;
+       offtab->ot_fd = fd;
+       offtab->ot_fdpos = fdpos;
+       offtab->ot_report = &offtab_bug;
+       offtab->ot_reportx = &offtab_bugx;
+       offtab->ot_mode = OFFTAB_MODE_NONE;
+}
+
+/*
+ * Destroy an offtab.
+ */
+void
+offtab_destroy(struct offtab *offtab)
+{
+
+       free(offtab->ot_offsets);
+}
+
+/*
+ * For an offtab that has been used to read data from disk, convert it
+ * to an offtab that can be used to write subsequent data to disk.
+ */
+void
+offtab_transmogrify_read_to_write(struct offtab *offtab)
+{
+
+       assert(offtab->ot_mode == OFFTAB_MODE_READ);
+       assert(offtab->ot_offsets[0] == htobe64(offtab->ot_fdpos +
+           (offtab->ot_n_offsets * sizeof(uint64_t))));
+       offtab->ot_mode = OFFTAB_MODE_WRITE;
+}
+
+/*
+ * Reset an offtab for reading an offset table from the beginning.
+ * Initializes in-memory state and may read data from offtab->ot_fd,
+ * which must currently be at byte position offtab->ot_fdpos.  Failure
+ * will be reported by the report/reportx routines, which are called
+ * like warn/warnx.  May fail; returns true on success, false on
+ * failure.
+ */
+bool
+offtab_reset_read(struct offtab *offtab,
+    void (*report)(const char *, ...) __printflike(1,2),
+    void (*reportx)(const char *, ...) __printflike(1,2))
+{
+
+       assert((lseek(offtab->ot_fd, 0, SEEK_CUR) == offtab->ot_fdpos) ||
+           ((lseek(offtab->ot_fd, 0, SEEK_CUR) == -1) && (errno == ESPIPE)));
+
+       offtab->ot_report = report;
+       offtab->ot_reportx = reportx;
+       offtab->ot_mode = OFFTAB_MODE_READ;
+
+       const ssize_t n_read = read_block(offtab->ot_fd, offtab->ot_offsets,
+           (offtab->ot_n_offsets * sizeof(uint64_t)));
+       if (n_read == -1) {
+               (*offtab->ot_report)("read offset table");
+               return false;
+       }
+       assert(n_read >= 0);
+       if ((size_t)n_read != (offtab->ot_n_offsets * sizeof(uint64_t))) {
+               (*offtab->ot_reportx)("partial read of offset table"
+                   ": %zu != %zu",
+                   (size_t)n_read,
+                   (size_t)(offtab->ot_n_offsets * sizeof(uint64_t)));
+               return false;
+       }
+
+       return true;
+}
+
+/*
+ * Do any I/O or bookkeeping necessary to fetch the offset for blkno in
+ * preparation for a call to offtab_get.  May fail; returns true on
+ * success, false on failure.
+ */
+bool
+offtab_prepare_get(struct offtab *offtab, uint32_t blkno)
+{
+
+       assert(offtab->ot_mode == OFFTAB_MODE_READ);
+       assert(blkno < offtab->ot_n_offsets);
+       offtab->ot_blkno = blkno;
+       return true;
+}
+
+/*
+ * Return the offset for blkno.  Caller must have called
+ * offtab_prepare_get beforehand.
+ */
+uint64_t
+offtab_get(struct offtab *offtab, uint32_t blkno)
+{
+
+       assert(offtab->ot_mode == OFFTAB_MODE_READ);
+       assert(blkno < offtab->ot_n_offsets);
+       assert(blkno == offtab->ot_blkno);
+       return be64toh(offtab->ot_offsets[blkno]);
+}
+
+/*
+ * Reset offtab for writing a fresh offset table.  Initializes
+ * in-memory state and writes an empty offset table to offtab->ot_fd,
+ * which must currently be at byte position offtab->ot_fdpos.  May
+ * fail; returns on success, aborts with err(3) on failure.
+ */
+void
+offtab_reset_write(struct offtab *offtab)
+{
+       uint32_t i;
+
+       assert(lseek(offtab->ot_fd, 0, SEEK_CUR) == offtab->ot_fdpos);
+
+       offtab->ot_mode = OFFTAB_MODE_WRITE;
+
+       /*
+        * Initialize the offset table to all ones (except for the
+        * fixed first offset) so that we can easily detect where we
+        * were interrupted if we want to restart.
+        */
+       __CTASSERT(MAX_N_OFFSETS <= UINT32_MAX);
+       assert(offtab->ot_n_offsets > 0);
+       offtab->ot_offsets[0] = htobe64(offtab->ot_fdpos +
+           (offtab->ot_n_offsets * sizeof(uint64_t)));
+       for (i = 1; i < offtab->ot_n_offsets; i++)
+               offtab->ot_offsets[i] = ~(uint64_t)0;
+
+       /* Write the initial (empty) offset table.  */
+       const ssize_t n_written = write(offtab->ot_fd, offtab->ot_offsets,
+           (offtab->ot_n_offsets * sizeof(uint64_t)));
+       if (n_written == -1)
+               err(1, "write initial offset table");
+       assert(n_written >= 0);
+       if ((size_t)n_written != (offtab->ot_n_offsets * sizeof(uint64_t)))
+               errx(1, "partial write of initial offset bytes: %zu <= %zu",
+                   (size_t)n_written,
+                   (size_t)(offtab->ot_n_offsets * sizeof(uint64_t)));
+}
+
+/*
+ * Guarantee that the disk reflects block offsets [0, n_offsets).  If
+ * OFFTAB_CHECKPOINT_SYNC is set in flags, will also fsync the entire
+ * offset table.  May fail; returns on success, aborts with err(3) on
+ * failure.  Fsync failure is considered success but is reported with a
+ * warning.
+ *
+ * This routine does not write state in memory, and does not read state
+ * that is not signal-safe.  The only state read is static for the
+ * existence of the offset table.
+ */
+void
+offtab_checkpoint(struct offtab *offtab, uint32_t n_offsets, int flags)
+{
+
+       assert(offtab->ot_mode == OFFTAB_MODE_WRITE);
+       assert(n_offsets <= offtab->ot_n_offsets);
+
+       const ssize_t n_written = pwrite(offtab->ot_fd, offtab->ot_offsets,
+           (n_offsets * sizeof(uint64_t)), offtab->ot_fdpos);
+       if (n_written == -1)
+               err_ss(1, "write partial offset table");
+       assert(n_written >= 0);
+       if ((size_t)n_written != (n_offsets * sizeof(uint64_t)))
+               errx_ss(1, "partial write of partial offset table: %zu != %zu",
+                   (size_t)n_written,
+                   (size_t)(n_offsets * sizeof(uint64_t)));
+
+       if (ISSET(flags, OFFTAB_CHECKPOINT_SYNC)) {
+               if (fsync_range(offtab->ot_fd, (FFILESYNC | FDISKSYNC),
+                       offtab->ot_fdpos,
+                       (offtab->ot_fdpos + (n_offsets * (sizeof(uint64_t)))))
+                   == -1)
+                       warn_ss("fsync of offset table failed");
+       }
+}
+
+/*
+ * Do any I/O or bookkeeping necessary to set an offset for blkno.  May
+ * fail; returns on success, aborts with err(3) on failure.
+ */
+void
+offtab_prepare_put(struct offtab *offtab, uint32_t blkno)
+{
+
+       assert(offtab->ot_mode == OFFTAB_MODE_WRITE);
+       assert(blkno < offtab->ot_n_offsets);
+       offtab->ot_blkno = blkno;
+}
+
+/*
+ * Actually set the offset for blkno.
+ */
+void
+offtab_put(struct offtab *offtab, uint32_t blkno, uint64_t offset)
+{
+
+       assert(offtab->ot_mode == OFFTAB_MODE_WRITE);
+       assert(blkno < offtab->ot_n_offsets);
+       assert(blkno == offtab->ot_blkno);
+       offtab->ot_offsets[blkno] = htobe64(offset);
+}
diff -r bbf20c8d6d00 -r 5be4ee53f924 usr.bin/vndcompress/offtab.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000



Home | Main Index | Thread Index | Old Index