diff --git a/src/backend/storage/file/copydir.c b/src/backend/storage/file/copydir.c index a51ee81..d80d18a 100644 --- a/src/backend/storage/file/copydir.c +++ b/src/backend/storage/file/copydir.c @@ -192,7 +192,7 @@ copy_file(char *fromfile, char *tofile) * cache and hopefully get the kernel to start writing them out before * the fsync comes. */ - pg_flush_data(dstfd, offset, nbytes); + pg_flush_data(dstfd, offset, nbytes, false); } if (CloseTransientFile(dstfd)) diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c index 3e02dce..f5da08c 100644 --- a/src/backend/storage/file/fd.c +++ b/src/backend/storage/file/fd.c @@ -395,8 +395,10 @@ pg_fdatasync(int fd) * flushed. */ void -pg_flush_data(int fd, off_t offset, off_t nbytes) +pg_flush_data(int fd, off_t offset, off_t nbytes, bool isdir) { + (void) isdir; /* this can be unused on some archs */ + /* * Right now file flushing is primarily used to avoid making later * fsync()/fdatasync() calls have a less impact. Thus don't trigger @@ -451,8 +453,31 @@ pg_flush_data(int fd, off_t offset, off_t nbytes) * We map the file (mmap()), tell the kernel to sync back the contents * (msync()), and then remove the mapping again (munmap()). */ + + /* mmap() will not work with dirs */ + if (isdir) + return; + + /* mmap() need exact length when we want to map whole file */ + if ((offset == 0) && (nbytes == 0)) + { + int pagesize = sysconf(_SC_PAGESIZE); + + nbytes = lseek(fd, 0, SEEK_END); + if (nbytes < 0) + ereport(WARNING, + (errcode_for_file_access(), + errmsg("could not determine dirty data size: %m"))); + + /* aling to pagesize with underestimation */ + nbytes = (nbytes/pagesize)*pagesize; + + if(nbytes == 0) + return; + } + p = mmap(NULL, nbytes, - PROT_READ | PROT_WRITE, MAP_SHARED, + PROT_READ, MAP_SHARED, fd, offset); if (p == MAP_FAILED) { @@ -1514,7 +1539,7 @@ FileWriteback(File file, off_t offset, int amount) if (returnCode < 0) return; - pg_flush_data(VfdCache[file].fd, offset, amount); + pg_flush_data(VfdCache[file].fd, offset, amount, false); } int @@ -2920,7 +2945,7 @@ pre_sync_fname(const char *fname, bool isdir, int elevel) * pg_flush_data() ignores errors, which is ok because this is only a * hint. */ - pg_flush_data(fd, 0, 0); + pg_flush_data(fd, 0, 0, isdir); (void) CloseTransientFile(fd); } diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h index be24369..60246f7 100644 --- a/src/include/storage/fd.h +++ b/src/include/storage/fd.h @@ -116,7 +116,7 @@ extern int pg_fsync(int fd); extern int pg_fsync_no_writethrough(int fd); extern int pg_fsync_writethrough(int fd); extern int pg_fdatasync(int fd); -extern void pg_flush_data(int fd, off_t offset, off_t amount); +extern void pg_flush_data(int fd, off_t offset, off_t amount, bool isdir); extern void fsync_fname(const char *fname, bool isdir); extern int durable_rename(const char *oldfile, const char *newfile, int loglevel); extern int durable_link_or_rename(const char *oldfile, const char *newfile, int loglevel);