Pass OpenFlags for OpenFileOp followups (#129)
parent
9cc4ff0bc9
commit
226fec2ce9
|
@ -299,11 +299,10 @@ func convertInMessage(
|
|||
if in == nil {
|
||||
return nil, errors.New("Corrupt OpOpen")
|
||||
}
|
||||
openFlags := fusekernel.OpenFlags(in.Flags)
|
||||
|
||||
o = &fuseops.OpenFileOp{
|
||||
Inode: fuseops.InodeID(inMsg.Header().Nodeid),
|
||||
OpenFlags: &openFlags,
|
||||
OpenFlags: fusekernel.OpenFlags(in.Flags),
|
||||
OpContext: fuseops.OpContext{Pid: inMsg.Header().Pid},
|
||||
}
|
||||
|
||||
|
|
|
@ -648,7 +648,7 @@ type OpenFileOp struct {
|
|||
// advance, for example, because contents are generated on the fly.
|
||||
UseDirectIO bool
|
||||
|
||||
OpenFlags *fusekernel.OpenFlags
|
||||
OpenFlags fusekernel.OpenFlags
|
||||
|
||||
OpContext OpContext
|
||||
}
|
||||
|
|
|
@ -33,6 +33,10 @@ type inode struct {
|
|||
// Mutable state
|
||||
/////////////////////////
|
||||
|
||||
// Name of the inode, only contains relative path.
|
||||
// For example, if the full path for an inode is /foo/bar/f1, its name is f1.
|
||||
name string
|
||||
|
||||
// The current attributes of this inode.
|
||||
//
|
||||
// INVARIANT: attrs.Mode &^ (os.ModePerm|os.ModeDir|os.ModeSymlink) == 0
|
||||
|
@ -73,7 +77,7 @@ type inode struct {
|
|||
|
||||
// Create a new inode with the supplied attributes, which need not contain
|
||||
// time-related information (the inode object will take care of that).
|
||||
func newInode(attrs fuseops.InodeAttributes) *inode {
|
||||
func newInode(attrs fuseops.InodeAttributes, name string) *inode {
|
||||
// Update time info.
|
||||
now := time.Now()
|
||||
attrs.Mtime = now
|
||||
|
@ -81,6 +85,7 @@ func newInode(attrs fuseops.InodeAttributes) *inode {
|
|||
|
||||
// Create the object.
|
||||
return &inode{
|
||||
name: name,
|
||||
attrs: attrs,
|
||||
xattrs: make(map[string][]byte),
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ package memfs
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
@ -29,6 +30,11 @@ import (
|
|||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
FileOpenFlagsXattrName = "fileOpenFlagsXattr"
|
||||
CheckFileOpenFlagsFileName = "checkFileOpenFlags"
|
||||
)
|
||||
|
||||
type memFS struct {
|
||||
fuseutil.NotImplementedFileSystem
|
||||
|
||||
|
@ -85,7 +91,7 @@ func NewMemFS(
|
|||
Gid: gid,
|
||||
}
|
||||
|
||||
fs.inodes[fuseops.RootInodeID] = newInode(rootAttrs)
|
||||
fs.inodes[fuseops.RootInodeID] = newInode(rootAttrs, "")
|
||||
|
||||
// Set up invariant checking.
|
||||
fs.mu = syncutil.NewInvariantMutex(fs.checkInvariants)
|
||||
|
@ -157,9 +163,9 @@ func (fs *memFS) getInodeOrDie(id fuseops.InodeID) *inode {
|
|||
//
|
||||
// LOCKS_REQUIRED(fs.mu)
|
||||
func (fs *memFS) allocateInode(
|
||||
attrs fuseops.InodeAttributes) (id fuseops.InodeID, inode *inode) {
|
||||
attrs fuseops.InodeAttributes, name string) (id fuseops.InodeID, inode *inode) {
|
||||
// Create the inode.
|
||||
inode = newInode(attrs)
|
||||
inode = newInode(attrs, name)
|
||||
|
||||
// Re-use a free ID if possible. Otherwise mint a new one.
|
||||
numFree := len(fs.freeInodes)
|
||||
|
@ -310,7 +316,7 @@ func (fs *memFS) MkDir(
|
|||
}
|
||||
|
||||
// Allocate a child.
|
||||
childID, child := fs.allocateInode(childAttrs)
|
||||
childID, child := fs.allocateInode(childAttrs, op.Name)
|
||||
|
||||
// Add an entry in the parent.
|
||||
parent.AddChild(childID, op.Name, fuseutil.DT_Directory)
|
||||
|
@ -371,7 +377,7 @@ func (fs *memFS) createFile(
|
|||
}
|
||||
|
||||
// Allocate a child.
|
||||
childID, child := fs.allocateInode(childAttrs)
|
||||
childID, child := fs.allocateInode(childAttrs, name)
|
||||
|
||||
// Add an entry in the parent.
|
||||
parent.AddChild(childID, name, fuseutil.DT_File)
|
||||
|
@ -438,7 +444,7 @@ func (fs *memFS) CreateSymlink(
|
|||
}
|
||||
|
||||
// Allocate a child.
|
||||
childID, child := fs.allocateInode(childAttrs)
|
||||
childID, child := fs.allocateInode(childAttrs, op.Name)
|
||||
|
||||
// Set up its target.
|
||||
child.target = op.Target
|
||||
|
@ -661,9 +667,6 @@ func (fs *memFS) OpenFile(
|
|||
// OpenFileOp should have a valid pid in context.
|
||||
return fuse.EINVAL
|
||||
}
|
||||
if op.OpenFlags == nil {
|
||||
return fuse.EINVAL
|
||||
}
|
||||
|
||||
fs.mu.Lock()
|
||||
defer fs.mu.Unlock()
|
||||
|
@ -677,6 +680,21 @@ func (fs *memFS) OpenFile(
|
|||
panic("Found non-file.")
|
||||
}
|
||||
|
||||
if inode.name == CheckFileOpenFlagsFileName {
|
||||
// For testing purpose only.
|
||||
// Set attribute (name=fileOpenFlagsXattr, value=OpenFlags) to test whether
|
||||
// we set OpenFlags correctly. The value is checked in test with getXattr.
|
||||
value := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(value, uint32(op.OpenFlags))
|
||||
err := fs.setXattrHelper(inode, &fuseops.SetXattrOp{
|
||||
Name: FileOpenFlagsXattrName,
|
||||
Value: value,
|
||||
})
|
||||
if err != nil {
|
||||
panic("unable to set fileOpenFlagsXattr")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -832,6 +850,11 @@ func (fs *memFS) SetXattr(ctx context.Context,
|
|||
defer fs.mu.Unlock()
|
||||
inode := fs.getInodeOrDie(op.Inode)
|
||||
|
||||
return fs.setXattrHelper(inode, op)
|
||||
}
|
||||
|
||||
// Required to hold fs.mu
|
||||
func (fs *memFS) setXattrHelper(inode *inode, op *fuseops.SetXattrOp) error {
|
||||
_, ok := inode.xattrs[op.Name]
|
||||
|
||||
switch op.Flags {
|
||||
|
|
|
@ -16,6 +16,7 @@ package memfs_test
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
@ -31,6 +32,7 @@ import (
|
|||
fallocate "github.com/detailyang/go-fallocate"
|
||||
"github.com/jacobsa/fuse"
|
||||
"github.com/jacobsa/fuse/fusetesting"
|
||||
"github.com/jacobsa/fuse/internal/fusekernel"
|
||||
"github.com/jacobsa/fuse/samples"
|
||||
"github.com/jacobsa/fuse/samples/memfs"
|
||||
. "github.com/jacobsa/oglematchers"
|
||||
|
@ -88,6 +90,15 @@ func applyUmask(m os.FileMode) os.FileMode {
|
|||
return m &^ os.FileMode(umask)
|
||||
}
|
||||
|
||||
func (t *MemFSTest) checkOpenFlagsXattr(
|
||||
fileName string, expectedOpenFlags fusekernel.OpenFlags) {
|
||||
dest := make([]byte, 4)
|
||||
_, err := unix.Getxattr(fileName, memfs.FileOpenFlagsXattrName, dest)
|
||||
AssertEq(nil, err)
|
||||
openFlags := binary.LittleEndian.Uint32(dest)
|
||||
AssertEq(openFlags, uint32(expectedOpenFlags))
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Boilerplate
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
@ -292,7 +303,7 @@ func (t *MemFSTest) CreateNewFile_InRoot() {
|
|||
var stat *syscall.Stat_t
|
||||
|
||||
// Write a file.
|
||||
fileName := path.Join(t.Dir, "foo")
|
||||
fileName := path.Join(t.Dir, memfs.CheckFileOpenFlagsFileName)
|
||||
const contents = "Hello\x00world"
|
||||
|
||||
createTime := time.Now()
|
||||
|
@ -304,7 +315,7 @@ func (t *MemFSTest) CreateNewFile_InRoot() {
|
|||
stat = fi.Sys().(*syscall.Stat_t)
|
||||
|
||||
AssertEq(nil, err)
|
||||
ExpectEq("foo", fi.Name())
|
||||
ExpectEq(memfs.CheckFileOpenFlagsFileName, fi.Name())
|
||||
ExpectEq(len(contents), fi.Size())
|
||||
ExpectEq(applyUmask(0400), fi.Mode())
|
||||
ExpectThat(fi, fusetesting.MtimeIsWithin(createTime, timeSlop))
|
||||
|
@ -321,6 +332,7 @@ func (t *MemFSTest) CreateNewFile_InRoot() {
|
|||
slice, err := ioutil.ReadFile(fileName)
|
||||
AssertEq(nil, err)
|
||||
ExpectEq(contents, string(slice))
|
||||
t.checkOpenFlagsXattr(fileName, fusekernel.OpenReadOnly)
|
||||
}
|
||||
|
||||
func (t *MemFSTest) CreateNewFile_InSubDir() {
|
||||
|
@ -372,7 +384,7 @@ func (t *MemFSTest) ModifyExistingFile_InRoot() {
|
|||
var stat *syscall.Stat_t
|
||||
|
||||
// Write a file.
|
||||
fileName := path.Join(t.Dir, "foo")
|
||||
fileName := path.Join(t.Dir, memfs.CheckFileOpenFlagsFileName)
|
||||
|
||||
createTime := time.Now()
|
||||
err = ioutil.WriteFile(fileName, []byte("Hello, world!"), 0600)
|
||||
|
@ -382,6 +394,7 @@ func (t *MemFSTest) ModifyExistingFile_InRoot() {
|
|||
f, err := os.OpenFile(fileName, os.O_WRONLY, 0400)
|
||||
t.ToClose = append(t.ToClose, f)
|
||||
AssertEq(nil, err)
|
||||
t.checkOpenFlagsXattr(fileName, fusekernel.OpenWriteOnly)
|
||||
|
||||
modifyTime := time.Now()
|
||||
n, err = f.WriteAt([]byte("H"), 0)
|
||||
|
@ -393,7 +406,7 @@ func (t *MemFSTest) ModifyExistingFile_InRoot() {
|
|||
stat = fi.Sys().(*syscall.Stat_t)
|
||||
|
||||
AssertEq(nil, err)
|
||||
ExpectEq("foo", fi.Name())
|
||||
ExpectEq(memfs.CheckFileOpenFlagsFileName, fi.Name())
|
||||
ExpectEq(len("Hello, world!"), fi.Size())
|
||||
ExpectEq(applyUmask(0600), fi.Mode())
|
||||
ExpectThat(fi, fusetesting.MtimeIsWithin(modifyTime, timeSlop))
|
||||
|
@ -410,6 +423,7 @@ func (t *MemFSTest) ModifyExistingFile_InRoot() {
|
|||
slice, err := ioutil.ReadFile(fileName)
|
||||
AssertEq(nil, err)
|
||||
ExpectEq("Hello, world!", string(slice))
|
||||
t.checkOpenFlagsXattr(fileName, fusekernel.OpenReadOnly)
|
||||
}
|
||||
|
||||
func (t *MemFSTest) ModifyExistingFile_InSubDir() {
|
||||
|
@ -832,7 +846,7 @@ func (t *MemFSTest) AppendMode() {
|
|||
buf := make([]byte, 1024)
|
||||
|
||||
// Create a file with some contents.
|
||||
fileName := path.Join(t.Dir, "foo")
|
||||
fileName := path.Join(t.Dir, memfs.CheckFileOpenFlagsFileName)
|
||||
err = ioutil.WriteFile(fileName, []byte("Jello, "), 0600)
|
||||
AssertEq(nil, err)
|
||||
|
||||
|
@ -840,6 +854,7 @@ func (t *MemFSTest) AppendMode() {
|
|||
f, err := os.OpenFile(fileName, os.O_RDWR|os.O_APPEND, 0600)
|
||||
t.ToClose = append(t.ToClose, f)
|
||||
AssertEq(nil, err)
|
||||
t.checkOpenFlagsXattr(fileName, fusekernel.OpenReadWrite)
|
||||
|
||||
// Seek to somewhere silly and then write.
|
||||
off, err = f.Seek(2, 0)
|
||||
|
@ -907,7 +922,7 @@ func (t *MemFSTest) ReadsPastEndOfFile() {
|
|||
|
||||
func (t *MemFSTest) Truncate_Smaller() {
|
||||
var err error
|
||||
fileName := path.Join(t.Dir, "foo")
|
||||
fileName := path.Join(t.Dir, memfs.CheckFileOpenFlagsFileName)
|
||||
|
||||
// Create a file.
|
||||
err = ioutil.WriteFile(fileName, []byte("taco"), 0600)
|
||||
|
@ -917,6 +932,7 @@ func (t *MemFSTest) Truncate_Smaller() {
|
|||
f, err := os.OpenFile(fileName, os.O_RDWR, 0)
|
||||
t.ToClose = append(t.ToClose, f)
|
||||
AssertEq(nil, err)
|
||||
t.checkOpenFlagsXattr(fileName, fusekernel.OpenReadWrite)
|
||||
|
||||
// Truncate it.
|
||||
err = f.Truncate(2)
|
||||
|
@ -931,6 +947,7 @@ func (t *MemFSTest) Truncate_Smaller() {
|
|||
contents, err := ioutil.ReadFile(fileName)
|
||||
AssertEq(nil, err)
|
||||
ExpectEq("ta", string(contents))
|
||||
t.checkOpenFlagsXattr(fileName, fusekernel.OpenReadOnly)
|
||||
}
|
||||
|
||||
func (t *MemFSTest) Truncate_SameSize() {
|
||||
|
|
Loading…
Reference in New Issue