Browse Source

Align msg buffer memory to allow O_DIRECT to work

pull/1209/head
Antonio SJ Musumeci 1 year ago
parent
commit
22833bdfe2
  1. 2
      libfuse/lib/fuse.c
  2. 72
      libfuse/lib/fuse_msgbuf.cpp
  3. 4
      libfuse/lib/fuse_msgbuf.hpp
  4. 25
      tests/TEST_o_direct

2
libfuse/lib/fuse.c

@ -2337,7 +2337,7 @@ fuse_lib_read(fuse_req_t req,
f = req_fuse_prepare(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); res = f->fs->op.read(&ffi,msgbuf->mem,arg->size,arg->offset);

72
libfuse/lib/fuse_msgbuf.cpp

@ -17,6 +17,7 @@
#include "fuse_msgbuf.hpp" #include "fuse_msgbuf.hpp"
#include "fuse.h" #include "fuse.h"
#include "fuse_kernel.h"
#include <unistd.h> #include <unistd.h>
@ -35,34 +36,52 @@ static std::atomic<std::uint_fast64_t> g_MSGBUF_ALLOC_COUNT;
static std::mutex g_MUTEX; static std::mutex g_MUTEX;
static std::vector<fuse_msgbuf_t*> g_MSGBUF_STACK; static std::vector<fuse_msgbuf_t*> g_MSGBUF_STACK;
static
__attribute__((constructor))
uint64_t
msgbuf_get_bufsize()
{
return g_BUFSIZE;
}
void 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 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 void
msgbuf_set_bufsize(const uint32_t size_in_pages_)
msgbuf_destroy()
{ {
g_BUFSIZE = ((size_in_pages_ + 1) * g_PAGESIZE);
} }
static static
@ -79,8 +98,11 @@ page_aligned_malloc(const uint64_t size_)
return buf; return buf;
} }
typedef void (*msgbuf_setup_func_t)(fuse_msgbuf_t*);
static
fuse_msgbuf_t* fuse_msgbuf_t*
msgbuf_alloc()
_msgbuf_alloc(msgbuf_setup_func_t setup_func_)
{ {
fuse_msgbuf_t *msgbuf; fuse_msgbuf_t *msgbuf;
@ -93,9 +115,6 @@ msgbuf_alloc()
if(msgbuf == NULL) if(msgbuf == NULL)
return NULL; return NULL;
msgbuf->mem = (((char*)msgbuf) + g_PAGESIZE);
msgbuf->size = g_BUFSIZE - g_PAGESIZE;
g_MSGBUF_ALLOC_COUNT++; g_MSGBUF_ALLOC_COUNT++;
} }
else else
@ -105,9 +124,26 @@ msgbuf_alloc()
g_MUTEX.unlock(); g_MUTEX.unlock();
} }
setup_func_(msgbuf);
return 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 static
void void
msgbuf_destroy(fuse_msgbuf_t *msgbuf_) msgbuf_destroy(fuse_msgbuf_t *msgbuf_)

4
libfuse/lib/fuse_msgbuf.hpp

@ -27,6 +27,7 @@ void msgbuf_set_bufsize(const uint32_t size);
uint64_t msgbuf_get_bufsize(); 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_free(fuse_msgbuf_t *msgbuf);
void msgbuf_gc(); void msgbuf_gc();
@ -35,4 +36,7 @@ void msgbuf_gc_10percent();
uint64_t msgbuf_alloc_count(); uint64_t msgbuf_alloc_count();
uint64_t msgbuf_avail_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 EXTERN_C_END

25
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)
Loading…
Cancel
Save