Skip to content
Snippets Groups Projects
Commit a50ad00b authored by Jan Včelák's avatar Jan Včelák :rocket:
Browse files

Merge branch 'full-journal-fix' of /git/repositories/labs/knot

parents 479eb094 be3c82ab
No related branches found
No related tags found
No related merge requests found
......@@ -958,23 +958,6 @@ int journal_trans_rollback(journal_t *journal)
return KNOT_ENOENT;
}
/* Preempt last (failed) node. */
journal_node_t *t_end = journal->nodes + journal->qtail;
dbg_journal("journal: rollback transaction id=<%hu,%hu> (@%u, l=%u)\n",
journal->tmark, journal->qtail, t_end->pos, t_end->len);
journal->free.pos = t_end->pos;
journal->free.len = t_end->len;
/* Best effort free. */
t_end->flags = JOURNAL_FREE;
(void) journal_update(journal, t_end);
/* Write back free segment state. */
int seek_ret = lseek(journal->fd, JOURNAL_HSIZE, SEEK_SET);
if (seek_ret < 0 || !sfwrite(&journal->free, sizeof(journal_node_t), journal->fd)) {
return KNOT_ERROR;
}
/* Clear in-transaction flags. */
journal->tmark = 0;
journal->bflags &= (~JOURNAL_TRANS);
......
......@@ -138,6 +138,8 @@ static uint32_t zones_soa_expire(knot_zone_t *zone)
*/
static int zones_expire_ev(event_t *e)
{
assert(e);
dbg_zones("zones: EXPIRE timer event\n");
if (e->data == NULL) {
return KNOT_EINVAL;
......@@ -197,6 +199,8 @@ static int zones_expire_ev(event_t *e)
*/
static int zones_refresh_ev(event_t *e)
{
assert(e);
dbg_zones("zones: REFRESH or RETRY timer event\n");
rcu_read_lock();
knot_zone_t *zone = (knot_zone_t *)e->data;
......@@ -287,6 +291,9 @@ static int zones_refresh_ev(event_t *e)
/*! \brief Function for marking nodes as synced and updated. */
static int zones_ixfrdb_sync_apply(journal_t *j, journal_node_t *n)
{
assert(j);
assert(n);
/* Check for dirty bit (not synced to permanent storage). */
if (n->flags & JOURNAL_DIRTY) {
......@@ -313,16 +320,13 @@ static bool zones_changesets_empty(const knot_changesets_t *chs)
return knot_changeset_is_empty(HEAD(chs->sets));
}
static int zones_store_changesets_begin_and_store(knot_zone_t *zone,
knot_changesets_t *chgsets,
journal_t **transaction)
static int zones_store_chgsets_try_store(knot_zone_t *zone,
knot_changesets_t *chgsets,
journal_t **transaction)
{
assert(zone != NULL);
assert(chgsets != NULL);
if (zones_changesets_empty(chgsets)) {
return KNOT_EINVAL;
}
assert(zone);
assert(chgsets);
assert(transaction);
*transaction = zones_store_changesets_begin(zone);
if (*transaction == NULL) {
......@@ -331,6 +335,8 @@ static int zones_store_changesets_begin_and_store(knot_zone_t *zone,
}
int ret = zones_store_changesets(zone, chgsets, *transaction);
/* In any case, rollback the transaction. */
if (ret != KNOT_EOK) {
zones_store_changesets_rollback(*transaction);
*transaction = NULL;
......@@ -342,24 +348,10 @@ static int zones_store_changesets_begin_and_store(knot_zone_t *zone,
return KNOT_EOK;
}
/*!
* \brief Sync chagnes in zone to zonefile.
*/
static int zones_zonefile_sync_ev(event_t *e)
static int zones_zonefile_sync_from_ev(knot_zone_t *zone, zonedata_t *zd)
{
dbg_zones("zones: IXFR database SYNC timer event\n");
/* Fetch zone. */
knot_zone_t *zone = (knot_zone_t *)e->data;
if (!zone) {
return KNOT_EINVAL;
}
/* Fetch zone data. */
zonedata_t *zd = zone->data;
if (!zd) {
return KNOT_EINVAL;
}
assert(zone);
assert(zd);
/* Only on zones with valid contents (non empty). */
int ret = KNOT_EOK;
......@@ -383,6 +375,31 @@ static int zones_zonefile_sync_ev(event_t *e)
rcu_read_unlock();
}
return ret;
}
/*!
* \brief Sync chagnes in zone to zonefile.
*/
static int zones_zonefile_sync_ev(event_t *e)
{
assert(e);
dbg_zones("zones: IXFR database SYNC timer event\n");
/* Fetch zone. */
knot_zone_t *zone = (knot_zone_t *)e->data;
if (!zone) {
return KNOT_EINVAL;
}
/* Fetch zone data. */
zonedata_t *zd = zone->data;
if (!zd) {
return KNOT_EINVAL;
}
int ret = zones_zonefile_sync_from_ev(zone, zd);
/* Reschedule. */
rcu_read_lock();
int next_timeout = zd->conf->dbsync_timeout * 1000;
......@@ -394,6 +411,51 @@ static int zones_zonefile_sync_ev(event_t *e)
return ret;
}
static int zones_store_changesets_begin_and_store(knot_zone_t *zone,
knot_changesets_t *chgsets,
journal_t **transaction)
{
assert(zone != NULL);
assert(chgsets != NULL);
if (zones_changesets_empty(chgsets)) {
return KNOT_EINVAL;
}
int ret = zones_store_chgsets_try_store(zone, chgsets, transaction);
/* If the journal was full (KNOT_EBUSY), we must flush it by hand and
* try to save the changesets once again. If this fails, the changesets
* are larger than max journal size, so return error.
*/
if (ret == KNOT_EBUSY) {
/* Fetch zone-specific data. */
zonedata_t *zd = (zonedata_t *)zone->data;
log_server_notice("Journal for '%s' is full, flushing.\n",
zd->conf->name);
/* Don't worry about sync event. It can't happen while this
* event (signing) is not finished. We may thus do the sync
* by hand and leave the planned one there to be executed
* later. */
assert(*transaction == NULL);
/* Transaction rolled back, journal released, we may flush. */
ret = zones_zonefile_sync_from_ev(zone, zd);
if (ret != KNOT_EOK) {
log_server_error("Failed to sync journal to zone file."
"\n");
return ret;
}
/* Begin the transaction anew. */
ret = zones_store_chgsets_try_store(zone, chgsets, transaction);
}
return ret;
}
/*----------------------------------------------------------------------------*/
/*! \brief Return 'serial_from' part of the key. */
......@@ -737,6 +799,9 @@ static int zones_merge_and_store_changesets(knot_zone_t *zone,
knot_changesets_t *sec_chs,
journal_t **transaction)
{
assert(zone);
assert(transaction);
if (zones_changesets_empty(diff_chs) &&
zones_changesets_empty(sec_chs)) {
return KNOT_EOK;
......@@ -853,6 +918,10 @@ static int zones_update_forward(int fd, knot_ns_transport_t ttype,
knot_zone_t *zone, const sockaddr_t *from,
knot_packet_t *query, size_t qsize)
{
assert(zone);
assert(from);
assert(query);
rcu_read_lock();
/* Check transport type. */
......@@ -909,6 +978,9 @@ static int replan_zone_sign_after_ddns(knot_zone_t *zone, zonedata_t *zd,
uint32_t used_lifetime,
uint32_t used_refresh)
{
assert(zone);
assert(zd);
int ret = KNOT_EOK;
uint32_t new_expire = time(NULL) + (used_lifetime - used_refresh);
if (new_expire < zd->dnssec_timer->tv.tv_sec) {
......@@ -940,6 +1012,14 @@ static int zones_process_update_auth(knot_zone_t *zone,
const sockaddr_t *addr,
knot_tsig_key_t *tsig_key)
{
assert(zone);
assert(resp);
assert(resp_wire);
assert(rsize);
assert(rcode);
assert(addr);
assert(tsig_key);
int ret = KNOT_EOK;
dbg_zones_verb("TSIG check successful. Answering query.\n");
......@@ -2259,14 +2339,7 @@ int zones_store_changesets(knot_zone_t *zone, knot_changesets_t *src, journal_t
break;
}
/* Flush if the journal is full. */
event_t *tmr = zd->ixfr_dbsync;
if (ret == KNOT_EBUSY && tmr) {
log_server_notice("Journal for '%s' is full, flushing.\n",
zd->conf->name);
evsched_cancel(tmr->parent, tmr);
evsched_schedule(tmr->parent, tmr, 0);
}
/*! @note If the journal is full, this function returns KNOT_EBUSY. */
/* Written changesets to journal. */
return ret;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment