Commit 720e8530 authored by Aaron Jacobs's avatar Aaron Jacobs

Fixed mtime tracking, tightened up other tests.

parents 96c65235 1828931c
...@@ -74,7 +74,7 @@ func NewMemFS( ...@@ -74,7 +74,7 @@ func NewMemFS(
Mode: 0700 | os.ModeDir, Mode: 0700 | os.ModeDir,
} }
fs.inodes[fuse.RootInodeID] = newInode(rootAttrs) fs.inodes[fuse.RootInodeID] = newInode(clock, rootAttrs)
// Set up invariant checking. // Set up invariant checking.
fs.mu = syncutil.NewInvariantMutex(fs.checkInvariants) fs.mu = syncutil.NewInvariantMutex(fs.checkInvariants)
...@@ -163,7 +163,7 @@ func (fs *memFS) getInodeForReadingOrDie(id fuse.InodeID) (inode *inode) { ...@@ -163,7 +163,7 @@ func (fs *memFS) getInodeForReadingOrDie(id fuse.InodeID) (inode *inode) {
func (fs *memFS) allocateInode( func (fs *memFS) allocateInode(
attrs fuse.InodeAttributes) (id fuse.InodeID, inode *inode) { attrs fuse.InodeAttributes) (id fuse.InodeID, inode *inode) {
// Create and lock the inode. // Create and lock the inode.
inode = newInode(attrs) inode = newInode(fs.clock, attrs)
inode.mu.Lock() inode.mu.Lock()
// Re-use a free ID if possible. Otherwise mint a new one. // Re-use a free ID if possible. Otherwise mint a new one.
...@@ -281,15 +281,10 @@ func (fs *memFS) MkDir( ...@@ -281,15 +281,10 @@ func (fs *memFS) MkDir(
// Set up attributes from the child, using the credentials of the calling // Set up attributes from the child, using the credentials of the calling
// process as owner (matching inode_init_owner, cf. http://goo.gl/5qavg8). // process as owner (matching inode_init_owner, cf. http://goo.gl/5qavg8).
now := fs.clock.Now()
childAttrs := fuse.InodeAttributes{ childAttrs := fuse.InodeAttributes{
Mode: req.Mode, Mode: req.Mode,
Atime: now, Uid: req.Header.Uid,
Mtime: now, Gid: req.Header.Gid,
Ctime: now,
Crtime: now,
Uid: req.Header.Uid,
Gid: req.Header.Gid,
} }
// Allocate a child. // Allocate a child.
......
...@@ -22,6 +22,7 @@ import ( ...@@ -22,6 +22,7 @@ import (
"github.com/jacobsa/fuse" "github.com/jacobsa/fuse"
"github.com/jacobsa/fuse/fuseutil" "github.com/jacobsa/fuse/fuseutil"
"github.com/jacobsa/gcloud/syncutil" "github.com/jacobsa/gcloud/syncutil"
"github.com/jacobsa/gcsfuse/timeutil"
) )
// Common attributes for files and directories. // Common attributes for files and directories.
...@@ -30,6 +31,12 @@ import ( ...@@ -30,6 +31,12 @@ import (
// been unlinked, including creating a new file. Make sure we don't screw up // been unlinked, including creating a new file. Make sure we don't screw up
// and reuse an inode ID while it is still in use. // and reuse an inode ID while it is still in use.
type inode struct { type inode struct {
/////////////////////////
// Dependencies
/////////////////////////
clock timeutil.Clock
///////////////////////// /////////////////////////
// Constant data // Constant data
///////////////////////// /////////////////////////
...@@ -84,9 +91,20 @@ type inode struct { ...@@ -84,9 +91,20 @@ type inode struct {
// Helpers // Helpers
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// Create a new inode with the supplied attributes, which need not contain
// time-related information (the inode object will take care of that).
// Initially the link count is one. // Initially the link count is one.
func newInode(attrs fuse.InodeAttributes) (in *inode) { func newInode(
clock timeutil.Clock,
attrs fuse.InodeAttributes) (in *inode) {
// Update time info.
now := clock.Now()
attrs.Mtime = now
attrs.Crtime = now
// Create the object.
in = &inode{ in = &inode{
clock: clock,
linkCount: 1, linkCount: 1,
dir: (attrs.Mode&os.ModeDir != 0), dir: (attrs.Mode&os.ModeDir != 0),
attributes: attrs, attributes: attrs,
...@@ -217,6 +235,9 @@ func (inode *inode) AddChild( ...@@ -217,6 +235,9 @@ func (inode *inode) AddChild(
dt fuseutil.DirentType) { dt fuseutil.DirentType) {
var index int var index int
// Update the modification time.
inode.attributes.Mtime = inode.clock.Now()
// No matter where we place the entry, make sure it has the correct Offset // No matter where we place the entry, make sure it has the correct Offset
// field. // field.
defer func() { defer func() {
...@@ -249,6 +270,9 @@ func (inode *inode) AddChild( ...@@ -249,6 +270,9 @@ func (inode *inode) AddChild(
// REQUIRES: An entry for the given name exists. // REQUIRES: An entry for the given name exists.
// EXCLUSIVE_LOCKS_REQUIRED(inode.mu) // EXCLUSIVE_LOCKS_REQUIRED(inode.mu)
func (inode *inode) RemoveChild(name string) { func (inode *inode) RemoveChild(name string) {
// Update the modification time.
inode.attributes.Mtime = inode.clock.Now()
// Find the entry. // Find the entry.
i, ok := inode.findChild(name) i, ok := inode.findChild(name)
if !ok { if !ok {
...@@ -324,6 +348,9 @@ func (inode *inode) WriteAt(p []byte, off int64) (n int, err error) { ...@@ -324,6 +348,9 @@ func (inode *inode) WriteAt(p []byte, off int64) (n int, err error) {
panic("WriteAt called on directory.") panic("WriteAt called on directory.")
} }
// Update the modification time.
inode.attributes.Mtime = inode.clock.Now()
// Ensure that the contents slice is long enough. // Ensure that the contents slice is long enough.
newLen := int(off) + len(p) newLen := int(off) + len(p)
if len(inode.contents) < newLen { if len(inode.contents) < newLen {
......
This diff is collapsed.
...@@ -218,6 +218,52 @@ func (t *PosixTest) WriteAtDoesntChangeOffset_AppendMode() { ...@@ -218,6 +218,52 @@ func (t *PosixTest) WriteAtDoesntChangeOffset_AppendMode() {
ExpectEq(4, offset) ExpectEq(4, offset)
} }
func (t *PosixTest) AppendMode() {
var err error
var n int
var off int64
buf := make([]byte, 1024)
// Create a file with some contents.
fileName := path.Join(t.dir, "foo")
err = ioutil.WriteFile(fileName, []byte("Jello, "), 0600)
AssertEq(nil, err)
// Open the file in append mode.
f, err := os.OpenFile(fileName, os.O_RDWR|os.O_APPEND, 0600)
t.toClose = append(t.toClose, f)
AssertEq(nil, err)
// Seek to somewhere silly and then write.
off, err = f.Seek(2, 0)
AssertEq(nil, err)
AssertEq(2, off)
n, err = f.Write([]byte("world!"))
AssertEq(nil, err)
AssertEq(6, n)
// The offset should have been updated to point at the end of the file.
off, err = getFileOffset(f)
AssertEq(nil, err)
ExpectEq(13, off)
// A random write should still work, without updating the offset.
n, err = f.WriteAt([]byte("H"), 0)
AssertEq(nil, err)
AssertEq(1, n)
off, err = getFileOffset(f)
AssertEq(nil, err)
ExpectEq(13, off)
// Read back the contents of the file, which should be correct even though we
// seeked to a silly place before writing the world part.
n, err = f.ReadAt(buf, 0)
AssertEq(io.EOF, err)
ExpectEq("Hello, world!", string(buf[:n]))
}
func (t *PosixTest) ReadsPastEndOfFile() { func (t *PosixTest) ReadsPastEndOfFile() {
var err error var err error
var n int var n int
......
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