aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Stark <stark@mit.edu>2010-02-28 21:05:30 +0000
committerGreg Stark <stark@mit.edu>2010-02-28 21:05:30 +0000
commit7d7db18a68b7a16df85e8dc9d345b3ee7f39d460 (patch)
tree42b74287e974d8e7d5cacb1afab9c9ca0cd4bc9b
parenta12333eed2af3399cd70170c070a6aa9a4550bc5 (diff)
downloadpostgresql-7d7db18a68b7a16df85e8dc9d345b3ee7f39d460.tar.gz
postgresql-7d7db18a68b7a16df85e8dc9d345b3ee7f39d460.zip
Second try at fsyncing directories in CREATE DATABASE. Let's see what the build farm says of opening directories read-only and ignoring EBADF from fsync of directories
-rw-r--r--src/port/copydir.c53
1 files changed, 38 insertions, 15 deletions
diff --git a/src/port/copydir.c b/src/port/copydir.c
index e1675b66391..0be12609fec 100644
--- a/src/port/copydir.c
+++ b/src/port/copydir.c
@@ -11,7 +11,7 @@
* as a service.
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/port/copydir.c,v 1.33 2010/02/26 02:01:38 momjian Exp $
+ * $PostgreSQL: pgsql/src/port/copydir.c,v 1.34 2010/02/28 21:05:30 stark Exp $
*
*-------------------------------------------------------------------------
*/
@@ -37,7 +37,7 @@
static void copy_file(char *fromfile, char *tofile);
-static void fsync_fname(char *fname);
+static void fsync_fname(char *fname, bool isdir);
/*
@@ -121,22 +121,17 @@ copydir(char *fromdir, char *todir, bool recurse)
errmsg("could not stat file \"%s\": %m", tofile)));
if (S_ISREG(fst.st_mode))
- fsync_fname(tofile);
+ fsync_fname(tofile, false);
}
FreeDir(xldir);
-#ifdef NOTYET
-
/*
* It's important to fsync the destination directory itself as individual
* file fsyncs don't guarantee that the directory entry for the file is
* synced. Recent versions of ext4 have made the window much wider but
* it's been true for ext3 and other filesystems in the past.
- *
- * However we can't do this just yet, it has portability issues.
*/
- fsync_fname(todir);
-#endif
+ fsync_fname(todir, true);
}
/*
@@ -216,20 +211,48 @@ copy_file(char *fromfile, char *tofile)
/*
* fsync a file
+ *
+ * Try to fsync directories but ignore errors that indicate the OS
+ * just doesn't allow/require fsyncing directories.
*/
static void
-fsync_fname(char *fname)
+fsync_fname(char *fname, bool isdir)
{
- int fd = BasicOpenFile(fname,
- O_RDWR | PG_BINARY,
- S_IRUSR | S_IWUSR);
+ int fd;
+ int returncode;
- if (fd < 0)
+ /* Some OSs require directories to be opened read-only whereas
+ * other systems don't allow us to fsync files opened read-only so
+ * we need both cases here
+ */
+ if (!isdir)
+ fd = BasicOpenFile(fname,
+ O_RDWR | PG_BINARY,
+ S_IRUSR | S_IWUSR);
+ else
+ fd = BasicOpenFile(fname,
+ O_RDONLY | PG_BINARY,
+ S_IRUSR | S_IWUSR);
+
+ /* Some OSs don't allow us to open directories at all */
+ if (fd < 0 && isdir && errno == EISDIR)
+ return;
+
+ else if (fd < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not open file \"%s\": %m", fname)));
- if (pg_fsync(fd) != 0)
+ returncode = pg_fsync(fd);
+
+ /* Some OSs don't allow us to fsync directories at all */
+ if (returncode != 0 && isdir && errno == EBADF)
+ {
+ close(fd);
+ return;
+ }
+
+ if (returncode != 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not fsync file \"%s\": %m", fname)));