Skip to content

Commit bf5bb2e

Browse files
committed
Move fsync routines of initdb into src/common/
The intention is to used those in other utilities such as pg_basebackup and pg_receivexlog. From: Michael Paquier <michael.paquier@gmail.com>
1 parent 6e65454 commit bf5bb2e

File tree

7 files changed

+313
-263
lines changed

7 files changed

+313
-263
lines changed

src/bin/initdb/initdb.c

Lines changed: 11 additions & 259 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
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"
@@ -70,13 +71,6 @@
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 */
8175
extern 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
238232
static char **readfile(const char *path);
239233
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);
247234
static FILE *popen_check(const char *command, const char *mode);
248235
static void exit_nicely(void);
249236
static char *get_id(void);
@@ -270,7 +257,6 @@ static void load_plpgsql(FILE *cmdfd);
270257
static void vacuum_db(FILE *cmdfd);
271258
static void make_template0(FILE *cmdfd);
272259
static void make_postgres(FILE *cmdfd);
273-
static void fsync_pgdata(void);
274260
static void trapsig(int signum);
275261
static void check_ok(void);
276262
static 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

src/bin/initdb/nls.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# src/bin/initdb/nls.mk
22
CATALOG_NAME = initdb
33
AVAIL_LANGUAGES = cs de es fr it ja ko pl pt_BR ru sv zh_CN
4-
GETTEXT_FILES = findtimezone.c initdb.c ../../common/exec.c ../../common/fe_memutils.c ../../common/pgfnames.c ../../common/restricted_token.c ../../common/rmtree.c ../../common/username.c ../../common/wait_error.c ../../port/dirmod.c
4+
GETTEXT_FILES = findtimezone.c initdb.c ../../common/exec.c ../../common/fe_memutils.c ../../common/file_utils.c ../../common/pgfnames.c ../../common/restricted_token.c ../../common/rmtree.c ../../common/username.c ../../common/wait_error.c ../../port/dirmod.c
55
GETTEXT_TRIGGERS = simple_prompt

src/bin/pg_basebackup/nls.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# src/bin/pg_basebackup/nls.mk
22
CATALOG_NAME = pg_basebackup
33
AVAIL_LANGUAGES = de es fr it ko pl pt_BR ru zh_CN
4-
GETTEXT_FILES = pg_basebackup.c pg_receivexlog.c pg_recvlogical.c receivelog.c streamutil.c ../../common/fe_memutils.c
4+
GETTEXT_FILES = pg_basebackup.c pg_receivexlog.c pg_recvlogical.c receivelog.c streamutil.c ../../common/fe_memutils.c ../../common/file_utils.c
55
GETTEXT_TRIGGERS = simple_prompt

src/common/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ OBJS_COMMON = config_info.o controldata_utils.o exec.o ip.o keywords.o \
4444
md5.o pg_lzcompress.o pgfnames.o psprintf.o relpath.o rmtree.o \
4545
string.o username.o wait_error.o
4646

47-
OBJS_FRONTEND = $(OBJS_COMMON) fe_memutils.o restricted_token.o
47+
OBJS_FRONTEND = $(OBJS_COMMON) fe_memutils.o file_utils.o restricted_token.o
4848

4949
OBJS_SRV = $(OBJS_COMMON:%.o=%_srv.o)
5050

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy