6161#endif
6262
6363#include "catalog/catalog.h"
64+ #include "common/file_utils.h"
6465#include "common/restricted_token.h"
6566#include "common/username.h"
6667#include "mb/pg_wchar.h"
7071#include "fe_utils/string_utils.h"
7172
7273
73- /* Define PG_FLUSH_DATA_WORKS if we have an implementation for pg_flush_data */
74- #if defined(HAVE_SYNC_FILE_RANGE )
75- #define PG_FLUSH_DATA_WORKS 1
76- #elif defined(USE_POSIX_FADVISE ) && defined(POSIX_FADV_DONTNEED )
77- #define PG_FLUSH_DATA_WORKS 1
78- #endif
79-
8074/* Ideally this would be in a .h file, but it hardly seems worth the trouble */
8175extern const char * select_default_timezone (const char * share_path );
8276
@@ -237,13 +231,6 @@ static char **filter_lines_with_token(char **lines, const char *token);
237231#endif
238232static char * * readfile (const char * path );
239233static void writefile (char * path , char * * lines );
240- static void walkdir (const char * path ,
241- void (* action ) (const char * fname , bool isdir ),
242- bool process_symlinks );
243- #ifdef PG_FLUSH_DATA_WORKS
244- static void pre_sync_fname (const char * fname , bool isdir );
245- #endif
246- static void fsync_fname_ext (const char * fname , bool isdir );
247234static FILE * popen_check (const char * command , const char * mode );
248235static void exit_nicely (void );
249236static char * get_id (void );
@@ -270,7 +257,6 @@ static void load_plpgsql(FILE *cmdfd);
270257static void vacuum_db (FILE * cmdfd );
271258static void make_template0 (FILE * cmdfd );
272259static void make_postgres (FILE * cmdfd );
273- static void fsync_pgdata (void );
274260static void trapsig (int signum );
275261static void check_ok (void );
276262static char * escape_quotes (const char * src );
@@ -528,177 +514,6 @@ writefile(char *path, char **lines)
528514 }
529515}
530516
531- /*
532- * walkdir: recursively walk a directory, applying the action to each
533- * regular file and directory (including the named directory itself).
534- *
535- * If process_symlinks is true, the action and recursion are also applied
536- * to regular files and directories that are pointed to by symlinks in the
537- * given directory; otherwise symlinks are ignored. Symlinks are always
538- * ignored in subdirectories, ie we intentionally don't pass down the
539- * process_symlinks flag to recursive calls.
540- *
541- * Errors are reported but not considered fatal.
542- *
543- * See also walkdir in fd.c, which is a backend version of this logic.
544- */
545- static void
546- walkdir (const char * path ,
547- void (* action ) (const char * fname , bool isdir ),
548- bool process_symlinks )
549- {
550- DIR * dir ;
551- struct dirent * de ;
552-
553- dir = opendir (path );
554- if (dir == NULL )
555- {
556- fprintf (stderr , _ ("%s: could not open directory \"%s\": %s\n" ),
557- progname , path , strerror (errno ));
558- return ;
559- }
560-
561- while (errno = 0 , (de = readdir (dir )) != NULL )
562- {
563- char subpath [MAXPGPATH ];
564- struct stat fst ;
565- int sret ;
566-
567- if (strcmp (de -> d_name , "." ) == 0 ||
568- strcmp (de -> d_name , ".." ) == 0 )
569- continue ;
570-
571- snprintf (subpath , MAXPGPATH , "%s/%s" , path , de -> d_name );
572-
573- if (process_symlinks )
574- sret = stat (subpath , & fst );
575- else
576- sret = lstat (subpath , & fst );
577-
578- if (sret < 0 )
579- {
580- fprintf (stderr , _ ("%s: could not stat file \"%s\": %s\n" ),
581- progname , subpath , strerror (errno ));
582- continue ;
583- }
584-
585- if (S_ISREG (fst .st_mode ))
586- (* action ) (subpath , false);
587- else if (S_ISDIR (fst .st_mode ))
588- walkdir (subpath , action , false);
589- }
590-
591- if (errno )
592- fprintf (stderr , _ ("%s: could not read directory \"%s\": %s\n" ),
593- progname , path , strerror (errno ));
594-
595- (void ) closedir (dir );
596-
597- /*
598- * It's important to fsync the destination directory itself as individual
599- * file fsyncs don't guarantee that the directory entry for the file is
600- * synced. Recent versions of ext4 have made the window much wider but
601- * it's been an issue for ext3 and other filesystems in the past.
602- */
603- (* action ) (path , true);
604- }
605-
606- /*
607- * Hint to the OS that it should get ready to fsync() this file.
608- *
609- * Ignores errors trying to open unreadable files, and reports other errors
610- * non-fatally.
611- */
612- #ifdef PG_FLUSH_DATA_WORKS
613-
614- static void
615- pre_sync_fname (const char * fname , bool isdir )
616- {
617- int fd ;
618-
619- fd = open (fname , O_RDONLY | PG_BINARY );
620-
621- if (fd < 0 )
622- {
623- if (errno == EACCES || (isdir && errno == EISDIR ))
624- return ;
625- fprintf (stderr , _ ("%s: could not open file \"%s\": %s\n" ),
626- progname , fname , strerror (errno ));
627- return ;
628- }
629-
630- /*
631- * We do what pg_flush_data() would do in the backend: prefer to use
632- * sync_file_range, but fall back to posix_fadvise. We ignore errors
633- * because this is only a hint.
634- */
635- #if defined(HAVE_SYNC_FILE_RANGE )
636- (void ) sync_file_range (fd , 0 , 0 , SYNC_FILE_RANGE_WRITE );
637- #elif defined(USE_POSIX_FADVISE ) && defined(POSIX_FADV_DONTNEED )
638- (void ) posix_fadvise (fd , 0 , 0 , POSIX_FADV_DONTNEED );
639- #else
640- #error PG_FLUSH_DATA_WORKS should not have been defined
641- #endif
642-
643- (void ) close (fd );
644- }
645-
646- #endif /* PG_FLUSH_DATA_WORKS */
647-
648- /*
649- * fsync_fname_ext -- Try to fsync a file or directory
650- *
651- * Ignores errors trying to open unreadable files, or trying to fsync
652- * directories on systems where that isn't allowed/required. Reports
653- * other errors non-fatally.
654- */
655- static void
656- fsync_fname_ext (const char * fname , bool isdir )
657- {
658- int fd ;
659- int flags ;
660- int returncode ;
661-
662- /*
663- * Some OSs require directories to be opened read-only whereas other
664- * systems don't allow us to fsync files opened read-only; so we need both
665- * cases here. Using O_RDWR will cause us to fail to fsync files that are
666- * not writable by our userid, but we assume that's OK.
667- */
668- flags = PG_BINARY ;
669- if (!isdir )
670- flags |= O_RDWR ;
671- else
672- flags |= O_RDONLY ;
673-
674- /*
675- * Open the file, silently ignoring errors about unreadable files (or
676- * unsupported operations, e.g. opening a directory under Windows), and
677- * logging others.
678- */
679- fd = open (fname , flags );
680- if (fd < 0 )
681- {
682- if (errno == EACCES || (isdir && errno == EISDIR ))
683- return ;
684- fprintf (stderr , _ ("%s: could not open file \"%s\": %s\n" ),
685- progname , fname , strerror (errno ));
686- return ;
687- }
688-
689- returncode = fsync (fd );
690-
691- /*
692- * Some OSes don't allow us to fsync directories at all, so we can ignore
693- * those errors. Anything else needs to be reported.
694- */
695- if (returncode != 0 && !(isdir && errno == EBADF ))
696- fprintf (stderr , _ ("%s: could not fsync file \"%s\": %s\n" ),
697- progname , fname , strerror (errno ));
698-
699- (void ) close (fd );
700- }
701-
702517/*
703518 * Open a subcommand with suitable error messaging
704519 */
@@ -2276,77 +2091,6 @@ make_postgres(FILE *cmdfd)
22762091 PG_CMD_PUTS (* line );
22772092}
22782093
2279- /*
2280- * Issue fsync recursively on PGDATA and all its contents.
2281- *
2282- * We fsync regular files and directories wherever they are, but we
2283- * follow symlinks only for pg_xlog and immediately under pg_tblspc.
2284- * Other symlinks are presumed to point at files we're not responsible
2285- * for fsyncing, and might not have privileges to write at all.
2286- *
2287- * Errors are reported but not considered fatal.
2288- */
2289- static void
2290- fsync_pgdata (void )
2291- {
2292- bool xlog_is_symlink ;
2293- char pg_xlog [MAXPGPATH ];
2294- char pg_tblspc [MAXPGPATH ];
2295-
2296- fputs (_ ("syncing data to disk ... " ), stdout );
2297- fflush (stdout );
2298-
2299- snprintf (pg_xlog , MAXPGPATH , "%s/pg_xlog" , pg_data );
2300- snprintf (pg_tblspc , MAXPGPATH , "%s/pg_tblspc" , pg_data );
2301-
2302- /*
2303- * If pg_xlog is a symlink, we'll need to recurse into it separately,
2304- * because the first walkdir below will ignore it.
2305- */
2306- xlog_is_symlink = false;
2307-
2308- #ifndef WIN32
2309- {
2310- struct stat st ;
2311-
2312- if (lstat (pg_xlog , & st ) < 0 )
2313- fprintf (stderr , _ ("%s: could not stat file \"%s\": %s\n" ),
2314- progname , pg_xlog , strerror (errno ));
2315- else if (S_ISLNK (st .st_mode ))
2316- xlog_is_symlink = true;
2317- }
2318- #else
2319- if (pgwin32_is_junction (pg_xlog ))
2320- xlog_is_symlink = true;
2321- #endif
2322-
2323- /*
2324- * If possible, hint to the kernel that we're soon going to fsync the data
2325- * directory and its contents.
2326- */
2327- #ifdef PG_FLUSH_DATA_WORKS
2328- walkdir (pg_data , pre_sync_fname , false);
2329- if (xlog_is_symlink )
2330- walkdir (pg_xlog , pre_sync_fname , false);
2331- walkdir (pg_tblspc , pre_sync_fname , true);
2332- #endif
2333-
2334- /*
2335- * Now we do the fsync()s in the same order.
2336- *
2337- * The main call ignores symlinks, so in addition to specially processing
2338- * pg_xlog if it's a symlink, pg_tblspc has to be visited separately with
2339- * process_symlinks = true. Note that if there are any plain directories
2340- * in pg_tblspc, they'll get fsync'd twice. That's not an expected case
2341- * so we don't worry about optimizing it.
2342- */
2343- walkdir (pg_data , fsync_fname_ext , false);
2344- if (xlog_is_symlink )
2345- walkdir (pg_xlog , fsync_fname_ext , false);
2346- walkdir (pg_tblspc , fsync_fname_ext , true);
2347-
2348- check_ok ();
2349- }
23502094
23512095
23522096/*
@@ -3512,7 +3256,10 @@ main(int argc, char *argv[])
35123256 exit_nicely ();
35133257 }
35143258
3515- fsync_pgdata ();
3259+ fputs (_ ("syncing data to disk ... " ), stdout );
3260+ fflush (stdout );
3261+ fsync_pgdata (pg_data , progname );
3262+ check_ok ();
35163263 return 0 ;
35173264 }
35183265
@@ -3574,7 +3321,12 @@ main(int argc, char *argv[])
35743321 initialize_data_directory ();
35753322
35763323 if (do_sync )
3577- fsync_pgdata ();
3324+ {
3325+ fputs (_ ("syncing data to disk ... " ), stdout );
3326+ fflush (stdout );
3327+ fsync_pgdata (pg_data , progname );
3328+ check_ok ();
3329+ }
35783330 else
35793331 printf (_ ("\nSync to disk skipped.\nThe data directory might become corrupt if the operating system crashes.\n" ));
35803332
0 commit comments