1
1
/*
2
2
* test_fsync.c
3
- * tests if fsync can be done from another process than the original write
3
+ * test various fsync() methods
4
4
*/
5
5
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"
8
10
9
11
#include <sys/types.h>
10
12
#include <sys/stat.h>
14
16
#include <time.h>
15
17
#include <sys/time.h>
16
18
#include <unistd.h>
19
+ #include <string.h>
17
20
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
20
37
#else
21
- #define FSYNC_FILENAME "/var/tmp/test_fsync.out"
38
+ #define PG_O_DIRECT 0
22
39
#endif
23
40
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
+ */
25
47
#if defined(O_SYNC )
26
- #define OPEN_SYNC_FLAG O_SYNC
48
+ #define BARE_OPEN_SYNC_FLAG O_SYNC
27
49
#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)
31
54
#endif
32
55
56
+ #if defined(O_DSYNC )
33
57
#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
36
95
#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"
37
104
#endif
38
105
39
- #define WAL_FILE_SIZE (16 * 1024 * 1024)
106
+ #define WRITE_SIZE (16 * 1024)
40
107
41
108
void die (char * str );
42
109
void print_elapse (struct timeval start_t , struct timeval elapse_t );
@@ -49,7 +116,7 @@ main(int argc, char *argv[])
49
116
int tmpfile ,
50
117
i ,
51
118
loops = 1000 ;
52
- char * strout = (char * ) malloc (WAL_FILE_SIZE ) ;
119
+ char * full_buf = (char * ) malloc (XLOG_SEG_SIZE ), * buf ;
53
120
char * filename = FSYNC_FILENAME ;
54
121
55
122
if (argc > 2 && strcmp (argv [1 ], "-f" ) == 0 )
@@ -62,23 +129,29 @@ main(int argc, char *argv[])
62
129
if (argc > 1 )
63
130
loops = atoi (argv [1 ]);
64
131
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' ;
67
134
68
135
if ((tmpfile = open (filename , O_RDWR | O_CREAT , S_IRUSR | S_IWUSR )) == -1 )
69
136
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" );
72
142
close (tmpfile );
73
143
144
+ buf = (char * )TYPEALIGN (ALIGNOF_XLOG_BUFFER , full_buf );
145
+
74
146
printf ("Simple write timing:\n" );
75
147
/* write only */
76
148
gettimeofday (& start_t , NULL );
77
149
for (i = 0 ; i < loops ; i ++ )
78
150
{
79
151
if ((tmpfile = open (filename , O_RDWR )) == -1 )
80
152
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" );
82
155
close (tmpfile );
83
156
}
84
157
gettimeofday (& elapse_t , NULL );
@@ -95,8 +168,10 @@ main(int argc, char *argv[])
95
168
{
96
169
if ((tmpfile = open (filename , O_RDWR )) == -1 )
97
170
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" );
100
175
close (tmpfile );
101
176
if ((tmpfile = open (filename , O_RDWR )) == -1 )
102
177
die ("Cannot open output file." );
@@ -114,12 +189,14 @@ main(int argc, char *argv[])
114
189
{
115
190
if ((tmpfile = open (filename , O_RDWR )) == -1 )
116
191
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" );
118
194
close (tmpfile );
119
195
/* reopen file */
120
196
if ((tmpfile = open (filename , O_RDWR )) == -1 )
121
197
die ("Cannot open output file." );
122
- fsync (tmpfile );
198
+ if (fsync (tmpfile ) != 0 )
199
+ die ("fsync failed" );
123
200
close (tmpfile );
124
201
}
125
202
gettimeofday (& elapse_t , NULL );
@@ -135,7 +212,8 @@ main(int argc, char *argv[])
135
212
die ("Cannot open output file." );
136
213
gettimeofday (& start_t , NULL );
137
214
for (i = 0 ; i < loops ; i ++ )
138
- write (tmpfile , strout , 16384 );
215
+ if (write (tmpfile , buf , WRITE_SIZE ) != WRITE_SIZE )
216
+ die ("write failed" );
139
217
gettimeofday (& elapse_t , NULL );
140
218
close (tmpfile );
141
219
printf ("\tone 16k o_sync write " );
@@ -148,8 +226,10 @@ main(int argc, char *argv[])
148
226
gettimeofday (& start_t , NULL );
149
227
for (i = 0 ; i < loops ; i ++ )
150
228
{
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" );
153
233
}
154
234
gettimeofday (& elapse_t , NULL );
155
235
close (tmpfile );
@@ -169,7 +249,8 @@ main(int argc, char *argv[])
169
249
die ("Cannot open output file." );
170
250
gettimeofday (& start_t , NULL );
171
251
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" );
173
254
gettimeofday (& elapse_t , NULL );
174
255
close (tmpfile );
175
256
printf ("\topen o_dsync, write " );
@@ -181,7 +262,8 @@ main(int argc, char *argv[])
181
262
die ("Cannot open output file." );
182
263
gettimeofday (& start_t , NULL );
183
264
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" );
185
267
gettimeofday (& elapse_t , NULL );
186
268
close (tmpfile );
187
269
printf ("\topen o_sync, write " );
@@ -199,7 +281,8 @@ main(int argc, char *argv[])
199
281
gettimeofday (& start_t , NULL );
200
282
for (i = 0 ; i < loops ; i ++ )
201
283
{
202
- write (tmpfile , strout , 8192 );
284
+ if (write (tmpfile , buf , WRITE_SIZE /2 ) != WRITE_SIZE /2 )
285
+ die ("write failed" );
203
286
fdatasync (tmpfile );
204
287
}
205
288
gettimeofday (& elapse_t , NULL );
@@ -217,8 +300,10 @@ main(int argc, char *argv[])
217
300
gettimeofday (& start_t , NULL );
218
301
for (i = 0 ; i < loops ; i ++ )
219
302
{
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" );
222
307
}
223
308
gettimeofday (& elapse_t , NULL );
224
309
close (tmpfile );
@@ -235,8 +320,10 @@ main(int argc, char *argv[])
235
320
gettimeofday (& start_t , NULL );
236
321
for (i = 0 ; i < loops ; i ++ )
237
322
{
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" );
240
327
}
241
328
gettimeofday (& elapse_t , NULL );
242
329
close (tmpfile );
@@ -254,8 +341,10 @@ main(int argc, char *argv[])
254
341
gettimeofday (& start_t , NULL );
255
342
for (i = 0 ; i < loops ; i ++ )
256
343
{
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" );
259
348
}
260
349
gettimeofday (& elapse_t , NULL );
261
350
close (tmpfile );
@@ -271,8 +360,10 @@ main(int argc, char *argv[])
271
360
gettimeofday (& start_t , NULL );
272
361
for (i = 0 ; i < loops ; i ++ )
273
362
{
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" );
276
367
fdatasync (tmpfile );
277
368
}
278
369
gettimeofday (& elapse_t , NULL );
@@ -290,16 +381,20 @@ main(int argc, char *argv[])
290
381
gettimeofday (& start_t , NULL );
291
382
for (i = 0 ; i < loops ; i ++ )
292
383
{
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" );
296
390
}
297
391
gettimeofday (& elapse_t , NULL );
298
392
close (tmpfile );
299
393
printf ("\twrite, fsync, " );
300
394
print_elapse (start_t , elapse_t );
301
395
printf ("\n" );
302
396
397
+ free (full_buf );
303
398
unlink (filename );
304
399
305
400
return 0 ;
0 commit comments