summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorderaadt <deraadt@openbsd.org>2013-11-06 12:06:56 +0000
committerderaadt <deraadt@openbsd.org>2013-11-06 12:06:56 +0000
commita16456879302ab3438e5eb9b74c29867bfa78a2a (patch)
treecb46433c0407aff778c0fd17d71be3dbd0538794
parentregen (diff)
downloadwireguard-openbsd-a16456879302ab3438e5eb9b74c29867bfa78a2a.tar.xz
wireguard-openbsd-a16456879302ab3438e5eb9b74c29867bfa78a2a.zip
teach the side-effect free drivers about the partition they are dealing
by passing a start/length in the HIB_INIT op. Then rebase all hibernate-time block offsets to be relative to the start of that partition. This simplifies things a lot. ok mlarkin
-rw-r--r--sys/dev/ata/ata_wdc.c13
-rw-r--r--sys/dev/ic/ahci.c11
-rw-r--r--sys/kern/subr_hibernate.c29
-rw-r--r--sys/sys/hibernate.h3
4 files changed, 35 insertions, 21 deletions
diff --git a/sys/dev/ata/ata_wdc.c b/sys/dev/ata/ata_wdc.c
index d31fe09007b..1f52488b1ae 100644
--- a/sys/dev/ata/ata_wdc.c
+++ b/sys/dev/ata/ata_wdc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ata_wdc.c,v 1.45 2013/01/17 02:36:45 deraadt Exp $ */
+/* $OpenBSD: ata_wdc.c,v 1.46 2013/11/06 12:06:58 deraadt Exp $ */
/* $NetBSD: ata_wdc.c,v 1.21 1999/08/09 09:43:11 bouyer Exp $ */
/*
@@ -121,6 +121,8 @@ wd_hibernate_io(dev_t dev, daddr_t blkno, vaddr_t addr, size_t size, int op, voi
struct wd_softc wd;
struct wdc_xfer xfer;
struct channel_softc chp;
+ daddr_t poffset;
+ size_t psize;
} *my = page;
struct wd_softc *real_wd, *wd = &my->wd;
struct wdc_xfer *xfer = &my->xfer;
@@ -129,8 +131,11 @@ wd_hibernate_io(dev_t dev, daddr_t blkno, vaddr_t addr, size_t size, int op, voi
extern struct cfdriver wd_cd;
/* early call for initialization */
- if (op == HIB_INIT)
+ if (op == HIB_INIT) {
+ my->poffset = blkno;
+ my->psize = size;
return(0);
+ }
real_wd = (struct wd_softc *)disk_lookup(&wd_cd, DISKUNIT(dev));
if (real_wd == NULL)
@@ -146,6 +151,10 @@ wd_hibernate_io(dev_t dev, daddr_t blkno, vaddr_t addr, size_t size, int op, voi
return (0);
}
+ if (blkno > my->psize)
+ return (E2BIG);
+ blkno += my->poffset;
+
/*
* Craft a fake set of softc and related structures
* which we think the driver modifies. Some of these will
diff --git a/sys/dev/ic/ahci.c b/sys/dev/ic/ahci.c
index c6524d50383..fe8b4168860 100644
--- a/sys/dev/ic/ahci.c
+++ b/sys/dev/ic/ahci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ahci.c,v 1.3 2013/07/09 17:53:46 deraadt Exp $ */
+/* $OpenBSD: ahci.c,v 1.4 2013/11/06 12:06:58 deraadt Exp $ */
/*
* Copyright (c) 2006 David Gwynne <dlg@openbsd.org>
@@ -3170,6 +3170,8 @@ ahci_hibernate_io(dev_t dev, daddr_t blkno, vaddr_t addr, size_t size,
struct ahci_ccb *ccb;
struct ahci_cmd_hdr *hdr_buf;
int pmp_port;
+ daddr_t poffset;
+ size_t psize;
} *my = page;
struct ata_fis_h2d *fis;
u_int32_t sector_count;
@@ -3189,6 +3191,9 @@ ahci_hibernate_io(dev_t dev, daddr_t blkno, vaddr_t addr, size_t size,
u_int64_t item_phys;
u_int32_t cmd;
+ my->poffset = blkno;
+ my->psize = size;
+
/* map dev to an ahci port */
disk = disk_lookup(&sd_cd, DISKUNIT(dev));
scsibus = disk->dv_parent;
@@ -3303,6 +3308,10 @@ ahci_hibernate_io(dev_t dev, daddr_t blkno, vaddr_t addr, size_t size,
return (0);
}
+ if (blkno > my->psize)
+ return (E2BIG);
+ blkno += my->poffset;
+
/* build fis */
sector_count = size / 512; /* dlg promises this is okay */
my->ccb->ccb_xa.flags = op == HIB_W ? ATA_F_WRITE : ATA_F_READ;
diff --git a/sys/kern/subr_hibernate.c b/sys/kern/subr_hibernate.c
index ad81b9baf1f..94e50f5c1a3 100644
--- a/sys/kern/subr_hibernate.c
+++ b/sys/kern/subr_hibernate.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: subr_hibernate.c,v 1.70 2013/11/06 00:52:46 mlarkin Exp $ */
+/* $OpenBSD: subr_hibernate.c,v 1.71 2013/11/06 12:06:58 deraadt Exp $ */
/*
* Copyright (c) 2011 Ariane van der Steldt <ariane@stack.nl>
@@ -675,12 +675,8 @@ get_hibernate_info(union hibernate_info *hiber_info, int suspend)
/* Magic number */
hiber_info->magic = HIBERNATE_MAGIC;
- /* Calculate swap offset from start of disk */
- hiber_info->swap_offset = dl.d_partitions[1].p_offset;
-
/* Calculate signature block location */
- hiber_info->sig_offset = DL_GETPOFFSET(&dl.d_partitions[1]) +
- DL_GETPSIZE(&dl.d_partitions[1]) -
+ hiber_info->sig_offset = DL_GETPSIZE(&dl.d_partitions[1]) -
sizeof(union hibernate_info)/hiber_info->secsize;
chunktable_size = HIBERNATE_CHUNK_TABLE_SIZE / hiber_info->secsize;
@@ -708,8 +704,10 @@ get_hibernate_info(union hibernate_info *hiber_info, int suspend)
* a matching HIB_DONE call performed after the write is
* completed.
*/
- if (hiber_info->io_func(hiber_info->device, 0,
- (vaddr_t)NULL, 0, HIB_INIT, hiber_info->io_page))
+ if (hiber_info->io_func(hiber_info->device,
+ DL_GETPOFFSET(&dl.d_partitions[1]),
+ (vaddr_t)NULL, DL_GETPSIZE(&dl.d_partitions[1]),
+ HIB_INIT, hiber_info->io_page))
goto fail;
} else {
@@ -1000,9 +998,9 @@ hibernate_clear_signature(void)
/* Write (zeroed) hibernate info to disk */
DPRINTF("clearing hibernate signature block location: %lld\n",
- hiber_info.sig_offset - hiber_info.swap_offset);
+ hiber_info.sig_offset);
if (hibernate_block_io(&hiber_info,
- hiber_info.sig_offset - hiber_info.swap_offset,
+ hiber_info.sig_offset,
hiber_info.secsize, (vaddr_t)&blank_hiber_info, 1))
printf("Warning: could not clear hibernate signature\n");
@@ -1160,10 +1158,10 @@ hibernate_resume(void)
s = splbio();
DPRINTF("reading hibernate signature block location: %lld\n",
- hiber_info.sig_offset - hiber_info.swap_offset);
+ hiber_info.sig_offset);
if (hibernate_block_io(&hiber_info,
- hiber_info.sig_offset - hiber_info.swap_offset,
+ hiber_info.sig_offset,
hiber_info.secsize, (vaddr_t)&disk_hiber_info, 0)) {
DPRINTF("error in hibernate read");
splx(s);
@@ -1634,8 +1632,7 @@ hibernate_read_image(union hibernate_info *hiber_info)
/* Calculate total chunk table size in disk blocks */
chunktable_size = HIBERNATE_CHUNK_TABLE_SIZE / hiber_info->secsize;
- blkctr = hiber_info->sig_offset - chunktable_size -
- hiber_info->swap_offset;
+ blkctr = hiber_info->sig_offset - chunktable_size;
chunktable = (vaddr_t)km_alloc(HIBERNATE_CHUNK_TABLE_SIZE, &kv_any,
&kp_none, &kd_nowait);
@@ -1868,7 +1865,7 @@ hibernate_read_chunks(union hibernate_info *hib_info, paddr_t pig_start,
img_cur = pig_start;
for (i = 0; i < nfchunks; i++) {
- blkctr = chunks[fchunks[i]].offset - hib_info->swap_offset;
+ blkctr = chunks[fchunks[i]].offset;
processed = 0;
compressed_size = chunks[fchunks[i]].compressed_size;
@@ -1943,7 +1940,7 @@ hibernate_suspend(void)
}
/* Calculate block offsets in swap */
- hib_info.image_offset = ctod(start) + hib_info.swap_offset;
+ hib_info.image_offset = ctod(start);
/* XXX side effect */
DPRINTF("hibernate @ block %lld max-length %lu blocks\n",
diff --git a/sys/sys/hibernate.h b/sys/sys/hibernate.h
index 79be3e95dc7..915695e0c1f 100644
--- a/sys/sys/hibernate.h
+++ b/sys/sys/hibernate.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: hibernate.h,v 1.25 2013/09/29 16:28:35 mlarkin Exp $ */
+/* $OpenBSD: hibernate.h,v 1.26 2013/11/06 12:06:56 deraadt Exp $ */
/*
* Copyright (c) 2011 Ariane van der Steldt <ariane@stack.nl>
@@ -88,7 +88,6 @@ union hibernate_info {
size_t chunk_ctr;
u_int32_t secsize;
dev_t device;
- daddr_t swap_offset;
daddr_t sig_offset;
daddr_t image_offset;
paddr_t piglet_pa;