aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTristan Schmelcher <tschmelcher@google.com>2013-11-11 13:03:06 -0500
committerRichard Weinberger <richard@nod.at>2014-04-20 17:10:44 -0400
commit0d71832e3004a0833938cc28a096823cd55b8e79 (patch)
treeb0079baf0cee87629cf68bd3cb2e1570a7565bf7
parenta798c10faf62a505d24e5f6213fbaf904a39623f (diff)
uml: Simplify tempdir logic.
Inferring the mount hierarchy correctly from /proc/mounts is hard when MS_MOVE may have been used, and the previous code did it wrongly. This change simplifies the logic to only require that /dev/shm be _on_ tmpfs (which can be checked trivially with statfs) rather than that it be a _mountpoint_ of tmpfs, since there isn't a compelling reason to be that strict. We also now check for tmpfs on whatever directory we ultimately use so that the user is better informed. This change also moves the more standard TMPDIR environment variable check ahead of the others. Applies to 3.12. Signed-off-by: Tristan Schmelcher <tschmelcher@google.com> Signed-off-by: Richard Weinberger <richard@nod.at>
-rw-r--r--arch/um/os-Linux/mem.c372
1 files changed, 75 insertions, 297 deletions
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 3c4af77e51a2..897e9ad0c108 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -12,337 +12,117 @@
12#include <string.h> 12#include <string.h>
13#include <sys/stat.h> 13#include <sys/stat.h>
14#include <sys/mman.h> 14#include <sys/mman.h>
15#include <sys/param.h> 15#include <sys/vfs.h>
16#include <linux/magic.h>
16#include <init.h> 17#include <init.h>
17#include <os.h> 18#include <os.h>
18 19
19/* Modified by which_tmpdir, which is called during early boot */ 20/* Set by make_tempfile() during early boot. */
20static char *default_tmpdir = "/tmp";
21
22/*
23 * Modified when creating the physical memory file and when checking
24 * the tmp filesystem for usability, both happening during early boot.
25 */
26static char *tempdir = NULL; 21static char *tempdir = NULL;
27 22
28static void __init find_tempdir(void) 23/* Check if dir is on tmpfs. Return 0 if yes, -1 if no or error. */
24static int __init check_tmpfs(const char *dir)
29{ 25{
30 const char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL }; 26 struct statfs st;
31 int i;
32 char *dir = NULL;
33
34 if (tempdir != NULL)
35 /* We've already been called */
36 return;
37 for (i = 0; dirs[i]; i++) {
38 dir = getenv(dirs[i]);
39 if ((dir != NULL) && (*dir != '\0'))
40 break;
41 }
42 if ((dir == NULL) || (*dir == '\0'))
43 dir = default_tmpdir;
44 27
45 tempdir = malloc(strlen(dir) + 2); 28 printf("Checking if %s is on tmpfs...", dir);
46 if (tempdir == NULL) { 29 if (statfs(dir, &st) < 0) {
47 fprintf(stderr, "Failed to malloc tempdir, " 30 printf("%s\n", strerror(errno));
48 "errno = %d\n", errno); 31 } else if (st.f_type != TMPFS_MAGIC) {
49 return; 32 printf("no\n");
50 } 33 } else {
51 strcpy(tempdir, dir); 34 printf("OK\n");
52 strcat(tempdir, "/"); 35 return 0;
53}
54
55/*
56 * Remove bytes from the front of the buffer and refill it so that if there's a
57 * partial string that we care about, it will be completed, and we can recognize
58 * it.
59 */
60static int pop(int fd, char *buf, size_t size, size_t npop)
61{
62 ssize_t n;
63 size_t len = strlen(&buf[npop]);
64
65 memmove(buf, &buf[npop], len + 1);
66 n = read(fd, &buf[len], size - len - 1);
67 if (n < 0)
68 return -errno;
69
70 buf[len + n] = '\0';
71 return 1;
72}
73
74/*
75 * This will return 1, with the first character in buf being the
76 * character following the next instance of c in the file. This will
77 * read the file as needed. If there's an error, -errno is returned;
78 * if the end of the file is reached, 0 is returned.
79 */
80static int next(int fd, char *buf, size_t size, char c)
81{
82 ssize_t n;
83 char *ptr;
84
85 while ((ptr = strchr(buf, c)) == NULL) {
86 n = read(fd, buf, size - 1);
87 if (n == 0)
88 return 0;
89 else if (n < 0)
90 return -errno;
91
92 buf[n] = '\0';
93 } 36 }
94 37 return -1;
95 return pop(fd, buf, size, ptr - buf + 1);
96} 38}
97 39
98/* 40/*
99 * Decode an octal-escaped and space-terminated path of the form used by 41 * Choose the tempdir to use. We want something on tmpfs so that our memory is
100 * /proc/mounts. May be used to decode a path in-place. "out" must be at least 42 * not subject to the host's vm.dirty_ratio. If a tempdir is specified in the
101 * as large as the input. The output is always null-terminated. "len" gets the 43 * environment, we use that even if it's not on tmpfs, but we warn the user.
102 * length of the output, excluding the trailing null. Returns 0 if a full path 44 * Otherwise, we try common tmpfs locations, and if no tmpfs directory is found
103 * was successfully decoded, otherwise an error. 45 * then we fall back to /tmp.
104 */ 46 */
105static int decode_path(const char *in, char *out, size_t *len) 47static char * __init choose_tempdir(void)
106{ 48{
107 char *first = out; 49 static const char * const vars[] = {
108 int c; 50 "TMPDIR",
51 "TMP",
52 "TEMP",
53 NULL
54 };
55 static const char fallback_dir[] = "/tmp";
56 static const char * const tmpfs_dirs[] = {
57 "/dev/shm",
58 fallback_dir,
59 NULL
60 };
109 int i; 61 int i;
110 int ret = -EINVAL; 62 const char *dir;
111 while (1) { 63
112 switch (*in) { 64 printf("Checking environment variables for a tempdir...");
113 case '\0': 65 for (i = 0; vars[i]; i++) {
114 goto out; 66 dir = getenv(vars[i]);
115 67 if ((dir != NULL) && (*dir != '\0')) {
116 case ' ': 68 printf("%s\n", dir);
117 ret = 0; 69 if (check_tmpfs(dir) >= 0)
118 goto out; 70 goto done;
119 71 else
120 case '\\': 72 goto warn;
121 in++;
122 c = 0;
123 for (i = 0; i < 3; i++) {
124 if (*in < '0' || *in > '7')
125 goto out;
126 c = (c << 3) | (*in++ - '0');
127 }
128 *(unsigned char *)out++ = (unsigned char) c;
129 break;
130
131 default:
132 *out++ = *in++;
133 break;
134 } 73 }
135 } 74 }
75 printf("none found\n");
136 76
137out: 77 for (i = 0; tmpfs_dirs[i]; i++) {
138 *out = '\0'; 78 dir = tmpfs_dirs[i];
139 *len = out - first; 79 if (check_tmpfs(dir) >= 0)
140 return ret; 80 goto done;
141}
142
143/*
144 * Computes the length of s when encoded with three-digit octal escape sequences
145 * for the characters in chars.
146 */
147static size_t octal_encoded_length(const char *s, const char *chars)
148{