summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorMike Larkin <mlarkin@cvs.openbsd.org>2011-07-11 03:30:33 +0000
committerMike Larkin <mlarkin@cvs.openbsd.org>2011-07-11 03:30:33 +0000
commit327054b12b2159c4ee15475bc999f4e1f4f1c13e (patch)
treef0c76386a2854baa62514769310c814625fdde82 /sys/kern
parentb97e0a0488930c2f92fc845f40f67dcaee962660 (diff)
Add hibernate_read_block and fix a couple of typos in the previous commit.
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/subr_hibernate.c68
1 files changed, 67 insertions, 1 deletions
diff --git a/sys/kern/subr_hibernate.c b/sys/kern/subr_hibernate.c
index 1e01e618a8e..9e7b737c993 100644
--- a/sys/kern/subr_hibernate.c
+++ b/sys/kern/subr_hibernate.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: subr_hibernate.c,v 1.12 2011/07/09 03:10:27 mlarkin Exp $ */
+/* $OpenBSD: subr_hibernate.c,v 1.13 2011/07/11 03:30:32 mlarkin Exp $ */
/*
* Copyright (c) 2011 Ariane van der Steldt <ariane@stack.nl>
@@ -24,6 +24,9 @@
#include <sys/systm.h>
#include <sys/disklabel.h>
#include <sys/conf.h>
+#include <sys/buf.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
#include <uvm/uvm.h>
#include <machine/hibernate.h>
@@ -850,3 +853,66 @@ hibernate_compare_signature(union hibernate_info *mine,
return (0);
}
+/*
+ * hibernate_read_block
+ *
+ * Reads read_size blocks from the hibernate device specified in
+ * hib_info at offset blkctr. Output is placed into the vaddr specified
+ * at dest.
+ *
+ * Separate offsets and pages are used to handle misaligned reads (reads
+ * that span a page boundary).
+ *
+ * blkctr specifies a relative offset (relative to the start of swap),
+ * not an absolute disk offset
+ *
+ */
+int
+hibernate_read_block(union hibernate_info *hib_info, daddr_t blkctr,
+ size_t read_size, vaddr_t dest)
+{
+ struct buf *bp;
+ struct bdevsw *bdsw;
+ int error;
+
+ bp = geteblk(read_size);
+ bdsw = &bdevsw[major(hib_info->device)];
+
+ error = (*bdsw->d_open)(hib_info->device, FREAD, S_IFCHR, curproc);
+ if (error) {
+ printf("hibernate_read_block open failed\n");
+ return (1);
+ }
+
+ bp->b_bcount = read_size;
+ bp->b_blkno = blkctr;
+ CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
+ SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
+ bp->b_dev = hib_info->device;
+ bp->b_cylinder = 0;
+ (*bdsw->d_strategy)(bp);
+
+ error = biowait(bp);
+ if (error) {
+ printf("hibernate_read_block biowait failed %d\n", error);
+ error = (*bdsw->d_close)(hib_info->device, 0, S_IFCHR,
+ curproc);
+ if (error)
+ printf("hibernate_read_block error close failed\n");
+ return (1);
+ }
+
+ error = (*bdsw->d_close)(hib_info->device, FREAD, S_IFCHR, curproc);
+ if (error) {
+ printf("hibernate_read_block close failed\n");
+ return (1);
+ }
+
+ bcopy(bp->b_data, (caddr_t)dest, read_size);
+
+ bp->b_flags |= B_INVAL;
+ brelse(bp);
+
+ return (0);
+}
+