diff options
author | Rob Landley <rob@landley.net> | 2006-04-18 22:21:43 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-04-19 09:13:51 -0700 |
commit | 966a082f80a073af1564c5ed6313ef2f0587dde3 (patch) | |
tree | da199abad4c035c60f04100b2759815655f46f31 /arch/um/os-Linux/mem.c | |
parent | f983c45ebedcaf686223afaecd8e681e8dcd15a9 (diff) |
[PATCH] uml: physical memory map file fixes
UML really wants shared memory semantics form its physical memory map file,
and the place for that is /dev/shm. So move the default, and fix the error
messages to recognize that this value can be overridden.
Signed-off-by: Rob Landley <rob@landley.net>
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/um/os-Linux/mem.c')
-rw-r--r-- | arch/um/os-Linux/mem.c | 118 |
1 files changed, 117 insertions, 1 deletions
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c index 71bb90a7606..c6432e72924 100644 --- a/arch/um/os-Linux/mem.c +++ b/arch/um/os-Linux/mem.c @@ -8,6 +8,7 @@ #include <fcntl.h> #include <sys/types.h> #include <sys/mman.h> +#include <sys/statfs.h> #include "kern_util.h" #include "user.h" #include "user_util.h" @@ -19,6 +20,7 @@ #include <sys/param.h> +static char *default_tmpdir = "/tmp"; static char *tempdir = NULL; static void __init find_tempdir(void) @@ -34,7 +36,7 @@ static void __init find_tempdir(void) break; } if((dir == NULL) || (*dir == '\0')) - dir = "/tmp"; + dir = default_tmpdir; tempdir = malloc(strlen(dir) + 2); if(tempdir == NULL){ @@ -46,6 +48,96 @@ static void __init find_tempdir(void) strcat(tempdir, "/"); } +/* This will return 1, with the first character in buf being the + * character following the next instance of c in the file. This will + * read the file as needed. If there's an error, -errno is returned; + * if the end of the file is reached, 0 is returned. + */ +static int next(int fd, char *buf, int size, char c) +{ + int n; + char *ptr; + + while((ptr = strchr(buf, c)) == NULL){ + n = read(fd, buf, size - 1); + if(n == 0) + return 0; + else if(n < 0) + return -errno; + + buf[n] = '\0'; + } + + ptr++; + memmove(buf, ptr, strlen(ptr) + 1); + return 1; +} + +static int checked_tmpdir = 0; + +/* Look for a tmpfs mounted at /dev/shm. I couldn't find a cleaner + * way to do this than to parse /proc/mounts. statfs will return the + * same filesystem magic number and fs id for both /dev and /dev/shm + * when they are both tmpfs, so you can't tell if they are different + * filesystems. Also, there seems to be no other way of finding the + * mount point of a filesystem from within it. + * + * If a /dev/shm tmpfs entry is found, then we switch to using it. + * Otherwise, we stay with the default /tmp. + */ +static void which_tmpdir(void) +{ + int fd, found; + char buf[128] = { '\0' }; + + if(checked_tmpdir) + return; + + checked_tmpdir = 1; + + printf("Checking for tmpfs mount on /dev/shm..."); + + fd = open("/proc/mounts", O_RDONLY); + if(fd < 0){ + printf("failed to open /proc/mounts, errno = %d\n", errno); + return; + } + + while(1){ + found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' '); + if(found != 1) + break; + + if(!strncmp(buf, "/dev/shm", strlen("/dev/shm"))) + goto found; + + found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), '\n'); + if(found != 1) + break; + } + +err: + if(found == 0) + printf("nothing mounted on /dev/shm\n"); + else if(found < 0) + printf("read returned errno %d\n", -found); + + return; + +found: + found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' '); + if(found != 1) + goto err; + + if(strncmp(buf, "tmpfs", strlen("tmpfs"))){ + printf("not tmpfs\n"); + return; + } + + printf("OK\n"); + default_tmpdir = "/dev/shm"; +} + /* * This proc still used in tt-mode * (file: kernel/tt/ptproxy/proxy.c, proc: start_debugger). @@ -56,6 +148,7 @@ int make_tempfile(const char *template, char **out_tempname, int do_unlink) char *tempname; int fd; + which_tmpdir(); tempname = malloc(MAXPATHLEN); find_tempdir(); @@ -137,3 +230,26 @@ int create_mem_file(unsigned long long len) } return(fd); } + + +void check_tmpexec(void) +{ + void *addr; + int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE); + + addr = mmap(NULL, UM_KERN_PAGE_SIZE, + PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0); + printf("Checking PROT_EXEC mmap in %s...",tempdir); + fflush(stdout); + if(addr == MAP_FAILED){ + err = errno; + perror("failed"); + if(err == EPERM) + printf("%s must be not mounted noexec\n",tempdir); + exit(1); + } + printf("OK\n"); + munmap(addr, UM_KERN_PAGE_SIZE); + + close(fd); +} |