1
0
mirror of https://github.com/postgrespro/pg_probackup.git synced 2025-09-16 09:26:30 +02:00

[Issue #237] Ignore EROFS when locking backup in shared mode

This commit is contained in:
Grigory Smolkin
2021-02-10 14:11:57 +03:00
parent 02a3665375
commit c30628cd1d

View File

@@ -36,6 +36,11 @@ static void unlock_backup(const char *backup_dir, const char *backup_id, bool ex
static void release_excl_lock_file(const char *backup_dir); static void release_excl_lock_file(const char *backup_dir);
static void release_shared_lock_file(const char *backup_dir); static void release_shared_lock_file(const char *backup_dir);
#define LOCK_OK 0
#define LOCK_FAIL_TIMEOUT 1
#define LOCK_FAIL_ENOSPC 2
#define LOCK_FAIL_EROFS 3
typedef struct LockInfo typedef struct LockInfo
{ {
char backup_id[10]; char backup_id[10];
@@ -187,18 +192,26 @@ lock_backup(pgBackup *backup, bool strict, bool exclusive)
rc = grab_excl_lock_file(backup->root_dir, base36enc(backup->start_time), strict); rc = grab_excl_lock_file(backup->root_dir, base36enc(backup->start_time), strict);
if (rc == 1) if (rc == LOCK_FAIL_TIMEOUT)
return false; return false;
else if (rc == 2) else if (rc == LOCK_FAIL_ENOSPC)
{ {
enospc_detected = true;
if (strict)
return false;
/* /*
* If we failed to take exclusive lock due to ENOSPC, * If we failed to take exclusive lock due to ENOSPC,
* then in lax mode treat such condition as if lock was taken. * then in lax mode treat such condition as if lock was taken.
*/ */
enospc_detected = true;
if (strict)
return false;
}
else if (rc == LOCK_FAIL_EROFS)
{
/*
* If we failed to take exclusive lock due to EROFS,
* then in shared mode treat such condition as if lock was taken.
*/
return !exclusive;
} }
/* /*
@@ -242,7 +255,7 @@ lock_backup(pgBackup *backup, bool strict, bool exclusive)
* freed some space on filesystem, thanks to unlinking of BACKUP_RO_LOCK_FILE. * freed some space on filesystem, thanks to unlinking of BACKUP_RO_LOCK_FILE.
* If somebody concurrently acquired exclusive lock file first, then we should give up. * If somebody concurrently acquired exclusive lock file first, then we should give up.
*/ */
if (grab_excl_lock_file(backup->root_dir, base36enc(backup->start_time), strict) == 1) if (grab_excl_lock_file(backup->root_dir, base36enc(backup->start_time), strict) == LOCK_FAIL_TIMEOUT)
return false; return false;
return true; return true;
@@ -271,18 +284,20 @@ lock_backup(pgBackup *backup, bool strict, bool exclusive)
return true; return true;
} }
/* Lock backup in exclusive mode /*
* Lock backup in exclusive mode
* Result codes: * Result codes:
* 0 Success * LOCK_OK Success
* 1 Failed to acquire lock in lock_timeout time * LOCK_FAIL_TIMEOUT Failed to acquire lock in lock_timeout time
* 2 Failed to acquire lock due to ENOSPC * LOCK_FAIL_ENOSPC Failed to acquire lock due to ENOSPC
* LOCK_FAIL_EROFS Failed to acquire lock due to EROFS
*/ */
int int
grab_excl_lock_file(const char *root_dir, const char *backup_id, bool strict) grab_excl_lock_file(const char *root_dir, const char *backup_id, bool strict)
{ {
char lock_file[MAXPGPATH]; char lock_file[MAXPGPATH];
int fd = 0; int fd = 0;
char buffer[MAXPGPATH * 2 + 256]; char buffer[256];
int ntries = LOCK_TIMEOUT; int ntries = LOCK_TIMEOUT;
int empty_tries = LOCK_STALE_TIMEOUT; int empty_tries = LOCK_STALE_TIMEOUT;
int len; int len;
@@ -312,6 +327,14 @@ grab_excl_lock_file(const char *root_dir, const char *backup_id, bool strict)
if (fd >= 0) if (fd >= 0)
break; /* Success; exit the retry loop */ break; /* Success; exit the retry loop */
/* read-only fs is a special case */
if (errno == EROFS)
{
elog(WARNING, "Could not create lock file \"%s\": %s",
lock_file, strerror(errno));
return LOCK_FAIL_EROFS;
}
/* /*
* Couldn't create the pid file. Probably it already exists. * Couldn't create the pid file. Probably it already exists.
* If file already exists or we have some permission problem (???), * If file already exists or we have some permission problem (???),
@@ -390,7 +413,7 @@ grab_excl_lock_file(const char *root_dir, const char *backup_id, bool strict)
* exist. * exist.
*/ */
if (encoded_pid == my_pid) if (encoded_pid == my_pid)
return 0; return LOCK_OK;
if (kill(encoded_pid, 0) == 0) if (kill(encoded_pid, 0) == 0)
{ {
@@ -437,7 +460,7 @@ grab_lock:
/* Failed to acquire exclusive lock in time */ /* Failed to acquire exclusive lock in time */
if (fd <= 0) if (fd <= 0)
return 1; return LOCK_FAIL_TIMEOUT;
/* /*
* Successfully created the file, now fill it. * Successfully created the file, now fill it.
@@ -457,7 +480,7 @@ grab_lock:
* Only delete command should be run in lax mode. * Only delete command should be run in lax mode.
*/ */
if (!strict && save_errno == ENOSPC) if (!strict && save_errno == ENOSPC)
return 2; return LOCK_FAIL_ENOSPC;
else else
elog(ERROR, "Could not write lock file \"%s\": %s", elog(ERROR, "Could not write lock file \"%s\": %s",
lock_file, strerror(save_errno)); lock_file, strerror(save_errno));
@@ -475,7 +498,7 @@ grab_lock:
* Only delete command should be run in lax mode. * Only delete command should be run in lax mode.
*/ */
if (!strict && save_errno == ENOSPC) if (!strict && save_errno == ENOSPC)
return 2; return LOCK_FAIL_ENOSPC;
else else
elog(ERROR, "Could not flush lock file \"%s\": %s", elog(ERROR, "Could not flush lock file \"%s\": %s",
lock_file, strerror(save_errno)); lock_file, strerror(save_errno));
@@ -488,7 +511,7 @@ grab_lock:
fio_unlink(lock_file, FIO_BACKUP_HOST); fio_unlink(lock_file, FIO_BACKUP_HOST);
if (!strict && errno == ENOSPC) if (!strict && errno == ENOSPC)
return 2; return LOCK_FAIL_ENOSPC;
else else
elog(ERROR, "Could not close lock file \"%s\": %s", elog(ERROR, "Could not close lock file \"%s\": %s",
lock_file, strerror(save_errno)); lock_file, strerror(save_errno));
@@ -498,7 +521,7 @@ grab_lock:
// base36enc(backup->start_time), // base36enc(backup->start_time),
// LOCK_TIMEOUT - ntries + LOCK_STALE_TIMEOUT - empty_tries); // LOCK_TIMEOUT - ntries + LOCK_STALE_TIMEOUT - empty_tries);
return 0; return LOCK_OK;
} }
/* Wait until all shared lock owners are gone /* Wait until all shared lock owners are gone
@@ -648,7 +671,12 @@ grab_shared_lock_file(pgBackup *backup)
fp_out = fopen(lock_file_tmp, "w"); fp_out = fopen(lock_file_tmp, "w");
if (fp_out == NULL) if (fp_out == NULL)
{
if (errno == EROFS)
return 0;
elog(ERROR, "Cannot open temp lock file \"%s\": %s", lock_file_tmp, strerror(errno)); elog(ERROR, "Cannot open temp lock file \"%s\": %s", lock_file_tmp, strerror(errno));
}
/* add my own pid */ /* add my own pid */
buffer_len += snprintf(buffer+buffer_len, sizeof(buffer), "%u\n", my_pid); buffer_len += snprintf(buffer+buffer_len, sizeof(buffer), "%u\n", my_pid);
@@ -679,7 +707,7 @@ unlock_backup(const char *backup_dir, const char *backup_id, bool exclusive)
} }
/* To remove shared lock, we must briefly obtain exclusive lock, ... */ /* To remove shared lock, we must briefly obtain exclusive lock, ... */
if (grab_excl_lock_file(backup_dir, backup_id, false) != 0) if (grab_excl_lock_file(backup_dir, backup_id, false) != LOCK_OK)
/* ... if it's not possible then leave shared lock */ /* ... if it's not possible then leave shared lock */
return; return;