unsigned int ns_idx;
struct mailbox_list_iterate_context *iter;
struct mailbox_info info;
- bool failed;
+ const char *error;
};
extern struct quota_backend quota_backend_count;
static int
quota_count_mailbox(struct quota_root *root, struct mail_namespace *ns,
- const char *vname, uint64_t *bytes, uint64_t *count)
+ const char *vname, uint64_t *bytes, uint64_t *count,
+ const char **error_r)
{
struct quota_rule *rule;
struct mailbox *box;
mailbox_get_status(box, STATUS_MESSAGES, &status) < 0) {
errstr = mailbox_get_last_internal_error(box, &error);
if (error == MAIL_ERROR_TEMP) {
- i_error("quota: Couldn't get size of mailbox %s: %s",
+ *error_r = t_strdup_printf(
+ "Couldn't get size of mailbox %s: %s",
vname, errstr);
ret = -1;
} else if (error == MAIL_ERROR_INUSE) {
/* started on background. don't log an error. */
+ /* FIXME: Should not log an error, will be fixed with
+ * upcoming enum addition. */
+ *error_r = t_strdup_printf(
+ "%s busy with background quota calculation",
+ vname);
ret = -1;
} else {
/* non-temporary error, e.g. ACLs denied access. */
iter = i_new(struct quota_mailbox_iter, 1);
iter->root = root;
+ iter->error = "";
return iter;
}
static int
-quota_mailbox_iter_deinit(struct quota_mailbox_iter **_iter)
+quota_mailbox_iter_deinit(struct quota_mailbox_iter **_iter,
+ const char **error_r)
{
struct quota_mailbox_iter *iter = *_iter;
- int ret = iter->failed ? -1 : 0;
+ int ret = *iter->error != '\0' ? -1 : 0;
*_iter = NULL;
+ const char *error2 = "";
if (iter->iter != NULL) {
if (mailbox_list_iter_deinit(&iter->iter) < 0) {
- i_error("quota: Listing namespace '%s' failed: %s",
+ error2 = t_strdup_printf(
+ "Listing namespace '%s' failed: %s",
iter->ns->prefix,
mailbox_list_get_last_internal_error(iter->ns->list, NULL));
ret = -1;
}
}
+ if (ret < 0) {
+ const char *separator =
+ *iter->error != '\0' && *error2 != '\0' ? " and " : "";
+ *error_r = t_strdup_printf("%s%s%s",
+ iter->error, separator, error2);
+ }
i_free(iter);
return ret;
}
return info;
}
if (mailbox_list_iter_deinit(&iter->iter) < 0) {
- i_error("quota: Listing namespace '%s' failed: %s",
+ iter->error = t_strdup_printf(
+ "Listing namespace '%s' failed: %s",
iter->ns->prefix,
mailbox_list_get_last_internal_error(iter->ns->list, NULL));
- iter->failed = TRUE;
}
if (iter->ns->prefix_len > 0 &&
(iter->ns->prefix_len != 6 ||
return quota_mailbox_iter_next(iter);
}
-int quota_count(struct quota_root *root, uint64_t *bytes_r, uint64_t *count_r)
+int quota_count(struct quota_root *root, uint64_t *bytes_r, uint64_t *count_r,
+ const char **error_r)
{
struct quota_mailbox_iter *iter;
const struct mailbox_info *info;
+ const char *error1 = "", *error2 = "";
int ret = 1;
*bytes_r = *count_r = 0;
iter = quota_mailbox_iter_begin(root);
while ((info = quota_mailbox_iter_next(iter)) != NULL) {
if (quota_count_mailbox(root, info->ns, info->vname,
- bytes_r, count_r) < 0) {
+ bytes_r, count_r, &error1) < 0) {
ret = -1;
break;
}
}
- if (quota_mailbox_iter_deinit(&iter) < 0)
+ if (quota_mailbox_iter_deinit(&iter, &error2) < 0)
ret = -1;
+ if (ret < 0) {
+ const char *separator =
+ *error1 != '\0' && *error2 != '\0' ? " and " : "";
+ *error_r = t_strdup_printf(
+ "quota-count failed: %s%s%s",
+ error1, separator, error2);
+ }
root->recounting = FALSE;
return ret;
}
static int quota_count_cached(struct count_quota_root *root,
- uint64_t *bytes_r, uint64_t *count_r)
+ uint64_t *bytes_r, uint64_t *count_r,
+ const char **error_r)
{
int ret;
*count_r = root->cached_count;
return 1;
}
- ret = quota_count(&root->root, bytes_r, count_r);
+ ret = quota_count(&root->root, bytes_r, count_r, error_r);
if (ret > 0) {
root->cache_timeval = ioloop_timeval;
root->cached_bytes = *bytes_r;
{
struct count_quota_root *root = (struct count_quota_root *)_root;
uint64_t bytes, count;
+ const char *error;
- if (quota_count_cached(root, &bytes, &count) < 0) {
- *error_r = "quota-count failed";
+ if (quota_count_cached(root, &bytes, &count, &error) < 0) {
+ *error_r = t_strdup_printf(
+ "quota-count: Failed to get %s: %s", name, error);
return -1;
}
return 1;
}
-static int quota_count_recalculate_box(struct mailbox *box)
+static int quota_count_recalculate_box(struct mailbox *box,
+ const char **error_r)
{
struct mail_index_transaction *trans;
struct mailbox_metadata metadata;
/* non-temporary error, e.g. ACLs denied access. */
return 0;
}
- i_error("Couldn't open mailbox %s: %s", box->vname, errstr);
+ *error_r = t_strdup_printf(
+ "Couldn't open mailbox %s: %s", box->vname, errstr);
return -1;
}
i_zero(&vsize_hdr);
mail_index_update_header_ext(trans, box->vsize_hdr_ext_id,
0, &vsize_hdr, sizeof(vsize_hdr));
- if (mail_index_transaction_commit(&trans) < 0)
+ if (mail_index_transaction_commit(&trans) < 0) {
+ *error_r = t_strdup_printf(
+ "Couldn't commit mail index transaction for %s: %s",
+ box->vname,
+ mail_index_get_error_message(box->view->index));
return -1;
+ }
/* getting the vsize now forces its recalculation */
if (mailbox_get_metadata(box, MAILBOX_METADATA_VIRTUAL_SIZE,
&metadata) < 0) {
- i_error("Couldn't get mailbox %s vsize: %s", box->vname,
+ *error_r = t_strdup_printf(
+ "Couldn't get mailbox %s vsize: %s", box->vname,
mailbox_get_last_internal_error(box, NULL));
return -1;
}
/* call sync to write the change to mailbox list index */
if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FAST) < 0) {
- i_error("Couldn't sync mailbox %s: %s", box->vname,
+ *error_r = t_strdup_printf(
+ "Couldn't sync mailbox %s: %s", box->vname,
mailbox_get_last_internal_error(box, NULL));
return -1;
}
return 0;
}
-static int quota_count_recalculate(struct quota_root *root)
+static int quota_count_recalculate(struct quota_root *root,
+ const char **error_r)
{
struct quota_mailbox_iter *iter;
const struct mailbox_info *info;
struct mailbox *box;
int ret = 0;
+ const char *error1 = "", *error2 = "";
iter = quota_mailbox_iter_begin(root);
while ((info = quota_mailbox_iter_next(iter)) != NULL) {
box = mailbox_alloc(info->ns->list, info->vname, 0);
mailbox_set_reason(box, "quota recalculate");
- if (quota_count_recalculate_box(box) < 0)
+ if (quota_count_recalculate_box(box, &error1) < 0)
ret = -1;
mailbox_free(&box);
}
- if (quota_mailbox_iter_deinit(&iter) < 0)
+ if (quota_mailbox_iter_deinit(&iter, &error2) < 0)
ret = -1;
+ if (ret < 0) {
+ const char *separator =
+ *error1 != '\0' && *error2 != '\0' ? " and " : "";
+ *error_r = t_strdup_printf(
+ "quota-count: recalculate failed: %s%s%s",
+ error1, separator, error2);
+ }
return ret;
}
croot->cache_timeval.tv_sec = 0;
if (ctx->recalculate == QUOTA_RECALCULATE_FORCED) {
- if (quota_count_recalculate(root) < 0) {
- *error_r = "Calculating quota failed";
+ if (quota_count_recalculate(root, error_r) < 0)
return -1;
- }
}
return 0;
}