PostgreSQL Source Code  git master
pg_test_fsync.c File Reference
#include "postgres_fe.h"
#include <limits.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include "access/xlogdefs.h"
#include "common/logging.h"
#include "getopt_long.h"
Include dependency graph for pg_test_fsync.c:

Go to the source code of this file.

Macros

#define FSYNC_FILENAME   "./pg_test_fsync.out"
 
#define XLOG_BLCKSZ_K   (XLOG_BLCKSZ / 1024)
 
#define LABEL_FORMAT   " %-30s"
 
#define NA_FORMAT   "%21s\n"
 
#define OPS_FORMAT   gettext_noop("%13.3f ops/sec %6.0f usecs/op\n")
 
#define USECS_SEC   1000000
 
#define START_TIMER
 
#define STOP_TIMER
 
#define die(msg)   do { pg_log_error("%s: %m", _(msg)); exit(1); } while(0)
 

Functions

static void handle_args (int argc, char *argv[])
 
static void prepare_buf (void)
 
static void test_open (void)
 
static void test_non_sync (void)
 
static void test_sync (int writes_per_op)
 
static void test_open_syncs (void)
 
static void test_open_sync (const char *msg, int writes_size)
 
static void test_file_descriptor_sync (void)
 
static void process_alarm (int sig)
 
static void signal_cleanup (int sig)
 
static void print_elapse (struct timeval start_t, struct timeval stop_t, int ops)
 
int main (int argc, char *argv[])
 
static int open_direct (const char *path, int flags, mode_t mode)
 

Variables

static const char * progname
 
static unsigned int secs_per_test = 5
 
static int needs_unlink = 0
 
static char full_buf [DEFAULT_XLOG_SEG_SIZE]
 
static char * buf
 
static char * filename = FSYNC_FILENAME
 
static struct timeval start_t stop_t
 
static bool alarm_triggered = false
 

Macro Definition Documentation

◆ die

◆ FSYNC_FILENAME

#define FSYNC_FILENAME   "./pg_test_fsync.out"

Definition at line 24 of file pg_test_fsync.c.

◆ LABEL_FORMAT

#define LABEL_FORMAT   " %-30s"

◆ NA_FORMAT

#define NA_FORMAT   "%21s\n"

Definition at line 29 of file pg_test_fsync.c.

Referenced by test_open_sync(), and test_sync().

◆ OPS_FORMAT

#define OPS_FORMAT   gettext_noop("%13.3f ops/sec %6.0f usecs/op\n")

Definition at line 31 of file pg_test_fsync.c.

Referenced by print_elapse().

◆ START_TIMER

#define START_TIMER
Value:
do { \
alarm_triggered = false; \
alarm(secs_per_test); \
gettimeofday(&start_t, NULL); \
} while (0)
static unsigned int secs_per_test
Definition: pg_test_fsync.c:66

Definition at line 36 of file pg_test_fsync.c.

Referenced by test_file_descriptor_sync(), test_non_sync(), test_open_sync(), and test_sync().

◆ STOP_TIMER

#define STOP_TIMER
Value:
do { \
gettimeofday(&stop_t, NULL); \
print_elapse(start_t, stop_t, ops); \
} while (0)
static struct timeval start_t stop_t
Definition: pg_test_fsync.c:71

Definition at line 57 of file pg_test_fsync.c.

Referenced by test_file_descriptor_sync(), test_non_sync(), test_open_sync(), and test_sync().

◆ USECS_SEC

#define USECS_SEC   1000000

Definition at line 32 of file pg_test_fsync.c.

Referenced by print_elapse().

◆ XLOG_BLCKSZ_K

#define XLOG_BLCKSZ_K   (XLOG_BLCKSZ / 1024)

Definition at line 26 of file pg_test_fsync.c.

Referenced by test_non_sync(), and test_sync().

Function Documentation

◆ handle_args()

static void handle_args ( int  argc,
char *  argv[] 
)
static

Definition at line 142 of file pg_test_fsync.c.

References _, filename, fprintf, getopt_long(), ngettext, optarg, optind, pg_log_error, pg_strdup(), printf, progname, required_argument, and secs_per_test.

Referenced by main().

143 {
144  static struct option long_options[] = {
145  {"filename", required_argument, NULL, 'f'},
146  {"secs-per-test", required_argument, NULL, 's'},
147  {NULL, 0, NULL, 0}
148  };
149 
150  int option; /* Command line option */
151  int optindex = 0; /* used by getopt_long */
152  unsigned long optval; /* used for option parsing */
153  char *endptr;
154 
155  if (argc > 1)
156  {
157  if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
158  {
159  printf(_("Usage: %s [-f FILENAME] [-s SECS-PER-TEST]\n"), progname);
160  exit(0);
161  }
162  if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
163  {
164  puts("pg_test_fsync (PostgreSQL) " PG_VERSION);
165  exit(0);
166  }
167  }
168 
169  while ((option = getopt_long(argc, argv, "f:s:",
170  long_options, &optindex)) != -1)
171  {
172  switch (option)
173  {
174  case 'f':
176  break;
177 
178  case 's':
179  errno = 0;
180  optval = strtoul(optarg, &endptr, 10);
181 
182  if (endptr == optarg || *endptr != '\0' ||
183  errno != 0 || optval != (unsigned int) optval)
184  {
185  pg_log_error("invalid argument for option %s", "--secs-per-test");
186  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
187  exit(1);
188  }
189 
190  secs_per_test = (unsigned int) optval;
191  if (secs_per_test == 0)
192  {
193  pg_log_error("%s must be in range %u..%u",
194  "--secs-per-test", 1, UINT_MAX);
195  exit(1);
196  }
197  break;
198 
199  default:
200  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
201  progname);
202  exit(1);
203  break;
204  }
205  }
206 
207  if (argc > optind)
208  {
209  pg_log_error("too many command-line arguments (first is \"%s\")",
210  argv[optind]);
211  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
212  progname);
213  exit(1);
214  }
215 
216  printf(ngettext("%u second per test\n",
217  "%u seconds per test\n",
218  secs_per_test),
219  secs_per_test);
220 #if defined(O_DIRECT)
221  printf(_("O_DIRECT supported on this platform for open_datasync and open_sync.\n"));
222 #elif defined(F_NOCACHE)
223  printf(_("F_NOCACHE supported on this platform for open_datasync and open_sync.\n"));
224 #else
225  printf(_("Direct I/O is not supported on this platform.\n"));
226 #endif
227 }
static char * filename
Definition: pg_test_fsync.c:70
#define pg_log_error(...)
Definition: logging.h:80
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: getopt_long.c:57
#define printf(...)
Definition: port.h:223
#define fprintf
Definition: port.h:221
#define required_argument
Definition: getopt_long.h:25
int optind
Definition: getopt.c:50
static const char * progname
Definition: pg_test_fsync.c:64
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
#define ngettext(s, p, n)
Definition: c.h:1182
static unsigned int secs_per_test
Definition: pg_test_fsync.c:66
char * optarg
Definition: getopt.c:52
#define _(x)
Definition: elog.c:89

◆ main()

int main ( int  argc,
char *  argv[] 
)

Definition at line 101 of file pg_test_fsync.c.

References filename, get_progname(), handle_args(), pg_logging_init(), PG_TEXTDOMAIN, pqsignal(), prepare_buf(), process_alarm(), progname, set_pglocale_pgservice(), SIGALRM, SIGHUP, signal_cleanup(), test_file_descriptor_sync(), test_non_sync(), test_open(), test_open_syncs(), and test_sync().

102 {
103  pg_logging_init(argv[0]);
104  set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_test_fsync"));
105  progname = get_progname(argv[0]);
106 
107  handle_args(argc, argv);
108 
109  /* Prevent leaving behind the test file */
110  pqsignal(SIGINT, signal_cleanup);
111  pqsignal(SIGTERM, signal_cleanup);
112 #ifndef WIN32
114 #endif
115 #ifdef SIGHUP
116  /* Not defined on win32 */
118 #endif
119 
120  prepare_buf();
121 
122  test_open();
123 
124  /* Test using 1 XLOG_BLCKSZ write */
125  test_sync(1);
126 
127  /* Test using 2 XLOG_BLCKSZ writes */
128  test_sync(2);
129 
130  test_open_syncs();
131 
133 
134  test_non_sync();
135 
136  unlink(filename);
137 
138  return 0;
139 }
static void test_sync(int writes_per_op)
static char * filename
Definition: pg_test_fsync.c:70
const char * get_progname(const char *argv0)
Definition: path.c:453
void pg_logging_init(const char *argv0)
Definition: logging.c:81
static void test_open(void)
static void prepare_buf(void)
static const char * progname
Definition: pg_test_fsync.c:64
#define SIGHUP
Definition: win32_port.h:167
#define PG_TEXTDOMAIN(domain)
Definition: c.h:1215
static void test_open_syncs(void)
static void test_non_sync(void)
static void process_alarm(int sig)
pqsigfunc pqsignal(int signum, pqsigfunc handler)
Definition: signal.c:170
static void signal_cleanup(int sig)
#define SIGALRM
Definition: win32_port.h:173
void set_pglocale_pgservice(const char *argv0, const char *app)
Definition: exec.c:433
static void test_file_descriptor_sync(void)
static void handle_args(int argc, char *argv[])

◆ open_direct()

static int open_direct ( const char *  path,
int  flags,
mode_t  mode 
)
static

Definition at line 264 of file pg_test_fsync.c.

References close, and fd().

Referenced by test_open_sync(), and test_sync().

265 {
266  int fd;
267 
268 #ifdef O_DIRECT
269  flags |= O_DIRECT;
270 #endif
271 
272  fd = open(path, flags, mode);
273 
274 #if !defined(O_DIRECT) && defined(F_NOCACHE)
275  if (fd >= 0 && fcntl(fd, F_NOCACHE, 1) < 0)
276  {
277  int save_errno = errno;
278 
279  close(fd);
280  errno = save_errno;
281  return -1;
282  }
283 #endif
284 
285  return fd;
286 }
static PgChecksumMode mode
Definition: pg_checksums.c:65
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define close(a)
Definition: win32.h:12

◆ prepare_buf()

static void prepare_buf ( void  )
static

Definition at line 230 of file pg_test_fsync.c.

References buf, DEFAULT_XLOG_SEG_SIZE, full_buf, random(), and TYPEALIGN.

Referenced by main().

231 {
232  int ops;
233 
234  /* write random data into buffer */
235  for (ops = 0; ops < DEFAULT_XLOG_SEG_SIZE; ops++)
236  full_buf[ops] = random();
237 
238  buf = (char *) TYPEALIGN(XLOG_BLCKSZ, full_buf);
239 }
long random(void)
Definition: random.c:22
#define DEFAULT_XLOG_SEG_SIZE
static char full_buf[DEFAULT_XLOG_SEG_SIZE]
Definition: pg_test_fsync.c:68
static char * buf
Definition: pg_test_fsync.c:68
#define TYPEALIGN(ALIGNVAL, LEN)
Definition: c.h:750

◆ print_elapse()

static void print_elapse ( struct timeval  start_t,
struct timeval  stop_t,
int  ops 
)
static

Definition at line 632 of file pg_test_fsync.c.

References _, OPS_FORMAT, printf, and USECS_SEC.

633 {
634  double total_time = (stop_t.tv_sec - start_t.tv_sec) +
635  (stop_t.tv_usec - start_t.tv_usec) * 0.000001;
636  double per_second = ops / total_time;
637  double avg_op_time_us = (total_time / ops) * USECS_SEC;
638 
639  printf(_(OPS_FORMAT), per_second, avg_op_time_us);
640 }
#define USECS_SEC
Definition: pg_test_fsync.c:32
#define printf(...)
Definition: port.h:223
static struct timeval start_t stop_t
Definition: pg_test_fsync.c:71
#define OPS_FORMAT
Definition: pg_test_fsync.c:31
#define _(x)
Definition: elog.c:89

◆ process_alarm()

static void process_alarm ( int  sig)
static

Definition at line 644 of file pg_test_fsync.c.

References alarm_triggered, and secs_per_test.

Referenced by main().

645 {
646  alarm_triggered = true;
647 }
static bool alarm_triggered
Definition: pg_test_fsync.c:73

◆ signal_cleanup()

static void signal_cleanup ( int  sig)
static

Definition at line 602 of file pg_test_fsync.c.

References fd(), filename, needs_unlink, and pg_fsync_writethrough().

Referenced by main().

603 {
604  /* Delete the file if it exists. Ignore errors */
605  if (needs_unlink)
606  unlink(filename);
607  /* Finish incomplete line on stdout */
608  puts("");
609  exit(signum);
610 }
static char * filename
Definition: pg_test_fsync.c:70
static int needs_unlink
Definition: pg_test_fsync.c:67

◆ test_file_descriptor_sync()

static void test_file_descriptor_sync ( void  )
static

Definition at line 508 of file pg_test_fsync.c.

References _, alarm_triggered, buf, close, die, filename, fsync, LABEL_FORMAT, PG_BINARY, printf, START_TIMER, generate_unaccent_rules::stdout, STOP_TIMER, and write.

Referenced by main().

509 {
510  int tmpfile,
511  ops;
512 
513  /*
514  * Test whether fsync can sync data written on a different descriptor for
515  * the same file. This checks the efficiency of multi-process fsyncs
516  * against the same file. Possibly this should be done with writethrough
517  * on platforms which support it.
518  */
519  printf(_("\nTest if fsync on non-write file descriptor is honored:\n"));
520  printf(_("(If the times are similar, fsync() can sync data written on a different\n"
521  "descriptor.)\n"));
522 
523  /*
524  * first write, fsync and close, which is the normal behavior without
525  * multiple descriptors
526  */
527  printf(LABEL_FORMAT, "write, fsync, close");
528  fflush(stdout);
529 
530  START_TIMER;
531  for (ops = 0; alarm_triggered == false; ops++)
532  {
533  if ((tmpfile = open(filename, O_RDWR | PG_BINARY, 0)) == -1)
534  die("could not open output file");
535  if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
536  die("write failed");
537  if (fsync(tmpfile) != 0)
538  die("fsync failed");
539  close(tmpfile);
540 
541  /*
542  * open and close the file again to be consistent with the following
543  * test
544  */
545  if ((tmpfile = open(filename, O_RDWR | PG_BINARY, 0)) == -1)
546  die("could not open output file");
547  close(tmpfile);
548  }
549  STOP_TIMER;
550 
551  /*
552  * Now open, write, close, open again and fsync This simulates processes
553  * fsyncing each other's writes.
554  */
555  printf(LABEL_FORMAT, "write, close, fsync");
556  fflush(stdout);
557 
558  START_TIMER;
559  for (ops = 0; alarm_triggered == false; ops++)
560  {
561  if ((tmpfile = open(filename, O_RDWR | PG_BINARY, 0)) == -1)
562  die("could not open output file");
563  if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
564  die("write failed");
565  close(tmpfile);
566  /* reopen file */
567  if ((tmpfile = open(filename, O_RDWR | PG_BINARY, 0)) == -1)
568  die("could not open output file");
569  if (fsync(tmpfile) != 0)
570  die("fsync failed");
571  close(tmpfile);
572  }
573  STOP_TIMER;
574 }
static char * filename
Definition: pg_test_fsync.c:70
#define write(a, b, c)
Definition: win32.h:14
#define printf(...)
Definition: port.h:223
#define PG_BINARY
Definition: c.h:1271
static bool alarm_triggered
Definition: pg_test_fsync.c:73
#define fsync(fd)
Definition: win32_port.h:76
static char * buf
Definition: pg_test_fsync.c:68
#define STOP_TIMER
Definition: pg_test_fsync.c:57
#define LABEL_FORMAT
Definition: pg_test_fsync.c:28
#define START_TIMER
Definition: pg_test_fsync.c:36
#define close(a)
Definition: win32.h:12
#define _(x)
Definition: elog.c:89
#define die(msg)
Definition: pg_test_fsync.c:97

◆ test_non_sync()

static void test_non_sync ( void  )
static

Definition at line 577 of file pg_test_fsync.c.

References _, alarm_triggered, buf, close, die, filename, LABEL_FORMAT, PG_BINARY, pg_pwrite(), printf, START_TIMER, generate_unaccent_rules::stdout, STOP_TIMER, and XLOG_BLCKSZ_K.

Referenced by main().

578 {
579  int tmpfile,
580  ops;
581 
582  /*
583  * Test a simple write without fsync
584  */
585  printf(_("\nNon-sync'ed %dkB writes:\n"), XLOG_BLCKSZ_K);
586  printf(LABEL_FORMAT, "write");
587  fflush(stdout);
588 
589  if ((tmpfile = open(filename, O_RDWR | PG_BINARY, 0)) == -1)
590  die("could not open output file");
591  START_TIMER;
592  for (ops = 0; alarm_triggered == false; ops++)
593  {
594  if (pg_pwrite(tmpfile, buf, XLOG_BLCKSZ, 0) != XLOG_BLCKSZ)
595  die("write failed");
596  }
597  STOP_TIMER;
598  close(tmpfile);
599 }
static char * filename
Definition: pg_test_fsync.c:70
#define printf(...)
Definition: port.h:223
#define PG_BINARY
Definition: c.h:1271
ssize_t pg_pwrite(int fd, const void *buf, size_t nbyte, off_t offset)
Definition: pwrite.c:27
static bool alarm_triggered
Definition: pg_test_fsync.c:73
static char * buf
Definition: pg_test_fsync.c:68
#define XLOG_BLCKSZ_K
Definition: pg_test_fsync.c:26
#define STOP_TIMER
Definition: pg_test_fsync.c:57
#define LABEL_FORMAT
Definition: pg_test_fsync.c:28
#define START_TIMER
Definition: pg_test_fsync.c:36
#define close(a)
Definition: win32.h:12
#define _(x)
Definition: elog.c:89
#define die(msg)
Definition: pg_test_fsync.c:97

◆ test_open()

static void test_open ( void  )
static

Definition at line 242 of file pg_test_fsync.c.

References close, DEFAULT_XLOG_SEG_SIZE, die, filename, fsync, full_buf, needs_unlink, PG_BINARY, S_IRUSR, S_IWUSR, and write.

Referenced by main().

243 {
244  int tmpfile;
245 
246  /*
247  * test if we can open the target file
248  */
249  if ((tmpfile = open(filename, O_RDWR | O_CREAT | PG_BINARY, S_IRUSR | S_IWUSR)) == -1)
250  die("could not open output file");
251  needs_unlink = 1;
252  if (write(tmpfile, full_buf, DEFAULT_XLOG_SEG_SIZE) !=
254  die("write failed");
255 
256  /* fsync now so that dirty buffers don't skew later tests */
257  if (fsync(tmpfile) != 0)
258  die("fsync failed");
259 
260  close(tmpfile);
261 }
static char * filename
Definition: pg_test_fsync.c:70
#define write(a, b, c)
Definition: win32.h:14
#define DEFAULT_XLOG_SEG_SIZE
#define PG_BINARY
Definition: c.h:1271
static char full_buf[DEFAULT_XLOG_SEG_SIZE]
Definition: pg_test_fsync.c:68
#define fsync(fd)
Definition: win32_port.h:76
#define S_IWUSR
Definition: win32_port.h:291
#define S_IRUSR
Definition: win32_port.h:288
static int needs_unlink
Definition: pg_test_fsync.c:67
#define close(a)
Definition: win32.h:12
#define die(msg)
Definition: pg_test_fsync.c:97

◆ test_open_sync()

static void test_open_sync ( const char *  msg,
int  writes_size 
)
static

Definition at line 472 of file pg_test_fsync.c.

References _, alarm_triggered, buf, close, die, filename, LABEL_FORMAT, NA_FORMAT, open_direct(), PG_BINARY, pg_pwrite(), printf, START_TIMER, generate_unaccent_rules::stdout, and STOP_TIMER.

Referenced by test_open_syncs().

473 {
474 #ifdef OPEN_SYNC_FLAG
475  int tmpfile,
476  ops,
477  writes;
478 #endif
479 
480  printf(LABEL_FORMAT, msg);
481  fflush(stdout);
482 
483 #ifdef OPEN_SYNC_FLAG
484  if ((tmpfile = open_direct(filename, O_RDWR | OPEN_SYNC_FLAG | PG_BINARY, 0)) == -1)
485  printf(NA_FORMAT, _("n/a*"));
486  else
487  {
488  START_TIMER;
489  for (ops = 0; alarm_triggered == false; ops++)
490  {
491  for (writes = 0; writes < 16 / writes_size; writes++)
492  if (pg_pwrite(tmpfile,
493  buf,
494  writes_size * 1024,
495  writes * writes_size * 1024) !=
496  writes_size * 1024)
497  die("write failed");
498  }
499  STOP_TIMER;
500  close(tmpfile);
501  }
502 #else
503  printf(NA_FORMAT, _("n/a"));
504 #endif
505 }
static char * filename
Definition: pg_test_fsync.c:70
static int open_direct(const char *path, int flags, mode_t mode)
#define printf(...)
Definition: port.h:223
#define PG_BINARY
Definition: c.h:1271
ssize_t pg_pwrite(int fd, const void *buf, size_t nbyte, off_t offset)
Definition: pwrite.c:27
static bool alarm_triggered
Definition: pg_test_fsync.c:73
static char * buf
Definition: pg_test_fsync.c:68
#define NA_FORMAT
Definition: pg_test_fsync.c:29
#define STOP_TIMER
Definition: pg_test_fsync.c:57
#define LABEL_FORMAT
Definition: pg_test_fsync.c:28
#define START_TIMER
Definition: pg_test_fsync.c:36
#define close(a)
Definition: win32.h:12
#define _(x)
Definition: elog.c:89
#define die(msg)
Definition: pg_test_fsync.c:97

◆ test_open_syncs()

static void test_open_syncs ( void  )
static

Definition at line 455 of file pg_test_fsync.c.

References _, printf, and test_open_sync().

Referenced by main().

456 {
457  printf(_("\nCompare open_sync with different write sizes:\n"));
458  printf(_("(This is designed to compare the cost of writing 16kB in different write\n"
459  "open_sync sizes.)\n"));
460 
461  test_open_sync(_(" 1 * 16kB open_sync write"), 16);
462  test_open_sync(_(" 2 * 8kB open_sync writes"), 8);
463  test_open_sync(_(" 4 * 4kB open_sync writes"), 4);
464  test_open_sync(_(" 8 * 2kB open_sync writes"), 2);
465  test_open_sync(_("16 * 1kB open_sync writes"), 1);
466 }
#define printf(...)
Definition: port.h:223
#define _(x)
Definition: elog.c:89
static void test_open_sync(const char *msg, int writes_size)

◆ test_sync()

static void test_sync ( int  writes_per_op)
static

Definition at line 289 of file pg_test_fsync.c.

References _, alarm_triggered, buf, close, die, filename, fsync, LABEL_FORMAT, NA_FORMAT, O_DSYNC, open_direct(), PG_BINARY, pg_fsync_writethrough(), pg_pwrite(), printf, START_TIMER, generate_unaccent_rules::stdout, STOP_TIMER, and XLOG_BLCKSZ_K.

Referenced by main().

290 {
291  int tmpfile,
292  ops,
293  writes;
294  bool fs_warning = false;
295 
296  if (writes_per_op == 1)
297  printf(_("\nCompare file sync methods using one %dkB write:\n"), XLOG_BLCKSZ_K);
298  else
299  printf(_("\nCompare file sync methods using two %dkB writes:\n"), XLOG_BLCKSZ_K);
300  printf(_("(in wal_sync_method preference order, except fdatasync is Linux's default)\n"));
301 
302  /*
303  * Test open_datasync if available
304  */
305  printf(LABEL_FORMAT, "open_datasync");
306  fflush(stdout);
307 
308 #ifdef OPEN_DATASYNC_FLAG
309  if ((tmpfile = open_direct(filename, O_RDWR | O_DSYNC | PG_BINARY, 0)) == -1)
310  {
311  printf(NA_FORMAT, _("n/a*"));
312  fs_warning = true;
313  }
314  else
315  {
316  START_TIMER;
317  for (ops = 0; alarm_triggered == false; ops++)
318  {
319  for (writes = 0; writes < writes_per_op; writes++)
320  if (pg_pwrite(tmpfile,
321  buf,
322  XLOG_BLCKSZ,
323  writes * XLOG_BLCKSZ) != XLOG_BLCKSZ)
324  die("write failed");
325  }
326  STOP_TIMER;
327  close(tmpfile);
328  }
329 #else
330  printf(NA_FORMAT, _("n/a"));
331 #endif
332 
333 /*
334  * Test fdatasync if available
335  */
336  printf(LABEL_FORMAT, "fdatasync");
337  fflush(stdout);
338 
339 #ifdef HAVE_FDATASYNC
340  if ((tmpfile = open(filename, O_RDWR | PG_BINARY, 0)) == -1)
341  die("could not open output file");
342  START_TIMER;
343  for (ops = 0; alarm_triggered == false; ops++)
344  {
345  for (writes = 0; writes < writes_per_op; writes++)
346  if (pg_pwrite(tmpfile,
347  buf,
348  XLOG_BLCKSZ,
349  writes * XLOG_BLCKSZ) != XLOG_BLCKSZ)
350  die("write failed");
351  fdatasync(tmpfile);
352  }
353  STOP_TIMER;
354  close(tmpfile);
355 #else
356  printf(NA_FORMAT, _("n/a"));
357 #endif
358 
359 /*
360  * Test fsync
361  */
362  printf(LABEL_FORMAT, "fsync");
363  fflush(stdout);
364 
365  if ((tmpfile = open(filename, O_RDWR | PG_BINARY, 0)) == -1)
366  die("could not open output file");
367  START_TIMER;
368  for (ops = 0; alarm_triggered == false; ops++)
369  {
370  for (writes = 0; writes < writes_per_op; writes++)
371  if (pg_pwrite(tmpfile,
372  buf,
373  XLOG_BLCKSZ,
374  writes * XLOG_BLCKSZ) != XLOG_BLCKSZ)
375  die("write failed");
376  if (fsync(tmpfile) != 0)
377  die("fsync failed");
378  }
379  STOP_TIMER;
380  close(tmpfile);
381 
382 /*
383  * If fsync_writethrough is available, test as well
384  */
385  printf(LABEL_FORMAT, "fsync_writethrough");
386  fflush(stdout);
387 
388 #ifdef HAVE_FSYNC_WRITETHROUGH
389  if ((tmpfile = open(filename, O_RDWR | PG_BINARY, 0)) == -1)
390  die("could not open output file");
391  START_TIMER;
392  for (ops = 0; alarm_triggered == false; ops++)
393  {
394  for (writes = 0; writes < writes_per_op; writes++)
395  if (pg_pwrite(tmpfile,
396  buf,
397  XLOG_BLCKSZ,
398  writes * XLOG_BLCKSZ) != XLOG_BLCKSZ)
399  die("write failed");
400  if (pg_fsync_writethrough(tmpfile) != 0)
401  die("fsync failed");
402  }
403  STOP_TIMER;
404  close(tmpfile);
405 #else
406  printf(NA_FORMAT, _("n/a"));
407 #endif
408 
409 /*
410  * Test open_sync if available
411  */
412  printf(LABEL_FORMAT, "open_sync");
413  fflush(stdout);
414 
415 #ifdef OPEN_SYNC_FLAG
416  if ((tmpfile = open_direct(filename, O_RDWR | OPEN_SYNC_FLAG | PG_BINARY, 0)) == -1)
417  {
418  printf(NA_FORMAT, _("n/a*"));
419  fs_warning = true;
420  }
421  else
422  {
423  START_TIMER;
424  for (ops = 0; alarm_triggered == false; ops++)
425  {
426  for (writes = 0; writes < writes_per_op; writes++)
427  if (pg_pwrite(tmpfile,
428  buf,
429  XLOG_BLCKSZ,
430  writes * XLOG_BLCKSZ) != XLOG_BLCKSZ)
431 
432  /*
433  * This can generate write failures if the filesystem has
434  * a large block size, e.g. 4k, and there is no support
435  * for O_DIRECT writes smaller than the file system block
436  * size, e.g. XFS.
437  */
438  die("write failed");
439  }
440  STOP_TIMER;
441  close(tmpfile);
442  }
443 #else
444  printf(NA_FORMAT, _("n/a"));
445 #endif
446 
447  if (fs_warning)
448  {
449  printf(_("* This file system and its mount options do not support direct\n"
450  " I/O, e.g. ext4 in journaled mode.\n"));
451  }
452 }
static char * filename
Definition: pg_test_fsync.c:70
int pg_fsync_writethrough(int fd)
Definition: fd.c:425
static int open_direct(const char *path, int flags, mode_t mode)
#define printf(...)
Definition: port.h:223
#define PG_BINARY
Definition: c.h:1271
ssize_t pg_pwrite(int fd, const void *buf, size_t nbyte, off_t offset)
Definition: pwrite.c:27
static bool alarm_triggered
Definition: pg_test_fsync.c:73
#define fsync(fd)
Definition: win32_port.h:76
static char * buf
Definition: pg_test_fsync.c:68
#define NA_FORMAT
Definition: pg_test_fsync.c:29
#define XLOG_BLCKSZ_K
Definition: pg_test_fsync.c:26
#define STOP_TIMER
Definition: pg_test_fsync.c:57
#define O_DSYNC
Definition: win32_port.h:336
#define LABEL_FORMAT
Definition: pg_test_fsync.c:28
#define START_TIMER
Definition: pg_test_fsync.c:36
#define close(a)
Definition: win32.h:12
#define _(x)
Definition: elog.c:89
#define die(msg)
Definition: pg_test_fsync.c:97

Variable Documentation

◆ alarm_triggered

bool alarm_triggered = false
static

◆ buf

char * buf
static

Definition at line 68 of file pg_test_fsync.c.

Referenced by _bt_clear_incomplete_split(), _bt_endpoint(), _bt_first(), _bt_get_endpoint(), _bt_getbuf(), _bt_getstackbuf(), _bt_killitems(), _bt_leftsib_splitflag(), _bt_moveright(), _bt_relandgetbuf(), _bt_rightsib_halfdeadflag(), _bt_unlink_halfdead_page(), _bt_walk_left(), _conv(), _discoverArchiveFormat(), _EndBlob(), _hash_doinsert(), _hash_first(), _hash_getbucketbuf_from_hashkey(), _hash_getbuf(), _hash_getbuf_with_condlock_cleanup(), _hash_getbuf_with_strategy(), _hash_getinitbuf(), _hash_getnewbuf(), _hash_init(), _hash_kill_items(), _hash_next(), _hash_readpage(), _LoadBlobs(), _PG_init(), _PrintFileData(), _skipData(), _tarAddFile(), _tarPositionTo(), _WriteBlobData(), abbroffset(), AbortBufferIO(), add_tablespace_footer(), AddFileToBackupManifest(), aes_cbc_decrypt(), AlterSequence(), append_database_pattern(), appendAggOrderBy(), appendConditions(), appendContextKeyword(), appendFunctionName(), appendGroupByClause(), appendLimitClause(), appendOrderByClause(), apply_error_callback(), array_dims(), array_recv(), array_send(), array_to_text_internal(), asyncQueueReadAllNotifications(), autoprewarm_database_main(), BaseBackup(), be_lo_export(), bind_param_error_callback(), bit_recv(), boolrecv(), boolsend(), bootstrap_template1(), box_recv(), box_send(), bpcharrecv(), bqarr_in(), brin_getinsertbuffer(), brin_vacuum_scan(), brin_xlog_createidx(), brin_xlog_revmap_extend(), bringetbitmap(), brininsert(), brinsummarize(), btree_xlog_dedup(), btree_xlog_split(), btvacuumpage(), buf_init(), BufferAlloc(), build_client_final_message(), build_client_first_message(), build_regexp_match_result(), build_regexp_split_result(), build_test_info_result(), build_test_match_result(), BuildIndexValueDescription(), BuildParamLogString(), bytearecv(), cache_locale_time(), calc_s2k_iter_salted(), calc_s2k_salted(), calc_s2k_simple(), cash_out(), cash_recv(), cash_send(), cash_words(), charrecv(), charsend(), check_key_cksum(), check_strxfrm_bug(), check_TSCurrentConfig(), CheckMD5Auth(), CheckPointTwoPhase(), CheckSASLAuth(), checkXLogConsistency(), ChooseExtendedStatisticNameAddition(), ChooseForeignKeyConstraintNameAddition(), ChooseIndexColumnNames(), ChooseIndexNameAddition(), cidr_recv(), cidrecv(), cidsend(), circle_recv(), circle_send(), cluster_conn_opts(), compile_pltcl_function(), complex_recv(), complex_send(), ConditionalLockBuffer(), conninfo_parse(), conninfo_uri_decode(), conninfo_uri_parse_options(), constructConnStr(), convertJsonbScalar(), copy_read_data(), CopyGetInt16(), CopyGetInt32(), CopySendInt16(), CopySendInt32(), count_nondeletable_pages(), create_cursor(), createBackupLabel(), cstring_recv(), cstring_send(), cube_out(), cube_recv(), cube_send(), date_out(), date_recv(), date_send(), date_test_fmt(), datum_to_json(), dblink_close(), dblink_fdw_validator(), dblink_fetch(), dblink_open(), DebugFileOpen(), decrypt_read(), DeleteAllExportedSnapshotFiles(), deparse_expression_pretty(), deparse_lquery(), deparse_ltree(), deparseAggref(), deparseArrayExpr(), deparseBoolExpr(), deparseCaseExpr(), deparseConst(), deparseDirectDeleteSql(), deparseDirectUpdateSql(), deparseDistinctExpr(), deparseExplicitTargetList(), deparseFromExpr(), deparseFromExprForRel(), deparseFuncExpr(), deparseLockingClause(), deparseNullTest(), deparseOpExpr(), deparseScalarArrayOpExpr(), deparseSelectSql(), deparseSelectStmtForRel(), deparseSortGroupClause(), deparseSubqueryTargetList(), deparseSubscriptingRef(), describeAccessMethods(), describeAggregates(), describeFunctions(), describeOneTableDetails(), describeOneTSConfig(), describeOneTSParser(), describeOperators(), describePublications(), DescribeQuery(), describeRoles(), describeSubscriptions(), describeTableDetails(), describeTablespaces(), describeTypes(), DispatchJobForTocEntry(), do_analyze_rel(), do_compile(), do_lo_list(), do_setval(), domain_recv(), DropDatabaseBuffers(), dropRoles(), dsm_cleanup_for_mmap(), dump_lo_buf(), dumpBlobs(), dumpDatabaseConfig(), dumpGroups(), dumpRoleMembership(), dumpRoles(), dumpTablespaces(), dumpTimestamp(), dumpUserConfig(), ean13_out(), ean2isn(), EndCompressor(), enum_recv(), enum_send(), escape_param_str(), escape_xml(), ExceptionalCondition(), exec_command_password(), exec_command_sf_sv(), ExecBuildSlotPartitionKeyDescription(), ExecBuildSlotValueDescription(), ExecEvalXmlExpr(), ExecQueryUsingCursor(), executeMetaCommand(), ExecuteSimpleCommands(), ExplainPropertyFloat(), ExplainPropertyInteger(), ExplainPropertyUInteger(), exportFile(), ExportSnapshot(), file_fdw_validator(), fill_seq_with_data(), find_provider(), FindStreamingStart(), FinishPreparedTransaction(), flatten_reloptions(), flatten_set_variable_args(), float4_numeric(), float4recv(), float4send(), float8_numeric(), float8recv(), float8send(), flush_pipe_input(), fmtlong(), format_aggregate_signature(), format_operator_extended(), format_procedure_extended(), format_type_extended(), formatPGVersionNumber(), FreePageManagerDump(), FreeSpaceMapPrepareTruncateRel(), fsm_readbuf(), fsm_search(), fsm_set_and_search(), fsm_vacuum_page(), generate_opclass_name(), generate_operator_name(), generate_trgm_only(), generate_wildcard_trgm(), get_agg_expr(), get_basic_select_query(), get_coercion_expr(), get_collation_actual_version(), get_column_alias_list(), get_connect_string(), get_const_collation(), get_const_expr(), get_delete_query_def(), get_errno_symbol(), get_from_clause(), get_from_clause_coldeflist(), get_from_clause_item(), get_func_expr(), get_func_sql_syntax(), get_insert_query_def(), get_oper_expr(), get_parallel_object_list(), get_prompt(), get_query_def(), get_range_partbound_string(), get_raw_page_internal(), get_rule_expr(), get_rule_expr_funccall(), get_rule_groupingset(), get_rule_orderby(), get_rule_sortgroupclause(), get_rule_windowclause(), get_rule_windowspec(), get_select_query_def(), get_setop_query(), get_special_variable(), get_sql_delete(), get_sql_insert(), get_sql_update(), get_sublink_expr(), get_tablefunc(), get_tablesample_def(), get_target_list(), get_tuple_of_interest(), get_update_query_def(), get_update_query_targetlist_def(), get_utility_query_def(), get_values_def(), get_variable(), get_wildcard_part(), get_windowfunc_expr(), get_with_clause(), getaddrinfo(), GetBufferFromRing(), GetHugePageSize(), GetNumRegisteredWaitEvents(), GetRecordedFreeSpace(), ginCompressPostingList(), gistfixsplit(), gnuish_strerror_r(), GROW(), handleCopyIn(), handleCopyOut(), hash_xlog_split_page(), hashbpchar(), hashbpcharextended(), hashbucketcleanup(), hashbulkdelete(), hashtext(), hashtextextended(), heap_force_common(), heap_index_delete_tuples(), heap_lock_updated_tuple_rec(), heap_vacuum_rel(), heapam_relation_copy_for_cluster(), hmac_finish(), hstore_recv(), hstore_send(), hstorePairs(), ignore_boolean_expression(), importFile(), indent_lines(), inet_recv(), infile(), init_params(), InitBufferPool(), initialize_worker_spi(), InitializeShmemGUCs(), InitLocalBuffers(), int2recv(), int2send(), int2vectorrecv(), int4recv(), int4send(), int8_avg_deserialize(), int8_avg_serialize(), int8out(), int8recv(), int8send(), interval_out(), interval_recv(), interval_send(), is_true_boolean_expression(), isn_out(), json_recv(), json_send(), jsonb_agg_transfn(), jsonb_object_agg_transfn(), jsonb_recv(), jsonb_send(), JsonEncodeDateTime(), jsonpath_recv(), jsonpath_send(), jsonPathFromCstring(), jsonPathToCstring(), KnownAssignedXidsDisplay(), lazy_scan_heap(), lazy_vacuum_heap_rel(), libpqrcv_get_conninfo(), line_recv(), line_send(), listAllDbs(), listCasts(), listCollations(), listConversions(), listDbRoleSettings(), listDefaultACLs(), listDomains(), listEventTriggers(), listExtendedStats(), listExtensionContents(), listExtensions(), listForeignDataWrappers(), listForeignServers(), listForeignTables(), listLanguages(), listOneExtensionContents(), listOperatorClasses(), listOperatorFamilies(), listOpFamilyFunctions(), listOpFamilyOperators(), listPartitionedTables(), listPublications(), listSchemas(), listTables(), listTSConfigs(), listTSConfigsVerbose(), listTSDictionaries(), listTSParsers(), listTSParsersVerbose(), listTSTemplates(), listUserMappings(), llvm_create_types(), lo_export(), lo_import_internal(), load_module(), local_fetch_file_range(), locale_date_order(), LockBuffer(), log_newpage_range(), LogicalDecodingProcessRecord(), LogicalRepApplyLoop(), LogRecoveryConflict(), LookupGXact(), lquery_in(), lquery_recv(), lquery_send(), lseg_recv(), lseg_send(), ltree_crc32_sz(), ltree_in(), ltree_recv(), ltree_send(), ltxtq_recv(), ltxtq_send(), macaddr8_recv(), macaddr8_send(), macaddr_recv(), macaddr_send(), main(), make_absolute_path(), make_ruledef(), makeMultirangeTypeName(), map_sql_identifier_to_xml_name(), map_sql_value_to_xml_value(), map_xml_name_to_sql_identifier(), MemoryContextSwitchTo(), merge_children(), mp_int_read_binary(), mp_int_read_unsigned(), mp_int_sqrt(), mp_px_rand(), multirange_out(), multirange_recv(), multirange_send(), mxid_to_string(), namerecv(), namesend(), network_send(), next_field_expand(), next_token(), nextval_internal(), NotifyMyFrontEnd(), num_word(), numeric_abbrev_convert(), numeric_avg_deserialize(), numeric_avg_serialize(), numeric_deserialize(), numeric_poly_deserialize(), numeric_poly_serialize(), numeric_recv(), numeric_send(), numeric_serialize(), objectDescription(), oidrecv(), oidsend(), oidvectorrecv(), overwrite(), packArcInfoCmp(), pad_eme_pkcs1_v15(), parse_literal_data(), parse_lquery(), parse_ltree(), parse_snapshot(), parseAclItem(), parseServiceFile(), passwordFromFile(), path_recv(), path_send(), patternToSQLRegex(), perform_base_backup(), permissionsList(), pg_armor(), pg_b64_decode(), pg_b64_encode(), pg_base64_decode(), pg_base64_encode(), pg_ceil_log2_64(), pg_collation_actual_version(), pg_dearmor(), pg_gen_salt(), pg_gen_salt_rounds(), pg_get_constraintdef_worker(), pg_get_function_arguments(), pg_get_function_identity_arguments(), pg_get_function_result(), pg_get_function_sqlbody(), pg_get_functiondef(), pg_get_indexdef_worker(), pg_get_line(), pg_get_partkeydef_worker(), pg_get_ruledef_worker(), pg_get_statisticsobj_worker(), pg_get_triggerdef_worker(), pg_get_viewdef_worker(), pg_local_sendauth(), pg_log_generic_v(), pg_lsn_mi(), pg_lsn_mii(), pg_lsn_out(), pg_lsn_pli(), pg_lsn_recv(), pg_lsn_send(), pg_prewarm(), pg_saslprep(), pg_sequence_last_value(), pg_size_pretty(), pg_snapshot_recv(), pg_snapshot_send(), pg_stat_get_wal(), pg_stat_statements_internal(), pg_strerror_r(), pg_strong_random(), pgp_armor_decode(), pgp_extract_armor_headers(), pgp_key_id_w(), pgp_mpi_hash(), pgp_mpi_write(), pgrowlocks(), pgstat_btree_page(), pgstat_gist_page(), pgstat_hash_page(), pgstathashindex(), PGTYPESdate_to_asc(), PGTYPESinterval_to_asc(), PGTYPESnumeric_div(), PGTYPEStimestamp_to_asc(), pgwin32_recv(), pgwin32_select(), pgwin32_waitforsinglesocket(), pgxmlNodeSetToText(), pickout(), PLy_exception_set(), PLy_exception_set_plural(), point_recv(), point_send(), poly_recv(), poly_send(), populate_scalar(), postgres_fdw_validator(), postgresImportForeignSchema(), PostgresMain(), postgresql_fdw_validator(), pq_sendint(), PQoidStatus(), prefix_init(), prepare_buf(), PrescanPreparedTransactions(), print_wchar_str(), PrintBufferLeakWarning(), PrintQueryStatus(), printRemoteParam(), printRemotePlaceholder(), printsimple(), printsimple_startup(), printSubscripts(), printtup(), process_file(), process_pipe_input(), processIndirection(), ProcessStartupPacket(), ProcessTwoPhaseBuffer(), ProcSleep(), psql_get_variable(), psql_start_command(), puttzcode(), puttzcodepass(), pwdfMatchesString(), px_debug(), px_find_combo(), qtext_load_file(), queryin(), quote_qualified_identifier(), range_bound_escape(), range_deparse(), range_parse_bound(), range_recv(), range_send(), read_binary_file(), read_file_contents(), read_text_file(), read_whole_file(), ReadBufferExtended(), ReadDataFromArchiveNone(), ReadStr(), readtup_alloc(), ReadTwoPhaseFile(), ReadyForQuery(), ReceiveBackupManifestInMemoryChunk(), ReceiveCopyBegin(), ReceiveTarFile(), record_in(), record_out(), record_recv(), record_send(), RecoverPreparedTransactions(), recv_password_packet(), RelationCopyStorage(), ReleaseExternalFD(), repairDependencyLoop(), replace_text_regexp(), report_invalid_encoding(), report_untranslatable_char(), ResetSequence(), restore(), restoreTwoPhaseData(), revmap_physical_extend(), rm_redo_error_callback(), rstacktoodeep(), run_crypt_des(), sanitize_char(), sanitize_str(), scan_file(), search_directory(), send_message_to_frontend(), send_message_to_server_log(), sendAuthRequest(), SendBackupHeader(), SendCopyBegin(), sendFile(), sendFileWithContent(), SendFunctionResult(), SendNegotiateProtocolVersion(), SendQuery(), SendTimeLineHistory(), SendXlogRecPtrResult(), sepgsql_audit_log(), serialize_deflist(), set_backtrace(), show_data_directory_mode(), show_log_file_mode(), show_unix_socket_permissions(), ShowTransactionStateRec(), SPI_result_code_string(), SplitToVariants(), ssl_extension_info(), StandbyRecoverPreparedTransactions(), StandbyTransactionIdIsPrepared(), StartBufferIO(), StartLogicalReplication(), StartReplication(), StartupXLOG(), statapprox_heap(), str_time(), StrategyGetBuffer(), string2ean(), syntax_error(), tar_getlasterror(), tarClose(), test_file_descriptor_sync(), test_non_sync(), test_open_sync(), test_sync(), textrecv(), textsend(), tidout(), tidrecv(), tidsend(), time_out(), time_recv(), time_send(), timeofday(), timestamp_out(), timestamp_recv(), timestamp_send(), timestamptz_out(), timestamptz_recv(), timestamptz_send(), timestamptz_to_str(), timetz_out(), timetz_recv(), timetz_send(), to_hex32(), to_hex64(), tokenize_file(), try_complete_step(), ts_stat_sql(), tsquery_rewrite_query(), tsvectorin(), tsvectorrecv(), tsvectorsend(), unaccent_lexize(), unicode_normalize_func(), unknownrecv(), unknownsend(), UnlockBuffers(), unpack_sql_state(), uuid_generate_v1mc(), uuid_out(), vacuum_one_database(), vacuumlo(), varbit_recv(), varbit_send(), varcharrecv(), VerifyOverwriteContrecord(), vm_readbuf(), void_send(), WaitEventSetWait(), WaitForCommands(), WALRead(), WalReceiverMain(), write_auto_conf_file(), write_csvlog(), write_target_range(), xid8recv(), xid8send(), xidrecv(), xidsend(), XLogInitBufferForRedo(), XLogInsertRecord(), XLogRecordPageWithFreeSpace(), XLOGShmemSize(), xml_out_internal(), xml_send(), xmlcomment(), xmlconcat(), xmlpi(), and xmlroot().

◆ filename

◆ full_buf

char full_buf[DEFAULT_XLOG_SEG_SIZE]
static

Definition at line 68 of file pg_test_fsync.c.

Referenced by prepare_buf(), and test_open().

◆ needs_unlink

int needs_unlink = 0
static

Definition at line 67 of file pg_test_fsync.c.

Referenced by signal_cleanup(), and test_open().

◆ progname

const char* progname
static

Definition at line 64 of file pg_test_fsync.c.

Referenced by handle_args(), and main().

◆ secs_per_test

unsigned int secs_per_test = 5
static

Definition at line 66 of file pg_test_fsync.c.

Referenced by handle_args(), and process_alarm().

◆ stop_t

struct timeval start_t stop_t
static

Definition at line 71 of file pg_test_fsync.c.