Commit d2167925 authored by Jakob Unterwurzacher's avatar Jakob Unterwurzacher

loopback: use futimens to implement the Utimens FUSE call

Futimes only takes microsecond resolution while the FUSE call
Utimens wants nanosecond precision. Switch from Futimes to futimens.

This is why UTIME_OMIT did not work - this change fixes the failure
of xfstests generic/221 (issue #60).
parent fa19882f
...@@ -204,34 +204,23 @@ func (f *loopbackFile) GetAttr(a *fuse.Attr) fuse.Status { ...@@ -204,34 +204,23 @@ func (f *loopbackFile) GetAttr(a *fuse.Attr) fuse.Status {
const _UTIME_NOW = ((1 << 30) - 1) const _UTIME_NOW = ((1 << 30) - 1)
const _UTIME_OMIT = ((1 << 30) - 2) const _UTIME_OMIT = ((1 << 30) - 2)
// timeToTimeval - Convert time.Time to syscall.Timeval
//
// Note: This does not use syscall.NsecToTimespec because
// that does not work properly for times before 1970,
// see https://github.com/golang/go/issues/12777
func timeToTimeval(t *time.Time) syscall.Timeval {
var tv syscall.Timeval
tv.Usec = int64(t.Nanosecond() / 1000)
tv.Sec = t.Unix()
return tv
}
func (f *loopbackFile) Utimens(a *time.Time, m *time.Time) fuse.Status { func (f *loopbackFile) Utimens(a *time.Time, m *time.Time) fuse.Status {
tv := make([]syscall.Timeval, 2) var ts [2]syscall.Timespec
if a == nil { if a == nil {
tv[0].Usec = _UTIME_OMIT ts[0].Nsec = _UTIME_OMIT
} else { } else {
tv[0] = timeToTimeval(a) ts[0].Sec = a.Unix()
} }
if m == nil { if m == nil {
tv[1].Usec = _UTIME_OMIT ts[1].Nsec = _UTIME_OMIT
} else { } else {
tv[1] = timeToTimeval(m) ts[1].Sec = m.Unix()
} }
f.lock.Lock() f.lock.Lock()
err := syscall.Futimes(int(f.File.Fd()), tv) err := futimens(int(f.File.Fd()), &ts)
f.lock.Unlock() f.lock.Unlock()
return fuse.ToStatus(err) return fuse.ToStatus(err)
} }
......
package nodefs
import (
"testing"
"time"
)
func TestTimeToTimeval(t *testing.T) {
// Check that dates before 1970 are handled correctly
date := time.Date(1960, time.January, 1, 23, 16, 44, 650951, time.UTC)
tv := timeToTimeval(&date)
if tv.Sec != -315535396 || tv.Usec != 650 {
t.Errorf("got timeval %v, want (-315535396, 650)", tv)
}
// Check recent date
date = time.Date(2015, time.September, 29, 20, 8, 7, 74522, time.UTC)
tv = timeToTimeval(&date)
if tv.Sec != 1443557287 || tv.Usec != 74 {
t.Errorf("got timeval %v, want (1443557287, 74)", tv)
}
}
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