# HG changeset patch # User Timo Sirainen # Date 1229331482 -7200 # Node ID c438437b709af4dd8f8e6d5481b61f9a309ea2b8 # Parent e8a8383895df304324b1dbfec031937b5f0c1e55 maildir: Allow opening mailbox and expunging messages when uidlist couldn't be locked (e.g. out of quota). diff -r e8a8383895df -r c438437b709a src/lib-storage/index/maildir/maildir-keywords.c --- a/src/lib-storage/index/maildir/maildir-keywords.c Sun Dec 14 08:36:10 2008 +0200 +++ b/src/lib-storage/index/maildir/maildir-keywords.c Mon Dec 15 10:58:02 2008 +0200 @@ -194,9 +194,6 @@ { void *p; - i_assert(mk->mbox == NULL || - maildir_uidlist_is_locked(mk->mbox->uidlist)); - p = hash_lookup(mk->hash, name); if (p == NULL) { if (mk->synced) @@ -256,6 +253,9 @@ if (i == count && count >= MAILDIR_MAX_KEYWORDS) return -1; + if (!maildir_uidlist_is_locked(mk->mbox->uidlist)) + return -1; + maildir_keywords_create(mk, name, i); return i; } @@ -266,9 +266,6 @@ const char *const *keywords; unsigned int count; - i_assert(mk->mbox == NULL || - maildir_uidlist_is_locked(mk->mbox->uidlist)); - keywords = array_get(&mk->list, &count); if (idx >= count) { if (mk->synced) diff -r e8a8383895df -r c438437b709a src/lib-storage/index/maildir/maildir-sync-index.c --- a/src/lib-storage/index/maildir/maildir-sync-index.c Sun Dec 14 08:36:10 2008 +0200 +++ b/src/lib-storage/index/maildir/maildir-sync-index.c Mon Dec 15 10:58:02 2008 +0200 @@ -105,15 +105,15 @@ return -1; } -static void maildir_handle_uid_insertion(struct maildir_index_sync_context *ctx, - enum maildir_uidlist_rec_flag uflags, - const char *filename, uint32_t uid) +static int maildir_handle_uid_insertion(struct maildir_index_sync_context *ctx, + enum maildir_uidlist_rec_flag uflags, + const char *filename, uint32_t uid) { int ret; if ((uflags & MAILDIR_UIDLIST_REC_FLAG_NONSYNCED) != 0) { /* partial syncing */ - return; + return 0; } /* most likely a race condition: we read the maildir, then someone else @@ -124,7 +124,7 @@ ctx->mbox->maildir_hdr.cur_check_time = 0; maildir_uidlist_add_flags(ctx->mbox->uidlist, filename, MAILDIR_UIDLIST_REC_FLAG_RACING); - return; + return 0; } if (ctx->uidlist_sync_ctx == NULL) { @@ -132,7 +132,8 @@ MAILDIR_UIDLIST_SYNC_PARTIAL | MAILDIR_UIDLIST_SYNC_KEEP_STATE, &ctx->uidlist_sync_ctx); - i_assert(ret > 0); + if (ret <= 0) + return -1; } uflags &= MAILDIR_UIDLIST_REC_FLAG_NEW_DIR; @@ -146,6 +147,7 @@ i_warning("Maildir %s: Expunged message reappeared, giving a new UID " "(old uid=%u, file=%s)", ctx->mbox->path, uid, filename); + return 0; } int maildir_sync_index_begin(struct maildir_mailbox *mbox, @@ -283,7 +285,6 @@ bool expunged, full_rescan = FALSE; i_assert(!mbox->syncing_commit); - i_assert(maildir_uidlist_is_locked(mbox->uidlist)); first_uid = 1; hdr = mail_index_get_header(view); @@ -328,8 +329,10 @@ if (seq > hdr->messages_count) { if (uid < hdr_next_uid) { - maildir_handle_uid_insertion(ctx, uflags, - filename, uid); + if (maildir_handle_uid_insertion(ctx, uflags, + filename, + uid) < 0) + ret = -1; seq--; continue; } @@ -367,8 +370,9 @@ } if (uid < rec->uid) { - maildir_handle_uid_insertion(ctx, uflags, - filename, uid); + if (maildir_handle_uid_insertion(ctx, uflags, + filename, uid) < 0) + ret = -1; seq--; continue; } diff -r e8a8383895df -r c438437b709a src/lib-storage/index/maildir/maildir-sync.c --- a/src/lib-storage/index/maildir/maildir-sync.c Sun Dec 14 08:36:10 2008 +0200 +++ b/src/lib-storage/index/maildir/maildir-sync.c Mon Dec 15 10:58:02 2008 +0200 @@ -670,7 +670,7 @@ { enum maildir_uidlist_sync_flags sync_flags; enum maildir_uidlist_rec_flag flags; - bool new_changed, cur_changed; + bool new_changed, cur_changed, lock_failure; int ret; *lost_files_r = FALSE; @@ -741,15 +741,39 @@ } ret = maildir_uidlist_sync_init(ctx->mbox->uidlist, sync_flags, &ctx->uidlist_sync_ctx); + lock_failure = ret <= 0; if (ret <= 0) { - /* failure / timeout */ - return ret; + struct mail_storage *storage = ctx->mbox->ibox.box.storage; + + if (ret == 0) { + /* timeout */ + return 0; + } + /* locking failed. sync anyway without locking so that it's + possible to expunge messages when out of quota. */ + if (forced) { + /* we're already forcing a sync, we're trying to find + a message that was probably already expunged, don't + loop for a long time trying to find it. */ + return -1; + } + ret = maildir_uidlist_sync_init(ctx->mbox->uidlist, sync_flags | + MAILDIR_UIDLIST_SYNC_NOLOCK, + &ctx->uidlist_sync_ctx); + i_assert(ret > 0); + + if (storage->callbacks->notify_no != NULL) { + storage->callbacks->notify_no(&ctx->mbox->ibox.box, + "Internal mailbox synchronization failure, " + "showing only old mails.", + storage->callback_context); + } } ctx->locked = maildir_uidlist_is_locked(ctx->mbox->uidlist); if (!ctx->locked) ctx->partial = TRUE; - if (!ctx->mbox->syncing_commit && ctx->locked) { + if (!ctx->mbox->syncing_commit && (ctx->locked || lock_failure)) { if (maildir_sync_index_begin(ctx->mbox, ctx, &ctx->index_sync_ctx) < 0) return -1; @@ -787,7 +811,7 @@ ctx->mbox->maildir_hdr.cur_mtime = 0; } - if (!ctx->mbox->syncing_commit && ctx->locked) { + if (ctx->index_sync_ctx != NULL) { /* NOTE: index syncing here might cause a re-sync due to files getting lost, so this function might be called re-entrantly. */ @@ -801,7 +825,8 @@ if (ret == 0) *lost_files_r = TRUE; - i_assert(maildir_uidlist_is_locked(ctx->mbox->uidlist)); + i_assert(maildir_uidlist_is_locked(ctx->mbox->uidlist) || + lock_failure); } if (find_uid != NULL && *find_uid != 0) { diff -r e8a8383895df -r c438437b709a src/lib-storage/index/maildir/maildir-uidlist.c --- a/src/lib-storage/index/maildir/maildir-uidlist.c Sun Dec 14 08:36:10 2008 +0200 +++ b/src/lib-storage/index/maildir/maildir-uidlist.c Mon Dec 15 10:58:02 2008 +0200 @@ -1287,14 +1287,21 @@ } } -int maildir_uidlist_sync_init(struct maildir_uidlist *uidlist, - enum maildir_uidlist_sync_flags sync_flags, - struct maildir_uidlist_sync_ctx **sync_ctx_r) +static int maildir_uidlist_sync_lock(struct maildir_uidlist *uidlist, + enum maildir_uidlist_sync_flags sync_flags, + bool *locked_r) { - struct maildir_uidlist_sync_ctx *ctx; - bool nonblock, refresh, locked; + bool nonblock, refresh; int ret; + *locked_r = FALSE; + + if ((sync_flags & MAILDIR_UIDLIST_SYNC_NOLOCK) != 0) { + if (maildir_uidlist_refresh(uidlist) < 0) + return -1; + return 1; + } + nonblock = (sync_flags & MAILDIR_UIDLIST_SYNC_TRYLOCK) != 0; refresh = (sync_flags & MAILDIR_UIDLIST_SYNC_NOREFRESH) == 0; @@ -1309,10 +1316,23 @@ /* forcing the sync anyway */ if (maildir_uidlist_refresh(uidlist) < 0) return -1; - locked = FALSE; } else { - locked = TRUE; + *locked_r = TRUE; } + return 1; +} + +int maildir_uidlist_sync_init(struct maildir_uidlist *uidlist, + enum maildir_uidlist_sync_flags sync_flags, + struct maildir_uidlist_sync_ctx **sync_ctx_r) +{ + struct maildir_uidlist_sync_ctx *ctx; + bool locked; + int ret; + + ret = maildir_uidlist_sync_lock(uidlist, sync_flags, &locked); + if (ret <= 0) + return ret; *sync_ctx_r = ctx = i_new(struct maildir_uidlist_sync_ctx, 1); ctx->uidlist = uidlist; diff -r e8a8383895df -r c438437b709a src/lib-storage/index/maildir/maildir-uidlist.h --- a/src/lib-storage/index/maildir/maildir-uidlist.h Sun Dec 14 08:36:10 2008 +0200 +++ b/src/lib-storage/index/maildir/maildir-uidlist.h Mon Dec 15 10:58:02 2008 +0200 @@ -15,7 +15,8 @@ MAILDIR_UIDLIST_SYNC_KEEP_STATE = 0x02, MAILDIR_UIDLIST_SYNC_FORCE = 0x04, MAILDIR_UIDLIST_SYNC_TRYLOCK = 0x08, - MAILDIR_UIDLIST_SYNC_NOREFRESH = 0x10 + MAILDIR_UIDLIST_SYNC_NOREFRESH = 0x10, + MAILDIR_UIDLIST_SYNC_NOLOCK = 0x20 }; enum maildir_uidlist_rec_flag {