Commit f822c9db authored by Kirill Smelkov's avatar Kirill Smelkov

X Demo that it is possible to change mmapping while under pagefault to it

--- FAIL: TestCacheControl (0.05s)
    cachecontrol_test.go:154: original: file mmap: got "Debian GNU/"  ; want "hello world"

If there was no mmapFixed(fmmap, "/etc/issue") under DataNode.Read the
test would not fail (i.e. it will see the old - not mmapped page)
parent a53ed6b9
......@@ -8,7 +8,7 @@ package test
import (
"os"
"io/ioutil"
//"io/ioutil"
"testing"
"golang.org/x/sys/unix"
......@@ -38,7 +38,21 @@ func (d *DataNode) GetAttr(out *fuse.Attr, _ nodefs.File, _ *fuse.Context) fuse.
return fuse.OK
}
var fetc *os.File
func init() {
var err error
fetc, err = os.Open("/etc/issue")
if err != nil {
panic(err)
}
}
func (d *DataNode) Read(_ nodefs.File, dest []byte, off int64, _ *fuse.Context) (fuse.ReadResult, fuse.Status) {
err := mmapFixed(fmmap, int(fetc.Fd()), unix.PROT_READ, unix.MAP_SHARED)
if err != nil {
panic(err)
}
l := int64(len(d.data))
end := off + l
if end > l {
......@@ -48,6 +62,8 @@ func (d *DataNode) Read(_ nodefs.File, dest []byte, off int64, _ *fuse.Context)
return fuse.ReadResultData(d.data[off:end]), fuse.OK
}
var fmmap []byte
// TestCacheControl verifies that FUSE server process can store/retrieve kernel data cache.
func TestCacheControl(t *testing.T) {
dir := testutil.TempDir()
......@@ -63,6 +79,7 @@ func TestCacheControl(t *testing.T) {
opts := nodefs.NewOptions()
opts.Debug = testutil.VerboseTest()
srv, fsconn, err := nodefs.MountRoot(dir, root, opts)
_ = fsconn
if err != nil {
t.Fatal(err)
}
......@@ -82,6 +99,7 @@ func TestCacheControl(t *testing.T) {
}
}()
/*
// assertFileRead asserts that the file content reads as dataOK.
assertFileRead := func(subj, dataOK string) {
t.Helper()
......@@ -97,13 +115,14 @@ func TestCacheControl(t *testing.T) {
// make sure the file reads correctly
assertFileRead("original", data0)
*/
// pin file content into OS cache
f, err := os.Open(dir + "/hello.txt")
if err != nil {
t.Fatal(err)
}
fmmap, err := unix.Mmap(int(f.Fd()), 0, len(data0), unix.PROT_READ, unix.MAP_SHARED)
fmmap, err = unix.Mmap(int(f.Fd()), 0, len(data0), unix.PROT_READ, unix.MAP_SHARED)
if err != nil {
t.Fatal(err)
}
......@@ -117,10 +136,10 @@ func TestCacheControl(t *testing.T) {
t.Fatal(err)
}
}()
err = unix.Mlock(fmmap)
if err != nil {
t.Fatal(err)
}
//err = unix.Mlock(fmmap)
//if err != nil {
// t.Fatal(err)
//}
// assertMmapRead asserts that file's mmaped memory reads as dataOK.
assertMmapRead := func(subj, dataOK string) {
......@@ -133,6 +152,7 @@ func TestCacheControl(t *testing.T) {
// make sure the cache has original data
assertMmapRead("original", data0)
/*
// store changed data into OS cache
st := fsconn.FileNotifyStoreCache(file.Inode(), 7, []byte("123"))
if st != fuse.OK {
......@@ -155,4 +175,5 @@ func TestCacheControl(t *testing.T) {
// make sure mmapped data and file read as original data
assertMmapRead("after invalcache", data0)
assertFileRead("after invalcache", data0)
*/
}
......@@ -5,3 +5,39 @@
// Package test holds the tests for Go-FUSE and is not for end-user
// consumption.
package test
import (
"reflect"
"unsafe"
"syscall"
)
/*
#include <sys/mman.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int mmapFixed(int fd, void *addr, size_t length, int prot, int flags) {
void *ok;
ok = mmap(addr, length, prot, flags | MAP_FIXED, fd, 0);
if (ok == MAP_FAILED) {
return errno;
}
if (ok != addr) {
fprintf(stderr, "mmap(fixed): ret != addr\n");
abort();
}
return 0;
}
*/
import "C"
func mmapFixed(where []byte, fd int, prot int, flags int) error {
bp := (*reflect.SliceHeader)(unsafe.Pointer(&where))
errno := C.mmapFixed(C.int(fd), unsafe.Pointer(bp.Data), C.size_t(bp.Len), C.int(prot), C.int(flags))
if errno != 0 {
return syscall.Errno(errno)
}
return nil
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment