From: Timo Sirainen Date: Mon, 14 Jun 2004 05:22:51 +0000 (+0300) Subject: Locking fixes. use less memory X-Git-Tag: 1.1.alpha1~3985 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d77c309fccbc6a7594f8cb08fb01009fa613c568;p=thirdparty%2Fdovecot%2Fcore.git Locking fixes. use less memory --HG-- branch : HEAD --- diff --git a/src/lib-storage/index/maildir/maildir-sync.c b/src/lib-storage/index/maildir/maildir-sync.c index 66db21a9c0..8f60cdb1e3 100644 --- a/src/lib-storage/index/maildir/maildir-sync.c +++ b/src/lib-storage/index/maildir/maildir-sync.c @@ -424,9 +424,6 @@ static int maildir_scan_dir(struct maildir_sync_context *ctx, int new_dir) enum maildir_uidlist_rec_flag flags; int move_new, ret = 1; - src = t_str_new(1024); - dest = t_str_new(1024); - dir = new_dir ? ctx->new_dir : ctx->cur_dir; dirp = opendir(dir); if (dirp == NULL) { @@ -435,6 +432,10 @@ static int maildir_scan_dir(struct maildir_sync_context *ctx, int new_dir) return -1; } + t_push(); + src = t_str_new(1024); + dest = t_str_new(1024); + move_new = new_dir && !mailbox_is_readonly(&ctx->ibox->box) && !ctx->ibox->keep_recent; while ((dp = readdir(dirp)) != NULL) { @@ -507,6 +508,8 @@ static int maildir_scan_dir(struct maildir_sync_context *ctx, int new_dir) mail_storage_set_critical(storage, "closedir(%s) failed: %m", dir); } + + t_pop(); return ret < 0 ? -1 : 0; } @@ -835,6 +838,15 @@ static int maildir_sync_context(struct maildir_sync_context *ctx) ctx->uidlist_sync_ctx = maildir_uidlist_sync_init(ctx->ibox->uidlist, ctx->partial); + /* we have to lock uidlist immediately, otherwise there's race + conditions with other processes who might write older maildir + file list into uidlist. + + alternative would be to lock it when new files are found, but + the directory scans _must_ be restarted then */ + if (maildir_uidlist_try_lock(ctx->ibox->uidlist) < 0) + return -1; + if (maildir_scan_dir(ctx, TRUE) < 0) return -1; if (cur_changed) { diff --git a/src/lib-storage/index/maildir/maildir-uidlist.c b/src/lib-storage/index/maildir/maildir-uidlist.c index bc51ab463d..f7b9c0145f 100644 --- a/src/lib-storage/index/maildir/maildir-uidlist.c +++ b/src/lib-storage/index/maildir/maildir-uidlist.c @@ -91,8 +91,12 @@ int maildir_uidlist_try_lock(struct maildir_uidlist *uidlist) "file_dotlock_open(%s) failed: %m", path); return -1; } - uidlist->lock_fd = fd; + + /* our view of uidlist must be up-to-date if we plan on changing it */ + if (maildir_uidlist_update(uidlist) < 0) + return -1; + return 1; } @@ -463,8 +467,10 @@ static int maildir_uidlist_rewrite_fd(struct maildir_uidlist *uidlist, iter = maildir_uidlist_iter_init(uidlist->ibox->uidlist); while (maildir_uidlist_iter_next(iter, &uid, &flags, &filename)) { + /* avoid overflowing str buffer so we don't eat more memory + than we need. */ if (str_len(str) + MAX_INT_STRLEN + - strlen(filename) + 2 >= 4096) { + strlen(filename) + 5 + 10 >= 4096) { /* flush buffer */ if (write_full(uidlist->lock_fd, str_data(str), str_len(str)) < 0) { @@ -592,6 +598,11 @@ static int maildir_uidlist_sync_uidlist(struct maildir_uidlist_sync_ctx *ctx) i_assert(!ctx->synced); + if (UIDLIST_IS_LOCKED(ctx->uidlist)) { + ctx->synced = TRUE; + return 1; + } + if (!ctx->uidlist->initial_read) { /* first time reading the uidlist, no locking yet */ @@ -612,10 +623,6 @@ static int maildir_uidlist_sync_uidlist(struct maildir_uidlist_sync_ctx *ctx) ctx->failed = TRUE; return -1; } - if (maildir_uidlist_update(ctx->uidlist) < 0) { - ctx->failed = TRUE; - return -1; - } ctx->synced = TRUE; return 1; @@ -842,8 +849,11 @@ int maildir_uidlist_sync_deinit(struct maildir_uidlist_sync_ctx *ctx) if (!ctx->finished) maildir_uidlist_sync_finish(ctx); - if (ctx->new_files_count != 0 && !ctx->failed && !ctx->locked) + if (ctx->new_files_count != 0 && !ctx->failed && !ctx->locked) { + t_push(); ret = maildir_uidlist_rewrite(ctx->uidlist); + t_pop(); + } if (ctx->partial) maildir_uidlist_mark_all(ctx->uidlist, FALSE);