diff options
author | Greg Stark <stark@mit.edu> | 2010-02-28 21:05:30 +0000 |
---|---|---|
committer | Greg Stark <stark@mit.edu> | 2010-02-28 21:05:30 +0000 |
commit | 7d7db18a68b7a16df85e8dc9d345b3ee7f39d460 (patch) | |
tree | 42b74287e974d8e7d5cacb1afab9c9ca0cd4bc9b | |
parent | a12333eed2af3399cd70170c070a6aa9a4550bc5 (diff) | |
download | postgresql-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.c | 53 |
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))); |