quota-dict.c revision 9c0cd052c03799d764938ffe500cf510bf9eb464
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2005-2015 Dovecot authors, see the included COPYING file */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "lib.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "str.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "dict.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "mail-user.h"
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen#include "mail-namespace.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "quota-private.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include <stdlib.h>
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#define DICT_QUOTA_CURRENT_PATH DICT_PATH_PRIVATE"quota/"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#define DICT_QUOTA_CURRENT_BYTES_PATH DICT_QUOTA_CURRENT_PATH"storage"
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen#define DICT_QUOTA_CURRENT_COUNT_PATH DICT_QUOTA_CURRENT_PATH"messages"
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
4fe3f07477bae6da3fb8d8fa9bab10ab82ada2bdTimo Sirainenstruct dict_quota_root {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen struct quota_root root;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen struct dict *dict;
5411e6f71afb0f753cdf831f4da4ee73e928796eTimo Sirainen};
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen
4fe3f07477bae6da3fb8d8fa9bab10ab82ada2bdTimo Sirainenextern struct quota_backend quota_backend_dict;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic struct quota_root *dict_quota_alloc(void)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct dict_quota_root *root;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen root = i_new(struct dict_quota_root, 1);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return &root->root;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic int dict_quota_init(struct quota_root *_root, const char *args,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen const char **error_r)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct dict_quota_root *root = (struct dict_quota_root *)_root;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct dict_settings set;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen const char *username, *p, *error;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen p = args == NULL ? NULL : strchr(args, ':');
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (p == NULL) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen *error_r = "URI missing from parameters";
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return -1;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
a356c4736fe6041142c6096045bc00c15a80af4eTimo Sirainen username = t_strdup_until(args, p);
a356c4736fe6041142c6096045bc00c15a80af4eTimo Sirainen args = p+1;
a356c4736fe6041142c6096045bc00c15a80af4eTimo Sirainen
a356c4736fe6041142c6096045bc00c15a80af4eTimo Sirainen for (;;) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* FIXME: pretty ugly in here. the parameters should have
a356c4736fe6041142c6096045bc00c15a80af4eTimo Sirainen been designed to be extensible. do it in a future version */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (strncmp(args, "noenforcing:", 12) == 0) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen _root->no_enforcing = TRUE;
c4900d31385344bfadaee53a897daeafdb3063d8Timo Sirainen args += 12;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen } else if (strncmp(args, "hidden:", 7) == 0) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen _root->hidden = TRUE;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen args += 7;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen } else if (strncmp(args, "ignoreunlimited:", 16) == 0) {
34a45b80c8ed18861c6e343fe40adbe360fc6badTimo Sirainen _root->disable_unlimited_tracking = TRUE;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen args += 16;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen } else if (strncmp(args, "ns=", 3) == 0) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen p = strchr(args, ':');
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (p == NULL)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen break;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen _root->ns_prefix = p_strdup_until(_root->pool,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen args + 3, p);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen args = p + 1;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen } else {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen break;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (*username == '\0')
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen username = _root->quota->user->username;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (_root->quota->set->debug) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_debug("dict quota: user=%s, uri=%s, noenforcing=%d",
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen username, args, _root->no_enforcing);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* FIXME: we should use 64bit integer as datatype instead but before
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen it can actually be used don't bother */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen memset(&set, 0, sizeof(set));
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen set.username = username;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen set.base_dir = _root->quota->user->set->base_dir;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (mail_user_get_home(_root->quota->user, &set.home_dir) <= 0)
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen set.home_dir = NULL;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (dict_init_full(args, &set, &root->dict, &error) < 0) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen *error_r = t_strdup_printf("dict_init(%s) failed: %s", args, error);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen return -1;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return 0;
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen}
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainenstatic void dict_quota_deinit(struct quota_root *_root)
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen{
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen struct dict_quota_root *root = (struct dict_quota_root *)_root;
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (root->dict != NULL)
4fe3f07477bae6da3fb8d8fa9bab10ab82ada2bdTimo Sirainen dict_deinit(&root->dict);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_free(root);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
4c20178a7f70bfe43d252e50796013aac1d8c74aTimo Sirainenstatic const char *const *
4c20178a7f70bfe43d252e50796013aac1d8c74aTimo Sirainendict_quota_root_get_resources(struct quota_root *root ATTR_UNUSED)
4c20178a7f70bfe43d252e50796013aac1d8c74aTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen static const char *resources[] = {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen QUOTA_NAME_STORAGE_KILOBYTES, QUOTA_NAME_MESSAGES, NULL
4fe3f07477bae6da3fb8d8fa9bab10ab82ada2bdTimo Sirainen };
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return resources;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen}
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainenstatic int
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainendict_quota_count(struct dict_quota_root *root,
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen bool want_bytes, uint64_t *value_r)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen{
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen struct dict_transaction_context *dt;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen uint64_t bytes, count;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (quota_count(&root->root, &bytes, &count) < 0)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen return -1;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen T_BEGIN {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen dt = dict_transaction_begin(root->dict);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* these unsets are mainly necessary for pgsql, because its
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen trigger otherwise increases quota without deleting it */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen dict_unset(dt, DICT_QUOTA_CURRENT_BYTES_PATH);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen dict_unset(dt, DICT_QUOTA_CURRENT_COUNT_PATH);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen dict_set(dt, DICT_QUOTA_CURRENT_BYTES_PATH, dec2str(bytes));
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen dict_set(dt, DICT_QUOTA_CURRENT_COUNT_PATH, dec2str(count));
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen } T_END;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen dict_transaction_commit_async(&dt, NULL, NULL);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen *value_r = want_bytes ? bytes : count;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return 1;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
8e1ecc6542da1e14c14e2e59d39dbccdbf68e2b5Timo Sirainenstatic int
8e1ecc6542da1e14c14e2e59d39dbccdbf68e2b5Timo Sirainendict_quota_get_resource(struct quota_root *_root,
8e1ecc6542da1e14c14e2e59d39dbccdbf68e2b5Timo Sirainen const char *name, uint64_t *value_r)
8e1ecc6542da1e14c14e2e59d39dbccdbf68e2b5Timo Sirainen{
8e1ecc6542da1e14c14e2e59d39dbccdbf68e2b5Timo Sirainen struct dict_quota_root *root = (struct dict_quota_root *)_root;
8e1ecc6542da1e14c14e2e59d39dbccdbf68e2b5Timo Sirainen bool want_bytes;
4fe3f07477bae6da3fb8d8fa9bab10ab82ada2bdTimo Sirainen int ret;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (strcmp(name, QUOTA_NAME_STORAGE_BYTES) == 0)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen want_bytes = TRUE;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen else if (strcmp(name, QUOTA_NAME_MESSAGES) == 0)
4e43828ef88183a0750a8a374b6ba4ecf227c58fTimo Sirainen want_bytes = FALSE;
4e43828ef88183a0750a8a374b6ba4ecf227c58fTimo Sirainen else
4e43828ef88183a0750a8a374b6ba4ecf227c58fTimo Sirainen return 0;
4e43828ef88183a0750a8a374b6ba4ecf227c58fTimo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen T_BEGIN {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen const char *value;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen ret = dict_lookup(root->dict, unsafe_data_stack_pool,
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen want_bytes ? DICT_QUOTA_CURRENT_BYTES_PATH :
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen DICT_QUOTA_CURRENT_COUNT_PATH, &value);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (ret < 0)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen *value_r = 0;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen else {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen long long tmp;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* recalculate quota if it's negative or if it
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen wasn't found */
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainen tmp = ret == 0 ? -1 : strtoll(value, NULL, 10);
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainen if (tmp >= 0)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen *value_r = tmp;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen else {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen ret = dict_quota_count(root, want_bytes,
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen value_r);
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainen }
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainen }
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen } T_END;
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainen return ret;
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainen}
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainenstatic void dict_quota_update_callback(int ret, void *context)
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainen{
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainen struct dict_quota_root *root = context;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen uint64_t value;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (ret == 0) {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen /* row doesn't exist, need to recalculate it */
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen (void)dict_quota_count(root, TRUE, &value);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen } else if (ret < 0) {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen i_error("dict quota: Quota update failed, it's now desynced");
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen }
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen}
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainenstatic int
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainendict_quota_update(struct quota_root *_root,
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen struct quota_transaction_context *ctx)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen{
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen struct dict_quota_root *root = (struct dict_quota_root *) _root;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen struct dict_transaction_context *dt;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen uint64_t value;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (ctx->recalculate) {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (dict_quota_count(root, TRUE, &value) < 0)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen return -1;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen } else {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen dt = dict_transaction_begin(root->dict);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (ctx->bytes_used != 0) {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen dict_atomic_inc(dt, DICT_QUOTA_CURRENT_BYTES_PATH,
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen ctx->bytes_used);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen }
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (ctx->count_used != 0) {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen dict_atomic_inc(dt, DICT_QUOTA_CURRENT_COUNT_PATH,
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen ctx->count_used);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen }
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen dict_transaction_commit_async(&dt, dict_quota_update_callback,
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen root);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen }
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen return 0;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen}
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainenstatic void dict_quota_flush(struct quota_root *_root)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen{
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen struct dict_quota_root *root = (struct dict_quota_root *)_root;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen (void)dict_wait(root->dict);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen}
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainenstruct quota_backend quota_backend_dict = {
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen "dict",
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen {
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen dict_quota_alloc,
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen dict_quota_init,
242abe3ad2423776e9cf05e1304eb8fda4831b23Timo Sirainen dict_quota_deinit,
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainen NULL,
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainen NULL,
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainen NULL,
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainen dict_quota_root_get_resources,
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen dict_quota_get_resource,
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen dict_quota_update,
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen NULL,
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen dict_quota_flush
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen }
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen};
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen