diff options
author | Bar Perach <barp@google.com> | 2019-04-12 14:04:51 +0300 |
---|---|---|
committer | Bar Perach <barp@google.com> | 2019-04-12 14:10:33 +0300 |
commit | 95a721e0cb55465dda5ceae50e1fde944ad8a354 (patch) | |
tree | d22f46c64800a0537259afdda8bd99454f22f5dd /src | |
parent | 0617259df0a6f58092a3ee1df32536320f6a72da (diff) | |
download | bindfs-95a721e0cb55465dda5ceae50e1fde944ad8a354.tar.gz |
Made bindfs mounts work with files opened with O_DIRECT
Diffstat (limited to 'src')
-rw-r--r-- | src/bindfs.c | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/src/bindfs.c b/src/bindfs.c index 332aa74..fff3a16 100644 --- a/src/bindfs.c +++ b/src/bindfs.c @@ -72,6 +72,9 @@ #include <sys/xattr.h> #endif +#include <sys/mman.h> +#include <fcntl.h> + #ifdef __LINUX__ #include <linux/fs.h> // For BLKGETSIZE64 #endif @@ -96,6 +99,10 @@ #define XATTR_APPLE_PREFIX "com.apple." #endif +#ifndef O_DIRECT +#define O_DIRECT 00040000 /* direct disk access hint */ +#endif + /* We pessimistically assume signed uid_t and gid_t in our overflow checks, mostly because supporting both cases would require a bunch more code. */ static const uid_t UID_T_MAX = ((1LL << (sizeof(uid_t)*8-1)) - 1); @@ -1098,14 +1105,30 @@ static int bindfs_read(const char *path, char *buf, size_t size, off_t offset, int res; (void) path; + char * target_buf = buf; + if (settings.read_limiter) { rate_limiter_wait(settings.read_limiter, size); } - res = pread(fi->fh, buf, size, offset); + unsigned int page_size = sysconf(_SC_PAGESIZE); + if (fi->flags & O_DIRECT) { + // allocate 512 bytes aligned buffer for direct io to work + target_buf = mmap(NULL, ((page_size - 1 + size) / page_size) * page_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); + if (target_buf == MAP_FAILED) { + return -ENOMEM; + } + } + + res = pread(fi->fh, target_buf, size, offset); if (res == -1) res = -errno; + if (target_buf != buf) { + memcpy(buf, target_buf, size); + munmap(target_buf, ((page_size - 1 + size) / page_size) * page_size); + } + return res; } @@ -1114,15 +1137,30 @@ static int bindfs_write(const char *path, const char *buf, size_t size, { int res; (void) path; + char * source_buf = buf; if (settings.write_limiter) { rate_limiter_wait(settings.write_limiter, size); } - res = pwrite(fi->fh, buf, size, offset); + unsigned int page_size = sysconf(_SC_PAGESIZE); + if (fi->flags & O_DIRECT) { + // allocate 512 bytes aligned buffer for direct io to work + source_buf = mmap(NULL, ((page_size - 1 + size) / page_size) * page_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); + if (source_buf == MAP_FAILED) { + return -ENOMEM; + } + memcpy(source_buf, buf, size); + } + + res = pwrite(fi->fh, source_buf, size, offset); if (res == -1) res = -errno; + if (source_buf != buf) { + munmap(source_buf, ((page_size - 1 + size) / page_size) * page_size); + } + return res; } |