From 5cf906e3ada5e51f9a0fe9b60d768e08491b69a0 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 16 Mar 2015 11:34:48 +1100 Subject: [PATCH 1/3] Declared a choke point for fixing expiration times. --- server.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/server.go b/server.go index 8e63280..dc28ccb 100644 --- a/server.go +++ b/server.go @@ -18,6 +18,7 @@ import ( "fmt" "io" "log" + "time" "github.com/jacobsa/gcsfuse/timeutil" "golang.org/x/net/context" @@ -43,6 +44,10 @@ func newServer(fs FileSystem) (s *server, err error) { return } +// Convert an absolute cache expiration time to a relative time from now for +// consumption by fuse. +func convertExpirationTime(t time.Time) time.Duration + func convertChildInodeEntry( clock timeutil.Clock, in *ChildInodeEntry, @@ -50,8 +55,8 @@ func convertChildInodeEntry( out.Node = bazilfuse.NodeID(in.Child) out.Generation = uint64(in.Generation) out.Attr = convertAttributes(in.Child, in.Attributes) - out.AttrValid = in.AttributesExpiration.Sub(clock.Now()) - out.EntryValid = in.EntryExpiration.Sub(clock.Now()) + out.AttrValid = convertExpirationTime(in.AttributesExpiration) + out.EntryValid = convertExpirationTime(in.EntryExpiration) } func convertHeader( @@ -165,7 +170,7 @@ func (s *server) handleFuseRequest(fuseReq bazilfuse.Request) { // Convert the response. fuseResp := &bazilfuse.GetattrResponse{ Attr: convertAttributes(req.Inode, resp.Attributes), - AttrValid: resp.AttributesExpiration.Sub(s.clock.Now()), + AttrValid: convertExpirationTime(resp.AttributesExpiration), } s.logger.Println("Responding:", fuseResp) @@ -205,7 +210,7 @@ func (s *server) handleFuseRequest(fuseReq bazilfuse.Request) { // Convert the response. fuseResp := &bazilfuse.SetattrResponse{ Attr: convertAttributes(req.Inode, resp.Attributes), - AttrValid: resp.AttributesExpiration.Sub(s.clock.Now()), + AttrValid: convertExpirationTime(resp.AttributesExpiration), } s.logger.Println("Responding:", fuseResp) From c73fe395269e6f8cbe2f776883269ac201b6f47b Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 16 Mar 2015 11:35:11 +1100 Subject: [PATCH 2/3] Removed server.clock. Its presence was confusing because it is never anything but the real clock. --- server.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/server.go b/server.go index dc28ccb..44d45b6 100644 --- a/server.go +++ b/server.go @@ -20,7 +20,6 @@ import ( "log" "time" - "github.com/jacobsa/gcsfuse/timeutil" "golang.org/x/net/context" bazilfuse "bazil.org/fuse" @@ -29,7 +28,6 @@ import ( // An object that terminates one end of the userspace <-> FUSE VFS connection. type server struct { logger *log.Logger - clock timeutil.Clock fs FileSystem } @@ -37,7 +35,6 @@ type server struct { func newServer(fs FileSystem) (s *server, err error) { s = &server{ logger: getLogger(), - clock: timeutil.RealClock(), fs: fs, } @@ -49,7 +46,6 @@ func newServer(fs FileSystem) (s *server, err error) { func convertExpirationTime(t time.Time) time.Duration func convertChildInodeEntry( - clock timeutil.Clock, in *ChildInodeEntry, out *bazilfuse.LookupResponse) { out.Node = bazilfuse.NodeID(in.Child) @@ -147,7 +143,7 @@ func (s *server) handleFuseRequest(fuseReq bazilfuse.Request) { // Convert the response. fuseResp := &bazilfuse.LookupResponse{} - convertChildInodeEntry(s.clock, &resp.Entry, fuseResp) + convertChildInodeEntry(&resp.Entry, fuseResp) s.logger.Println("Responding:", fuseResp) typed.Respond(fuseResp) @@ -235,7 +231,7 @@ func (s *server) handleFuseRequest(fuseReq bazilfuse.Request) { // Convert the response. fuseResp := &bazilfuse.MkdirResponse{} - convertChildInodeEntry(s.clock, &resp.Entry, &fuseResp.LookupResponse) + convertChildInodeEntry(&resp.Entry, &fuseResp.LookupResponse) s.logger.Println("Responding:", fuseResp) typed.Respond(fuseResp) @@ -264,7 +260,7 @@ func (s *server) handleFuseRequest(fuseReq bazilfuse.Request) { Handle: bazilfuse.HandleID(resp.Handle), }, } - convertChildInodeEntry(s.clock, &resp.Entry, &fuseResp.LookupResponse) + convertChildInodeEntry(&resp.Entry, &fuseResp.LookupResponse) s.logger.Println("Responding:", fuseResp) typed.Respond(fuseResp) From 7e4aefc8dbd475431296f160ca5ef146c28309a1 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Mon, 16 Mar 2015 11:40:01 +1100 Subject: [PATCH 3/3] Implemented convertExpirationTime. --- server.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/server.go b/server.go index 44d45b6..173df74 100644 --- a/server.go +++ b/server.go @@ -43,7 +43,22 @@ func newServer(fs FileSystem) (s *server, err error) { // Convert an absolute cache expiration time to a relative time from now for // consumption by fuse. -func convertExpirationTime(t time.Time) time.Duration +func convertExpirationTime(t time.Time) (d time.Duration) { + // Fuse represents durations as unsigned 64-bit counts of seconds and 32-bit + // counts of nanoseconds (cf. http://goo.gl/EJupJV). The bazil.org/fuse + // package converts time.Duration values to this form in a straightforward + // way (cf. http://goo.gl/FJhV8j). + // + // So negative durations are right out. There is no need to cap the positive + // magnitude, because 2^64 seconds is well longer than the 2^63 ns range of + // time.Duration. + d = t.Sub(time.Now()) + if d < 0 { + d = 0 + } + + return +} func convertChildInodeEntry( in *ChildInodeEntry,