Skip to content

Commit 0d9e0d9

Browse files
committed
Copy fsync() defines into test_fsync.c, someday place them in an
include. Propery align for O_DIRECT. Check for write()/fsync() failures.
1 parent f14d43d commit 0d9e0d9

File tree

1 file changed

+136
-41
lines changed

1 file changed

+136
-41
lines changed

src/tools/fsync/test_fsync.c

Lines changed: 136 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
/*
22
* test_fsync.c
3-
* tests if fsync can be done from another process than the original write
3+
* test various fsync() methods
44
*/
55

6-
#include "../../include/pg_config.h"
7-
#include "../../include/pg_config_os.h"
6+
#include "postgres.h"
7+
8+
#include "access/xlog_internal.h"
9+
#include "access/xlog.h"
810

911
#include <sys/types.h>
1012
#include <sys/stat.h>
@@ -14,29 +16,94 @@
1416
#include <time.h>
1517
#include <sys/time.h>
1618
#include <unistd.h>
19+
#include <string.h>
1720

18-
#ifdef WIN32
19-
#define FSYNC_FILENAME "./test_fsync.out"
21+
/* ---------------------------------------------------------------
22+
* Copied from xlog.c. Some day this should be moved an include file.
23+
*/
24+
25+
/*
26+
* Because O_DIRECT bypasses the kernel buffers, and because we never
27+
* read those buffers except during crash recovery, it is a win to use
28+
* it in all cases where we sync on each write(). We could allow O_DIRECT
29+
* with fsync(), but because skipping the kernel buffer forces writes out
30+
* quickly, it seems best just to use it for O_SYNC. It is hard to imagine
31+
* how fsync() could be a win for O_DIRECT compared to O_SYNC and O_DIRECT.
32+
* Also, O_DIRECT is never enough to force data to the drives, it merely
33+
* tries to bypass the kernel cache, so we still need O_SYNC or fsync().
34+
*/
35+
#ifdef O_DIRECT
36+
#define PG_O_DIRECT O_DIRECT
2037
#else
21-
#define FSYNC_FILENAME "/var/tmp/test_fsync.out"
38+
#define PG_O_DIRECT 0
2239
#endif
2340

24-
/* O_SYNC and O_FSYNC are the same */
41+
/*
42+
* This chunk of hackery attempts to determine which file sync methods
43+
* are available on the current platform, and to choose an appropriate
44+
* default method. We assume that fsync() is always available, and that
45+
* configure determined whether fdatasync() is.
46+
*/
2547
#if defined(O_SYNC)
26-
#define OPEN_SYNC_FLAG O_SYNC
48+
#define BARE_OPEN_SYNC_FLAG O_SYNC
2749
#elif defined(O_FSYNC)
28-
#define OPEN_SYNC_FLAG O_FSYNC
29-
#elif defined(O_DSYNC)
30-
#define OPEN_DATASYNC_FLAG O_DSYNC
50+
#define BARE_OPEN_SYNC_FLAG O_FSYNC
51+
#endif
52+
#ifdef BARE_OPEN_SYNC_FLAG
53+
#define OPEN_SYNC_FLAG (BARE_OPEN_SYNC_FLAG | PG_O_DIRECT)
3154
#endif
3255

56+
#if defined(O_DSYNC)
3357
#if defined(OPEN_SYNC_FLAG)
34-
#if defined(O_DSYNC) && (O_DSYNC != OPEN_SYNC_FLAG)
35-
#define OPEN_DATASYNC_FLAG O_DSYNC
58+
/* O_DSYNC is distinct? */
59+
#if O_DSYNC != BARE_OPEN_SYNC_FLAG
60+
#define OPEN_DATASYNC_FLAG (O_DSYNC | PG_O_DIRECT)
61+
#endif
62+
#else /* !defined(OPEN_SYNC_FLAG) */
63+
/* Win32 only has O_DSYNC */
64+
#define OPEN_DATASYNC_FLAG (O_DSYNC | PG_O_DIRECT)
65+
#endif
66+
#endif
67+
68+
#if defined(OPEN_DATASYNC_FLAG)
69+
#define DEFAULT_SYNC_METHOD_STR "open_datasync"
70+
#define DEFAULT_SYNC_METHOD SYNC_METHOD_OPEN
71+
#define DEFAULT_SYNC_FLAGBIT OPEN_DATASYNC_FLAG
72+
#elif defined(HAVE_FDATASYNC)
73+
#define DEFAULT_SYNC_METHOD_STR "fdatasync"
74+
#define DEFAULT_SYNC_METHOD SYNC_METHOD_FDATASYNC
75+
#define DEFAULT_SYNC_FLAGBIT 0
76+
#elif defined(HAVE_FSYNC_WRITETHROUGH_ONLY)
77+
#define DEFAULT_SYNC_METHOD_STR "fsync_writethrough"
78+
#define DEFAULT_SYNC_METHOD SYNC_METHOD_FSYNC_WRITETHROUGH
79+
#define DEFAULT_SYNC_FLAGBIT 0
80+
#else
81+
#define DEFAULT_SYNC_METHOD_STR "fsync"
82+
#define DEFAULT_SYNC_METHOD SYNC_METHOD_FSYNC
83+
#define DEFAULT_SYNC_FLAGBIT 0
84+
#endif
85+
86+
87+
/*
88+
* Limitation of buffer-alignment for direct IO depends on OS and filesystem,
89+
* but XLOG_BLCKSZ is assumed to be enough for it.
90+
*/
91+
#ifdef O_DIRECT
92+
#define ALIGNOF_XLOG_BUFFER XLOG_BLCKSZ
93+
#else
94+
#define ALIGNOF_XLOG_BUFFER ALIGNOF_BUFFER
3695
#endif
96+
97+
/* ------------ from xlog.c --------------- */
98+
99+
#ifdef WIN32
100+
#define FSYNC_FILENAME "./test_fsync.out"
101+
#else
102+
/* /tmp might be a memory file system */
103+
#define FSYNC_FILENAME "/var/tmp/test_fsync.out"
37104
#endif
38105

39-
#define WAL_FILE_SIZE (16 * 1024 * 1024)
106+
#define WRITE_SIZE (16 * 1024)
40107

41108
void die(char *str);
42109
void print_elapse(struct timeval start_t, struct timeval elapse_t);
@@ -49,7 +116,7 @@ main(int argc, char *argv[])
49116
int tmpfile,
50117
i,
51118
loops = 1000;
52-
char *strout = (char *) malloc(WAL_FILE_SIZE);
119+
char *full_buf = (char *) malloc(XLOG_SEG_SIZE), *buf;
53120
char *filename = FSYNC_FILENAME;
54121

55122
if (argc > 2 && strcmp(argv[1], "-f") == 0)
@@ -62,23 +129,29 @@ main(int argc, char *argv[])
62129
if (argc > 1)
63130
loops = atoi(argv[1]);
64131

65-
for (i = 0; i < WAL_FILE_SIZE; i++)
66-
strout[i] = 'a';
132+
for (i = 0; i < XLOG_SEG_SIZE; i++)
133+
full_buf[i] = 'a';
67134

68135
if ((tmpfile = open(filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) == -1)
69136
die("Cannot open output file.");
70-
write(tmpfile, strout, WAL_FILE_SIZE);
71-
fsync(tmpfile); /* fsync so later fsync's don't have to do it */
137+
if (write(tmpfile, full_buf, XLOG_SEG_SIZE) != XLOG_SEG_SIZE)
138+
die("write failed");
139+
/* fsync so later fsync's don't have to do it */
140+
if (fsync(tmpfile) != 0)
141+
die("fsync failed");
72142
close(tmpfile);
73143

144+
buf = (char *)TYPEALIGN(ALIGNOF_XLOG_BUFFER, full_buf);
145+
74146
printf("Simple write timing:\n");
75147
/* write only */
76148
gettimeofday(&start_t, NULL);
77149
for (i = 0; i < loops; i++)
78150
{
79151
if ((tmpfile = open(filename, O_RDWR)) == -1)
80152
die("Cannot open output file.");
81-
write(tmpfile, strout, 8192);
153+
if (write(tmpfile, buf, WRITE_SIZE/2) != WRITE_SIZE/2)
154+
die("write failed");
82155
close(tmpfile);
83156
}
84157
gettimeofday(&elapse_t, NULL);
@@ -95,8 +168,10 @@ main(int argc, char *argv[])
95168
{
96169
if ((tmpfile = open(filename, O_RDWR)) == -1)
97170
die("Cannot open output file.");
98-
write(tmpfile, strout, 8192);
99-
fsync(tmpfile);
171+
if (write(tmpfile, buf, WRITE_SIZE/2) != WRITE_SIZE/2)
172+
die("write failed");
173+
if (fsync(tmpfile) != 0)
174+
die("fsync failed");
100175
close(tmpfile);
101176
if ((tmpfile = open(filename, O_RDWR)) == -1)
102177
die("Cannot open output file.");
@@ -114,12 +189,14 @@ main(int argc, char *argv[])
114189
{
115190
if ((tmpfile = open(filename, O_RDWR)) == -1)
116191
die("Cannot open output file.");
117-
write(tmpfile, strout, 8192);
192+
if (write(tmpfile, buf, WRITE_SIZE/2) != WRITE_SIZE/2)
193+
die("write failed");
118194
close(tmpfile);
119195
/* reopen file */
120196
if ((tmpfile = open(filename, O_RDWR)) == -1)
121197
die("Cannot open output file.");
122-
fsync(tmpfile);
198+
if (fsync(tmpfile) != 0)
199+
die("fsync failed");
123200
close(tmpfile);
124201
}
125202
gettimeofday(&elapse_t, NULL);
@@ -135,7 +212,8 @@ main(int argc, char *argv[])
135212
die("Cannot open output file.");
136213
gettimeofday(&start_t, NULL);
137214
for (i = 0; i < loops; i++)
138-
write(tmpfile, strout, 16384);
215+
if (write(tmpfile, buf, WRITE_SIZE) != WRITE_SIZE)
216+
die("write failed");
139217
gettimeofday(&elapse_t, NULL);
140218
close(tmpfile);
141219
printf("\tone 16k o_sync write ");
@@ -148,8 +226,10 @@ main(int argc, char *argv[])
148226
gettimeofday(&start_t, NULL);
149227
for (i = 0; i < loops; i++)
150228
{
151-
write(tmpfile, strout, 8192);
152-
write(tmpfile, strout, 8192);
229+
if (write(tmpfile, buf, WRITE_SIZE/2) != WRITE_SIZE/2)
230+
die("write failed");
231+
if (write(tmpfile, buf, WRITE_SIZE/2) != WRITE_SIZE/2)
232+
die("write failed");
153233
}
154234
gettimeofday(&elapse_t, NULL);
155235
close(tmpfile);
@@ -169,7 +249,8 @@ main(int argc, char *argv[])
169249
die("Cannot open output file.");
170250
gettimeofday(&start_t, NULL);
171251
for (i = 0; i < loops; i++)
172-
write(tmpfile, strout, 8192);
252+
if (write(tmpfile, buf, WRITE_SIZE/2) != WRITE_SIZE/2)
253+
die("write failed");
173254
gettimeofday(&elapse_t, NULL);
174255
close(tmpfile);
175256
printf("\topen o_dsync, write ");
@@ -181,7 +262,8 @@ main(int argc, char *argv[])
181262
die("Cannot open output file.");
182263
gettimeofday(&start_t, NULL);
183264
for (i = 0; i < loops; i++)
184-
write(tmpfile, strout, 8192);
265+
if (write(tmpfile, buf, WRITE_SIZE/2) != WRITE_SIZE/2)
266+
die("write failed");
185267
gettimeofday(&elapse_t, NULL);
186268
close(tmpfile);
187269
printf("\topen o_sync, write ");
@@ -199,7 +281,8 @@ main(int argc, char *argv[])
199281
gettimeofday(&start_t, NULL);
200282
for (i = 0; i < loops; i++)
201283
{
202-
write(tmpfile, strout, 8192);
284+
if (write(tmpfile, buf, WRITE_SIZE/2) != WRITE_SIZE/2)
285+
die("write failed");
203286
fdatasync(tmpfile);
204287
}
205288
gettimeofday(&elapse_t, NULL);
@@ -217,8 +300,10 @@ main(int argc, char *argv[])
217300
gettimeofday(&start_t, NULL);
218301
for (i = 0; i < loops; i++)
219302
{
220-
write(tmpfile, strout, 8192);
221-
fsync(tmpfile);
303+
if (write(tmpfile, buf, WRITE_SIZE/2) != WRITE_SIZE/2)
304+
die("write failed");
305+
if (fsync(tmpfile) != 0)
306+
die("fsync failed");
222307
}
223308
gettimeofday(&elapse_t, NULL);
224309
close(tmpfile);
@@ -235,8 +320,10 @@ main(int argc, char *argv[])
235320
gettimeofday(&start_t, NULL);
236321
for (i = 0; i < loops; i++)
237322
{
238-
write(tmpfile, strout, 8192);
239-
write(tmpfile, strout, 8192);
323+
if (write(tmpfile, buf, WRITE_SIZE/2) != WRITE_SIZE/2)
324+
die("write failed");
325+
if (write(tmpfile, buf, WRITE_SIZE/2) != WRITE_SIZE/2)
326+
die("write failed");
240327
}
241328
gettimeofday(&elapse_t, NULL);
242329
close(tmpfile);
@@ -254,8 +341,10 @@ main(int argc, char *argv[])
254341
gettimeofday(&start_t, NULL);
255342
for (i = 0; i < loops; i++)
256343
{
257-
write(tmpfile, strout, 8192);
258-
write(tmpfile, strout, 8192);
344+
if (write(tmpfile, buf, WRITE_SIZE/2) != WRITE_SIZE/2)
345+
die("write failed");
346+
if (write(tmpfile, buf, WRITE_SIZE/2) != WRITE_SIZE/2)
347+
die("write failed");
259348
}
260349
gettimeofday(&elapse_t, NULL);
261350
close(tmpfile);
@@ -271,8 +360,10 @@ main(int argc, char *argv[])
271360
gettimeofday(&start_t, NULL);
272361
for (i = 0; i < loops; i++)
273362
{
274-
write(tmpfile, strout, 8192);
275-
write(tmpfile, strout, 8192);
363+
if (write(tmpfile, buf, WRITE_SIZE/2) != WRITE_SIZE/2)
364+
die("write failed");
365+
if (write(tmpfile, buf, WRITE_SIZE/2) != WRITE_SIZE/2)
366+
die("write failed");
276367
fdatasync(tmpfile);
277368
}
278369
gettimeofday(&elapse_t, NULL);
@@ -290,16 +381,20 @@ main(int argc, char *argv[])
290381
gettimeofday(&start_t, NULL);
291382
for (i = 0; i < loops; i++)
292383
{
293-
write(tmpfile, strout, 8192);
294-
write(tmpfile, strout, 8192);
295-
fsync(tmpfile);
384+
if (write(tmpfile, buf, WRITE_SIZE/2) != WRITE_SIZE/2)
385+
die("write failed");
386+
if (write(tmpfile, buf, WRITE_SIZE/2) != WRITE_SIZE/2)
387+
die("write failed");
388+
if (fsync(tmpfile) != 0)
389+
die("fsync failed");
296390
}
297391
gettimeofday(&elapse_t, NULL);
298392
close(tmpfile);
299393
printf("\twrite, fsync, ");
300394
print_elapse(start_t, elapse_t);
301395
printf("\n");
302396

397+
free(full_buf);
303398
unlink(filename);
304399

305400
return 0;

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