61
61
#endif
62
62
63
63
#include "catalog/catalog.h"
64
+ #include "common/file_utils.h"
64
65
#include "common/restricted_token.h"
65
66
#include "common/username.h"
66
67
#include "mb/pg_wchar.h"
70
71
#include "fe_utils/string_utils.h"
71
72
72
73
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
-
80
74
/* Ideally this would be in a .h file, but it hardly seems worth the trouble */
81
75
extern const char * select_default_timezone (const char * share_path );
82
76
@@ -237,13 +231,6 @@ static char **filter_lines_with_token(char **lines, const char *token);
237
231
#endif
238
232
static char * * readfile (const char * path );
239
233
static 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 );
247
234
static FILE * popen_check (const char * command , const char * mode );
248
235
static void exit_nicely (void );
249
236
static char * get_id (void );
@@ -270,7 +257,6 @@ static void load_plpgsql(FILE *cmdfd);
270
257
static void vacuum_db (FILE * cmdfd );
271
258
static void make_template0 (FILE * cmdfd );
272
259
static void make_postgres (FILE * cmdfd );
273
- static void fsync_pgdata (void );
274
260
static void trapsig (int signum );
275
261
static void check_ok (void );
276
262
static char * escape_quotes (const char * src );
@@ -528,177 +514,6 @@ writefile(char *path, char **lines)
528
514
}
529
515
}
530
516
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
-
702
517
/*
703
518
* Open a subcommand with suitable error messaging
704
519
*/
@@ -2276,77 +2091,6 @@ make_postgres(FILE *cmdfd)
2276
2091
PG_CMD_PUTS (* line );
2277
2092
}
2278
2093
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
- }
2350
2094
2351
2095
2352
2096
/*
@@ -3512,7 +3256,10 @@ main(int argc, char *argv[])
3512
3256
exit_nicely ();
3513
3257
}
3514
3258
3515
- fsync_pgdata ();
3259
+ fputs (_ ("syncing data to disk ... " ), stdout );
3260
+ fflush (stdout );
3261
+ fsync_pgdata (pg_data , progname );
3262
+ check_ok ();
3516
3263
return 0 ;
3517
3264
}
3518
3265
@@ -3574,7 +3321,12 @@ main(int argc, char *argv[])
3574
3321
initialize_data_directory ();
3575
3322
3576
3323
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
+ }
3578
3330
else
3579
3331
printf (_ ("\nSync to disk skipped.\nThe data directory might become corrupt if the operating system crashes.\n" ));
3580
3332
0 commit comments