quota-private.h revision 10207755f33a4cf1a1e901968137ae4f2bc93bbf
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen#ifndef QUOTA_PRIVATE_H
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen#define QUOTA_PRIVATE_H
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen#include "mail-storage-private.h"
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen#include "mail-namespace.h"
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen#include "quota.h"
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen/* Modules should use do "my_id = quota_module_id++" and
72f67d7d7681934bb3d4baaea1d88f79521dee3dTimo Sirainen use quota_module_contexts[id] for their own purposes. */
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainenextern unsigned int quota_module_id;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainenstruct quota {
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen struct mail_user *user;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen struct quota_settings *set;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen ARRAY(struct quota_root *) roots;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen ARRAY(struct mail_namespace *) namespaces;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen struct mail_namespace *unwanted_ns;
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen};
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainenstruct quota_settings {
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen pool_t pool;
50fe5e053d565b40b0ed2cc7a64b6b98971c0305Timo Sirainen
50fe5e053d565b40b0ed2cc7a64b6b98971c0305Timo Sirainen ARRAY(struct quota_root_settings *) root_sets;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen enum quota_alloc_result (*test_alloc)(
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen struct quota_transaction_context *ctx, uoff_t size);
1cfdcb36985904eff281fc6d7ea2d13b3c375980Timo Sirainen
1cfdcb36985904eff281fc6d7ea2d13b3c375980Timo Sirainen uoff_t max_mail_size;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen const char *quota_exceeded_msg;
1cfdcb36985904eff281fc6d7ea2d13b3c375980Timo Sirainen bool debug:1;
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen bool initialized:1;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen bool vsizes:1;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen};
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainenstruct quota_rule {
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen const char *mailbox_mask;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen int64_t bytes_limit, count_limit;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen /* relative to default_rule */
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen int bytes_percent, count_percent;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen /* Don't include this mailbox in quota */
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen bool ignore:1;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen};
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainenstruct quota_warning_rule {
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen struct quota_rule rule;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen const char *command;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen bool reverse:1;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen};
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainenstruct quota_backend_vfuncs {
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen struct quota_root *(*alloc)(void);
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen int (*init)(struct quota_root *root, const char *args,
94163c620a8880024d0e8bbb503c788159fa222bTimo Sirainen const char **error_r);
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen void (*deinit)(struct quota_root *root);
1cfdcb36985904eff281fc6d7ea2d13b3c375980Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen bool (*parse_rule)(struct quota_root_settings *root_set,
72f67d7d7681934bb3d4baaea1d88f79521dee3dTimo Sirainen struct quota_rule *rule,
72f67d7d7681934bb3d4baaea1d88f79521dee3dTimo Sirainen const char *str, const char **error_r);
72f67d7d7681934bb3d4baaea1d88f79521dee3dTimo Sirainen int (*init_limits)(struct quota_root *root);
72f67d7d7681934bb3d4baaea1d88f79521dee3dTimo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen /* called once for each namespace */
1cfdcb36985904eff281fc6d7ea2d13b3c375980Timo Sirainen void (*namespace_added)(struct quota *quota,
1cfdcb36985904eff281fc6d7ea2d13b3c375980Timo Sirainen struct mail_namespace *ns);
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen const char *const *(*get_resources)(struct quota_root *root);
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen int (*get_resource)(struct quota_root *root,
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen const char *name, uint64_t *value_r);
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen int (*update)(struct quota_root *root,
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen struct quota_transaction_context *ctx);
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen bool (*match_box)(struct quota_root *root, struct mailbox *box);
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen void (*flush)(struct quota_root *root);
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen};
d84c270231a617298088f597474a73f4a14921aeTimo Sirainen
d84c270231a617298088f597474a73f4a14921aeTimo Sirainenstruct quota_backend {
d84c270231a617298088f597474a73f4a14921aeTimo Sirainen /* quota backends equal if backend1.name == backend2.name */
d84c270231a617298088f597474a73f4a14921aeTimo Sirainen const char *name;
d84c270231a617298088f597474a73f4a14921aeTimo Sirainen struct quota_backend_vfuncs v;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen};
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainenstruct quota_root_settings {
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen /* Unique quota root name. */
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen const char *name;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen /* Name in settings, e.g. "quota", "quota2", .. */
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen const char *set_name;
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen struct quota_settings *set;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen const char *args;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen const struct quota_backend *backend;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen struct quota_rule default_rule;
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen ARRAY(struct quota_rule) rules;
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen ARRAY(struct quota_warning_rule) warning_rules;
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen const char *limit_set;
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen /* If user is under quota before saving a mail, allow the last mail to
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen bring the user over quota by this many bytes. */
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen uint64_t last_mail_max_extra_bytes;
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen struct quota_rule grace_rule;
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen /* Limits in default_rule override backend's quota limits */
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen bool force_default_rule:1;
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen /* TRUE if any of the warning_rules have reverse==TRUE */
50fe5e053d565b40b0ed2cc7a64b6b98971c0305Timo Sirainen bool have_reverse_warnings:1;
50fe5e053d565b40b0ed2cc7a64b6b98971c0305Timo Sirainen};
50fe5e053d565b40b0ed2cc7a64b6b98971c0305Timo Sirainen
50fe5e053d565b40b0ed2cc7a64b6b98971c0305Timo Sirainenstruct quota_root {
50fe5e053d565b40b0ed2cc7a64b6b98971c0305Timo Sirainen pool_t pool;
6899af0c40f5e1ef80bd18961cea3a192134a4a4Timo Sirainen
6899af0c40f5e1ef80bd18961cea3a192134a4a4Timo Sirainen struct quota_root_settings *set;
6899af0c40f5e1ef80bd18961cea3a192134a4a4Timo Sirainen struct quota *quota;
6899af0c40f5e1ef80bd18961cea3a192134a4a4Timo Sirainen struct quota_backend backend;
50fe5e053d565b40b0ed2cc7a64b6b98971c0305Timo Sirainen struct dict *limit_set_dict;
d84c270231a617298088f597474a73f4a14921aeTimo Sirainen
d84c270231a617298088f597474a73f4a14921aeTimo Sirainen /* this quota root applies only to this namespace. it may also be
d84c270231a617298088f597474a73f4a14921aeTimo Sirainen a public namespace without an owner. */
6899af0c40f5e1ef80bd18961cea3a192134a4a4Timo Sirainen struct mail_namespace *ns;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen /* this is set in quota init(), because namespaces aren't known yet.
396999508030c8498cb538eb8943e6b61394994cTimo Sirainen when accessing shared users the ns_prefix may be non-NULL but
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen ns=NULL, so when checking if quota root applies only to a specific
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen namespace use the ns_prefix!=NULL check. */
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen const char *ns_prefix;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen /* initially the same as set->default_rule.*_limit, but some backends
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen may change these by reading the limits elsewhere (e.g. Maildir++,
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen FS quota) */
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen int64_t bytes_limit, count_limit;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen /* Module-specific contexts. See quota_module_id. */
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen ARRAY(void) quota_module_contexts;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen /* don't enforce quota when saving */
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen bool no_enforcing:1;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen /* quota is automatically updated. update() should be called but the
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen bytes won't be changed. count is still changed, because it's cheap
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen to do and it's internally used to figure out whether there have
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen been some changes and that quota_warnings should be checked. */
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen bool auto_updating:1;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen /* If user has unlimited quota, disable quota tracking */
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen bool disable_unlimited_tracking:1;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen /* Set while quota is being recalculated to avoid recursion. */
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen bool recounting:1;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen /* Quota root is hidden (to e.g. IMAP GETQUOTAROOT) */
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen bool hidden:1;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen /* Did we already check quota_over_flag correctness? */
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen bool quota_over_flag_checked:1;
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen};
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
396999508030c8498cb538eb8943e6b61394994cTimo Sirainenstruct quota_transaction_context {
396999508030c8498cb538eb8943e6b61394994cTimo Sirainen union mailbox_transaction_module_context module_ctx;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen struct quota *quota;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen struct mailbox *box;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen int64_t bytes_used, count_used;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen /* how many bytes/mails can be saved until limit is reached.
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen (set once, not updated by bytes_used/count_used).
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen if last_mail_max_extra_bytes>0, the bytes_ceil is initially
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen increased by that much, while bytes_ceil2 contains the real ceiling.
396999508030c8498cb538eb8943e6b61394994cTimo Sirainen after the first allocation is done, bytes_ceil is set to
396999508030c8498cb538eb8943e6b61394994cTimo Sirainen bytes_ceil2. */
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen uint64_t bytes_ceil, bytes_ceil2, count_ceil;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen /* How many bytes/mails we are over quota. Like *_ceil, these are set
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen only once and not updated by bytes_used/count_used. (Either *_ceil
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen or *_over is always zero.) */
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen uint64_t bytes_over, count_over;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen struct mail *tmp_mail;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen enum quota_recalculate recalculate;
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen bool limits_set:1;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen bool failed:1;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen bool sync_transaction:1;
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen /* TRUE if all roots have auto_updating=TRUE */
4b94ae3dcbace4781b64e87aea00ec0bc03a0d8aTimo Sirainen bool auto_updating:1;
4b94ae3dcbace4781b64e87aea00ec0bc03a0d8aTimo Sirainen /* Quota doesn't need to be updated within this transaction. */
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen bool no_quota_updates:1;
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen};
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen/* Register storage to all user's quota roots. */
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainenvoid quota_add_user_namespace(struct quota *quota, struct mail_namespace *ns);
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainenvoid quota_remove_user_namespace(struct mail_namespace *ns);
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainenint quota_root_default_init(struct quota_root *root, const char *args,
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen const char **error_r);
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainenstruct quota *quota_get_mail_user_quota(struct mail_user *user);
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainenbool quota_root_is_namespace_visible(struct quota_root *root,
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainen struct mail_namespace *ns);
56439f2879ad690d9ac637e2b90b612760d2f219Timo Sirainenstruct quota_rule *
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainenquota_root_rule_find(struct quota_root_settings *root_set, const char *name);
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainenvoid quota_root_recalculate_relative_rules(struct quota_root_settings *root_set,
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen int64_t bytes_limit,
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen int64_t count_limit);
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen/* Returns 1 if values were returned successfully, 0 if we're recursing into
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen the same function, -1 if error. */
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainenint quota_count(struct quota_root *root, uint64_t *bytes_r, uint64_t *count_r);
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainenint quota_root_parse_grace(struct quota_root_settings *root_set,
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen const char *value, const char **error_r);
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainenbool quota_warning_match(const struct quota_warning_rule *w,
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen uint64_t bytes_before, uint64_t bytes_current,
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen uint64_t count_before, uint64_t count_current,
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen const char **reason_r);
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainenbool quota_transaction_is_over(struct quota_transaction_context *ctx, uoff_t size);
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainenint quota_transaction_set_limits(struct quota_transaction_context *ctx);
d84c270231a617298088f597474a73f4a14921aeTimo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainenvoid quota_backend_register(const struct quota_backend *backend);
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainenvoid quota_backend_unregister(const struct quota_backend *backend);
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen#endif
e9e5e84ffb2ce2e606a24ce6d930580367562ff0Timo Sirainen