Skip to content

Commit

Permalink
ovsdb-idl: Force reconnect when missing updates encountered.
Browse files Browse the repository at this point in the history
When processing update2 messages, if the IDL detects that previous
updates were missed, clear db->last_id and trigger a reconnect such that
the IDL refreshes its complete view of the database.

Such scenarios can happen for example when bugs in
ovsdb-server/ovsdb-idl are encountered. One such situation is reported
in https://bugzilla.redhat.com/show_bug.cgi?id=1808580.

This commit doesn't fix the root cause of the bug above but adds the
recovery mechanism to avoid staying in an inconsistent state for ever.

CC: Andy Zhou <azhou@ovn.org>
Fixes: db2b575 ("lib: add monitor2 support in ovsdb-idl.")
Signed-off-by: Dumitru Ceara <dceara@redhat.com>
Signed-off-by: 0-day Robot <robot@bytheb.org>
  • Loading branch information
dceara authored and ovsrobot committed Apr 3, 2020
1 parent cdc5d9c commit e78a5ef
Showing 1 changed file with 32 additions and 4 deletions.
36 changes: 32 additions & 4 deletions lib/ovsdb-idl.c
Expand Up @@ -324,7 +324,8 @@ static bool ovsdb_idl_process_update(struct ovsdb_idl_table *,
static bool ovsdb_idl_process_update2(struct ovsdb_idl_table *,
const struct uuid *,
const char *operation,
const struct json *row);
const struct json *row,
bool *inconsistent);
static void ovsdb_idl_insert_row(struct ovsdb_idl_row *, const struct json *);
static void ovsdb_idl_delete_row(struct ovsdb_idl_row *);
static bool ovsdb_idl_modify_row(struct ovsdb_idl_row *, const struct json *);
Expand Down Expand Up @@ -2318,10 +2319,25 @@ ovsdb_idl_db_parse_update__(struct ovsdb_idl_db *db,
row = shash_find_data(json_object(row_update), operation);

if (row) {
bool inconsistent = false;

if (ovsdb_idl_process_update2(table, &uuid, operation,
row)) {
row, &inconsistent)) {
db->change_seqno++;
}

/* If the db is in an inconsistent state, clear the
* db->last_id and retry to retrieve the complete DB.
*/
if (inconsistent) {
memset(&db->last_id, 0, sizeof db->last_id);
ovsdb_idl_retry(db->idl);
return ovsdb_error(NULL,
"<row_update2> received for "
"inconsistent IDL: "
"reconnecting IDL with "
"fast resync disabled");
}
break;
}
}
Expand Down Expand Up @@ -2445,16 +2461,26 @@ ovsdb_idl_process_update(struct ovsdb_idl_table *table,
}

/* Returns true if a column with mode OVSDB_IDL_MODE_RW changed, false
* otherwise. */
* otherwise.
*
* NOTE: When processing the "modify" updates, the IDL can determine that
* previous updates were missed (e.g., due to bugs) and that rows that don't
* exist locally should be updated. This indicates that the
* IDL is in an inconsistent state and, unlike in ovsdb_idl_process_update(),
* the missing rows cannot be inserted. If this is the case, 'inconsistent'
* is set to true to indicate the catastrophic failure.
*/
static bool
ovsdb_idl_process_update2(struct ovsdb_idl_table *table,
const struct uuid *uuid,
const char *operation,
const struct json *json_row)
const struct json *json_row,
bool *inconsistent)
{
struct ovsdb_idl_row *row;

row = ovsdb_idl_get_row(table, uuid);
*inconsistent = false;
if (!strcmp(operation, "delete")) {
/* Delete row. */
if (row && !ovsdb_idl_row_is_orphan(row)) {
Expand Down Expand Up @@ -2486,11 +2512,13 @@ ovsdb_idl_process_update2(struct ovsdb_idl_table *table,
VLOG_WARN_RL(&semantic_rl, "cannot modify missing but "
"referenced row "UUID_FMT" in table %s",
UUID_ARGS(uuid), table->class_->name);
*inconsistent = true;
return false;
}
} else {
VLOG_WARN_RL(&semantic_rl, "cannot modify missing row "UUID_FMT" "
"in table %s", UUID_ARGS(uuid), table->class_->name);
*inconsistent = true;
return false;
}
} else {
Expand Down

0 comments on commit e78a5ef

Please sign in to comment.