]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Consolidate xhdr fixups
authorMark Andrews <marka@isc.org>
Thu, 13 May 2021 05:44:02 +0000 (15:44 +1000)
committerMark Andrews <marka@isc.org>
Tue, 25 May 2021 22:16:35 +0000 (08:16 +1000)
lib/dns/journal.c

index e2dfbeb1cf1da71c94c4e4f26a56d579f00ec8ab..10c032b6ba4d8f12f15cb8990953b60ad74447b7 100644 (file)
@@ -854,6 +854,73 @@ ixfr_order(const void *av, const void *bv) {
        return (r);
 }
 
+static isc_result_t
+maybe_fixup_xhdr(dns_journal_t *j, journal_xhdr_t *xhdr, uint32_t serial,
+                isc_offset_t offset) {
+       isc_result_t result = ISC_R_SUCCESS;
+
+       /*
+        * Handle mixture of version 1 and version 2
+        * transaction headers in a version 1 journal.
+        */
+       if ((xhdr->serial0 != serial ||
+            isc_serial_le(xhdr->serial1, xhdr->serial0))) {
+               if (j->xhdr_version == XHDR_VERSION1 && xhdr->serial1 == serial)
+               {
+                       isc_log_write(
+                               JOURNAL_COMMON_LOGARGS, ISC_LOG_DEBUG(3),
+                               "%s: XHDR_VERSION1 -> XHDR_VERSION2 at %u",
+                               j->filename, serial);
+                       j->xhdr_version = XHDR_VERSION2;
+                       CHECK(journal_seek(j, offset));
+                       CHECK(journal_read_xhdr(j, xhdr));
+                       j->recovered = true;
+               } else if (j->xhdr_version == XHDR_VERSION2 &&
+                          xhdr->count == serial) {
+                       isc_log_write(
+                               JOURNAL_COMMON_LOGARGS, ISC_LOG_DEBUG(3),
+                               "%s: XHDR_VERSION2 -> XHDR_VERSION1 at %u",
+                               j->filename, serial);
+                       j->xhdr_version = XHDR_VERSION1;
+                       CHECK(journal_seek(j, offset));
+                       CHECK(journal_read_xhdr(j, xhdr));
+                       j->recovered = true;
+               }
+       }
+
+       /*
+        * Handle <size, serial0, serial1, 0> transaction header.
+        */
+       if (j->xhdr_version == XHDR_VERSION1) {
+               uint32_t value;
+
+               CHECK(journal_read(j, &value, sizeof(value)));
+               if (value != 0L) {
+                       CHECK(journal_seek(j, offset + 12));
+               } else {
+                       isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_DEBUG(3),
+                                     "%s: XHDR_VERSION1 count zero at %u",
+                                     j->filename, serial);
+                       j->xhdr_version = XHDR_VERSION2;
+                       j->recovered = true;
+               }
+       } else if (j->xhdr_version == XHDR_VERSION2 && xhdr->count == serial &&
+                  xhdr->serial1 == 0U &&
+                  isc_serial_gt(xhdr->serial0, xhdr->count))
+       {
+               isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_DEBUG(3),
+                             "%s: XHDR_VERSION2 count zero at %u", j->filename,
+                             serial);
+               xhdr->serial1 = xhdr->serial0;
+               xhdr->serial0 = xhdr->count;
+               xhdr->count = 0;
+               j->recovered = true;
+       }
+
+failure:
+       return (result);
+}
+
 /*
  * Advance '*pos' to the next journal transaction.
  *
@@ -871,7 +938,7 @@ ixfr_order(const void *av, const void *bv) {
  *    Other results due to file errors are possible.
  */
 static isc_result_t
-journal_next(dns_journal_t *j, journal_pos_t *pos, bool retry) {
+journal_next(dns_journal_t *j, journal_pos_t *pos) {
        isc_result_t result;
        journal_xhdr_t xhdr;
        size_t hdrsize;
@@ -896,46 +963,20 @@ journal_next(dns_journal_t *j, journal_pos_t *pos, bool retry) {
                return (result);
        }
 
+       if (j->header_ver1) {
+               CHECK(maybe_fixup_xhdr(j, &xhdr, pos->serial, pos->offset));
+       }
+
        /*
         * Check serial number consistency.
         */
        if (xhdr.serial0 != pos->serial ||
            isc_serial_le(xhdr.serial1, xhdr.serial0)) {
-               if (j->header_ver1 && j->xhdr_version == XHDR_VERSION1 &&
-                   xhdr.serial1 == pos->serial && !retry)
-               {
-                       /* XHDR_VERSION1 -> XHDR_VERSION2 */
-                       isc_log_write(
-                               JOURNAL_COMMON_LOGARGS, ISC_LOG_DEBUG(3),
-                               "%s: XHDR_VERSION1 -> XHDR_VERSION2 at %u",
-                               j->filename, pos->serial);
-                       j->xhdr_version = XHDR_VERSION2;
-                       result = journal_next(j, pos, true);
-                       if (result == ISC_R_SUCCESS) {
-                               j->recovered = true;
-                       }
-                       return (result);
-               } else if (j->header_ver1 && j->xhdr_version == XHDR_VERSION2 &&
-                          xhdr.count == pos->serial && !retry)
-               {
-                       /* XHDR_VERSION2 -> XHDR_VERSION1 */
-                       isc_log_write(
-                               JOURNAL_COMMON_LOGARGS, ISC_LOG_DEBUG(3),
-                               "%s: XHDR_VERSION2 -> XHDR_VERSION1 at %u",
-                               j->filename, pos->serial);
-                       j->xhdr_version = XHDR_VERSION1;
-                       result = journal_next(j, pos, true);
-                       if (result == ISC_R_SUCCESS) {
-                               j->recovered = true;
-                       }
-                       return (result);
-               } else {
-                       isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
-                                     "%s: journal file corrupt: "
-                                     "expected serial %u, got %u",
-                                     j->filename, pos->serial, xhdr.serial0);
-                       return (ISC_R_UNEXPECTED);
-               }
+               isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+                             "%s: journal file corrupt: "
+                             "expected serial %u, got %u",
+                             j->filename, pos->serial, xhdr.serial0);
+               return (ISC_R_UNEXPECTED);
        }
 
        /*
@@ -945,29 +986,6 @@ journal_next(dns_journal_t *j, journal_pos_t *pos, bool retry) {
                          ? sizeof(journal_rawxhdr_t)
                          : sizeof(journal_rawxhdr_ver1_t);
 
-       /*
-        * Handle <size, serial0, serial1, 0> transaction header.
-        */
-       if (j->header_ver1 && j->xhdr_version == XHDR_VERSION1) {
-               uint32_t value;
-
-               CHECK(journal_read(j, &value, sizeof(value)));
-               if (value != 0L) {
-                       CHECK(journal_seek(j, pos->offset + 12));
-               } else {
-                       j->recovered = true;
-                       hdrsize += 4;
-               }
-       } else if (j->header_ver1 && j->xhdr_version == XHDR_VERSION2 &&
-                  xhdr.count == pos->serial && xhdr.serial1 == 0U &&
-                  isc_serial_gt(xhdr.serial0, xhdr.count))
-       {
-               xhdr.serial1 = xhdr.serial0;
-               xhdr.serial0 = xhdr.count;
-               xhdr.count = 0;
-               j->recovered = true;
-       }
-
        if ((isc_offset_t)(pos->offset + hdrsize + xhdr.size) < pos->offset) {
                isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
                              "%s: offset too large", j->filename);
@@ -1114,7 +1132,7 @@ journal_find(dns_journal_t *j, uint32_t serial, journal_pos_t *pos) {
                if (DNS_SERIAL_GT(current_pos.serial, serial)) {
                        return (ISC_R_NOTFOUND);
                }
-               result = journal_next(j, &current_pos, false);
+               result = journal_next(j, &current_pos);
                if (result != ISC_R_SUCCESS) {
                        return (result);
                }
@@ -1326,7 +1344,7 @@ dns_journal_commit(dns_journal_t *j) {
        if (!JOURNAL_EMPTY(&j->header)) {
                while (!DNS_SERIAL_GT(j->x.pos[1].serial,
                                      j->header.begin.serial)) {
-                       CHECK(journal_next(j, &j->header.begin, false));
+                       CHECK(journal_next(j, &j->header.begin));
                }
                index_invalidate(j, j->x.pos[1].serial);
        }
@@ -1806,7 +1824,7 @@ dns_journal_get_sourceserial(dns_journal_t *j, uint32_t *sourceserial) {
  */
 
 static isc_result_t
-read_one_rr(dns_journal_t *j, bool retry);
+read_one_rr(dns_journal_t *j);
 
 /*
  * Make sure the buffer 'b' is has at least 'size' bytes
@@ -1860,39 +1878,10 @@ dns_journal_iter_init(dns_journal_t *j, uint32_t begin_serial,
                do {
                        CHECK(journal_seek(j, pos.offset));
                        CHECK(journal_read_xhdr(j, &xhdr));
-                       /*
-                        * Handle mixture of version 1 and version 2
-                        * transaction headers in a version 1 journal.
-                        */
-                       if (j->header_ver1 &&
-                           (xhdr.serial0 != pos.serial ||
-                            isc_serial_le(xhdr.serial1, xhdr.serial0)))
-                       {
-                               if (j->xhdr_version == XHDR_VERSION1 &&
-                                   xhdr.serial1 == pos.serial) {
-                                       j->xhdr_version = XHDR_VERSION2;
-                                       CHECK(journal_seek(j, pos.offset));
-                                       CHECK(journal_read_xhdr(j, &xhdr));
-                               } else if (j->xhdr_version == XHDR_VERSION2 &&
-                                          xhdr.count == pos.serial) {
-                                       j->xhdr_version = XHDR_VERSION1;
-                                       CHECK(journal_seek(j, pos.offset));
-                                       CHECK(journal_read_xhdr(j, &xhdr));
-                               }
-                       }
 
-                       /*
-                        * Handle <size, serial0, serial1, 0> transaction
-                        * header.
-                        */
-                       if (j->header_ver1 &&
-                           j->xhdr_version == XHDR_VERSION2 &&
-                           xhdr.count == pos.serial && xhdr.serial1 == 0U &&
-                           isc_serial_gt(xhdr.serial0, xhdr.count))
-                       {
-                               xhdr.serial1 = xhdr.serial0;
-                               xhdr.serial0 = xhdr.count;
-                               xhdr.count = 0;
+                       if (j->header_ver1) {
+                               CHECK(maybe_fixup_xhdr(j, &xhdr, pos.serial,
+                                                      pos.offset));
                        }
 
                        /*
@@ -1906,7 +1895,7 @@ dns_journal_iter_init(dns_journal_t *j, uint32_t begin_serial,
                        size += xhdr.size;
                        count += xhdr.count;
 
-                       result = journal_next(j, &pos, false);
+                       result = journal_next(j, &pos);
                        if (result == ISC_R_NOMORE) {
                                result = ISC_R_SUCCESS;
                        }
@@ -1942,14 +1931,14 @@ dns_journal_first_rr(dns_journal_t *j) {
        j->it.xsize = 0; /* We have no transaction data yet... */
        j->it.xpos = 0;  /* ...and haven't used any of it. */
 
-       return (read_one_rr(j, false));
+       return (read_one_rr(j));
 
 failure:
        return (result);
 }
 
 static isc_result_t
-read_one_rr(dns_journal_t *j, bool retry) {
+read_one_rr(dns_journal_t *j) {
        isc_result_t result;
        dns_rdatatype_t rdtype;
        dns_rdataclass_t rdclass;
@@ -1980,34 +1969,15 @@ read_one_rr(dns_journal_t *j, bool retry) {
                                      j->filename);
                        FAIL(ISC_R_UNEXPECTED);
                }
+
+               if (j->header_ver1) {
+                       CHECK(maybe_fixup_xhdr(j, &xhdr, j->it.current_serial,
+                                              save.offset));
+               }
+
                if (xhdr.serial0 != j->it.current_serial ||
                    isc_serial_le(xhdr.serial1, xhdr.serial0))
                {
-                       if (!retry && j->header_ver1 &&
-                           j->xhdr_version == XHDR_VERSION2 &&
-                           xhdr.count == j->it.current_serial)
-                       {
-                               /* XHDR_VERSION2 -> XHDR_VERSION1 */
-                               j->xhdr_version = XHDR_VERSION1;
-                               CHECK(journal_seek(j, save.offset));
-                               result = read_one_rr(j, true);
-                               if (result == ISC_R_SUCCESS) {
-                                       j->recovered = true;
-                               }
-                               return (result);
-                       } else if (!retry && j->header_ver1 &&
-                                  j->xhdr_version == XHDR_VERSION1 &&
-                                  xhdr.serial1 == j->it.current_serial)
-                       {
-                               /* XHDR_VERSION1 -> XHDR_VERSION2 */
-                               j->xhdr_version = XHDR_VERSION2;
-                               CHECK(journal_seek(j, save.offset));
-                               result = read_one_rr(j, true);
-                               if (result == ISC_R_SUCCESS) {
-                                       j->recovered = true;
-                               }
-                               return (result);
-                       }
                        isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
                                      "%s: journal file corrupt: "
                                      "expected serial %u, got %u",
@@ -2016,29 +1986,6 @@ read_one_rr(dns_journal_t *j, bool retry) {
                        FAIL(ISC_R_UNEXPECTED);
                }
 
-               /*
-                * Handle <size, serial0, serial1, 0> transaction header.
-                */
-               if (j->header_ver1 && j->xhdr_version == XHDR_VERSION1) {
-                       uint32_t value;
-
-                       CHECK(journal_read(j, &value, sizeof(value)));
-                       if (value != 0L) {
-                               CHECK(journal_seek(j, save.offset + 12));
-                       } else {
-                               j->recovered = true;
-                       }
-               } else if (j->header_ver1 && j->xhdr_version == XHDR_VERSION2 &&
-                          xhdr.count == j->it.current_serial &&
-                          xhdr.serial1 == 0U &&
-                          isc_serial_gt(xhdr.serial0, xhdr.count))
-               {
-                       xhdr.serial1 = xhdr.serial0;
-                       xhdr.serial0 = xhdr.count;
-                       xhdr.count = 0;
-                       j->recovered = true;
-               }
-
                j->it.xsize = xhdr.size;
                j->it.xpos = 0;
        }
@@ -2122,7 +2069,7 @@ failure:
 
 isc_result_t
 dns_journal_next_rr(dns_journal_t *j) {
-       j->it.result = read_one_rr(j, false);
+       j->it.result = read_one_rr(j);
        return (j->it.result);
 }
 
@@ -2609,7 +2556,7 @@ dns_journal_compact(isc_mem_t *mctx, char *filename, uint32_t serial,
 
        current_pos = best_guess;
        while (current_pos.serial != serial) {
-               CHECK(journal_next(j1, &current_pos, false));
+               CHECK(journal_next(j1, &current_pos));
                if (current_pos.serial == j1->header.end.serial) {
                        break;
                }
@@ -2627,7 +2574,7 @@ dns_journal_compact(isc_mem_t *mctx, char *filename, uint32_t serial,
 
        INSIST(best_guess.serial != j1->header.end.serial);
        if (best_guess.serial != serial) {
-               CHECK(journal_next(j1, &best_guess, false));
+               CHECK(journal_next(j1, &best_guess));
                serial = best_guess.serial;
        }
 
@@ -2773,7 +2720,7 @@ dns_journal_compact(isc_mem_t *mctx, char *filename, uint32_t serial,
                current_pos = j2->header.begin;
                while (current_pos.serial != j2->header.end.serial) {
                        index_add(j2, &current_pos);
-                       CHECK(journal_next(j2, &current_pos, false));
+                       CHECK(journal_next(j2, &current_pos));
                }
 
                /*