diff options
author | Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> | 2006-07-01 07:36:23 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-07-01 12:56:03 -0400 |
commit | 912ad92220038b0bb67e3310b8447e4d8802d581 (patch) | |
tree | a4131156931d9ebd5022d969ffbbf3c6bc51e055 /arch/um/os-Linux/umid.c | |
parent | 47e5243afe0bd2a1aca1e1f05dfbcc214267fbc9 (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.c | 48 |
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 | 109 | static inline int is_umdir_used(char *dir) | |
108 | static 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 | |||
163 | out_close: | 157 | out_close: |
164 | close(fd); | 158 | close(fd); |
165 | out: | 159 | out: |
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 | */ | ||
169 | static 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 | |||
169 | static void __init create_pid_file(void) | 183 | static 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); |