02dea0875b
Changes since first version added check for MADV_REMOVE support on the host fixed error return botch shrunk sprintf array by one character This adds hotplug memory support to UML. The mconsole syntax is config mem=[+-]n[KMG] In other words, add or subtract some number of kilobytes, megabytes, or gigabytes. Unplugged pages are allocated and then madvise(MADV_TRUNCATE), which is a currently experimental madvise extension. These pages are tracked so they can be plugged back in later if the admin decides to give them back. The first page to be unplugged is used to keep track of about 4M of other pages. A list_head is the first thing on this page. The rest is filled with addresses of other unplugged pages. This first page is not madvised, obviously. When this page is filled, the next page is used in a similar way and linked onto a list with the first page. Etc. This whole process reverses when pages are plugged back in. When a tracking page no longer tracks any unplugged pages, then it is next in line for plugging, which is done by freeing pages back to the kernel. Signed-off-by: Jeff Dike <jdike@addtoit.com> Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
137 lines
2.4 KiB
C
137 lines
2.4 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stddef.h>
|
|
#include <stdarg.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <fcntl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/mman.h>
|
|
#include "kern_util.h"
|
|
#include "user.h"
|
|
#include "user_util.h"
|
|
#include "mem_user.h"
|
|
#include "init.h"
|
|
#include "os.h"
|
|
#include "tempfile.h"
|
|
#include "kern_constants.h"
|
|
|
|
#include <sys/param.h>
|
|
|
|
static char *tempdir = NULL;
|
|
|
|
static void __init find_tempdir(void)
|
|
{
|
|
char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL };
|
|
int i;
|
|
char *dir = NULL;
|
|
|
|
if(tempdir != NULL) return; /* We've already been called */
|
|
for(i = 0; dirs[i]; i++){
|
|
dir = getenv(dirs[i]);
|
|
if((dir != NULL) && (*dir != '\0'))
|
|
break;
|
|
}
|
|
if((dir == NULL) || (*dir == '\0'))
|
|
dir = "/tmp";
|
|
|
|
tempdir = malloc(strlen(dir) + 2);
|
|
if(tempdir == NULL){
|
|
fprintf(stderr, "Failed to malloc tempdir, "
|
|
"errno = %d\n", errno);
|
|
return;
|
|
}
|
|
strcpy(tempdir, dir);
|
|
strcat(tempdir, "/");
|
|
}
|
|
|
|
/*
|
|
* This proc still used in tt-mode
|
|
* (file: kernel/tt/ptproxy/proxy.c, proc: start_debugger).
|
|
* So it isn't 'static' yet.
|
|
*/
|
|
int make_tempfile(const char *template, char **out_tempname, int do_unlink)
|
|
{
|
|
char tempname[MAXPATHLEN];
|
|
int fd;
|
|
|
|
find_tempdir();
|
|
if (*template != '/')
|
|
strcpy(tempname, tempdir);
|
|
else
|
|
*tempname = 0;
|
|
strcat(tempname, template);
|
|
fd = mkstemp(tempname);
|
|
if(fd < 0){
|
|
fprintf(stderr, "open - cannot create %s: %s\n", tempname,
|
|
strerror(errno));
|
|
return -1;
|
|
}
|
|
if(do_unlink && (unlink(tempname) < 0)){
|
|
perror("unlink");
|
|
return -1;
|
|
}
|
|
if(out_tempname){
|
|
*out_tempname = strdup(tempname);
|
|
if(*out_tempname == NULL){
|
|
perror("strdup");
|
|
return -1;
|
|
}
|
|
}
|
|
return(fd);
|
|
}
|
|
|
|
#define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
|
|
|
|
/*
|
|
* This proc is used in start_up.c
|
|
* So it isn't 'static'.
|
|
*/
|
|
int create_tmp_file(unsigned long long len)
|
|
{
|
|
int fd, err;
|
|
char zero;
|
|
|
|
fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1);
|
|
if(fd < 0) {
|
|
exit(1);
|
|
}
|
|
|
|
err = fchmod(fd, 0777);
|
|
if(err < 0){
|
|
perror("os_mode_fd");
|
|
exit(1);
|
|
}
|
|
|
|
if (lseek64(fd, len, SEEK_SET) < 0) {
|
|
perror("os_seek_file");
|
|
exit(1);
|
|
}
|
|
|
|
zero = 0;
|
|
|
|
err = os_write_file(fd, &zero, 1);
|
|
if(err != 1){
|
|
errno = -err;
|
|
perror("os_write_file");
|
|
exit(1);
|
|
}
|
|
|
|
return(fd);
|
|
}
|
|
|
|
int create_mem_file(unsigned long long len)
|
|
{
|
|
int err, fd;
|
|
|
|
fd = create_tmp_file(len);
|
|
|
|
err = os_set_exec_close(fd, 1);
|
|
if(err < 0){
|
|
errno = -err;
|
|
perror("exec_close");
|
|
}
|
|
return(fd);
|
|
}
|