Hi Shihao and Heikki, Thanks for testing and for the feedback.
*1. Meson coverage — Shihao #1* > t/009_initdb_option.pl is not listed in > src/bin/pg_upgrade/meson.build, so it never runs in a meson build. Thanks, included t/009_initdb_option.pl in the Meson test list. *2. Group access — Shihao #2* > The group access setting from initdb -g is not copied from the old > cluster. The current patch now preserves the old cluster's group-access setting by passing --allow-group-access to initdb when the old cluster allows group access. *3. Missing -B — Shihao #3 and Heikki* Shihao Zhong wrote: > resolve_new_bindir() is a nice cleanup, but the new callers pass > os_info.progname. That is get_progname(argv[0]), so it has no directory > in it. find_my_exec() then searches PATH instead of using argv[0]. Heikki Linnakangas wrote: > Another little issue I noticed: Without the --new-bindir/-B option, it > fails to find the binary: > > $ bin/pg_upgrade --check -d data -b bin -D data-new2 --initdb > could not find a "pg_upgrade" to execute The current patch now passes the original argv[0] to resolve_new_bindir(). Without -B or PGBINNEW, the new binary directory defaults to the directory containing pg_upgrade, matching the existing behavior. *4. Log location and cleanup — Shihao #4* > The <pgdata>.initdb_log directory is never deleted. It stays after a > successful run and after --check, and --retain has no effect on it. The patch is updated so that it now writes --initdb logs under ./pg_upgrade_output.d in the current working directory, using the normal cleanup and --retain handling. Successful runs, including --check, remove their logs unless --retain is given; failed runs keep them. This avoids requiring write access to the new data directory's parent just for logging. Logs stay outside the new data directory because initdb requires it to be empty. *5. Existing empty target — Shihao #5* > A small note on the empty directory check. It stops initdb from > running where there are files, but the cleanup still calls rmtree() on > the directory itself. So a directory the operator made by hand is gone > after a failed run. The patch now leaves initialization-failure cleanup to initdb, which preserves an operator-created directory. It removes the contents of a pre-existing empty target or removes a directory it created, unless --no-clean was requested. Initdb sets the directory permissions as usual, and the original mode is not restored. Once initialization succeeds, pg_upgrade leaves the new cluster in place if any later pg_upgrade step fails, as it does for a manually initialized cluster. *6. --check --initdb — Shihao #6 and Heikki* Shihao Zhong wrote: > Two things about --check --initdb. I saw that v5 turned this into a > dry run instead of blocking it. First, the live check problem Daniel > reported for v2 is back. With the old cluster running, plain --check > says "Clusters are compatible", while --check --initdb says "There seems > to be a postmaster servicing the old cluster". Second, the dry run > returns 0 for a cluster that cannot be upgraded. With a regproc column > in the old cluster, --check --initdb returns 0 and the real run returns > 1. Heikki Linnakangas wrote: > That's not good, that essentially means that --check doesn't work with > the --initdb option. Some of the checks check that the new cluster is > compatible with the old cluster, and assuming we run initdb correctly, > there's no need to run those checks with --initdb. But we should still > run all the checks we can on the old cluster. The current patch now allows --check --initdb to check a running old server without stopping it. The new server must use a different port. Additionally, the patch now initializes the new cluster and runs the compatibility checks on both clusters for --check --initdb, without performing the upgrade. Unsupported regproc columns cause the check to fail. --check --initdb retains the initialized new cluster whether the compatibility checks succeed or fail. After a successful check, rerun pg_upgrade against that cluster without --check, --initdb, or --initdb-options. *7. -O and extra initdb options — Heikki* > But why forbid using -O with --initdb? I > would imagine that the -O options are passed to the postmaster the same > way with or without --initdb. Right, the patch now allows -O with --initdb and passes it only to the new postmaster, using the existing server-option handling. *8. Source-server startup description — Heikki* > Hmm, how's that different from how it works without --initdb? pg_upgrade > needs to launch the old cluster anyway to perform the compatibility > checks, right? Yes. With --initdb, the old cluster's encoding and locale are read before initializing the new cluster. The current implementation now omits this startup detail from the option documentation since the Notes already describe temporary server starts. *9. Passing extra options to initdb — Heikki* > Is there a way to pass extra options to initdb? Or do you require the > user to run initdb first or change the settings afterwards, if they want > some additional settings? The current patch now provides --initdb-options to pass additional arguments to initdb, for example: pg_upgrade --initdb \ --initdb-options='-c huge_pages=off --waldir=/wal/new' ... It requires --initdb and it can be repeated, preserving upstream initdb option ordering. Settings passed with initdb -c apply during initialization and remain in postgresql.conf. Options that conflict with pg_upgrade's managed settings are rejected, while other option values and paths are validated by initdb. Github repo: https://github.com/LeeBohyun/postgres/tree/pg_upgrade_initdb Best, Bohyun On Mon, Oct 5, 2026 at 2:49 PM Heikki Linnakangas <[email protected]> wrote: > On 17/07/2026 15:10, Bohyun Lee wrote: > > -O: dropped support with --initdb entirely, as you originally suggested. > > The partial "-c only" forwarding still broke on quoted values with > > spaces. pg_upgrade now rejects -O + --initdb during option parsing, with > > a test and a doc note. > > > @@ -244,6 +249,17 @@ parseCommandLine(int argc, char *argv[]) > > if (optind < argc) > > pg_fatal("too many command-line arguments (first is > \"%s\")", argv[optind]); > > > > + /* > > + * -O passes options to the new cluster's postmaster, but with > --initdb > > + * the new cluster is created by initdb, which accepts a > different option > > + * set. Rather than guess which -O options initdb also > understands, reject > > + * the combination and let the user create the cluster manually > (without > > + * --initdb) if they need postmaster-only options. > > + */ > > + if (new_cluster.pgopts && user_opts.initdb_new_cluster) > > + pg_fatal("options %s and %s cannot be used together", > > + "-O/--new-options", "--initdb"); > > + > > if (!user_opts.sync_method) > > user_opts.sync_method = pg_strdup("fsync"); > > > > That doesn't sound right. There's indeed no reason think that initdb > would accept the same options as postmaster, so it doesn't make sense to > pass the -O options to initdb. But why forbid using -O with --initdb? I > would imagine that the -O options are passed to the postmaster the same > way with or without --initdb. > > Is there a way to pass extra options to initdb? Or do you require the > user to run initdb first or change the settings afterwards, if they want > some additional settings? > > > + <para> > > + To discover the old cluster's encoding and locale, > > + <option>--initdb</option> briefly starts the old server in > > + binary-upgrade mode (which disables autovacuum) and stops it > again > > + before creating the new cluster. If a compatibility check > fails after > > + the new cluster has been created, its data directory is removed > > + automatically, so the upgrade can be retried without manual > cleanup. > > + </para> > > Hmm, how's that different from how it works without --initdb? pg_upgrade > needs to launch the old cluster anyway to perform the compatibility > checks, right? > > - Heikki > >
v7-0001-pg_upgrade-initdb-doc.patch
Description: Binary data
v7-0002-pg_upgrade-initdb.patch
Description: Binary data
