1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-26 21:57:41 +03:00

recovery: data corruption of persistent DBs after recoveries: don't delete emtpy records

The record-by-record mode of recovery deletes empty records.
For persistent databases, this can lead to data corruption
by deleting records that should be there:

- Assume the cluster has been running for a while.

- A record R in a persistent database has been created and
  deleted a couple of times, the last operation being deletion,
  leaving an empty record with a high RSN, say 10.

- Now a node N is turned off.

- This leaves the local database copy of D on N with the empty
  copy of R and RSN 10. On all other nodes, the recovery has deleted
  the copy of record R.

- Now the record is created again while node N is turned off.
  This creates R with RSN = 1 on all nodes except for N.

- Now node N is turned on again. The following recovery will chose
  the older empty copy of R due to RSN 10 > RSN 1.

==> Hence the record is gone after the recovery.

On databases like Samba's registry, this can damage the higher-level
data structures built from the various tdb-level records.

This patch fixes that problem by not deleting empty records in recoveries
for persistent databases.

Signed-off-by: Michael Adam <obnox@samba.org>

(This used to be ctdb commit 6860c79aea416f56cfd7a6af790bbdf495dbc54e)
This commit is contained in:
Michael Adam 2012-11-19 17:28:03 +01:00
parent 9c65a7ef81
commit 8732e2356f

View File

@ -1202,8 +1202,37 @@ static int traverse_recdb(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data,
struct ctdb_rec_data *rec;
struct ctdb_ltdb_header *hdr;
/* skip empty records */
if (data.dsize <= sizeof(struct ctdb_ltdb_header)) {
/*
* skip empty records - but NOT for persistent databases:
*
* The record-by-record mode of recovery deletes empty records.
* For persistent databases, this can lead to data corruption
* by deleting records that should be there:
*
* - Assume the cluster has been running for a while.
*
* - A record R in a persistent database has been created and
* deleted a couple of times, the last operation being deletion,
* leaving an empty record with a high RSN, say 10.
*
* - Now a node N is turned off.
*
* - This leaves the local database copy of D on N with the empty
* copy of R and RSN 10. On all other nodes, the recovery has deleted
* the copy of record R.
*
* - Now the record is created again while node N is turned off.
* This creates R with RSN = 1 on all nodes except for N.
*
* - Now node N is turned on again. The following recovery will chose
* the older empty copy of R due to RSN 10 > RSN 1.
*
* ==> Hence the record is gone after the recovery.
*
* On databases like Samba's registry, this can damage the higher-level
* data structures built from the various tdb-level records.
*/
if (!params->persistent && data.dsize <= sizeof(struct ctdb_ltdb_header)) {
return 0;
}