On Mon, Nov 22, 2010 at 03:36:07PM +0100, Sébastien Michel wrote: > > > You have got to be kidding me. Unless there's actually something which > > > requires the files to be rewritten (i.e. an expunge event) then this > > > should not happen. Again, Cyrus 2.4.x will be much more efficient in > > > this regard, only rewriting if you have explicitly enable immediate > > > expunge rather than "default" expunge. > > > It is a 2.3.16. Tu be sure I have tested again with a fresh downloaded > tarball. Just sending a mail in LMTP and opening the mailbox several times > (SELECT/CLOSE only) > A binary diff indicated that Generation Number is incremented but nothing > else. Ok - that's definitely fixed in 2.4. I'm also attaching some patches against 2.4 if anyone else wants to have a play with them. The first makes Cyrus open the index and cache files O_RDONLY if the index is locked in shared mode (which implies a read-only session). The second patch then makes index EXAMINE commands use a shared lock! Bron.
>From 2b358b943677bc50830774e465537fc040917dde Mon Sep 17 00:00:00 2001 From: Bron Gondwana <brong@xxxxxxxxx> Date: Tue, 23 Nov 2010 00:26:40 +1100 Subject: [PATCH 2/5] Open Files Readonly - mailbox_open_irl => read only filehandles --- imap/mailbox.c | 26 ++++++++++++++++++++------ imap/mailbox.h | 1 + 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/imap/mailbox.c b/imap/mailbox.c index 1f2bbb0..8a1cafc 100644 --- a/imap/mailbox.c +++ b/imap/mailbox.c @@ -456,6 +456,7 @@ int mailbox_open_cache(struct mailbox *mailbox) struct stat sbuf; unsigned generation; int retry = 0; + int openflags = mailbox->is_readonly ? O_RDONLY : O_RDWR; /* already got everything? great */ if (mailbox->cache_fd != -1 && !mailbox->need_cache_refresh) @@ -471,7 +472,7 @@ int mailbox_open_cache(struct mailbox *mailbox) abort(); fname = mailbox_meta_fname(mailbox, META_CACHE); - mailbox->cache_fd = open(fname, O_RDWR, 0); + mailbox->cache_fd = open(fname, openflags, 0); if (mailbox->cache_fd == -1) goto fail; } @@ -573,6 +574,8 @@ int mailbox_append_cache(struct mailbox *mailbox, { int r; + assert(mailbox_index_islocked(mailbox, 1)); + /* no cache content */ if (!record->crec.len) return 0; @@ -852,6 +855,9 @@ int mailbox_open_advanced(const char *name, mailbox->acl = xstrdup(mbentry.acl); mailbox->mbtype = mbentry.mbtype; + if (index_locktype == LOCK_SHARED) + mailbox->is_readonly = 1; + r = mailbox_open_index(mailbox); if (r) { syslog(LOG_ERR, "IOERROR: opening index %s: %m", mailbox->name); @@ -901,6 +907,7 @@ int mailbox_open_index(struct mailbox *mailbox) { struct stat sbuf; char *fname; + int openflags = mailbox->is_readonly ? O_RDONLY : O_RDWR; if (mailbox->i.dirty || mailbox->cache_dirty) abort(); @@ -924,7 +931,7 @@ int mailbox_open_index(struct mailbox *mailbox) if (!fname) return IMAP_MAILBOX_BADNAME; - mailbox->index_fd = open(fname, O_RDWR, 0); + mailbox->index_fd = open(fname, openflags, 0); if (mailbox->index_fd == -1) return IMAP_IOERROR; @@ -1445,12 +1452,19 @@ int mailbox_lock_index(struct mailbox *mailbox, int locktype) restart: - if (locktype == LOCK_EXCLUSIVE) - r = lock_blocking(mailbox->index_fd); - else + if (locktype == LOCK_EXCLUSIVE) { + /* handle read-only case cleanly - we need to re-open read-write first! */ + if (mailbox->is_readonly) { + mailbox->is_readonly = 0; + r = mailbox_open_index(mailbox); + } + if (!r) r = lock_blocking(mailbox->index_fd); + } + else { r = lock_shared(mailbox->index_fd); + } - if (r == -1) { + if (r) { syslog(LOG_ERR, "IOERROR: locking index for %s: %m", mailbox->name); return IMAP_IOERROR; diff --git a/imap/mailbox.h b/imap/mailbox.h index 77bcc1b..1f2aca3 100644 --- a/imap/mailbox.h +++ b/imap/mailbox.h @@ -194,6 +194,7 @@ struct mailbox { unsigned long cache_len; /* mapped size */ int index_locktype; /* 0 = none, 1 = shared, 2 = exclusive */ + int is_readonly; /* true = open index and cache files readonly */ ino_t header_file_ino; bit32 header_file_crc; -- 1.7.2.3
>From 49e4793e97559d750571d9252074aeb388c73dab Mon Sep 17 00:00:00 2001 From: Bron Gondwana <brong@xxxxxxxxx> Date: Tue, 23 Nov 2010 13:34:12 +1100 Subject: [PATCH 3/5] Open with read lock in EXAMINE --- imap/index.c | 15 +++++++++++---- 1 files changed, 11 insertions(+), 4 deletions(-) diff --git a/imap/index.c b/imap/index.c index a00dbef..77664c8 100644 --- a/imap/index.c +++ b/imap/index.c @@ -214,13 +214,16 @@ int index_open(const char *name, struct index_init *init, struct index_state *state = xzmalloc(sizeof(struct index_state)); struct seqset *vanishedlist = NULL; - r = mailbox_open_iwl(name, &state->mailbox); - if (r) goto fail; - if (init) { state->myrights = cyrus_acl_myrights(init->authstate, state->mailbox->acl); - if (init->examine_mode) + if (init->examine_mode) { state->myrights &= ~ACL_READ_WRITE; + r = mailbox_open_irl(name, &state->mailbox); + if (r) goto fail; + } else { + r = mailbox_open_iwl(name, &state->mailbox); + if (r) goto fail; + } state->authstate = init->authstate; state->userid = init->userid ? xstrdup(init->userid) : NULL; @@ -232,6 +235,10 @@ int index_open(const char *name, struct index_init *init, state->out = init->out; state->qresync = init->qresync; } + else { + r = mailbox_open_iwl(name, &state->mailbox); + if (r) goto fail; + } /* initialise the index_state */ index_refresh(state); -- 1.7.2.3
---- Cyrus Home Page: http://www.cyrusimap.org/ List Archives/Info: http://lists.andrew.cmu.edu/pipermail/info-cyrus/