Skip to content

Commit

Permalink
fuse: Print debug flags in stable order
Browse files Browse the repository at this point in the history
This helps to compare fuse logs of e.g. different test runs. For example
below are two INIT messages with the same flags, but formatted, before
hereby patch, differently:

     rx 2: INIT n0 {7.37 Ra 131072 EXPORT_SUPPORT,SPLICE_READ,AUTO_INVAL_DATA,ASYNC_DIO,WRITEBACK_CACHE,BIG_WRITES,NO_OPEN_SUPPORT,PARALLEL_DIROPS,POSIX_ACL,EXPLICIT_INVAL_DATA,NO_OPENDIR_SUPPORT,ASYNC_READ,DONT_MASK,SPLICE_MOVE,IOCTL_DIR,READDIRPLUS,READDIRPLUS_AUTO,HANDLE_KILLPRIV,POSIX_LOCKS,ATOMIC_O_TRUNC,SPLICE_WRITE,FLOCK_LOCKS,ABORT_ERROR,MAX_PAGES,CACHE_SYMLINKS,0x70000000} "\x03\x00\x00\x00\x00\x00\x00\x00"... 48b

     rx 2: INIT n0 {7.37 Ra 131072 EXPORT_SUPPORT,SPLICE_READ,AUTO_INVAL_DATA,ASYNC_DIO,WRITEBACK_CACHE,BIG_WRITES,NO_OPEN_SUPPORT,PARALLEL_DIROPS,POSIX_ACL,EXPLICIT_INVAL_DATA,ASYNC_READ,DONT_MASK,SPLICE_MOVE,IOCTL_DIR,READDIRPLUS,READDIRPLUS_AUTO,HANDLE_KILLPRIV,NO_OPENDIR_SUPPORT,POSIX_LOCKS,ATOMIC_O_TRUNC,SPLICE_WRITE,FLOCK_LOCKS,ABORT_ERROR,MAX_PAGES,CACHE_SYMLINKS,0x70000000} "\x03\x00\x00\x00\x00\x00\x00\x00"... 48b

which leads to corresponding lines to be present in the diff and
requires human attention to verify that the messages are really the
same.

After this patch above INIT always formats as

     rx 2: INIT n0 {7.37 Ra 131072 ASYNC_READ,POSIX_LOCKS,ATOMIC_O_TRUNC,EXPORT_SUPPORT,BIG_WRITES,DONT_MASK,SPLICE_WRITE,SPLICE_MOVE,SPLICE_READ,FLOCK_LOCKS,IOCTL_DIR,AUTO_INVAL_DATA,READDIRPLUS,READDIRPLUS_AUTO,ASYNC_DIO,WRITEBACK_CACHE,NO_OPEN_SUPPORT,PARALLEL_DIROPS,HANDLE_KILLPRIV,POSIX_ACL,ABORT_ERROR,MAX_PAGES,CACHE_SYMLINKS,NO_OPENDIR_SUPPORT,EXPLICIT_INVAL_DATA,0x70000000} "\x03\x00\x00\x00\x00\x00\x00\x00"... 48b

and the diff log does not unnecessarily distract attention to it.

flagString is used for many messages, this fix should benefit all of
them.

Change-Id: Id4bdab9dd90552313ede41a3b9a6c337588e4b3e
  • Loading branch information
navytux authored and hanwen committed Jun 16, 2023
1 parent 9836d61 commit d5638ff
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 27 deletions.
85 changes: 64 additions & 21 deletions fuse/print.go
Expand Up @@ -12,14 +12,14 @@ import (
)

var (
writeFlagNames = map[int64]string{
writeFlagNames = newFlagNames(map[int64]string{
WRITE_CACHE: "CACHE",
WRITE_LOCKOWNER: "LOCKOWNER",
}
readFlagNames = map[int64]string{
})
readFlagNames = newFlagNames(map[int64]string{
READ_LOCKOWNER: "LOCKOWNER",
}
initFlagNames = map[int64]string{
})
initFlagNames = newFlagNames(map[int64]string{
CAP_ASYNC_READ: "ASYNC_READ",
CAP_POSIX_LOCKS: "POSIX_LOCKS",
CAP_FILE_OPS: "FILE_OPS",
Expand All @@ -46,11 +46,11 @@ var (
CAP_CACHE_SYMLINKS: "CACHE_SYMLINKS",
CAP_NO_OPENDIR_SUPPORT: "NO_OPENDIR_SUPPORT",
CAP_EXPLICIT_INVAL_DATA: "EXPLICIT_INVAL_DATA",
}
releaseFlagNames = map[int64]string{
})
releaseFlagNames = newFlagNames(map[int64]string{
RELEASE_FLUSH: "FLUSH",
}
openFlagNames = map[int64]string{
})
openFlagNames = newFlagNames(map[int64]string{
int64(os.O_WRONLY): "WRONLY",
int64(os.O_RDWR): "RDWR",
int64(os.O_APPEND): "APPEND",
Expand All @@ -64,30 +64,73 @@ var (

int64(syscall.O_CLOEXEC): "CLOEXEC",
int64(syscall.O_DIRECTORY): "DIRECTORY",
}
fuseOpenFlagNames = map[int64]string{
})
fuseOpenFlagNames = newFlagNames(map[int64]string{
FOPEN_DIRECT_IO: "DIRECT",
FOPEN_KEEP_CACHE: "CACHE",
FOPEN_NONSEEKABLE: "NONSEEK",
FOPEN_CACHE_DIR: "CACHE_DIR",
FOPEN_STREAM: "STREAM",
}
accessFlagName = map[int64]string{
})
accessFlagName = newFlagNames(map[int64]string{
X_OK: "x",
W_OK: "w",
R_OK: "r",
}
getAttrFlagNames = map[int64]string{
})
getAttrFlagNames = newFlagNames(map[int64]string{
FUSE_GETATTR_FH: "FH",
}
})
)

func flagString(names map[int64]string, fl int64, def string) string {
// flagNames associate flag bits to their names.
type flagNames [64]flagNameEntry

// flagNameEntry describes one flag value.
//
// Usually a flag constitues only one bit, but, for example at least O_SYNC and
// O_TMPFILE are represented by a value with two bits set. To handle such
// situations we map all bits of a flag to the same flagNameEntry.
type flagNameEntry struct {
bits int64
name string
}

// newFlagNames creates flagNames from flag->name map.
func newFlagNames(names map[int64]string) *flagNames {
var v flagNames
for flag, name := range names {
v.set(flag, name)
}
return &v
}

// set associates flag value with name.
func (names *flagNames) set(flag int64, name string) {
entry := flagNameEntry{bits: flag, name: name}
for i := 0; i < 64; i++ {
if flag&(1<<i) != 0 {
if ie := names[i]; ie.bits != 0 {
panic(fmt.Sprintf("%s (%x) overlaps with %s (%x)", name, flag, ie.name, ie.bits))
}
names[i] = entry
}
}
}

func flagString(names *flagNames, fl int64, def string) string {
s := []string{}
for k, v := range names {
if fl&k != 0 {
s = append(s, v)
fl ^= k
// emit flags in their numeric order
for i := range names {
entry := &names[i]
if entry.bits == 0 {
continue
}
if fl&entry.bits == entry.bits {
s = append(s, entry.name)
fl ^= entry.bits
if fl == 0 {
break
}
}
}
if len(s) == 0 && def != "" {
Expand Down
6 changes: 3 additions & 3 deletions fuse/print_darwin.go
Expand Up @@ -9,9 +9,9 @@ import (
)

func init() {
initFlagNames[CAP_XTIMES] = "XTIMES"
initFlagNames[CAP_VOL_RENAME] = "VOL_RENAME"
initFlagNames[CAP_CASE_INSENSITIVE] = "CASE_INSENSITIVE"
initFlagNames.set(CAP_XTIMES, "XTIMES")
initFlagNames.set(CAP_VOL_RENAME, "VOL_RENAME")
initFlagNames.set(CAP_CASE_INSENSITIVE, "CASE_INSENSITIVE")
}

func (a *Attr) string() string {
Expand Down
6 changes: 3 additions & 3 deletions fuse/print_linux.go
Expand Up @@ -10,9 +10,9 @@ import (
)

func init() {
openFlagNames[syscall.O_DIRECT] = "DIRECT"
openFlagNames[syscall.O_LARGEFILE] = "LARGEFILE"
openFlagNames[syscall_O_NOATIME] = "NOATIME"
openFlagNames.set(syscall.O_DIRECT, "DIRECT")
openFlagNames.set(syscall.O_LARGEFILE, "LARGEFILE")
openFlagNames.set(syscall_O_NOATIME, "NOATIME")
}

func (a *Attr) string() string {
Expand Down
22 changes: 22 additions & 0 deletions fuse/print_test.go
@@ -0,0 +1,22 @@
// Copyright 2023 the Go-FUSE Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package fuse

import (
"testing"
)

// verify that flagString always formats flags in the same order.
func TestFlagStringOrder(t *testing.T) {
var flags int64 = CAP_ASYNC_READ | CAP_SPLICE_WRITE | CAP_READDIRPLUS | CAP_MAX_PAGES | CAP_EXPLICIT_INVAL_DATA
want := "ASYNC_READ,SPLICE_WRITE,READDIRPLUS,MAX_PAGES,EXPLICIT_INVAL_DATA"
// loop many times to check for sure the order is untied from map iteration order
for i := 0; i < 100; i++ {
have := flagString(initFlagNames, flags, "")
if have != want {
t.Fatalf("flagString:\nhave: %q\nwant: %q", have, want)
}
}
}

0 comments on commit d5638ff

Please sign in to comment.