From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S265093AbUIOL0Q (ORCPT ); Wed, 15 Sep 2004 07:26:16 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S265196AbUIOL0D (ORCPT ); Wed, 15 Sep 2004 07:26:03 -0400 Received: from gprs214-49.eurotel.cz ([160.218.214.49]:20865 "EHLO amd.ucw.cz") by vger.kernel.org with ESMTP id S265093AbUIOLZW (ORCPT ); Wed, 15 Sep 2004 07:25:22 -0400 Date: Wed, 15 Sep 2004 13:25:02 +0200 From: Pavel Machek To: kernel list , Patrick Mochel Subject: swsusp: cleanup memory freeing Message-ID: <20040915112501.GA22601@elf.ucw.cz> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-Warning: Reading this can be dangerous to your mental health. User-Agent: Mutt/1.5.5.1+cvs20040105i Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Hi! This cleans up memory freeing. I'm not sure that freeing everything that is PageNosave is good idea, some 'private, do not touch' data might be marked as that... And this code looks nicer, anyway. It had 3 or so testers... Pavel --- clean-mm/kernel/power/swsusp.c 2004-09-15 12:58:11.000000000 +0200 +++ linux-mm/kernel/power/swsusp.c 2004-09-15 13:00:51.000000000 +0200 @@ -578,50 +569,20 @@ struct pbe * pbe = pagedir_nosave; for_each_zone(zone) { - if (!is_highmem(zone)) - for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) { - if (saveable(zone, &zone_pfn)) { - struct page * page; - page = pfn_to_page(zone_pfn + zone->zone_start_pfn); - pbe->orig_address = (long) page_address(page); - /* copy_page is no usable for copying task structs. */ - memcpy((void *)pbe->address, (void *)pbe->orig_address, PAGE_SIZE); - pbe++; - } - } - } -} - - -static void free_suspend_pagedir_zone(struct zone *zone, unsigned long pagedir) -{ - unsigned long zone_pfn, pagedir_end, pagedir_pfn, pagedir_end_pfn; - pagedir_end = pagedir + (PAGE_SIZE << pagedir_order); - pagedir_pfn = __pa(pagedir) >> PAGE_SHIFT; - pagedir_end_pfn = __pa(pagedir_end) >> PAGE_SHIFT; - for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) { - struct page *page; - unsigned long pfn = zone_pfn + zone->zone_start_pfn; - if (!pfn_valid(pfn)) - continue; - page = pfn_to_page(pfn); - if (!TestClearPageNosave(page)) - continue; - else if (pfn >= pagedir_pfn && pfn < pagedir_end_pfn) + if (is_highmem(zone)) continue; - __free_page(page); - } -} - -void swsusp_free(void) -{ - unsigned long p = (unsigned long)pagedir_save; - struct zone *zone; - for_each_zone(zone) { - if (!is_highmem(zone)) - free_suspend_pagedir_zone(zone, p); + mark_free_pages(zone); + for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) { + if (saveable(zone, &zone_pfn)) { + struct page * page; + page = pfn_to_page(zone_pfn + zone->zone_start_pfn); + pbe->orig_address = (long) page_address(page); + /* copy_page is not usable for copying task structs. */ + memcpy((void *)pbe->address, (void *)pbe->orig_address, PAGE_SIZE); + pbe++; + } + } } - free_pages(p, pagedir_order); } @@ -687,6 +648,24 @@ return 0; } +/** + * free_image_pages - Free pages allocated for snapshot + */ + +static void free_image_pages(void) +{ + struct pbe * p; + int i; + + p = pagedir_save; + for (i = 0, p = pagedir_save; i < nr_copy_pages; i++, p++) { + if (p->address) { + ClearPageNosave(virt_to_page(p->address)); + free_page(p->address); + p->address = 0; + } + } +} /** * alloc_image_pages - Allocate pages for the snapshot. @@ -700,18 +679,19 @@ for (i = 0, p = pagedir_save; i < nr_copy_pages; i++, p++) { p->address = get_zeroed_page(GFP_ATOMIC | __GFP_COLD); - if(!p->address) - goto Error; + if (!p->address) + return -ENOMEM; SetPageNosave(virt_to_page(p->address)); } return 0; - Error: - do { - if (p->address) - free_page(p->address); - p->address = 0; - } while (p-- > pagedir_save); - return -ENOMEM; +} + +void swsusp_free(void) +{ + BUG_ON(PageNosave(virt_to_page(pagedir_save))); + BUG_ON(PageNosaveFree(virt_to_page(pagedir_save))); + free_image_pages(); + free_pages((unsigned long) pagedir_save, pagedir_order); } @@ -875,6 +855,7 @@ /* Even mappings of "global" things (vmalloc) need to be fixed */ __flush_tlb_global(); + wbinvd(); /* Nigel says wbinvd here is good idea... */ return 0; } @@ -1100,6 +1081,7 @@ return -EPERM; } nr_copy_pages = swsusp_info.image_pages; + pagedir_order = get_bitmask_order(SUSPEND_PD_PAGES(nr_copy_pages)); return error; } @@ -1166,9 +1148,7 @@ int i, n = swsusp_info.pagedir_pages; int error = 0; - pagedir_order = get_bitmask_order(n); - - addr =__get_free_pages(GFP_ATOMIC, pagedir_order); + addr = __get_free_pages(GFP_ATOMIC, pagedir_order); if (!addr) return -ENOMEM; pagedir_nosave = (struct pbe *)addr; -- People were complaining that M$ turns users into beta-testers... ...jr ghea gurz vagb qrirybcref, naq gurl frrz gb yvxr vg gung jnl!