diff options
author | 2013-11-06 12:06:56 +0000 | |
---|---|---|
committer | 2013-11-06 12:06:56 +0000 | |
commit | a16456879302ab3438e5eb9b74c29867bfa78a2a (patch) | |
tree | cb46433c0407aff778c0fd17d71be3dbd0538794 | |
parent | regen (diff) | |
download | wireguard-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.c | 13 | ||||
-rw-r--r-- | sys/dev/ic/ahci.c | 11 | ||||
-rw-r--r-- | sys/kern/subr_hibernate.c | 29 | ||||
-rw-r--r-- | sys/sys/hibernate.h | 3 |
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; |