summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Adam <obnox@samba.org>2007-07-20 16:39:42 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:28:52 -0500
commit7712e7eeb6358c05677ae718a6bd5bcb27d509a4 (patch)
treef5984569aa005e43c54ab4e6ec4bc1184bf651b5
parent84f352caa58a5a903087ff93e56113a07a7840aa (diff)
downloadsamba-7712e7eeb6358c05677ae718a6bd5bcb27d509a4.tar.gz
samba-7712e7eeb6358c05677ae718a6bd5bcb27d509a4.tar.bz2
samba-7712e7eeb6358c05677ae718a6bd5bcb27d509a4.zip
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)
-rw-r--r--source3/lib/util_tdb.c83
1 files changed, 60 insertions, 23 deletions
diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c
index cc10e4c9ad..471a8c7da9 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));