diff options
author | Michael Adam <obnox@samba.org> | 2007-07-20 16:39:42 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:28:52 -0500 |
commit | 7712e7eeb6358c05677ae718a6bd5bcb27d509a4 (patch) | |
tree | f5984569aa005e43c54ab4e6ec4bc1184bf651b5 /source3 | |
parent | 84f352caa58a5a903087ff93e56113a07a7840aa (diff) | |
download | samba-7712e7eeb6358c05677ae718a6bd5bcb27d509a4.tar.gz |
r23981: Make tdb_validate_and_backup try harder to end up with a valid tdb:
If restoring a backup fails due to lack of space, remove the
corrupt tdb previously moved away to "name.corrupt", and retry.
If restoring still fails, move the backup in place instead of
copying it.
Michael
(This used to be commit f81f2bf480a955213be8461636ee6f81643f17b8)
Diffstat (limited to 'source3')
-rw-r--r-- | source3/lib/util_tdb.c | 83 |
1 files changed, 60 insertions, 23 deletions
diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index cc10e4c9add..471a8c7da9c 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -1183,6 +1183,7 @@ static int tdb_backup(TALLOC_CTX *ctx, const char *src_path, char *tmp_path = NULL; struct stat st; int count1, count2; + int saved_errno = 0; int ret = -1; if (stat(src_path, &st) != 0) { @@ -1212,6 +1213,7 @@ static int tdb_backup(TALLOC_CTX *ctx, const char *src_path, if (dst_tdb == NULL) { DEBUG(3, ("Error creating tdb '%s': %s\n", tmp_path, strerror(errno))); + saved_errno = errno; unlink(tmp_path); goto done; } @@ -1264,6 +1266,9 @@ done: unlink(tmp_path); TALLOC_FREE(tmp_path); } + if (saved_errno != 0) { + errno = saved_errno; + } return ret; } @@ -1296,17 +1301,45 @@ static int rename_file_with_suffix(TALLOC_CTX *ctx, const char *path, */ static int tdb_backup_with_rotate(TALLOC_CTX *ctx, const char *src_path, const char *dst_path, int hash_size, - const char *rotate_suffix) + const char *rotate_suffix, + BOOL retry_norotate_if_nospc, + BOOL rename_as_last_resort_if_nospc) { int ret; - ret = rename_file_with_suffix(ctx, dst_path, rotate_suffix); + rename_file_with_suffix(ctx, dst_path, rotate_suffix); - /* ignore return value of rename here: - * the more important thing is to do the backup */ - ret = tdb_backup(ctx, src_path, dst_path, hash_size); + ret = tdb_backup(ctx, src_path, dst_path, hash_size); - return ret; + if (ret != 0) { + DEBUG(10, ("backup of %s failed: %s\n", src_path, strerror(errno))); + } + if ((ret != 0) && (errno == ENOSPC) && retry_norotate_if_nospc) + { + char *rotate_path = talloc_asprintf(ctx, "%s%s", dst_path, + rotate_suffix); + DEBUG(10, ("backup of %s failed due to lack of space\n", + src_path)); + DEBUGADD(10, ("trying to free some space by removing rotated " + "dst %s\n", rotate_path)); + if (unlink(rotate_path) == -1) { + DEBUG(10, ("unlink of %s failed: %s\n", rotate_path, + strerror(errno))); + } else { + ret = tdb_backup(ctx, src_path, dst_path, hash_size); + } + TALLOC_FREE(rotate_path); + } + + if ((ret != 0) && (errno == ENOSPC) && rename_as_last_resort_if_nospc) + { + DEBUG(10, ("backup of %s failed due to lack of space\n", + src_path)); + DEBUGADD(10, ("using 'rename' as a last resort\n")); + ret = rename(src_path, dst_path); + } + + return ret; } /* @@ -1347,7 +1380,7 @@ int tdb_validate_and_backup(const char *tdb_path, if (ret == 0) { DEBUG(1, ("tdb '%s' is valid\n", tdb_path)); ret = tdb_backup_with_rotate(ctx, tdb_path, tdb_path_backup, 0, - rotate_suffix); + rotate_suffix, True, False); if (ret != 0) { DEBUG(1, ("Error creating backup of tdb '%s'\n", tdb_path)); @@ -1360,32 +1393,36 @@ int tdb_validate_and_backup(const char *tdb_path, } else { DEBUG(1, ("tdb '%s' is invalid\n", tdb_path)); - /* move corrupt tdb away first, but don't return on error*/ - ret = rename_file_with_suffix(ctx, tdb_path, corrupt_suffix); + ret =stat(tdb_path_backup, &st); if (ret != 0) { - DEBUG(1, ("Error moving tdb to '%s%s'\n", tdb_path, - corrupt_suffix)); - } else { - DEBUG(1, ("Corrupt tdb stored as '%s%s'\n", tdb_path, - corrupt_suffix)); - } - - if (stat(tdb_path_backup, &st) != 0) { DEBUG(5, ("Could not stat '%s': %s\n", tdb_path_backup, strerror(errno))); DEBUG(1, ("No backup found.\n")); - ret = -1; - goto done; + } else { + DEBUG(1, ("backup '%s' found.\n", tdb_path_backup)); + ret = tdb_validate(tdb_path_backup, validate_fn); + if (ret != 0) { + DEBUG(1, ("Backup '%s' is invalid.\n", + tdb_path_backup)); + } } - DEBUG(1, ("backup '%s' found.\n", tdb_path_backup)); - ret = tdb_validate(tdb_path_backup, validate_fn); + if (ret != 0) { - DEBUG(1, ("Backup '%s' is invalid.\n",tdb_path_backup)); + int renamed = rename_file_with_suffix(ctx, tdb_path, + corrupt_suffix); + if (renamed != 0) { + DEBUG(1, ("Error moving tdb to '%s%s'\n", + tdb_path, corrupt_suffix)); + } else { + DEBUG(1, ("Corrupt tdb stored as '%s%s'\n", + tdb_path, corrupt_suffix)); + } goto done; } DEBUG(1, ("valid backup '%s' found\n", tdb_path_backup)); - ret = tdb_backup(ctx, tdb_path_backup, tdb_path, 0); + ret = tdb_backup_with_rotate(ctx, tdb_path_backup, tdb_path, 0, + corrupt_suffix, True, True); if (ret != 0) { DEBUG(1, ("Error restoring backup from '%s'\n", tdb_path_backup)); |