Skip to content

Commit

Permalink
Merge pull request #1209 from trapexit/o_direct
Browse files Browse the repository at this point in the history
Align msg buffer memory to allow O_DIRECT to work
  • Loading branch information
trapexit authored Jul 9, 2023
2 parents 775c3ca + 22833bd commit 36a4b7a
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 20 deletions.
2 changes: 1 addition & 1 deletion libfuse/lib/fuse.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
72 changes: 54 additions & 18 deletions libfuse/lib/fuse_msgbuf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "fuse_msgbuf.hpp"
#include "fuse.h"
#include "fuse_kernel.h"

#include <unistd.h>

Expand All @@ -35,34 +36,52 @@ static std::atomic<std::uint_fast64_t> g_MSGBUF_ALLOC_COUNT;
static std::mutex g_MUTEX;
static std::vector<fuse_msgbuf_t*> 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
Expand All @@ -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;

Expand All @@ -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
Expand All @@ -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_)
Expand Down
6 changes: 5 additions & 1 deletion libfuse/lib/fuse_msgbuf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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
25 changes: 25 additions & 0 deletions tests/TEST_o_direct
Original file line number Diff line number Diff line change
@@ -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)

0 comments on commit 36a4b7a

Please sign in to comment.