From eb28931e4a2c89e53d2b0c1a02a843240bff0806 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Sat, 1 Jul 2006 04:36:24 -0700 Subject: [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 Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/os-Linux/umid.c | 53 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 16 deletions(-) (limited to 'arch') 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: return err; } -static int actually_do_remove(char *dir) +/* + * Unlinks the files contained in @dir and then removes @dir. + * Doesn't handle directory trees, so it's not like rm -rf, but almost such. We + * ignore ENOENT errors for anything (they happen, strangely enough - possibly due + * to races between multiple dying UML threads). + */ +static int remove_files_and_dir(char *dir) { DIR *directory; struct dirent *ent; int len; char file[256]; + int ret; directory = opendir(dir); - if(directory == NULL) - return -errno; + if (directory == NULL) { + if (errno != ENOENT) + return -errno; + else + return 0; + } - while((ent = readdir(directory)) != NULL){ - if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) + while ((ent = readdir(directory)) != NULL) { + if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) continue; len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1; - if(len > sizeof(file)) - return -E2BIG; + if (len > sizeof(file)) { + ret = -E2BIG; + goto out; + } sprintf(file, "%s/%s", dir, ent->d_name); - if(unlink(file) < 0) - return -errno; + if (unlink(file) < 0 && errno != ENOENT) { + ret = -errno; + goto out; + } } - if(rmdir(dir) < 0) - return -errno; - return 0; + if (rmdir(dir) < 0 && errno != ENOENT) { + ret = -errno; + goto out; + } + + ret = 0; +out: + closedir(directory); + return ret; } /* 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) if (is_umdir_used(dir)) return -EEXIST; - ret = actually_do_remove(dir); + ret = remove_files_and_dir(dir); if (ret) { - printk("is_umdir_used - actually_do_remove failed with " + printk("is_umdir_used - remove_files_and_dir failed with " "err = %d\n", ret); } return ret; @@ -354,9 +375,9 @@ static void remove_umid_dir(void) char dir[strlen(uml_dir) + UMID_LEN + 1], err; sprintf(dir, "%s%s", uml_dir, umid); - err = actually_do_remove(dir); + err = remove_files_and_dir(dir); if(err) - printf("remove_umid_dir - actually_do_remove failed with " + printf("remove_umid_dir - remove_files_and_dir failed with " "err = %d\n", err); } -- cgit v1.2.3-55-g7522 1-0/+1 * NFSD: Traverse unconfirmed client through hash-tableKinglong Mee2014-03-281-8/+5Star * svcrpc: explicitly reject compounds that are not padded out to 4-byte multipleJeff Layton2014-03-271-1/+6 * net: Mark functions as static in net/sunrpc/svc_xprt.cRashika Kheria2014-03-271-3/+3 * svcrdma: fix printk when memory allocation failsJeff Layton2014-03-271-2/+1Star * nfsd: notify_change needs elevated write countJ. Bruce Fields2014-03-271-0/+9 * nfsd4: fix test_stateid error reply encodingJ. Bruce Fields2014-03-271-0/+3 * nfsd4: leave reply buffer space for failed setattrJ. Bruce Fields2014-03-271-1/+1 * nfsd4: make set of large acl return efbig, not resourceJ. Bruce Fields2014-03-271-1/+1 * nfsd4: session needs room for following op to error outJ. Bruce Fields2014-03-271-0/+6 * nfsd4: buffer-length check for SUPPATTR_EXCLCREATJ. Bruce Fields2014-03-271-0/+2 * nfsd: fix lost nfserrno() call in nfsd_setattr()J. R. Okajima2014-02-181-0/+1 * lockd: send correct lock when granting a delayed lock.NeilBrown2014-02-131-0/+8 * nfsd4: fix acl buffer overrunJ. Bruce Fields2014-02-111-6/+3Star * Linux 3.14-rc2Linus Torvalds2014-02-101-1/+1 * Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmo...Linus Torvalds2014-02-102-0/+6 |\ | * Merge branch 'stable-3.14' of git://git.infradead.org/users/pcmoore/selinux i...James Morris2014-02-102-0/+6 | |\ | | * SELinux: Fix kernel BUG on empty security contexts.Stephen Smalley2014-02-051-0/+4 | | * selinux: add SOCK_DIAG_BY_FAMILY to the list of netlink message typesPaul Moore2014-02-051-0/+2 | | * Merge tag 'v3.13' into stable-3.14Paul Moore2014-02-05