dovecot-2.2: dict quota: Fixed a potential crash if quota recalc...

dovecot at dovecot.org dovecot at dovecot.org
Mon Oct 29 17:55:54 EET 2012


details:   http://hg.dovecot.org/dovecot-2.2/rev/41aac09497ee
changeset: 15310:41aac09497ee
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Oct 16 03:34:51 2012 +0300
description:
dict quota: Fixed a potential crash if quota recalculation was triggered at deinit.

diffstat:

 src/plugins/quota/quota-dict.c    |  14 ++++++++++----
 src/plugins/quota/quota-dirsize.c |   1 +
 src/plugins/quota/quota-fs.c      |   3 ++-
 src/plugins/quota/quota-maildir.c |   1 +
 src/plugins/quota/quota-private.h |   2 +-
 src/plugins/quota/quota-storage.c |  20 ++++++++++++++++++++
 6 files changed, 35 insertions(+), 6 deletions(-)

diffs (123 lines):

diff -r 0262ede193e5 -r 41aac09497ee src/plugins/quota/quota-dict.c
--- a/src/plugins/quota/quota-dict.c	Tue Oct 16 03:08:21 2012 +0300
+++ b/src/plugins/quota/quota-dict.c	Tue Oct 16 03:34:51 2012 +0300
@@ -86,10 +86,8 @@
 {
 	struct dict_quota_root *root = (struct dict_quota_root *)_root;
 
-	if (root->dict != NULL) {
-		(void)dict_wait(root->dict);
+	if (root->dict != NULL)
 		dict_deinit(&root->dict);
-	}
 	i_free(root);
 }
 
@@ -208,6 +206,13 @@
 	return 0;
 }
 
+static void dict_quota_flush(struct quota_root *_root)
+{
+	struct dict_quota_root *root = (struct dict_quota_root *)_root;
+
+	(void)dict_wait(root->dict);
+}
+
 struct quota_backend quota_backend_dict = {
 	"dict",
 
@@ -221,6 +226,7 @@
 		dict_quota_root_get_resources,
 		dict_quota_get_resource,
 		dict_quota_update,
-		NULL
+		NULL,
+		dict_quota_flush
 	}
 };
diff -r 0262ede193e5 -r 41aac09497ee src/plugins/quota/quota-dirsize.c
--- a/src/plugins/quota/quota-dirsize.c	Tue Oct 16 03:08:21 2012 +0300
+++ b/src/plugins/quota/quota-dirsize.c	Tue Oct 16 03:34:51 2012 +0300
@@ -219,6 +219,7 @@
 		dirsize_quota_root_get_resources,
 		dirsize_quota_get_resource,
 		dirsize_quota_update,
+		NULL,
 		NULL
 	}
 };
diff -r 0262ede193e5 -r 41aac09497ee src/plugins/quota/quota-fs.c
--- a/src/plugins/quota/quota-fs.c	Tue Oct 16 03:08:21 2012 +0300
+++ b/src/plugins/quota/quota-fs.c	Tue Oct 16 03:34:51 2012 +0300
@@ -831,7 +831,8 @@
 		fs_quota_get_resource,
 		fs_quota_update,
 
-		fs_quota_match_box
+		fs_quota_match_box,
+		NULL
 	}
 };
 
diff -r 0262ede193e5 -r 41aac09497ee src/plugins/quota/quota-maildir.c
--- a/src/plugins/quota/quota-maildir.c	Tue Oct 16 03:08:21 2012 +0300
+++ b/src/plugins/quota/quota-maildir.c	Tue Oct 16 03:34:51 2012 +0300
@@ -913,6 +913,7 @@
 		maildir_quota_root_get_resources,
 		maildir_quota_get_resource,
 		maildir_quota_update,
+		NULL,
 		NULL
 	}
 };
diff -r 0262ede193e5 -r 41aac09497ee src/plugins/quota/quota-private.h
--- a/src/plugins/quota/quota-private.h	Tue Oct 16 03:08:21 2012 +0300
+++ b/src/plugins/quota/quota-private.h	Tue Oct 16 03:34:51 2012 +0300
@@ -67,7 +67,7 @@
 	int (*update)(struct quota_root *root, 
 		      struct quota_transaction_context *ctx);
 	bool (*match_box)(struct quota_root *root, struct mailbox *box);
-
+	void (*flush)(struct quota_root *root);
 };
 
 struct quota_backend {
diff -r 0262ede193e5 -r 41aac09497ee src/plugins/quota/quota-storage.c
--- a/src/plugins/quota/quota-storage.c	Tue Oct 16 03:08:21 2012 +0300
+++ b/src/plugins/quota/quota-storage.c	Tue Oct 16 03:34:51 2012 +0300
@@ -366,14 +366,34 @@
 	return ret;
 }
 
+static void quota_roots_flush(struct quota *quota)
+{
+	struct quota_root *const *roots;
+	unsigned int i, count;
+
+	roots = array_get(&quota->roots, &count);
+	for (i = 0; i < count; i++) {
+		if (roots[i]->backend.v.flush != NULL)
+			roots[i]->backend.v.flush(roots[i]);
+	}
+}
+
 static void quota_mailbox_close(struct mailbox *box)
 {
 	struct quota_mailbox *qbox = QUOTA_CONTEXT(box);
+	struct quota_user *quser = QUOTA_USER_CONTEXT(box->storage->user);
 
 	/* sync_notify() may be called outside sync_begin()..sync_deinit().
 	   make sure we apply changes at close time at latest. */
 	quota_mailbox_sync_commit(qbox);
 
+	/* make sure quota backend flushes all data. this could also be done
+	   somewhat later, but user.deinit() is too late, since the flushing
+	   can trigger quota recalculation which isn't safe to do anymore
+	   at user.deinit() when most of the loaded plugins have already been
+	   deinitialized. */
+	quota_roots_flush(quser->quota);
+
 	qbox->module_ctx.super.close(box);
 }
 


More information about the dovecot-cvs mailing list