From: Timo Sirainen Date: Mon, 9 Nov 2009 23:22:37 +0000 (-0500) Subject: Added "size" setting type, which supports B/k/M/G/T suffixes. X-Git-Tag: 2.0.alpha3~14 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=61618d4c58080570f689614fec204ae14e90cef2;p=thirdparty%2Fdovecot%2Fcore.git Added "size" setting type, which supports B/k/M/G/T suffixes. --HG-- branch : HEAD --- diff --git a/doc/example-config/conf.d/auth.conf b/doc/example-config/conf.d/auth.conf index a89787d6ad..1edda31ddc 100644 --- a/doc/example-config/conf.d/auth.conf +++ b/doc/example-config/conf.d/auth.conf @@ -2,9 +2,8 @@ ## Authentication processes ## -# Authentication cache size in kilobytes. 0 means it's disabled. -# Note that bsdauth, PAM and vpopmail require cache_key to be set for caching -# to be used. +# Authentication cache size (e.g. 10M). 0 means it's disabled. Note that +# bsdauth, PAM and vpopmail require cache_key to be set for caching to be used. #auth_cache_size = 0 # Time to live in seconds for cached data. After this many seconds the cached # record is no longer used, *except* if the main database lookup returns diff --git a/doc/example-config/conf.d/imap.conf b/doc/example-config/conf.d/imap.conf index c7699828ba..708326ea9a 100644 --- a/doc/example-config/conf.d/imap.conf +++ b/doc/example-config/conf.d/imap.conf @@ -3,10 +3,10 @@ ## protocol imap { - # Maximum IMAP command line length in bytes. Some clients generate very long - # command lines with huge mailboxes, so you may need to raise this if you get + # Maximum IMAP command line length. Some clients generate very long command + # lines with huge mailboxes, so you may need to raise this if you get # "Too long argument" or "IMAP command line too large" errors often. - #imap_max_line_length = 65536 + #imap_max_line_length = 64k # Maximum number of IMAP connections allowed for a user from each IP address. # NOTE: The username is compared case-sensitively. diff --git a/doc/example-config/conf.d/mail.conf b/doc/example-config/conf.d/mail.conf index cf3b7e875e..d50e9ffe93 100644 --- a/doc/example-config/conf.d/mail.conf +++ b/doc/example-config/conf.d/mail.conf @@ -295,7 +295,7 @@ # aren't immediately visible to other MUAs. #mbox_lazy_writes = yes -# If mbox size is smaller than this (in kilobytes), don't write index files. +# If mbox size is smaller than this (e.g. 100k), don't write index files. # If an index file already exists it's still read, just not updated. #mbox_min_index_size = 0 @@ -303,12 +303,11 @@ ## mdbox-specific settings ## -# Maximum dbox file size in kilobytes until it's rotated. -#mdbox_rotate_size = 2048 +# Maximum dbox file size until it's rotated. +#mdbox_rotate_size = 2M -# Minimum dbox file size in kilobytes before it's rotated -# (overrides mdbox_rotate_days) -#mdbox_rotate_min_size = 16 +# Minimum dbox file size before it's rotated (overrides mdbox_rotate_days) +#mdbox_rotate_min_size = 16k # Maximum dbox file age in days until it's rotated. Day always begins from # midnight, so 1 = today, 2 = yesterday, etc. 0 = check disabled. diff --git a/doc/example-config/conf.d/master.conf b/doc/example-config/conf.d/master.conf index ac0141c128..95e44fe0fe 100644 --- a/doc/example-config/conf.d/master.conf +++ b/doc/example-config/conf.d/master.conf @@ -1,6 +1,6 @@ #default_process_limit = 100 #default_client_limit = 1000 -#default_vsz_limit = 256 +#default_vsz_limit = 256M service imap-login { inet_listener { @@ -17,7 +17,7 @@ service imap-login { #service_count = 1 # If you set service_count=0, you probably need to grow this. - #vsz_limit = 64 + #vsz_limit = 64M } service pop3-login { @@ -39,7 +39,7 @@ service lmtp { service imap { # Most of the memory goes to mmap()ing files. You may need to increase this # limit if you have huge mailboxes. - #vsz_limit = 256 + #vsz_limit = 256M } service auth { diff --git a/src/auth/auth-settings.c b/src/auth/auth-settings.c index 5ac8f1fd15..5b45b7055d 100644 --- a/src/auth/auth-settings.c +++ b/src/auth/auth-settings.c @@ -151,7 +151,7 @@ static const struct setting_define auth_setting_defines[] = { DEF(SET_STR, mechanisms), DEF(SET_STR, realms), DEF(SET_STR, default_realm), - DEF(SET_UINT, cache_size), + DEF(SET_SIZE, cache_size), DEF(SET_UINT, cache_ttl), DEF(SET_UINT, cache_negative_ttl), DEF(SET_STR, username_chars), diff --git a/src/auth/auth-settings.h b/src/auth/auth-settings.h index 7f504b024d..86853b0884 100644 --- a/src/auth/auth-settings.h +++ b/src/auth/auth-settings.h @@ -20,7 +20,7 @@ struct auth_settings { const char *mechanisms; const char *realms; const char *default_realm; - unsigned int cache_size; + uoff_t cache_size; unsigned int cache_ttl; unsigned int cache_negative_ttl; const char *username_chars; diff --git a/src/auth/passdb-cache.c b/src/auth/passdb-cache.c index ef2366a31b..e5094fffc3 100644 --- a/src/auth/passdb-cache.c +++ b/src/auth/passdb-cache.c @@ -127,7 +127,7 @@ void passdb_cache_init(const struct auth_settings *set) if (set->cache_size == 0 || set->cache_ttl == 0) return; - passdb_cache = auth_cache_new(set->cache_size * 1024UL, set->cache_ttl, + passdb_cache = auth_cache_new(set->cache_size, set->cache_ttl, set->cache_negative_ttl); } diff --git a/src/config/config-request.c b/src/config/config-request.c index 4eab8e782c..33111b9163 100644 --- a/src/config/config-request.c +++ b/src/config/config-request.c @@ -128,6 +128,14 @@ settings_export(struct settings_export_context *ctx, } break; } + case SET_SIZE: { + const uoff_t *val = value, *dval = default_value; + if (dump_default || dval == NULL || *val != *dval) { + str_printfa(ctx->value, "%llu", + (unsigned long long)*val); + } + break; + } case SET_UINT: { const unsigned int *val = value, *dval = default_value; if (dump_default || dval == NULL || *val != *dval) diff --git a/src/imap/imap-settings.c b/src/imap/imap-settings.c index bbde4f1064..7ba2667377 100644 --- a/src/imap/imap-settings.c +++ b/src/imap/imap-settings.c @@ -62,7 +62,7 @@ static const struct setting_define imap_setting_defines[] = { DEF(SET_BOOL, mail_debug), DEF(SET_BOOL, verbose_proctitle), - DEF(SET_UINT, imap_max_line_length), + DEF(SET_SIZE, imap_max_line_length), DEF(SET_UINT, imap_idle_notify_interval), DEF(SET_STR, imap_capability), DEF(SET_STR, imap_client_workarounds), @@ -80,7 +80,7 @@ static const struct imap_settings imap_default_settings = { /* RFC-2683 recommends at least 8000 bytes. Some clients however don't break large message sets to multiple commands, so we're pretty liberal by default. */ - MEMBER(imap_max_line_length) 65536, + MEMBER(imap_max_line_length) 64*1024, MEMBER(imap_idle_notify_interval) 120, MEMBER(imap_capability) "", MEMBER(imap_client_workarounds) "outlook-idle", diff --git a/src/imap/imap-settings.h b/src/imap/imap-settings.h index 09bd52b8b7..e8bdf7e585 100644 --- a/src/imap/imap-settings.h +++ b/src/imap/imap-settings.h @@ -16,7 +16,7 @@ struct imap_settings { bool verbose_proctitle; /* imap: */ - unsigned int imap_max_line_length; + uoff_t imap_max_line_length; unsigned int imap_idle_notify_interval; const char *imap_capability; const char *imap_client_workarounds; diff --git a/src/lib-master/service-settings.h b/src/lib-master/service-settings.h index 0d66fa6b08..77fc6d3b12 100644 --- a/src/lib-master/service-settings.h +++ b/src/lib-master/service-settings.h @@ -42,7 +42,7 @@ struct service_settings { unsigned int process_limit; unsigned int client_limit; unsigned int service_count; - unsigned int vsz_limit; + uoff_t vsz_limit; ARRAY_TYPE(file_listener_settings) unix_listeners; ARRAY_TYPE(file_listener_settings) fifo_listeners; diff --git a/src/lib-settings/settings-parser.c b/src/lib-settings/settings-parser.c index f38904b1fc..a1435469f3 100644 --- a/src/lib-settings/settings-parser.c +++ b/src/lib-settings/settings-parser.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -308,6 +309,61 @@ get_uint(struct setting_parser_context *ctx, const char *value, return 0; } +static int +get_size(struct setting_parser_context *ctx, const char *value, + uoff_t *result_r) +{ + unsigned long long num, multiply; + char *p; + + num = strtoull(value, &p, 10); + switch (i_toupper(*p)) { + case '\0': + multiply = 1; + break; + case 'B': + multiply = 1; + p += 1; + break; + case 'K': + multiply = 1024; + p += 1; + break; + case 'M': + multiply = 1024*1024; + p += 1; + break; + case 'G': + multiply = 1024*1024*1024; + p += 1; + break; + case 'T': + multiply = 1024ULL*1024*1024*1024; + p += 1; + break; + } + + if (multiply > 1) { + /* Allow: k, ki, kiB */ + if (i_toupper(*p) == 'I') + p++; + if (i_toupper(*p) == 'B') + p++; + } + if (*p != '\0') { + ctx->error = p_strconcat(ctx->parser_pool, "Invalid size: ", + value, NULL); + return -1; + } + if (num > -1ULL / multiply) { + ctx->error = p_strconcat(ctx->parser_pool, + "Size is too large: ", value, NULL); + return -1; + } + *result_r = num * multiply; + return 0; +} + static int get_enum(struct setting_parser_context *ctx, const char *value, char **result_r, const char *allowed_values) { @@ -448,6 +504,10 @@ settings_parse(struct setting_parser_context *ctx, struct setting_link *link, if (get_uint(ctx, value, (unsigned int *)ptr) < 0) return -1; break; + case SET_SIZE: + if (get_size(ctx, value, (uoff_t *)ptr) < 0) + return -1; + break; case SET_STR: *((char **)ptr) = p_strdup(ctx->set_pool, value); break; @@ -902,6 +962,7 @@ settings_var_expand_info(const struct setting_parser_info *info, switch (def->type) { case SET_BOOL: case SET_UINT: + case SET_SIZE: case SET_STR: case SET_ENUM: case SET_STRLIST: @@ -971,6 +1032,7 @@ bool settings_vars_have_key(const struct setting_parser_info *info, void *set, switch (def->type) { case SET_BOOL: case SET_UINT: + case SET_SIZE: case SET_STR: case SET_ENUM: case SET_STRLIST: @@ -1045,6 +1107,13 @@ setting_copy(enum setting_type type, const void *src, void *dest, pool_t pool) *dest_uint = *src_uint; break; } + case SET_SIZE: { + const uoff_t *src_size = src; + uoff_t *dest_size = dest; + + *dest_size = *src_size; + break; + } case SET_STR_VARS: case SET_STR: case SET_ENUM: { @@ -1139,6 +1208,7 @@ settings_changes_dup(const struct setting_parser_info *info, switch (def->type) { case SET_BOOL: case SET_UINT: + case SET_SIZE: case SET_STR_VARS: case SET_STR: case SET_ENUM: diff --git a/src/lib-settings/settings-parser.h b/src/lib-settings/settings-parser.h index 5f05648f2c..f9bab64cc8 100644 --- a/src/lib-settings/settings-parser.h +++ b/src/lib-settings/settings-parser.h @@ -19,6 +19,7 @@ struct var_expand_table; enum setting_type { SET_BOOL, SET_UINT, + SET_SIZE, SET_STR, SET_STR_VARS, /* string with %variables */ SET_ENUM, @@ -47,6 +48,10 @@ struct setting_define { { SET_UINT + COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE( \ ((struct struct_name *)0)->name, unsigned int), \ #name, offsetof(struct struct_name, name), NULL } +#define SETTING_DEFINE_STRUCT_SIZE(name, struct_name) \ + { SET_SIZE + COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE( \ + ((struct struct_name *)0)->name, uoff_t), \ + #name, offsetof(struct struct_name, name), NULL } #define SETTING_DEFINE_STRUCT_STR(name, struct_name) \ { SET_STR + COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE( \ ((struct struct_name *)0)->name, const char *), \ @@ -185,5 +190,7 @@ int settings_parser_apply_changes(struct setting_parser_context *dest, /* Return section name escaped */ const char *settings_section_escape(const char *name); +/* Parse a size string to actual size. */ +int settings_parse_size(const char *str, uoff_t *size_r, const char **error_r); #endif diff --git a/src/lib-storage/index/dbox-multi/mdbox-settings.c b/src/lib-storage/index/dbox-multi/mdbox-settings.c index ba564412f7..5b63f0d9e1 100644 --- a/src/lib-storage/index/dbox-multi/mdbox-settings.c +++ b/src/lib-storage/index/dbox-multi/mdbox-settings.c @@ -15,8 +15,8 @@ static bool mdbox_settings_verify(void *_set, pool_t pool ATTR_UNUSED, const char **error_r); static const struct setting_define mdbox_setting_defines[] = { - DEF(SET_UINT, mdbox_rotate_size), - DEF(SET_UINT, mdbox_rotate_min_size), + DEF(SET_SIZE, mdbox_rotate_size), + DEF(SET_SIZE, mdbox_rotate_min_size), DEF(SET_UINT, mdbox_rotate_days), DEF(SET_UINT, mdbox_max_open_files), DEF(SET_UINT, mdbox_purge_min_percentage), @@ -25,7 +25,7 @@ static const struct setting_define mdbox_setting_defines[] = { }; static const struct mdbox_settings mdbox_default_settings = { - MEMBER(mdbox_rotate_size) 2048*1024, + MEMBER(mdbox_rotate_size) 2*1024*1024, MEMBER(mdbox_rotate_min_size) 16*1024, MEMBER(mdbox_rotate_days) 0, MEMBER(mdbox_max_open_files) 64, diff --git a/src/lib-storage/index/dbox-multi/mdbox-settings.h b/src/lib-storage/index/dbox-multi/mdbox-settings.h index 5425e309c4..ef265340fc 100644 --- a/src/lib-storage/index/dbox-multi/mdbox-settings.h +++ b/src/lib-storage/index/dbox-multi/mdbox-settings.h @@ -2,8 +2,8 @@ #define MDBOX_SETTINGS_H struct mdbox_settings { - unsigned int mdbox_rotate_size; - unsigned int mdbox_rotate_min_size; + uoff_t mdbox_rotate_size; + uoff_t mdbox_rotate_min_size; unsigned int mdbox_rotate_days; unsigned int mdbox_max_open_files; unsigned int mdbox_purge_min_percentage; diff --git a/src/lib-storage/index/mbox/mbox-settings.c b/src/lib-storage/index/mbox/mbox-settings.c index 6c32af2e93..48f7031731 100644 --- a/src/lib-storage/index/mbox/mbox-settings.c +++ b/src/lib-storage/index/mbox/mbox-settings.c @@ -16,7 +16,7 @@ static const struct setting_define mbox_setting_defines[] = { DEF(SET_STR, mbox_write_locks), DEF(SET_UINT, mbox_lock_timeout), DEF(SET_UINT, mbox_dotlock_change_timeout), - DEF(SET_UINT, mbox_min_index_size), + DEF(SET_SIZE, mbox_min_index_size), DEF(SET_BOOL, mbox_dirty_syncs), DEF(SET_BOOL, mbox_very_dirty_syncs), DEF(SET_BOOL, mbox_lazy_writes), diff --git a/src/lib-storage/index/mbox/mbox-settings.h b/src/lib-storage/index/mbox/mbox-settings.h index 7c3188c4be..19322afadc 100644 --- a/src/lib-storage/index/mbox/mbox-settings.h +++ b/src/lib-storage/index/mbox/mbox-settings.h @@ -6,7 +6,7 @@ struct mbox_settings { const char *mbox_write_locks; unsigned int mbox_lock_timeout; unsigned int mbox_dotlock_change_timeout; - unsigned int mbox_min_index_size; + uoff_t mbox_min_index_size; bool mbox_dirty_syncs; bool mbox_very_dirty_syncs; bool mbox_lazy_writes; diff --git a/src/lib-storage/index/mbox/mbox-storage.c b/src/lib-storage/index/mbox/mbox-storage.c index 49b01eeab5..15ebffa833 100644 --- a/src/lib-storage/index/mbox/mbox-storage.c +++ b/src/lib-storage/index/mbox/mbox-storage.c @@ -329,7 +329,7 @@ static bool want_memory_indexes(struct mbox_storage *storage, const char *path) return FALSE; } } - return st.st_size / 1024 < storage->set->mbox_min_index_size; + return (uoff_t)st.st_size < storage->set->mbox_min_index_size; } static struct mailbox * diff --git a/src/master/master-settings.c b/src/master/master-settings.c index f7ee1e0d92..1fbd489d26 100644 --- a/src/master/master-settings.c +++ b/src/master/master-settings.c @@ -111,7 +111,7 @@ static const struct setting_define service_setting_defines[] = { DEF(SET_UINT, process_limit), DEF(SET_UINT, client_limit), DEF(SET_UINT, service_count), - DEF(SET_UINT, vsz_limit), + DEF(SET_SIZE, vsz_limit), DEFLIST_UNIQUE(unix_listeners, "unix_listener", &file_listener_setting_parser_info), @@ -140,7 +140,7 @@ static const struct service_settings service_default_settings = { MEMBER(process_limit) -1U, MEMBER(client_limit) 0, MEMBER(service_count) 0, - MEMBER(vsz_limit) -1U, + MEMBER(vsz_limit) (uoff_t)-1, MEMBER(unix_listeners) ARRAY_INIT, MEMBER(fifo_listeners) ARRAY_INIT, @@ -174,7 +174,7 @@ static const struct setting_define master_setting_defines[] = { DEF(SET_ENUM, ssl), DEF(SET_UINT, default_process_limit), DEF(SET_UINT, default_client_limit), - DEF(SET_UINT, default_vsz_limit), + DEF(SET_SIZE, default_vsz_limit), DEF(SET_BOOL, version_ignore), DEF(SET_BOOL, mail_debug), @@ -198,7 +198,7 @@ static const struct master_settings master_default_settings = { MEMBER(ssl) "yes:no:required", MEMBER(default_process_limit) 100, MEMBER(default_client_limit) 1000, - MEMBER(default_vsz_limit) 256, + MEMBER(default_vsz_limit) 256*1024*1024, MEMBER(version_ignore) FALSE, MEMBER(mail_debug) FALSE, diff --git a/src/master/master-settings.h b/src/master/master-settings.h index 25c1d8eab5..bff8f356eb 100644 --- a/src/master/master-settings.h +++ b/src/master/master-settings.h @@ -11,7 +11,7 @@ struct master_settings { const char *ssl; unsigned int default_process_limit; unsigned int default_client_limit; - unsigned int default_vsz_limit; + uoff_t default_vsz_limit; bool version_ignore; bool mail_debug; diff --git a/src/master/service-process.c b/src/master/service-process.c index b786bbee43..07340cb3b8 100644 --- a/src/master/service-process.c +++ b/src/master/service-process.c @@ -137,7 +137,7 @@ drop_privileges(struct service *service) unsigned int len; if (service->vsz_limit != 0) - restrict_process_size(service->vsz_limit, -1U); + restrict_process_size(service->vsz_limit/1024, -1U); restrict_access_init(&rset); rset.uid = service->uid; @@ -350,8 +350,8 @@ get_exit_status_message(struct service *service, enum fatal_exit_status status) if (service->vsz_limit == 0) return "Out of memory"; return t_strdup_printf("Out of memory (vsz_limit=%u MB, " - "you may need to increase it)", - service->vsz_limit); + "you may need to increase it)", + (unsigned int)(service->vsz_limit/1024/1024)); case FATAL_EXEC: return "exec() failed"; diff --git a/src/master/service.c b/src/master/service.c index ce24f4626c..a70c716a94 100644 --- a/src/master/service.c +++ b/src/master/service.c @@ -176,7 +176,7 @@ service_create(pool_t pool, const struct service_settings *set, service->client_limit < set->service_count) service->client_limit = set->service_count; - service->vsz_limit = set->vsz_limit != -1U ? set->vsz_limit : + service->vsz_limit = set->vsz_limit != (uoff_t)-1 ? set->vsz_limit : set->master_set->default_vsz_limit; service->type = service->set->parsed_type; diff --git a/src/master/service.h b/src/master/service.h index 5fc9d71c0c..e2e4870f8b 100644 --- a/src/master/service.h +++ b/src/master/service.h @@ -65,7 +65,7 @@ struct service { /* Maximum number of client connections a process can handle. */ unsigned int client_limit; /* set->vsz_limit or set->master_set->default_client_limit */ - unsigned int vsz_limit; + uoff_t vsz_limit; /* log process pipe file descriptors. */ int log_fd[2];