summaryrefslogtreecommitdiffstats
path: root/arch/um/os-Linux
diff options
context:
space:
mode:
authorJeff Dike2006-03-31 12:30:08 +0200
committerLinus Torvalds2006-03-31 22:18:50 +0200
commit02dea0875b0f9b331a65fd6097dfd6115ca4ef24 (patch)
tree100126d72e889296a5d8d8714dd681ab041710cb /arch/um/os-Linux
parent[PATCH] Fix suspend with traced tasks (diff)
downloadkernel-qcow2-linux-02dea0875b0f9b331a65fd6097dfd6115ca4ef24.tar.gz
kernel-qcow2-linux-02dea0875b0f9b331a65fd6097dfd6115ca4ef24.tar.xz
kernel-qcow2-linux-02dea0875b0f9b331a65fd6097dfd6115ca4ef24.zip
[PATCH] UML: Hotplug memory, take 2
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>
Diffstat (limited to 'arch/um/os-Linux')
-rw-r--r--arch/um/os-Linux/mem.c27
-rw-r--r--arch/um/os-Linux/process.c44
-rw-r--r--arch/um/os-Linux/start_up.c20
3 files changed, 45 insertions, 46 deletions
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 9d7d69a523bb..6ab372da9657 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -121,36 +121,11 @@ int create_tmp_file(unsigned long long len)
return(fd);
}
-static int create_anon_file(unsigned long long len)
-{
- void *addr;
- int fd;
-
- fd = open("/dev/anon", O_RDWR);
- if(fd < 0) {
- perror("opening /dev/anon");
- exit(1);
- }
-
- addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
- if(addr == MAP_FAILED){
- perror("mapping physmem file");
- exit(1);
- }
- munmap(addr, len);
-
- return(fd);
-}
-
-extern int have_devanon;
-
int create_mem_file(unsigned long long len)
{
int err, fd;
- if(have_devanon)
- fd = create_anon_file(len);
- else fd = create_tmp_file(len);
+ fd = create_tmp_file(len);
err = os_set_exec_close(fd, 1);
if(err < 0){
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index d261888f39c4..8176b0b52047 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -11,6 +11,7 @@
#include <linux/unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
+#include <sys/mman.h>
#include "ptrace_user.h"
#include "os.h"
#include "user.h"
@@ -20,6 +21,7 @@
#include "kern_util.h"
#include "longjmp.h"
#include "skas_ptrace.h"
+#include "kern_constants.h"
#define ARBITRARY_ADDR -1
#define FAILURE_PID -1
@@ -187,6 +189,48 @@ int os_unmap_memory(void *addr, int len)
return(0);
}
+#ifndef MADV_REMOVE
+#define MADV_REMOVE 0x5 /* remove these pages & resources */
+#endif
+
+int os_drop_memory(void *addr, int length)
+{
+ int err;
+
+ err = madvise(addr, length, MADV_REMOVE);
+ if(err < 0)
+ err = -errno;
+ return err;
+}
+
+int can_drop_memory(void)
+{
+ void *addr;
+ int fd;
+
+ printk("Checking host MADV_REMOVE support...");
+ fd = create_mem_file(UM_KERN_PAGE_SIZE);
+ if(fd < 0){
+ printk("Creating test memory file failed, err = %d\n", -fd);
+ return 0;
+ }
+
+ addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE, fd, 0);
+ if(addr == MAP_FAILED){
+ printk("Mapping test memory file failed, err = %d\n", -errno);
+ return 0;
+ }
+
+ if(madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0){
+ printk("MADV_REMOVE failed, err = %d\n", -errno);
+ return 0;
+ }
+
+ printk("OK\n");
+ return 1;
+}
+
void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
{
int flags = 0, pages;
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 32753131f8d8..387e26af301a 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -470,25 +470,6 @@ int can_do_skas(void)
}
#endif
-int have_devanon = 0;
-
-/* Runs on boot kernel stack - already safe to use printk. */
-
-void check_devanon(void)
-{
- int fd;
-
- printk("Checking for /dev/anon on the host...");
- fd = open("/dev/anon", O_RDWR);
- if(fd < 0){
- printk("Not available (open failed with errno %d)\n", errno);
- return;
- }
-
- printk("OK\n");
- have_devanon = 1;
-}
-
int __init parse_iomem(char *str, int *add)
{
struct iomem_region *new;
@@ -664,6 +645,5 @@ void os_check_bugs(void)
{
check_ptrace();
check_sigio();
- check_devanon();
}