summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2020-03-04 11:10:54 +0100
committerantirez <antirez@gmail.com>2020-03-05 12:51:14 +0100
commitbaaf869fc3e138cfcb4cfda09f09fd3c87c8f924 (patch)
tree737c9ebd60f015ccda4c84efa4f45972ac6e9922
parentbe4bc1a5be26a7fde2fd05acd8187f5f0ed59f25 (diff)
downloadredis-baaf869fc3e138cfcb4cfda09f09fd3c87c8f924.tar.gz
Introduce bg_unlink().
-rw-r--r--src/replication.c34
1 files changed, 31 insertions, 3 deletions
diff --git a/src/replication.c b/src/replication.c
index e71b269d8..8a05b9696 100644
--- a/src/replication.c
+++ b/src/replication.c
@@ -79,6 +79,34 @@ char *replicationGetSlaveName(client *c) {
return buf;
}
+/* Plain unlink() can block for quite some time in order to actually apply
+ * the file deletion to the filesystem. This call removes the file in a
+ * background thread instead. We actually just do close() in the thread,
+ * by using the fact that if there is another instance of the same file open,
+ * the foreground unlink() will not really do anything, and deleting the
+ * file will only happen once the last reference is lost. */
+int bg_unlink(const char *filename) {
+ int fd = open(filename,O_RDONLY|O_NONBLOCK);
+ if (fd == -1) {
+ /* Can't open the file? Fall back to unlinking in the main thread. */
+ return unlink(filename);
+ } else {
+ /* The following unlink() will not do anything since file
+ * is still open. */
+ int retval = unlink(filename);
+ if (retval == -1) {
+ /* If we got an unlink error, we just return it, closing the
+ * new reference we have to the file. */
+ int old_errno = errno;
+ close(fd); /* This would overwrite our errno. So we saved it. */
+ errno = old_errno;
+ return -1;
+ }
+ bioCreateBackgroundJob(BIO_CLOSE_FILE,(void*)(long)fd,NULL,NULL);
+ return 0; /* Success. */
+ }
+}
+
/* ---------------------------------- MASTER -------------------------------- */
void createReplicationBacklog(void) {
@@ -917,7 +945,7 @@ void removeRDBUsedToSyncReplicas(void) {
}
if (delrdb) {
RDBGeneratedByReplication = 0;
- unlink(server.rdb_filename);
+ bg_unlink(server.rdb_filename);
}
}
}
@@ -1679,14 +1707,14 @@ void readSyncBulkPayload(connection *conn) {
"Failed trying to load the MASTER synchronization "
"DB from disk");
cancelReplicationHandshake();
- if (allPersistenceDisabled()) unlink(server.rdb_filename);
+ if (allPersistenceDisabled()) bg_unlink(server.rdb_filename);
/* Note that there's no point in restarting the AOF on sync failure,
it'll be restarted when sync succeeds or replica promoted. */
return;
}
/* Cleanup. */
- if (allPersistenceDisabled()) unlink(server.rdb_filename);
+ if (allPersistenceDisabled()) bg_unlink(server.rdb_filename);
zfree(server.repl_transfer_tmpfile);
close(server.repl_transfer_fd);
server.repl_transfer_fd = -1;