|
11 | 11 | * as a service. |
12 | 12 | * |
13 | 13 | * IDENTIFICATION |
14 | | - * $PostgreSQL: pgsql/src/port/copydir.c,v 1.33 2010/02/26 02:01:38 momjian Exp $ |
| 14 | + * $PostgreSQL: pgsql/src/port/copydir.c,v 1.34 2010/02/28 21:05:30 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 | +static void fsync_fname(char *fname, bool isdir); |
41 | 41 |
|
42 | 42 |
|
43 | 43 | /* |
@@ -121,22 +121,17 @@ copydir(char *fromdir, char *todir, bool recurse) |
121 | 121 | errmsg("could not stat file \"%s\": %m", tofile))); |
122 | 122 |
|
123 | 123 | if (S_ISREG(fst.st_mode)) |
124 | | - fsync_fname(tofile); |
| 124 | + fsync_fname(tofile, false); |
125 | 125 | } |
126 | 126 | FreeDir(xldir); |
127 | 127 |
|
128 | | -#ifdef NOTYET |
129 | | - |
130 | 128 | /* |
131 | 129 | * It's important to fsync the destination directory itself as individual |
132 | 130 | * file fsyncs don't guarantee that the directory entry for the file is |
133 | 131 | * synced. Recent versions of ext4 have made the window much wider but |
134 | 132 | * it's been true for ext3 and other filesystems in the past. |
135 | | - * |
136 | | - * However we can't do this just yet, it has portability issues. |
137 | 133 | */ |
138 | | - fsync_fname(todir); |
139 | | -#endif |
| 134 | + fsync_fname(todir, true); |
140 | 135 | } |
141 | 136 |
|
142 | 137 | /* |
@@ -216,20 +211,48 @@ copy_file(char *fromfile, char *tofile) |
216 | 211 |
|
217 | 212 | /* |
218 | 213 | * fsync a file |
| 214 | + * |
| 215 | + * Try to fsync directories but ignore errors that indicate the OS |
| 216 | + * just doesn't allow/require fsyncing directories. |
219 | 217 | */ |
220 | 218 | static void |
221 | | -fsync_fname(char *fname) |
| 219 | +fsync_fname(char *fname, bool isdir) |
222 | 220 | { |
223 | | - int fd = BasicOpenFile(fname, |
224 | | - O_RDWR | PG_BINARY, |
225 | | - S_IRUSR | S_IWUSR); |
| 221 | + int fd; |
| 222 | + int returncode; |
226 | 223 |
|
227 | | - if (fd < 0) |
| 224 | + /* Some OSs require directories to be opened read-only whereas |
| 225 | + * other systems don't allow us to fsync files opened read-only so |
| 226 | + * we need both cases here |
| 227 | + */ |
| 228 | + if (!isdir) |
| 229 | + fd = BasicOpenFile(fname, |
| 230 | + O_RDWR | PG_BINARY, |
| 231 | + S_IRUSR | S_IWUSR); |
| 232 | + else |
| 233 | + fd = BasicOpenFile(fname, |
| 234 | + O_RDONLY | PG_BINARY, |
| 235 | + S_IRUSR | S_IWUSR); |
| 236 | + |
| 237 | + /* Some OSs don't allow us to open directories at all */ |
| 238 | + if (fd < 0 && isdir && errno == EISDIR) |
| 239 | + return; |
| 240 | + |
| 241 | + else if (fd < 0) |
228 | 242 | ereport(ERROR, |
229 | 243 | (errcode_for_file_access(), |
230 | 244 | errmsg("could not open file \"%s\": %m", fname))); |
231 | 245 |
|
232 | | - if (pg_fsync(fd) != 0) |
| 246 | + returncode = pg_fsync(fd); |
| 247 | + |
| 248 | + /* Some OSs don't allow us to fsync directories at all */ |
| 249 | + if (returncode != 0 && isdir && errno == EBADF) |
| 250 | + { |
| 251 | + close(fd); |
| 252 | + return; |
| 253 | + } |
| 254 | + |
| 255 | + if (returncode != 0) |
233 | 256 | ereport(ERROR, |
234 | 257 | (errcode_for_file_access(), |
235 | 258 | errmsg("could not fsync file \"%s\": %m", fname))); |
|
0 commit comments