From 5d17fd66e08612574ffe0c39ff7624259319059c Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Wed, 6 Nov 2024 10:40:43 -0600 Subject: [PATCH v1 6/8] In pg_upgrade's catalog-swap mode, only sync files as necessary. THIS IS A PROOF OF CONCEPT AND IS NOT READY FOR SERIOUS REVIEW. In this mode, it can be much faster to use "--sync-method fsync", which now skips synchronizing data files moved from the old cluster (which we assumed were synchronized before pg_upgrade). --- src/bin/pg_upgrade/pg_upgrade.c | 6 ++-- src/bin/pg_upgrade/relfilenumber.c | 52 ++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 663235816f..f5946ac89a 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -210,10 +210,12 @@ main(int argc, char **argv) { prep_status("Sync data directory to disk"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, - "\"%s/initdb\" --sync-only \"%s\" --sync-method %s", + "\"%s/initdb\" --sync-only \"%s\" --sync-method %s %s", new_cluster.bindir, new_cluster.pgdata, - user_opts.sync_method); + user_opts.sync_method, + (user_opts.transfer_mode == TRANSFER_MODE_CATALOG_SWAP) ? + "--no-sync-data-files" : ""); check_ok(); } diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index 9d8fce3c4a..dcca4bb2e7 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -25,8 +25,49 @@ typedef struct move_catalog_file_context FileNameMap *maps; int size; char *target; + bool sync_moved; } move_catalog_file_context; +#define SYNC_QUEUE_MAX_LEN (1024) + +static char *sync_queue[SYNC_QUEUE_MAX_LEN]; +static bool sync_queue_inited; +static int sync_queue_len; + +static inline void +sync_queue_init(void) +{ + if (sync_queue_inited) + return; + + sync_queue_inited = true; + for (int i = 0; i < SYNC_QUEUE_MAX_LEN; i++) + sync_queue[i] = palloc(MAXPGPATH); +} + +static inline void +sync_queue_sync_all(void) +{ + if (!sync_queue_inited) + return; + + for (int i = 0; i < sync_queue_len; i++) + fsync_fname(sync_queue[i], false, NULL); + sync_queue_len = 0; +} + +static inline void +sync_queue_push(const char *fname) +{ + sync_queue_init(); + + pre_sync_fname(fname, false, NULL); + + strncpy(sync_queue[sync_queue_len++], fname, MAXPGPATH); + if (sync_queue_len >= SYNC_QUEUE_MAX_LEN) + sync_queue_sync_all(); +} + /* * transfer_all_new_tablespaces() * @@ -138,6 +179,8 @@ transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, /* We allocate something even for n_maps == 0 */ pg_free(mappings); } + + sync_queue_sync_all(); } static int @@ -195,6 +238,9 @@ move_catalog_file(const char *fname, bool isdir, void *arg) if (rename(fname, dst) != 0) pg_fatal("could not rename \"%s\" to \"%s\": %m", fname, dst); + if (context->sync_moved) + sync_queue_push(dst); + return 0; } @@ -250,10 +296,12 @@ do_catalog_transfer(FileNameMap *maps, int size, char *old_tablespace) context.maps = maps; context.size = size; context.target = old_cat; + context.sync_moved = false; walkdir(new_dat, move_catalog_file, false, &context); /* move catalogs in moved-aside data dir in place */ context.target = new_dat; + context.sync_moved = (sync_method != DATA_DIR_SYNC_METHOD_SYNCFS); walkdir(moved_dat, move_catalog_file, false, &context); /* no need to sync things individually if we are going to syncfs() later */ @@ -265,6 +313,8 @@ do_catalog_transfer(FileNameMap *maps, int size, char *old_tablespace) pg_fatal("could not synchronize directory \"%s\": %m", moved_dat); if (fsync_fname(old_cat, true, NULL) != 0) pg_fatal("could not synchronize directory \"%s\": %m", old_cat); + if (fsync_fname(new_dat, true, NULL) != 0) + pg_fatal("could not synchronize directory \"%s\": %m", new_dat); /* * XXX: We could instead fsync() these directories once at the end instead @@ -276,6 +326,8 @@ do_catalog_transfer(FileNameMap *maps, int size, char *old_tablespace) pg_fatal("could not synchronize directory \"%s\": %m", old_tblspc); if (fsync_fname(moved_tblspc, true, NULL) != 0) pg_fatal("could not synchronize directory \"%s\": %m", moved_tblspc); + if (fsync_fname(new_tblspc, true, NULL) != 0) + pg_fatal("could not synchronize directory \"%s\": %m", new_tblspc); } /* -- 2.39.5 (Apple Git-154)