changeset 19167:7f26cfb08fcd

quota: Added quota_vsizes=yes setting to count quotas using virtual sizes instead of physical sizes. This doesn't work with all the quota backends.
author Timo Sirainen <tss@iki.fi>
date Mon, 21 Sep 2015 16:24:30 +0300
parents 7ea1b001a82e
children e29d2f7fe53f
files src/plugins/quota/quota-count.c src/plugins/quota/quota-private.h src/plugins/quota/quota-storage.c src/plugins/quota/quota.c
diffstat 4 files changed, 25 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/src/plugins/quota/quota-count.c	Mon Sep 21 16:12:43 2015 +0300
+++ b/src/plugins/quota/quota-count.c	Mon Sep 21 16:24:30 2015 +0300
@@ -25,12 +25,14 @@
 	}
 
 	box = mailbox_alloc(ns->list, vname, MAILBOX_FLAG_READONLY);
-	if (mailbox_get_metadata(box, MAILBOX_METADATA_PHYSICAL_SIZE,
+	if (mailbox_get_metadata(box, root->quota->set->vsizes ?
+				 MAILBOX_METADATA_VIRTUAL_SIZE :
+				 MAILBOX_METADATA_PHYSICAL_SIZE,
 				 &metadata) < 0 ||
 	    mailbox_get_status(box, STATUS_MESSAGES, &status) < 0) {
 		errstr = mailbox_get_last_error(box, &error);
 		if (error == MAIL_ERROR_TEMP) {
-			i_error("quota: Couldn't get physical size of mailbox %s: %s",
+			i_error("quota: Couldn't get size of mailbox %s: %s",
 				vname, errstr);
 			ret = -1;
 		} else {
@@ -39,7 +41,8 @@
 		}
 	} else {
 		ret = 1;
-		*bytes_r = metadata.physical_size;
+		*bytes_r = root->quota->set->vsizes ?
+			metadata.virtual_size : metadata.physical_size;
 		*count_r = status.messages;
 	}
 	mailbox_free(&box);
--- a/src/plugins/quota/quota-private.h	Mon Sep 21 16:12:43 2015 +0300
+++ b/src/plugins/quota/quota-private.h	Mon Sep 21 16:24:30 2015 +0300
@@ -28,6 +28,7 @@
 	const char *quota_exceeded_msg;
 	unsigned int debug:1;
 	unsigned int initialized:1;
+	unsigned int vsizes:1;
 };
 
 struct quota_rule {
--- a/src/plugins/quota/quota-storage.c	Mon Sep 21 16:12:43 2015 +0300
+++ b/src/plugins/quota/quota-storage.c	Mon Sep 21 16:24:30 2015 +0300
@@ -48,14 +48,20 @@
 {
 	struct mail_private *mail = (struct mail_private *)_mail;
 	struct quota_mailbox *qbox = QUOTA_CONTEXT(_mail->box);
+	struct quota_user *quser = QUOTA_USER_CONTEXT(_mail->box->storage->user);
 	union mail_module_context *qmail = QUOTA_MAIL_CONTEXT(mail);
 	uoff_t size;
+	int ret;
 
 	/* We need to handle the situation where multiple transactions expunged
 	   the mail at the same time. In here we'll just save the message's
 	   physical size and do the quota freeing later when the message was
 	   known to be expunged. */
-	if (mail_get_physical_size(_mail, &size) == 0) {
+	if (quser->quota->set->vsizes)
+		ret = mail_get_virtual_size(_mail, &size);
+	else
+		ret = mail_get_physical_size(_mail, &size);
+	if (ret == 0) {
 		if (!array_is_created(&qbox->expunge_uids)) {
 			i_array_init(&qbox->expunge_uids, 64);
 			i_array_init(&qbox->expunge_sizes, 64);
@@ -310,6 +316,7 @@
 				      enum mailbox_sync_type sync_type)
 {
 	struct quota_mailbox *qbox = QUOTA_CONTEXT(box);
+	struct quota_user *quser = QUOTA_USER_CONTEXT(box->storage->user);
 	const uint32_t *uids;
 	const uoff_t *sizep;
 	unsigned int i, count;
@@ -369,10 +376,16 @@
 			mail_alloc(qbox->expunge_trans,
 				   MAIL_FETCH_PHYSICAL_SIZE, NULL);
 	}
-	if (mail_set_uid(qbox->expunge_qt->tmp_mail, uid) &&
-	    mail_get_physical_size(qbox->expunge_qt->tmp_mail, &size) == 0)
+	if (!mail_set_uid(qbox->expunge_qt->tmp_mail, uid))
+		;
+	else if (!quser->quota->set->vsizes) {
+		if (mail_get_physical_size(qbox->expunge_qt->tmp_mail, &size) == 0) {
+			quota_free_bytes(qbox->expunge_qt, size);
+			return;
+		}
+	} else if (mail_get_virtual_size(qbox->expunge_qt->tmp_mail, &size) == 0) {
 		quota_free_bytes(qbox->expunge_qt, size);
-	else {
+	} else {
 		/* there's no way to get the size. recalculate the quota. */
 		quota_recalculate(qbox->expunge_qt);
 		qbox->recalculate = TRUE;
--- a/src/plugins/quota/quota.c	Mon Sep 21 16:12:43 2015 +0300
+++ b/src/plugins/quota/quota.c	Mon Sep 21 16:24:30 2015 +0300
@@ -229,6 +229,7 @@
 		mail_user_plugin_getenv(user, "quota_exceeded_message");
 	if (quota_set->quota_exceeded_msg == NULL)
 		quota_set->quota_exceeded_msg = DEFAULT_QUOTA_EXCEEDED_MSG;
+	quota_set->vsizes = mail_user_plugin_getenv(user, "quota_vsizes") != NULL;
 
 	p_array_init(&quota_set->root_sets, pool, 4);
 	if (i_strocpy(root_name, "quota", sizeof(root_name)) < 0)