Hi,

i discovered that my patch for bug #3862 (rollback db changes on mupdate failure), which was includes in cyrus-imapd 2.4.19, 2.5.8 and 3.0.0-beta2, has a bug if a
mailbox is moved to an other partition and a rollback is needed.

For the rollback my old patch did recreate the old entry and then delete the new entry. But in case of moving the mailbox to a other partition the oldname and newname are
the same, so the mailbox will be deleted for the mailboxes.db
Recovery form this error is tricky. Reconstruct (reconstruct -p oldpartiton "mailboxname")
will fail because the mupdate master still has the entry the the mailbox.
So you have to manually add the mailbox to the mailboxes.db on the backend,
or delete the mailbox from the mailboxes.db on the mupdate master.


Attached is a patch for 2.4.20 which will reverse the order, so the "new" mailbox is
deleted first and then the old entry is recreated.

The same is needed for the other branches.

Regards

   Michael Menge


--------------------------------------------------------------------------------
M.Menge                                Tel.: (49) 7071/29-70316
Universität Tübingen                   Fax.: (49) 7071/29-5912
Zentrum für Datenverarbeitung mail: michael.me...@zdv.uni-tuebingen.de
Wächterstraße 76
72074 Tübingen
diff -u -r cyrus-imapd-2.4.20/imap/mboxlist.c cyrus-imapd-2.4.20.mupdate_commit_patch2/imap/mboxlist.c
--- cyrus-imapd-2.4.20/imap/mboxlist.c	2017-08-18 02:29:14.000000000 +0200
+++ cyrus-imapd-2.4.20.mupdate_commit_patch2/imap/mboxlist.c	2017-09-14 13:59:06.000000000 +0200
@@ -1186,14 +1186,14 @@
         if (mupdatecommiterror) {
             r = 0;
 
-            /* recreate an old entry */
+            /* delete the new entry */
             if (!isusermbox)
-                r = DB->store(mbdb, oldname, strlen(oldname),
-                              mboxent, strlen(mboxent), &tid);
+                r = DB->delete(mbdb, newname, strlen(newname), &tid, 0);
 
-            /* delete the new entry */
+            /* recreate an old entry */
             if (!r)
-                r = DB->delete(mbdb, newname, strlen(newname), &tid, 0);
+                r = DB->store(mbdb, oldname, strlen(oldname),
+                              mboxent, strlen(mboxent), &tid);
 
             /* Commit transaction */
             if (!r)

Reply via email to