From 9948b23246ff267ba581d8817810d80858391464 Mon Sep 17 00:00:00 2001 From: mlarkin Date: Sat, 26 Apr 2014 05:43:00 +0000 Subject: [PATCH] Perform MAXPHYS-sized reads for the chunktable instead of PAGE_SIZE-sized reads. Also fix a VA leak in the chunktable read error path. --- sys/kern/subr_hibernate.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/sys/kern/subr_hibernate.c b/sys/kern/subr_hibernate.c index 025194da1d5..fc8ed07d599 100644 --- a/sys/kern/subr_hibernate.c +++ b/sys/kern/subr_hibernate.c @@ -1,4 +1,4 @@ -/* $OpenBSD: subr_hibernate.c,v 1.88 2014/04/20 14:02:57 mlarkin Exp $ */ +/* $OpenBSD: subr_hibernate.c,v 1.89 2014/04/26 05:43:00 mlarkin Exp $ */ /* * Copyright (c) 2011 Ariane van der Steldt @@ -1566,8 +1566,9 @@ hibernate_read_image(union hibernate_info *hib) vaddr_t chunktable = (vaddr_t)NULL; paddr_t piglet_chunktable = hib->piglet_pa + HIBERNATE_CHUNK_SIZE; - int i; + int i, status; + status = 0; pmap_activate(curproc); /* Calculate total chunk table size in disk blocks */ @@ -1581,15 +1582,17 @@ hibernate_read_image(union hibernate_info *hib) if (!chunktable) return (1); - /* Read the chunktable from disk into the piglet chunktable */ - for (i = 0; i < HIBERNATE_CHUNK_TABLE_SIZE; - i += PAGE_SIZE, blkctr += PAGE_SIZE/DEV_BSIZE) { + /* Map chunktable pages */ + for (i = 0; i < HIBERNATE_CHUNK_TABLE_SIZE; i += PAGE_SIZE) pmap_kenter_pa(chunktable + i, piglet_chunktable + i, VM_PROT_ALL); - pmap_update(pmap_kernel()); - hibernate_block_io(hib, blkctr, PAGE_SIZE, + pmap_update(pmap_kernel()); + + /* Read the chunktable from disk into the piglet chunktable */ + for (i = 0; i < HIBERNATE_CHUNK_TABLE_SIZE; + i += MAXPHYS, blkctr += MAXPHYS/DEV_BSIZE) + hibernate_block_io(hib, blkctr, MAXPHYS, chunktable + i, 0); - } blkctr = hib->image_offset; compressed_size = 0; @@ -1607,8 +1610,10 @@ hibernate_read_image(union hibernate_info *hib) /* Allocate the pig area */ pig_sz = compressed_size + HIBERNATE_CHUNK_SIZE; - if (uvm_pmr_alloc_pig(&pig_start, pig_sz) == ENOMEM) - return (1); + if (uvm_pmr_alloc_pig(&pig_start, pig_sz) == ENOMEM) { + status = 1; + goto unmap; + } pig_end = pig_start + pig_sz; @@ -1619,13 +1624,15 @@ hibernate_read_image(union hibernate_info *hib) hibernate_read_chunks(hib, image_start, image_end, disk_size, chunks); - pmap_kremove(chunktable, PAGE_SIZE); - pmap_update(pmap_kernel()); - /* Prepare the resume time pmap/page table */ hibernate_populate_resume_pt(hib, image_start, image_end); - return (0); +unmap: + /* Unmap chunktable pages */ + pmap_kremove(chunktable, HIBERNATE_CHUNK_TABLE_SIZE); + pmap_update(pmap_kernel()); + + return (status); } /* -- 2.20.1