* MM, TLB and speeding up suspend to disk for 2.4
@ 2005-02-07 16:30 Stefan Voelkel
0 siblings, 0 replies; only message in thread
From: Stefan Voelkel @ 2005-02-07 16:30 UTC (permalink / raw)
To: Linux-mm
[-- Attachment #1: Type: text/plain, Size: 1507 bytes --]
Hello,
since neither Understanding the Linux VMM nor the kernelnewbies ML could
help me, I am takin the problem here:
I have a IBM Thinkpad 600X and use the suspend to disk feature (called
hibernation) when carring the notebook around, but writing ~600MB to the
disk takes a while.
After finding out, that the bios does only write used pages to disk, I
wrote a small userspace programm called mhog (see attached mhog.c), that
allocates roughly as many pages as used by the page cache. mhog retrieves
the number of pages to allocate from /proc/meminfo.
This works find, but does take a while, so I wrote a kernel module
(see attached nocache.c) to do the same. During module initilization I
simply loop around a get_free_page(GFP_NIO) to get all pages that can be
discarded, and upon the first failure I free all reserved pages again and
return -ENOMEM.
The kernel module does not speed up hibernation (pages are freed just
fine), but something must be diffrent between userspace and kernelspace
page allocation. I suspect the TLB, but did not find a hint on which of the
many tlb flushing calls to use.
So what am I missing?
thanks in advance
Stefan
--
Stefan Volkel stefan.voelkel@millenux.com
Millenux GmbH mobile: +49.170.79177.17
Lilienthalstrasse 2 phone: +49.711.88770.300
70825 Stuttgart-Korntal fax: +49.711.88770.349
-= linux without limits -=- http://linux.zSeries.org/ =-
[-- Attachment #2: nocache.c --]
[-- Type: application/octet-stream, Size: 1530 bytes --]
/*
nocache.c (c) 2005 Stefan.Voelkel@millenux.com
licensed under the GPL v2.
*/
#include <linux/module.h>
#include <linux/version.h>
#include <linux/mm.h>
#include <asm/pgalloc.h>
struct nc_pages;
#define NC_PAGES ((PAGE_SIZE - sizeof(struct nc_pages *) - sizeof(unsigned int))/ sizeof(unsigned long))
struct nc_pages {
struct nc_pages *next;
unsigned int order;
unsigned long pages[NC_PAGES];
};
static struct nc_pages *pa = 0;
static inline void nc_alloc_pages(void) {
struct nc_pages *list;
unsigned long page;
unsigned long index = 0;
unsigned int order = MAX_ORDER - 1;
while (order < MAX_ORDER) {
page = __get_free_pages(GFP_NOIO, order);
if (!page) {
--order;
continue;
}
if (!pa || index >= NC_PAGES || order != pa->order) {
list = (struct nc_pages *) get_zeroed_page(GFP_NOIO);
if (!list) {
free_pages(page, order);
break;
}
list->next = pa;
pa = list;
pa->order = order;
index = 0;
}
pa->pages[index] = page;
++index;
}
}
static inline void nc_free_pages(void) {
struct nc_pages *save;
unsigned long index;
while(pa) {
for (index = 0; index < NC_PAGES && pa->pages[index]; ++index)
free_pages(pa->pages[index], pa->order);
save = pa;
pa = pa->next;
free_page((unsigned long) save);
}
}
int init_module(void)
{
nc_alloc_pages();
nc_free_pages();
flush_tlb();
return -ENOMEM;
}
void cleanup_module(void)
{
}
MODULE_AUTHOR("Stefan Völkel <stefan.voelkel@millenux.com>");
MODULE_LICENSE("GPL");
EXPORT_NO_SYMBOLS;
[-- Attachment #3: mhog.c --]
[-- Type: application/octet-stream, Size: 1346 bytes --]
/*
* mhog.c (c) Stefan Völkel <stefan.voelkel@millenux.com>
*
* LICENSED UNDER THE GPL v2
*
*/
#include <string.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#define PAGE_BIT 12
#define PAGE_SIZE (1 << PAGE_BIT)
int main(void)
{
FILE *f;
long buffers, cached, free, memory;
int ret;
/* get free memory, buffers and cached from /proc to calculate the
* number of pages we need to malloc() in order to invalidate the
* cache */
f = fopen("/proc/meminfo", "r");
if (!f) {
printf("E: fopen() %d:'%s'\n", errno, strerror(errno));
exit(errno);
}
ret = fscanf(f, "%*s %*s %*s %*s %*s %*s\n");
if (ret) {
printf("E: sscanf() (1) %d:'%s'\n", errno, strerror(errno));
exit(errno);
}
ret = fscanf(f, "%*s %*ld %*ld %ld %*ld %ld %ld\n", &free,
&buffers, &cached);
if (3 != ret) {
printf("E: %d = sscanf() (2) %d:'%s'\n", ret, errno,
strerror(errno));
exit(errno);
}
fclose(f);
memory = buffers + cached + free;
memory >>= PAGE_BIT;
printf("Need to flush %ld pages\n", memory);
/* we need to write at least one byte to each page to take it away from
* the system */
while (memory--) {
char *c = malloc(PAGE_SIZE);
*c = '0';
printf("%d left \r", memory);
}
return 0;
}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2005-02-07 16:30 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-02-07 16:30 MM, TLB and speeding up suspend to disk for 2.4 Stefan Voelkel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox