From: Timo Sirainen Date: Tue, 16 Oct 2012 00:34:51 +0000 (+0300) Subject: dict quota: Fixed a potential crash if quota recalculation was triggered at deinit. X-Git-Tag: 2.2.alpha1~20^2~26 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=048e40f9364fa68482bc276dd4a5d595a3d742e9;p=thirdparty%2Fdovecot%2Fcore.git dict quota: Fixed a potential crash if quota recalculation was triggered at deinit. --- diff --git a/src/plugins/quota/quota-dict.c b/src/plugins/quota/quota-dict.c index 877589a5ca..8620e87d0e 100644 --- a/src/plugins/quota/quota-dict.c +++ b/src/plugins/quota/quota-dict.c @@ -86,10 +86,8 @@ static void dict_quota_deinit(struct quota_root *_root) { 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 @@ dict_quota_update(struct quota_root *_root, 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 @@ struct quota_backend quota_backend_dict = { dict_quota_root_get_resources, dict_quota_get_resource, dict_quota_update, - NULL + NULL, + dict_quota_flush } }; diff --git a/src/plugins/quota/quota-dirsize.c b/src/plugins/quota/quota-dirsize.c index 8e527dae5a..f6cd0e6827 100644 --- a/src/plugins/quota/quota-dirsize.c +++ b/src/plugins/quota/quota-dirsize.c @@ -219,6 +219,7 @@ struct quota_backend quota_backend_dirsize = { dirsize_quota_root_get_resources, dirsize_quota_get_resource, dirsize_quota_update, + NULL, NULL } }; diff --git a/src/plugins/quota/quota-fs.c b/src/plugins/quota/quota-fs.c index 446dedbdc4..c58e182798 100644 --- a/src/plugins/quota/quota-fs.c +++ b/src/plugins/quota/quota-fs.c @@ -831,7 +831,8 @@ struct quota_backend quota_backend_fs = { fs_quota_get_resource, fs_quota_update, - fs_quota_match_box + fs_quota_match_box, + NULL } }; diff --git a/src/plugins/quota/quota-maildir.c b/src/plugins/quota/quota-maildir.c index f93e2e011d..ed27f12d4e 100644 --- a/src/plugins/quota/quota-maildir.c +++ b/src/plugins/quota/quota-maildir.c @@ -913,6 +913,7 @@ struct quota_backend quota_backend_maildir = { maildir_quota_root_get_resources, maildir_quota_get_resource, maildir_quota_update, + NULL, NULL } }; diff --git a/src/plugins/quota/quota-private.h b/src/plugins/quota/quota-private.h index fa408f5e63..50bbe5edc6 100644 --- a/src/plugins/quota/quota-private.h +++ b/src/plugins/quota/quota-private.h @@ -67,7 +67,7 @@ struct quota_backend_vfuncs { 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 --git a/src/plugins/quota/quota-storage.c b/src/plugins/quota/quota-storage.c index ee561f332f..de4fdfa431 100644 --- a/src/plugins/quota/quota-storage.c +++ b/src/plugins/quota/quota-storage.c @@ -366,14 +366,34 @@ static int quota_mailbox_sync_deinit(struct mailbox_sync_context *ctx, return ret; } +static void quota_roots_flush(struct quota *quota) +{ + struct quota_root *const *roots; + unsigned int i, count; + + roots = array_get("a->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); }