From 22833bdfe25e05890c6474bc2851134ba3dd069f Mon Sep 17 00:00:00 2001 From: Antonio SJ Musumeci Date: Sun, 9 Jul 2023 02:04:32 -0500 Subject: [PATCH] Align msg buffer memory to allow O_DIRECT to work --- libfuse/lib/fuse.c | 2 +- libfuse/lib/fuse_msgbuf.cpp | 72 +++++++++++++++++++++++++++---------- libfuse/lib/fuse_msgbuf.hpp | 6 +++- tests/TEST_o_direct | 25 +++++++++++++ 4 files changed, 85 insertions(+), 20 deletions(-) create mode 100755 tests/TEST_o_direct diff --git a/libfuse/lib/fuse.c b/libfuse/lib/fuse.c index b11f24b1..7c8398cb 100644 --- a/libfuse/lib/fuse.c +++ b/libfuse/lib/fuse.c @@ -2337,7 +2337,7 @@ fuse_lib_read(fuse_req_t req, f = req_fuse_prepare(req); - msgbuf = msgbuf_alloc(); + msgbuf = msgbuf_alloc_page_aligned(); res = f->fs->op.read(&ffi,msgbuf->mem,arg->size,arg->offset); diff --git a/libfuse/lib/fuse_msgbuf.cpp b/libfuse/lib/fuse_msgbuf.cpp index 329f7180..e683874d 100644 --- a/libfuse/lib/fuse_msgbuf.cpp +++ b/libfuse/lib/fuse_msgbuf.cpp @@ -17,6 +17,7 @@ #include "fuse_msgbuf.hpp" #include "fuse.h" +#include "fuse_kernel.h" #include @@ -35,34 +36,52 @@ static std::atomic g_MSGBUF_ALLOC_COUNT; static std::mutex g_MUTEX; static std::vector g_MSGBUF_STACK; -static -__attribute__((constructor)) +uint64_t +msgbuf_get_bufsize() +{ + return g_BUFSIZE; +} + void -msgbuf_constructor() +msgbuf_set_bufsize(const uint32_t size_in_pages_) { - g_PAGESIZE = sysconf(_SC_PAGESIZE); - // +2 because to do O_DIRECT we need to offset the buffer to align - g_BUFSIZE = (g_PAGESIZE * (FUSE_MAX_MAX_PAGES + 2)); + g_BUFSIZE = ((size_in_pages_ + 1) * g_PAGESIZE); } -static -__attribute__((destructor)) void -msgbuf_destroy() +msgbuf_page_align(fuse_msgbuf_t *msgbuf_) { + msgbuf_->mem = (char*)msgbuf_; + msgbuf_->mem += g_PAGESIZE; + msgbuf_->size = (g_BUFSIZE - g_PAGESIZE); +} +void +msgbuf_write_align(fuse_msgbuf_t *msgbuf_) +{ + msgbuf_->mem = (char*)msgbuf_; + msgbuf_->mem += g_PAGESIZE; + msgbuf_->mem -= sizeof(struct fuse_in_header); + msgbuf_->mem -= sizeof(struct fuse_write_in); + msgbuf_->size = (g_BUFSIZE - g_PAGESIZE); } -uint64_t -msgbuf_get_bufsize() +static +__attribute__((constructor)) +void +msgbuf_constructor() { - return g_BUFSIZE; + g_PAGESIZE = sysconf(_SC_PAGESIZE); + // FUSE_MAX_MAX_PAGES for payload + 1 for message header + msgbuf_set_bufsize(FUSE_MAX_MAX_PAGES + 1); } +static +__attribute__((destructor)) void -msgbuf_set_bufsize(const uint32_t size_in_pages_) +msgbuf_destroy() { - g_BUFSIZE = ((size_in_pages_ + 1) * g_PAGESIZE); + } static @@ -79,8 +98,11 @@ page_aligned_malloc(const uint64_t size_) return buf; } +typedef void (*msgbuf_setup_func_t)(fuse_msgbuf_t*); + +static fuse_msgbuf_t* -msgbuf_alloc() +_msgbuf_alloc(msgbuf_setup_func_t setup_func_) { fuse_msgbuf_t *msgbuf; @@ -93,9 +115,6 @@ msgbuf_alloc() if(msgbuf == NULL) return NULL; - msgbuf->mem = (((char*)msgbuf) + g_PAGESIZE); - - msgbuf->size = g_BUFSIZE - g_PAGESIZE; g_MSGBUF_ALLOC_COUNT++; } else @@ -105,9 +124,26 @@ msgbuf_alloc() g_MUTEX.unlock(); } + setup_func_(msgbuf); + return msgbuf; } +// Offset the memory so write request payload will be placed on page +// boundry so O_DIRECT can work. No impact on other message types +// except for `read` which will require using `msgbuf_page_align`. +fuse_msgbuf_t* +msgbuf_alloc() +{ + return _msgbuf_alloc(msgbuf_write_align); +} + +fuse_msgbuf_t* +msgbuf_alloc_page_aligned() +{ + return _msgbuf_alloc(msgbuf_page_align); +} + static void msgbuf_destroy(fuse_msgbuf_t *msgbuf_) diff --git a/libfuse/lib/fuse_msgbuf.hpp b/libfuse/lib/fuse_msgbuf.hpp index 1fe67f59..0e3bc6f1 100644 --- a/libfuse/lib/fuse_msgbuf.hpp +++ b/libfuse/lib/fuse_msgbuf.hpp @@ -26,7 +26,8 @@ EXTERN_C_BEGIN void msgbuf_set_bufsize(const uint32_t size); uint64_t msgbuf_get_bufsize(); -fuse_msgbuf_t* msgbuf_alloc(); +fuse_msgbuf_t *msgbuf_alloc(); +fuse_msgbuf_t *msgbuf_alloc_page_aligned(); void msgbuf_free(fuse_msgbuf_t *msgbuf); void msgbuf_gc(); @@ -35,4 +36,7 @@ void msgbuf_gc_10percent(); uint64_t msgbuf_alloc_count(); uint64_t msgbuf_avail_count(); +void msgbuf_page_align(fuse_msgbuf_t *msgbuf); +void msgbuf_write_align(fuse_msgbuf_t *msgbuf); + EXTERN_C_END diff --git a/tests/TEST_o_direct b/tests/TEST_o_direct new file mode 100755 index 00000000..8414fba9 --- /dev/null +++ b/tests/TEST_o_direct @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +import os +import sys +import tempfile +import mmap +import resource + +(fd,filepath) = tempfile.mkstemp(dir=sys.argv[1]) + +os.close(fd) + +fd = os.open(filepath,os.O_RDWR|os.O_DIRECT|os.O_TRUNC) + +os.unlink(filepath) + +data = mmap.mmap(-1, resource.getpagesize()) + +os.write(fd,data) + +os.lseek(fd,0,os.SEEK_SET) + +data = os.read(fd,resource.getpagesize()) + +os.close(fd)