aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
authorPaolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>2006-07-01 07:36:24 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-07-01 12:56:03 -0400
commiteb28931e4a2c89e53d2b0c1a02a843240bff0806 (patch)
tree14592f5cb45c8d4f4dace422b5deb98e9a9d5574 /arch/um
parent912ad92220038b0bb67e3310b8447e4d8802d581 (diff)
[PATCH] uml: rename and improve actually_do_remove()
Rename actually_do_remove() to remove_files_and_dir(), make it call closedir(), make it ignore ENOENT (I see it frequently enough). ENOENT is probably due to multiple threads calling the exitcall functions together*, but fixing that is non-trivial; and ignoring it is perfectly ok in any case. * it can surely happen: last_ditch_exit() is installed as SIGTERM handler at boot, and it's not removed on thread creation. So killall vmlinux (which I do) surely causes that. I've seen also a crash which seems to do the same. Installing the handler on only the main thread would make UML do no cleanup when another thread exits, and we're not sure we want that. And mutual exclusion in that context is tricky - we can't use spinlock in code not on a kernel stack (spinlock debugging uses "current" a lot). 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')
-rw-r--r--arch/um/os-Linux/umid.c53
1 files changed, 37 insertions, 16 deletions
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
index d5811710126e..48092b95c8ab 100644
--- a/arch/um/os-Linux/umid.c
+++ b/arch/um/os-Linux/umid.c
@@ -67,32 +67,53 @@ err:
67 return err; 67 return err;
68} 68}
69 69
70static int actually_do_remove(char *dir) 70/*
71 * Unlinks the files contained in @dir and then removes @dir.
72 * Doesn't handle directory trees, so it's not like rm -rf, but almost such. We
73 * ignore ENOENT errors for anything (they happen, strangely enough - possibly due
74 * to races between multiple dying UML threads).
75 */
76static int remove_files_and_dir(char *dir)
71{ 77{
72 DIR *directory; 78 DIR *directory;
73 struct dirent *ent; 79 struct dirent *ent;
74 int len; 80 int len;
75 char file[256]; 81 char file[256];
82 int ret;
76 83
77 directory = opendir(dir); 84 directory = opendir(dir);
78 if(directory == NULL) 85 if (directory == NULL) {
79 return -errno; 86 if (errno != ENOENT)
87 return -errno;
88 else
89 return 0;
90 }
80 91
81 while((ent = readdir(directory)) != NULL){ 92 while ((ent = readdir(directory)) != NULL) {
82 if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) 93 if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
83 continue; 94 continue;
84 len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1; 95 len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1;
85 if(len > sizeof(file)) 96 if (len > sizeof(file)) {
86 return -E2BIG; 97 ret = -E2BIG;
98 goto out;
99 }
87 100
88 sprintf(file, "%s/%s", dir, ent->d_name); 101 sprintf(file, "%s/%s", dir, ent->d_name);
89 if(unlink(file) < 0) 102 if (unlink(file) < 0 && errno != ENOENT) {
90 return -errno; 103 ret = -errno;
104 goto out;
105 }
91 } 106 }
92 if(rmdir(dir) < 0)
93 return -errno;
94 107
95 return 0; 108 if (rmdir(dir) < 0 && errno != ENOENT) {
109 ret = -errno;
110 goto out;
111 }
112
113 ret = 0;
114out:
115 closedir(directory);
116 return ret;
96} 117}
97 118
98/* This says that there isn't already a user of the specified directory even if 119/* This says that there isn't already a user of the specified directory even if
@@ -172,9 +193,9 @@ static int umdir_take_if_dead(char *dir)
172 if (is_umdir_used(dir)) 193 if (is_umdir_used(dir))
173 return -EEXIST; 194 return -EEXIST;
174 195
175 ret = actually_do_remove(dir); 196 ret = remove_files_and_dir(dir);
176 if (ret) { 197 if (ret) {
177 printk("is_umdir_used - actually_do_remove failed with " 198 printk("is_umdir_used - remove_files_and_dir failed with "
178 "err = %d\n", ret); 199 "err = %d\n", ret);
179 } 200 }
180 return ret; 201 return ret;
@@ -354,9 +375,9 @@ static void remove_umid_dir(void)
354 char dir[strlen(uml_dir) + UMID_LEN + 1], err; 375 char dir[strlen(uml_dir) + UMID_LEN + 1], err;
355 376
356 sprintf(dir, "%s%s", uml_dir, umid); 377 sprintf(dir, "%s%s", uml_dir, umid);
357 err = actually_do_remove(dir); 378 err = remove_files_and_dir(dir);
358 if(err) 379 if(err)
359 printf("remove_umid_dir - actually_do_remove failed with " 380 printf("remove_umid_dir - remove_files_and_dir failed with "
360 "err = %d\n", err); 381 "err = %d\n", err);
361} 382}
362 383