changeset 22336:8f674d4111cf

lib-storage: When index dir rmdir() fails with ENOTEMPTY, retry it for 1 second This helps to avoid leaving those index directories lying around with NFS. Hopefully within the 1 second any existing processes that have been keeping those files open have finished their task. Especially IMAP IDLE will take 0.5 seconds to start syncing indexes and realize that they're deleted.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Fri, 14 Jul 2017 02:11:56 +0300
parents 510ee47cc21f
children 31d2459cfcf2
files src/lib-storage/list/mailbox-list-delete.c
diffstat 1 files changed, 14 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/list/mailbox-list-delete.c	Fri Jul 14 01:54:31 2017 +0300
+++ b/src/lib-storage/list/mailbox-list-delete.c	Fri Jul 14 02:11:56 2017 +0300
@@ -205,6 +205,9 @@
 			mailbox_list_set_critical(list,
 				"unlink(%s) failed: %m", str_c(full_path));
 			ret = -1;
+		} else {
+			/* child directories still exist */
+			rmdir_path = FALSE;
 		}
 	}
 	if (errno != 0) {
@@ -220,6 +223,17 @@
 		return -1;
 
 	if (rmdir_path) {
+		unsigned int try_count = 0;
+		int ret = rmdir(path);
+		while (ret < 0 && errno == ENOTEMPTY && try_count++ < 10) {
+			/* We didn't see any child directories, so this is
+			   either a race condition or .nfs* files were left
+			   lying around. In case it's .nfs* files, retry after
+			   waiting a bit. Hopefully all processes keeping those
+			   files open will have closed them by then. */
+			usleep(100000);
+			ret = rmdir(path);
+		}
 		if (rmdir(path) == 0)
 			unlinked_something = TRUE;
 		else if (errno == ENOENT) {