Mercurial > dovecot > original-hg > dovecot-1.2
changeset 5891:db959f0d94e3 HEAD
Leave uidlist fd open so we can check if uidlist has been rewritten from
inode instead of relying on mtime changes. Removed utime() call for
uidlist.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 04 Jul 2007 05:07:48 +0300 |
parents | 989abd5017a4 |
children | 36056f044f1f |
files | src/lib-storage/index/maildir/maildir-uidlist.c |
diffstat | 1 files changed, 44 insertions(+), 24 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/index/maildir/maildir-uidlist.c Wed Jul 04 04:47:28 2007 +0300 +++ b/src/lib-storage/index/maildir/maildir-uidlist.c Wed Jul 04 05:07:48 2007 +0300 @@ -17,7 +17,6 @@ #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> -#include <utime.h> /* NFS: How many times to retry reading dovecot-uidlist file if ESTALE error occurs in the middle of reading it */ @@ -40,11 +39,13 @@ struct maildir_mailbox *mbox; char *fname; + int fd; + dev_t fd_dev; + ino_t fd_ino; + int lock_fd; unsigned int lock_count; - time_t last_mtime; - pool_t record_pool; ARRAY_TYPE(maildir_uidlist_rec_p) records; struct hash_table *files; @@ -179,6 +180,7 @@ struct maildir_uidlist *uidlist; uidlist = i_new(struct maildir_uidlist, 1); + uidlist->fd = -1; uidlist->mbox = mbox; uidlist->fname = i_strconcat(mbox->control_dir, "/" MAILDIR_UIDLIST_NAME, NULL); @@ -202,6 +204,11 @@ { i_assert(!UIDLIST_IS_LOCKED(uidlist)); + if (uidlist->fd != -1) { + if (close(uidlist->fd) < 0) + i_error("close(%s) failed: %m", uidlist->fname); + } + hash_destroy(uidlist->files); if (uidlist->record_pool != NULL) pool_unref(uidlist->record_pool); @@ -293,7 +300,14 @@ struct stat st; int fd, ret; - *retry_r = FALSE; + *retry_r = FALSE; + + if (uidlist->fd != -1) { + if (close(uidlist->fd) < 0) + i_error("close(%s) failed: %m", uidlist->fname); + uidlist->fd = -1; + uidlist->fd_ino = 0; + } fd = nfs_safe_open(uidlist->fname, O_RDONLY); if (fd == -1) { @@ -326,7 +340,7 @@ uidlist->version = 0; - input = i_stream_create_file(fd, default_pool, 4096, TRUE); + input = i_stream_create_file(fd, default_pool, 4096, FALSE); /* get header */ line = i_stream_read_next_line(input); @@ -371,10 +385,11 @@ if (ret == 0) { /* file is broken */ (void)unlink(uidlist->fname); - uidlist->last_mtime = 0; } else if (ret > 0) { /* success */ - uidlist->last_mtime = st.st_mtime; + uidlist->fd = fd; + uidlist->fd_dev = st.st_dev; + uidlist->fd_ino = st.st_ino; } else { /* I/O error */ if (input->stream_errno == ESTALE && try_retry) @@ -384,9 +399,13 @@ mail_storage_set_critical(storage, "read(%s) failed: %m", uidlist->fname); } - } + } i_stream_destroy(&input); + if (ret <= 0) { + if (close(fd) < 0) + i_error("close(%s) failed: %m", uidlist->fname); + } return ret; } @@ -398,7 +417,7 @@ bool retry; int ret; - if (uidlist->last_mtime != 0) { + if (uidlist->fd != -1) { if (nfs_safe_stat(uidlist->fname, &st) < 0) { if (errno != ENOENT) { mail_storage_set_critical(storage, @@ -408,7 +427,8 @@ return 0; } - if (st.st_mtime == uidlist->last_mtime) { + if (st.st_ino == uidlist->fd_ino && + CMP_DEV_T(st.st_dev, uidlist->fd_dev)) { /* unchanged */ return 1; } @@ -469,7 +489,7 @@ rec = maildir_uidlist_lookup_rec(uidlist, uid, &idx); if (rec == NULL) { - if (uidlist->last_mtime != 0) + if (uidlist->fd != -1) return NULL; /* the uidlist doesn't exist. */ @@ -554,7 +574,6 @@ { struct mail_storage *storage = &uidlist->mbox->storage->storage; struct maildir_uidlist_iter_ctx *iter; - struct utimbuf ut; string_t *str; uint32_t uid; enum maildir_uidlist_rec_flag flags; @@ -618,17 +637,6 @@ return -1; } - /* uidlist's mtime must grow every time */ - uidlist->last_mtime = ioloop_time <= uidlist->last_mtime ? - uidlist->last_mtime + 1 : ioloop_time; - ut.actime = ioloop_time; - ut.modtime = uidlist->last_mtime; - if (utime(temp_path, &ut) < 0) { - mail_storage_set_critical(storage, - "utime(%s) failed: %m", temp_path); - return -1; - } - if (!uidlist->mbox->ibox.fsync_disable) { if (fsync(uidlist->lock_fd) < 0) { mail_storage_set_critical(storage, @@ -644,6 +652,7 @@ { struct maildir_mailbox *mbox = uidlist->mbox; const char *temp_path, *db_path; + struct stat st; int ret; i_assert(uidlist->lock_count == @@ -657,11 +666,22 @@ db_path = t_strconcat(mbox->control_dir, "/" MAILDIR_UIDLIST_NAME, NULL); - if (file_dotlock_replace(&uidlist->dotlock, 0) <= 0) { + if (file_dotlock_replace(&uidlist->dotlock, + DOTLOCK_REPLACE_FLAG_DONT_CLOSE_FD) <= 0) { mail_storage_set_critical(&mbox->storage->storage, "file_dotlock_replace(%s) failed: %m", db_path); (void)unlink(temp_path); + (void)close(uidlist->lock_fd); ret = -1; + } else { + uidlist->fd = uidlist->lock_fd; + if (fstat(uidlist->fd, &st) < 0) { + i_error("fstat(%s) failed: %m", uidlist->fname); + uidlist->fd_ino = 0; + } else { + uidlist->fd_dev = st.st_dev; + uidlist->fd_ino = st.st_ino; + } } uidlist->lock_fd = -1;