Re: problematic upgrade 2.3.16 -> 2.4.3

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Nov 11, 2010 at 01:45:34PM +1100, Bron Gondwana wrote:
> Now - I'm going to look into cyrus.expunge handling magic for you.

Here's the rest of that series - a fix against the first lot of
patches I sent which is necessary, otherwise replication breaks.
Oops.  I did most testing of the rest of the world later...

And a fix against a pop3 issue you probably don't care too much
about right now ;)

And finally - a patch to reconstruct (even in -s mode) which will
look for a spare cyrus.expunge and just delete all the mentioned
records.  It will let you put the cyrus.expunge files from backup
into the directories and then just clean up :)  Hopefully.  It
won't hurt to use it on folders which upgraded correctly either.

These patches are all on github:

http://github.com/brong/cyrus-imapd/

In the for244 branch on top of cyrus-imapd-2.4, and in the master
branch at CMU on top of master, and of course in the fastmail
branch which always lives on top of master.

Bron.
>From 732e6e1b30d6a67aa549a06093d6dc6929d9dfcb Mon Sep 17 00:00:00 2001
From: Bron Gondwana <brong@xxxxxxxxx>
Date: Thu, 11 Nov 2010 14:50:32 +1100
Subject: [PATCH 5/7] Bug 3335 - make pop3 expunge efficient

---
 imap/pop3d.c |   61 ++++++++++++++++++++++++++++++++++++---------------------
 1 files changed, 38 insertions(+), 23 deletions(-)

diff --git a/imap/pop3d.c b/imap/pop3d.c
index f96723f..e8ae12c 100644
--- a/imap/pop3d.c
+++ b/imap/pop3d.c
@@ -147,8 +147,6 @@ int popd_starttls_done = 0;
 
 static int popd_myrights;
 
-static mailbox_decideproc_t expungedeleted;
-
 /* the sasl proxy policy context */
 static struct proxy_context popd_proxyctx = {
     0, 1, &popd_authstate, NULL, NULL
@@ -813,6 +811,42 @@ void kpop(void)
 }
 #endif
 
+static int expunge_deleted(void)
+{
+    struct index_record record;
+    uint32_t msgno;
+    int r = 0;
+
+    /* loop over all known messages looking for deletes */
+    for (msgno = 1; msgno <= popd_exists; msgno++) {
+	/* not deleted? skip */
+	if (!popd_msg[msgno].deleted)
+	    continue;
+
+	/* error reading? abort */
+	r = mailbox_read_index_record(popd_mailbox, popd_msg[msgno].recno, &record);
+	if (r) break;
+
+	/* already expunged? skip */
+	if (record.system_flags & FLAG_EXPUNGED)
+	    continue;
+
+	/* mark expunged */
+	record.system_flags |= FLAG_EXPUNGED;
+
+	/* store back to the mailbox */
+	r = mailbox_rewrite_index_record(popd_mailbox, &record);
+	if (r) break;
+    }
+
+    if (r) {
+	syslog(LOG_ERR, "IOERROR: %s failed to expunge record %u uid %u, aborting",
+	       popd_mailbox->name, msgno, popd_msg[msgno].uid);
+    }
+
+    return r;
+}
+
 /*
  * Top-level command loop parsing
  */
@@ -931,12 +965,8 @@ static void cmdloop(void)
 		if (msgno <= popd_exists)
 		    update_seen();
 
-		/* check for changes */
-		for (msgno = 1; msgno <= popd_exists; msgno++)
-		    if (popd_msg[msgno].deleted) break;
-
-		if (msgno <= popd_exists)
-		    mailbox_expunge(popd_mailbox, expungedeleted, NULL, NULL);
+		/* process looking for deleted messages */
+		expunge_deleted();
 
 		mailbox_commit(popd_mailbox);
 		mailbox_unlock_index(popd_mailbox, NULL);
@@ -1905,21 +1935,6 @@ static int blat(int msgno, int lines)
     return 0;
 }
 
-static unsigned expungedeleted(struct mailbox *mailbox __attribute__((unused)),
-			       struct index_record *record,
-			       void *rock __attribute__((unused)))
-{
-    uint32_t msgno;
-
-    /* XXX - could make this more efficient with binary search */
-    for (msgno = 1; msgno <= popd_exists; msgno++) {
-	if (popd_msg[msgno].uid == record->uid) {
-	    return popd_msg[msgno].deleted;
-	}
-    }
-    return 0;
-}
-
 /* Reset the given sasl_conn_t to a sane state */
 static int reset_saslconn(sasl_conn_t **conn) 
 {
-- 
1.7.1

>From 9d52edfb1d24ca4b101570be6f9625038385c6fc Mon Sep 17 00:00:00 2001
From: Bron Gondwana <brong@xxxxxxxxx>
Date: Thu, 11 Nov 2010 15:26:27 +1100
Subject: [PATCH 6/7] Update counts fix - don't break sync_crc

---
 imap/mailbox.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/imap/mailbox.c b/imap/mailbox.c
index 045261a..c904d97 100644
--- a/imap/mailbox.c
+++ b/imap/mailbox.c
@@ -1962,7 +1962,7 @@ int mailbox_index_recalc(struct mailbox *mailbox)
     for (recno = 1; recno <= mailbox->i.num_records; recno++) {
 	r = mailbox_read_index_record(mailbox, recno, &record);
 	if (r) return r;
-	header_update_counts(&mailbox->i, &record, 1);
+	mailbox_index_update_counts(mailbox, &record, 1);
     }
 
     return 0;
-- 
1.7.1

>From ee79061faf8e0dfce154a60c981bc6856865902d Mon Sep 17 00:00:00 2001
From: Bron Gondwana <brong@xxxxxxxxx>
Date: Thu, 11 Nov 2010 15:21:55 +1100
Subject: [PATCH 7/7] Use old cyrus.expunge file to clean out bogus records.

---
 imap/mailbox.c |   72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 72 insertions(+), 0 deletions(-)

diff --git a/imap/mailbox.c b/imap/mailbox.c
index c904d97..d7c7e9e 100644
--- a/imap/mailbox.c
+++ b/imap/mailbox.c
@@ -3227,6 +3227,75 @@ static int find_files(struct mailbox *mailbox, struct found_files *files,
     return 0;
 }
 
+static void cleanup_stale_expunged(struct mailbox *mailbox)
+{
+    const char *fname;
+    int expunge_fd = -1;
+    const char *expunge_base = NULL;
+    unsigned long expunge_len = 0;   /* mapped size */
+    unsigned long expunge_num;
+    unsigned long emapnum;
+    uint32_t erecno;
+    uint32_t uid;
+    bit32 eoffset, expungerecord_size;
+    const char *bufp;
+    struct stat sbuf;
+    int count = 0;
+    int r;
+
+    /* it's always read-writes */
+    fname = mailbox_meta_fname(mailbox, META_EXPUNGE);
+    expunge_fd = open(fname, O_RDWR, 0);
+    if (expunge_fd == -1)
+	goto done; /* yay, no crappy expunge file */
+
+    /* boo - gotta read and find out the UIDs */
+    r = fstat(expunge_fd, &sbuf);
+    if (r == -1)
+	goto done;
+
+    if (sbuf.st_size < INDEX_HEADER_SIZE)
+	goto done;
+
+    map_refresh(expunge_fd, 1, &expunge_base,
+		&expunge_len, sbuf.st_size, "expunge",
+		mailbox->name);
+
+    /* use the expunge file's header information just in case
+     * versions are skewed for some reason */
+    eoffset = ntohl(*((bit32 *)(expunge_base+OFFSET_START_OFFSET)));
+    expungerecord_size = ntohl(*((bit32 *)(expunge_base+OFFSET_RECORD_SIZE)));
+
+    /* bogus data at the start of the expunge file? */
+    if (!eoffset || !expungerecord_size)
+	goto done;
+
+    expunge_num = ntohl(*((bit32 *)(expunge_base+OFFSET_NUM_RECORDS)));
+    emapnum = (sbuf.st_size - eoffset) / expungerecord_size;
+    if (emapnum < expunge_num) {
+	expunge_num = emapnum;
+    }
+
+    /* add every UID to the files list */
+    for (erecno = 1; erecno <= expunge_num; erecno++) {
+	bufp = expunge_base + eoffset + (erecno-1)*expungerecord_size;
+	uid = ntohl(*((bit32 *)(bufp+OFFSET_UID)));
+	fname = mailbox_message_fname(mailbox, uid);
+	unlink(fname);
+	count++;
+    }
+
+    printf("%s removed %d records from stale cyrus.expunge\n",
+	   mailbox->name, count);
+
+    fname = mailbox_meta_fname(mailbox, META_EXPUNGE);
+    unlink(fname);
+
+done:
+    if (expunge_base) map_free(&expunge_base, &expunge_len);
+    if (expunge_fd != -1) close(expunge_fd);
+}
+
 /* this is kind of like mailbox_create, but we try to rescue
  * what we can from the filesystem! */
 static int mailbox_reconstruct_create(const char *name, struct mailbox **mbptr)
@@ -3774,6 +3843,9 @@ int mailbox_reconstruct(const char *name, int flags)
 	mailbox->need_cache_refresh = 1;
     }
 
+    /* find cyrus.expunge file if present */
+    cleanup_stale_expunged(mailbox);
+
     r = find_files(mailbox, &files, flags);
     if (r) goto close;
     init_files(&discovered);
-- 
1.7.1

----
Cyrus Home Page: http://www.cyrusimap.org/
List Archives/Info: http://lists.andrew.cmu.edu/pipermail/info-cyrus/

[Index of Archives]     [Cyrus SASL]     [Squirrel Mail]     [Asterisk PBX]     [Video For Linux]     [Photo]     [Yosemite News]     [gtk]     [KDE]     [Gimp on Windows]     [Steve's Art]

  Powered by Linux