11
11
* as a service.
12
12
*
13
13
* IDENTIFICATION
14
- * $PostgreSQL: pgsql/src/port/copydir.c,v 1.25 2010/02/14 17 :50:52 stark Exp $
14
+ * $PostgreSQL: pgsql/src/port/copydir.c,v 1.26 2010/02/15 00 :50:57 stark Exp $
15
15
*
16
16
*-------------------------------------------------------------------------
17
17
*/
37
37
38
38
39
39
static void copy_file (char * fromfile , char * tofile );
40
+ static void fsync_fname (char * fname );
40
41
41
42
42
43
/*
@@ -91,27 +92,32 @@ copydir(char *fromdir, char *todir, bool recurse)
91
92
copy_file (fromfile , tofile );
92
93
}
93
94
94
- FreeDir (xldir );
95
-
96
95
/*
97
- * fsync the directory to make sure not just the data but also the
98
- * new directory file entries have reached the disk. While needed
99
- * by most filesystems, the window got bigger with newer ones like
100
- * ext4.
96
+ * Be paranoid here and fsync all files to ensure we catch problems.
101
97
*/
102
- dirfd = BasicOpenFile (todir ,
103
- O_RDONLY | PG_BINARY ,
104
- S_IRUSR | S_IWUSR );
105
- if (dirfd == -1 )
106
- ereport (ERROR ,
107
- (errcode_for_file_access (),
108
- errmsg ("could not open directory for fsync \"%s\": %m" , todir )));
109
-
110
- if (pg_fsync (dirfd ) == -1 )
98
+ if (xldir == NULL )
111
99
ereport (ERROR ,
112
100
(errcode_for_file_access (),
113
- errmsg ("could not fsync directory \"%s\": %m" , todir )));
114
- close (dirfd );
101
+ errmsg ("could not open directory \"%s\": %m" , fromdir )));
102
+
103
+ while ((xlde = ReadDir (xldir , fromdir )) != NULL )
104
+ {
105
+ if (strcmp (xlde -> d_name , "." ) == 0 ||
106
+ strcmp (xlde -> d_name , ".." ) == 0 )
107
+ continue ;
108
+
109
+ snprintf (tofile , MAXPGPATH , "%s/%s" , todir , xlde -> d_name );
110
+ fsync_fname (tofile );
111
+ }
112
+ FreeDir (xldir );
113
+
114
+ /* It's important to fsync the destination directory itself as
115
+ * individual file fsyncs don't guarantee that the directory entry
116
+ * for the file is synced. Recent versions of ext4 have made the
117
+ * window much wider but it's been true for ext3 and other
118
+ * filesyetems in the past
119
+ */
120
+ fsync_fname (todir );
115
121
}
116
122
117
123
/*
@@ -124,6 +130,7 @@ copy_file(char *fromfile, char *tofile)
124
130
int srcfd ;
125
131
int dstfd ;
126
132
int nbytes ;
133
+ off_t offset ;
127
134
128
135
/* Use palloc to ensure we get a maxaligned buffer */
129
136
#define COPY_BUF_SIZE (8 * BLCKSZ)
@@ -149,7 +156,7 @@ copy_file(char *fromfile, char *tofile)
149
156
/*
150
157
* Do the data copying.
151
158
*/
152
- for (;; )
159
+ for (offset = 0 ; ; offset += nbytes )
153
160
{
154
161
nbytes = read (srcfd , buffer , COPY_BUF_SIZE );
155
162
if (nbytes < 0 )
@@ -168,15 +175,14 @@ copy_file(char *fromfile, char *tofile)
168
175
(errcode_for_file_access (),
169
176
errmsg ("could not write to file \"%s\": %m" , tofile )));
170
177
}
171
- }
172
178
173
- /*
174
- * Be paranoid here to ensure we catch problems.
175
- */
176
- if ( pg_fsync ( dstfd ) != 0 )
177
- ereport ( ERROR ,
178
- ( errcode_for_file_access (),
179
- errmsg ( "could not fsync file \"%s\": %m" , tofile )));
179
+ /*
180
+ * We fsync the files later but first flush them to avoid spamming
181
+ * the cache and hopefully get the kernel to start writing them
182
+ * out before the fsync comes.
183
+ */
184
+ pg_flush_data ( dstfd , offset , nbytes );
185
+ }
180
186
181
187
if (close (dstfd ))
182
188
ereport (ERROR ,
@@ -187,3 +193,27 @@ copy_file(char *fromfile, char *tofile)
187
193
188
194
pfree (buffer );
189
195
}
196
+
197
+
198
+
199
+ /*
200
+ * fsync a file
201
+ */
202
+ static void
203
+ fsync_fname (char * fname )
204
+ {
205
+ int fd = BasicOpenFile (fname ,
206
+ O_RDONLY | PG_BINARY ,
207
+ S_IRUSR | S_IWUSR );
208
+
209
+ if (fd < 0 )
210
+ ereport (ERROR ,
211
+ (errcode_for_file_access (),
212
+ errmsg ("could not open file \"%s\": %m" , fname )));
213
+
214
+ if (pg_fsync (fd ) != 0 )
215
+ ereport (ERROR ,
216
+ (errcode_for_file_access (),
217
+ errmsg ("could not fsync file \"%s\": %m" , fname )));
218
+ close (fd );
219
+ }
0 commit comments