changeset 21471:9d407a044289

lib-storage: Fix autoexpunge locking to actually work correctly. It wasn't actually skipping the autoexpunging if the lock already existed. It autoexpunged anyway.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Fri, 03 Feb 2017 19:40:54 +0200
parents b4c91e015ec7
children 1d4c93fafa9f
files src/lib-storage/mail-autoexpunge.c
diffstat 1 files changed, 19 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/mail-autoexpunge.c	Fri Feb 03 14:22:02 2017 +0200
+++ b/src/lib-storage/mail-autoexpunge.c	Fri Feb 03 19:40:54 2017 +0200
@@ -17,7 +17,7 @@
 	int fd;
 };
 
-static void mailbox_autoexpunge_lock(struct mail_user *user,
+static bool mailbox_autoexpunge_lock(struct mail_user *user,
 				     struct mailbox_autoexpunge_lock *lock)
 {
 	struct file_create_settings lock_set;
@@ -25,13 +25,16 @@
 	const char *home, *error;
 	int ret;
 
+	if (lock->fd != -1)
+		return TRUE;
+
 	/* Try to lock the autoexpunging. If the lock already exists, another
 	   process is already busy with expunging, so we don't have to do it.
 	   The easiest place where to store the lock file to is the home
 	   directory, but allow autoexpunging to work even if we can't get
 	   it. The lock isn't really required; it 1) improves performance
 	   so that multiple processes won't do the same work unnecessarily,
-	   and 2) it helps to avoid duplicates mails being added with
+	   and 2) it helps to avoid duplicate mails being added with
 	   lazy_expunge. */
 	if ((ret = mail_user_get_home(user, &home)) > 0) {
 		const struct mail_storage_settings *mail_set =
@@ -42,12 +45,16 @@
 		lock->fd = file_create_locked(lock->path, &lock_set,
 					      &lock->lock, &created, &error);
 		if (lock->fd == -1) {
-			if (errno != EAGAIN && errno != ENOENT)
+			if (errno == EAGAIN)
+				return FALSE;
+			if (errno != ENOENT)
 				i_error("autoexpunge: Couldn't lock %s: %s", lock->path, error);
+			return TRUE;
 		}
 	} else if (ret == 0) {
 		i_warning("autoexpunge: User has no home directory, can't lock");
 	}
+	return TRUE;
 }
 
 static int
@@ -174,7 +181,7 @@
 	}
 }
 
-static void
+static bool
 mail_namespace_autoexpunge(struct mail_namespace *ns,
 			   struct mailbox_autoexpunge_lock *lock)
 {
@@ -182,14 +189,15 @@
 	const char *vname;
 
 	if (!array_is_created(&ns->set->mailboxes))
-		return;
+		return TRUE;
 
 	array_foreach(&ns->set->mailboxes, box_set) {
 		if ((*box_set)->autoexpunge == 0 &&
 		    (*box_set)->autoexpunge_max_mails == 0)
 			continue;
 
-		mailbox_autoexpunge_lock(ns->user, lock);
+		if (!mailbox_autoexpunge_lock(ns->user, lock))
+			return FALSE;
 
 		if (strpbrk((*box_set)->name, "*?") != NULL)
 			mailbox_autoexpunge_wildcards(ns, *box_set);
@@ -203,6 +211,7 @@
 						(*box_set)->autoexpunge_max_mails);
 		}
 	}
+	return TRUE;
 }
 
 void mail_user_autoexpunge(struct mail_user *user)
@@ -211,8 +220,10 @@
 	struct mail_namespace *ns;
 
 	for (ns = user->namespaces; ns != NULL; ns = ns->next) {
-		if (ns->alias_for == NULL)
-			mail_namespace_autoexpunge(ns, &lock);
+		if (ns->alias_for == NULL) {
+			if (!mail_namespace_autoexpunge(ns, &lock))
+				break;
+		}
 	}
 	if (lock.fd != -1) {
 		i_unlink(lock.path);