From: Timo Sirainen Date: Sat, 18 Oct 2008 17:26:35 +0000 (+0300) Subject: Fixes to handling "out of disk space/quota" write failures. X-Git-Tag: 1.2.alpha3~23 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=25c22e54d1071d120641e9eecd0023e7373e65ff;p=thirdparty%2Fdovecot%2Fcore.git Fixes to handling "out of disk space/quota" write failures. --HG-- branch : HEAD --- diff --git a/src/lib-index/mail-cache-compress.c b/src/lib-index/mail-cache-compress.c index 3ed982b226..03f4f5ebb4 100644 --- a/src/lib-index/mail-cache-compress.c +++ b/src/lib-index/mail-cache-compress.c @@ -394,6 +394,10 @@ static int mail_cache_compress_locked(struct mail_cache *cache, } if (mail_cache_copy(cache, trans, fd, &file_seq, &ext_offsets) < 0) { + /* the fields may have been updated in memory already. + reverse those changes by re-reading them from file. */ + if (mail_cache_header_fields_read(cache) < 0) + return -1; (void)file_dotlock_delete(&dotlock); return -1; } diff --git a/src/lib-index/mail-cache.c b/src/lib-index/mail-cache.c index 6eb9ff1ff7..24663fbe38 100644 --- a/src/lib-index/mail-cache.c +++ b/src/lib-index/mail-cache.c @@ -188,6 +188,29 @@ int mail_cache_reopen(struct mail_cache *cache) return 1; } +static void mail_cache_update_need_compress(struct mail_cache *cache) +{ + const struct mail_cache_header *hdr = cache->hdr; + unsigned int cont_percentage; + uoff_t max_del_space; + + cont_percentage = hdr->continued_record_count * 100 / + (cache->index->map->rec_map->records_count == 0 ? 1 : + cache->index->map->rec_map->records_count); + if (cont_percentage >= MAIL_CACHE_COMPRESS_CONTINUED_PERCENTAGE && + hdr->used_file_size >= MAIL_CACHE_COMPRESS_MIN_SIZE) { + /* too many continued rows, compress */ + cache->need_compress_file_seq = hdr->file_seq; + } + + /* see if we've reached the max. deleted space in file */ + max_del_space = hdr->used_file_size / 100 * + MAIL_CACHE_COMPRESS_PERCENTAGE; + if (hdr->deleted_space >= max_del_space && + hdr->used_file_size >= MAIL_CACHE_COMPRESS_MIN_SIZE) + cache->need_compress_file_seq = hdr->file_seq; +} + static bool mail_cache_verify_header(struct mail_cache *cache) { const struct mail_cache_header *hdr = cache->data; @@ -282,6 +305,8 @@ int mail_cache_map(struct mail_cache *cache, size_t offset, size_t size) sizeof(cache->hdr_ro_copy)); } cache->hdr = &cache->hdr_ro_copy; + if (offset == 0) + mail_cache_update_need_compress(cache); return 0; } @@ -326,6 +351,8 @@ int mail_cache_map(struct mail_cache *cache, size_t offset, size_t size) } cache->hdr = cache->data; + if (offset == 0) + mail_cache_update_need_compress(cache); return 0; } @@ -599,29 +626,6 @@ int mail_cache_try_lock(struct mail_cache *cache) return mail_cache_lock_full(cache, FALSE, TRUE); } -static void mail_cache_update_need_compress(struct mail_cache *cache) -{ - const struct mail_cache_header *hdr = cache->hdr; - unsigned int cont_percentage; - uoff_t max_del_space; - - cont_percentage = hdr->continued_record_count * 100 / - (cache->index->map->rec_map->records_count == 0 ? 1 : - cache->index->map->rec_map->records_count); - if (cont_percentage >= MAIL_CACHE_COMPRESS_CONTINUED_PERCENTAGE && - hdr->used_file_size >= MAIL_CACHE_COMPRESS_MIN_SIZE) { - /* too many continued rows, compress */ - cache->need_compress_file_seq = hdr->file_seq; - } - - /* see if we've reached the max. deleted space in file */ - max_del_space = hdr->used_file_size / 100 * - MAIL_CACHE_COMPRESS_PERCENTAGE; - if (hdr->deleted_space >= max_del_space && - hdr->used_file_size >= MAIL_CACHE_COMPRESS_MIN_SIZE) - cache->need_compress_file_seq = hdr->file_seq; -} - int mail_cache_unlock(struct mail_cache *cache) { int ret = 0; diff --git a/src/lib-index/mail-transaction-log-append.c b/src/lib-index/mail-transaction-log-append.c index a10499edac..2758e2072b 100644 --- a/src/lib-index/mail-transaction-log-append.c +++ b/src/lib-index/mail-transaction-log-append.c @@ -87,6 +87,8 @@ static int log_buffer_move_to_memory(struct log_append_context *ctx) i_assert(file->buffer_offset + file->buffer->used == file->sync_offset); buffer_append_buf(file->buffer, ctx->output, 0, (size_t)-1); + buffer_write(file->buffer, file->sync_offset - file->buffer_offset, + &ctx->first_append_size, sizeof(uint32_t)); file->sync_offset = file->buffer_offset + file->buffer->used; return 0; } diff --git a/src/lib-index/mail-transaction-log-file.c b/src/lib-index/mail-transaction-log-file.c index d9f85def2d..1b93a37cfb 100644 --- a/src/lib-index/mail-transaction-log-file.c +++ b/src/lib-index/mail-transaction-log-file.c @@ -1555,4 +1555,8 @@ void mail_transaction_log_file_move_to_memory(struct mail_transaction_log_file file->filepath, "close()"); } file->fd = -1; + + i_free(file->filepath); + file->filepath = i_strconcat(file->log->index->filepath, + MAIL_TRANSACTION_LOG_SUFFIX, NULL); } diff --git a/src/lib-index/mail-transaction-log-private.h b/src/lib-index/mail-transaction-log-private.h index 46c1fc5b8c..a50f7c92be 100644 --- a/src/lib-index/mail-transaction-log-private.h +++ b/src/lib-index/mail-transaction-log-private.h @@ -4,6 +4,8 @@ #include "file-dotlock.h" #include "mail-transaction-log.h" +#define MAIL_TRANSACTION_LOG_SUFFIX ".log" + /* Synchronization can take a while sometimes, especially when copying lots of mails. */ #define MAIL_TRANSCATION_LOG_LOCK_TIMEOUT (3*60) diff --git a/src/lib-index/mail-transaction-log.c b/src/lib-index/mail-transaction-log.c index 2032d0124f..d75a448577 100644 --- a/src/lib-index/mail-transaction-log.c +++ b/src/lib-index/mail-transaction-log.c @@ -14,7 +14,6 @@ #include #include -#define MAIL_TRANSACTION_LOG_SUFFIX ".log" #define LOG_NEW_DOTLOCK_SUFFIX ".newlock" static void diff --git a/src/lib-storage/index/maildir/maildir-save.c b/src/lib-storage/index/maildir/maildir-save.c index 04d7adf891..3418cf5455 100644 --- a/src/lib-storage/index/maildir/maildir-save.c +++ b/src/lib-storage/index/maildir/maildir-save.c @@ -441,8 +441,10 @@ static int maildir_save_finish_real(struct mail_save_context *_ctx) path = t_strconcat(ctx->tmpdir, "/", ctx->file_last->basename, NULL); if (o_stream_flush(ctx->output) < 0) { - mail_storage_set_critical(storage, - "o_stream_flush(%s) failed: %m", path); + if (!mail_storage_set_error_from_errno(storage)) { + mail_storage_set_critical(storage, + "o_stream_flush(%s) failed: %m", path); + } ctx->failed = TRUE; }