aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/os-Linux/umid.c
diff options
context:
space:
mode:
authorPaolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>2006-07-01 07:36:23 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-07-01 12:56:03 -0400
commit912ad92220038b0bb67e3310b8447e4d8802d581 (patch)
treea4131156931d9ebd5022d969ffbbf3c6bc51e055 /arch/um/os-Linux/umid.c
parent47e5243afe0bd2a1aca1e1f05dfbcc214267fbc9 (diff)
[PATCH] uml: fix not_dead_yet when directory is in bad state
The bug occurred to me when a UML left an empty ~/.uml/Sarge-norm folder - when trying to reuse not_dead_yet() failed one of its check. The comment says that's ok and means that we can take the directory, but while normally not_dead_yet() removes it and returns 0 (i.e. go on, use this), on failure it returns 0 but forgets to remove it. The fix is to remove it anytime we're going to return 0. But since "not_dead_yet" didn't make the interface so clear, causing this bug, and I couldn't find a convenient name for the mix of things it did, I split it into two parts: is_umdir_used() - returns a boolean, contains all checks of not_dead_yet() umdir_take_if_dead - tries to remove the dir unless it's used - returns whether it removed it, that is we now own it. With this changes the control flow is IMHO a bit clearer and needs less comment for control flow. Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Cc: 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/umid.c')
-rw-r--r--arch/um/os-Linux/umid.c48
1 files changed, 29 insertions, 19 deletions
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
index 362db059fe30..d5811710126e 100644
--- a/arch/um/os-Linux/umid.c
+++ b/arch/um/os-Linux/umid.c
@@ -103,9 +103,10 @@ static int actually_do_remove(char *dir)
103 * something other than UML sticking stuff in the directory 103 * something other than UML sticking stuff in the directory
104 * this boot racing with a shutdown of the other UML 104 * this boot racing with a shutdown of the other UML
105 * In any of these cases, the directory isn't useful for anything else. 105 * In any of these cases, the directory isn't useful for anything else.
106 *
107 * Boolean return: 1 if in use, 0 otherwise.
106 */ 108 */
107 109static inline int is_umdir_used(char *dir)
108static int not_dead_yet(char *dir)
109{ 110{
110 char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; 111 char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
111 char pid[sizeof("nnnnn\0")], *end; 112 char pid[sizeof("nnnnn\0")], *end;
@@ -113,7 +114,7 @@ static int not_dead_yet(char *dir)
113 114
114 n = snprintf(file, sizeof(file), "%s/pid", dir); 115 n = snprintf(file, sizeof(file), "%s/pid", dir);
115 if(n >= sizeof(file)){ 116 if(n >= sizeof(file)){
116 printk("not_dead_yet - pid filename too long\n"); 117 printk("is_umdir_used - pid filename too long\n");
117 err = -E2BIG; 118 err = -E2BIG;
118 goto out; 119 goto out;
119 } 120 }
@@ -123,7 +124,7 @@ static int not_dead_yet(char *dir)
123 if(fd < 0) { 124 if(fd < 0) {
124 fd = -errno; 125 fd = -errno;
125 if(fd != -ENOENT){ 126 if(fd != -ENOENT){
126 printk("not_dead_yet : couldn't open pid file '%s', " 127 printk("is_umdir_used : couldn't open pid file '%s', "
127 "err = %d\n", file, -fd); 128 "err = %d\n", file, -fd);
128 } 129 }
129 goto out; 130 goto out;
@@ -132,18 +133,18 @@ static int not_dead_yet(char *dir)
132 err = 0; 133 err = 0;
133 n = read(fd, pid, sizeof(pid)); 134 n = read(fd, pid, sizeof(pid));
134 if(n < 0){ 135 if(n < 0){
135 printk("not_dead_yet : couldn't read pid file '%s', " 136 printk("is_umdir_used : couldn't read pid file '%s', "
136 "err = %d\n", file, errno); 137 "err = %d\n", file, errno);
137 goto out_close; 138 goto out_close;
138 } else if(n == 0){ 139 } else if(n == 0){
139 printk("not_dead_yet : couldn't read pid file '%s', " 140 printk("is_umdir_used : couldn't read pid file '%s', "
140 "0-byte read\n", file); 141 "0-byte read\n", file);
141 goto out_close; 142 goto out_close;
142 } 143 }
143 144
144 p = strtoul(pid, &end, 0); 145 p = strtoul(pid, &end, 0);
145 if(end == pid){ 146 if(end == pid){
146 printk("not_dead_yet : couldn't parse pid file '%s', " 147 printk("is_umdir_used : couldn't parse pid file '%s', "
147 "errno = %d\n", file, errno); 148 "errno = %d\n", file, errno);
148 goto out_close; 149 goto out_close;
149 } 150 }
@@ -153,19 +154,32 @@ static int not_dead_yet(char *dir)
153 return 1; 154 return 1;
154 } 155 }
155 156
156 err = actually_do_remove(dir);
157 if(err)
158 printk("not_dead_yet - actually_do_remove failed with "
159 "err = %d\n", err);
160
161 return err;
162
163out_close: 157out_close:
164 close(fd); 158 close(fd);
165out: 159out:
166 return 0; 160 return 0;
167} 161}
168 162
163/*
164 * Try to remove the directory @dir unless it's in use.
165 * Precondition: @dir exists.
166 * Returns 0 for success, < 0 for failure in removal or if the directory is in
167 * use.
168 */
169static int umdir_take_if_dead(char *dir)
170{
171 int ret;
172 if (is_umdir_used(dir))
173 return -EEXIST;
174
175 ret = actually_do_remove(dir);
176 if (ret) {
177 printk("is_umdir_used - actually_do_remove failed with "
178 "err = %d\n", ret);
179 }
180 return ret;
181}
182
169static void __init create_pid_file(void) 183static void __init create_pid_file(void)
170{ 184{
171 char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; 185 char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
@@ -244,11 +258,7 @@ int __init make_umid(void)
244 if(err != -EEXIST) 258 if(err != -EEXIST)
245 goto err; 259 goto err;
246 260
247 /* 1 -> this umid is already in use 261 if (umdir_take_if_dead(tmp) < 0)
248 * < 0 -> we couldn't remove the umid directory
249 * In either case, we can't use this umid, so return -EEXIST.
250 */
251 if(not_dead_yet(tmp) != 0)
252 goto err; 262 goto err;
253 263
254 err = mkdir(tmp, 0777); 264 err = mkdir(tmp, 0777);