From e665df71795a3a4656f6eae70211bb59723cd01e Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Sat, 17 Nov 2018 17:44:21 +0100 Subject: [PATCH] syscallcompat: downgrade DT_UNKNOWN message level on XFS Old XFS filesystems always return DT_UNKNOWN. Downgrade the message to "info" level if we are on XFS. Using the "warning" level means that users on old XFS filesystems cannot run the test suite as it intentionally aborts on any warnings. Fixes https://github.com/rfjakob/gocryptfs/issues/267 --- internal/syscallcompat/getdents_linux.go | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/internal/syscallcompat/getdents_linux.go b/internal/syscallcompat/getdents_linux.go index 1387023..3853f2d 100644 --- a/internal/syscallcompat/getdents_linux.go +++ b/internal/syscallcompat/getdents_linux.go @@ -123,6 +123,21 @@ func getdentsName(s unix.Dirent) (string, error) { var dtUnknownWarnOnce sync.Once +func dtUnknownWarn(dirfd int) { + const XFS_SUPER_MAGIC = 0x58465342 // From man 2 statfs + var buf syscall.Statfs_t + err := syscall.Fstatfs(dirfd, &buf) + if err == nil && buf.Type == XFS_SUPER_MAGIC { + // Old XFS filesystems always return DT_UNKNOWN. Downgrade the message + // to "info" level if we are on XFS. + // https://github.com/rfjakob/gocryptfs/issues/267 + tlog.Info.Printf("Getdents: convertDType: received DT_UNKNOWN, fstype=xfs, falling back to stat") + } else { + tlog.Warn.Printf("Getdents: convertDType: received DT_UNKNOWN, fstype=%#x, falling back to stat", + buf.Type) + } +} + // convertDType converts a Dirent.Type to at Stat_t.Mode value. func convertDType(dirfd int, name string, dtype uint8) (uint32, error) { if dtype != syscall.DT_UNKNOWN { @@ -130,9 +145,7 @@ func convertDType(dirfd int, name string, dtype uint8) (uint32, error) { return uint32(dtype) << 12, nil } // DT_UNKNOWN: we have to call stat() - dtUnknownWarnOnce.Do(func() { - tlog.Warn.Printf("Getdents: convertDType: received DT_UNKNOWN, falling back to stat") - }) + dtUnknownWarnOnce.Do(func() { dtUnknownWarn(dirfd) }) var st unix.Stat_t err := Fstatat(dirfd, name, &st, unix.AT_SYMLINK_NOFOLLOW) if err != nil {