Skip to content

Commit c94cb2f

Browse files
committed
perf(vfs,mount2): remove redundant readdir sort
POSIX/FUSE do not require sorted readdir output. The mount2 sort was a workaround for an Emby metadata refresh bug (now fixed). ReadDirAll's sort duplicated list.DirSorted's earlier sort. Signed-off-by: Anagh Kumar Baranwal <6824881+darthShadow@users.noreply.github.com>
1 parent c0e5633 commit c94cb2f

File tree

5 files changed

+23
-16
lines changed

5 files changed

+23
-16
lines changed

cmd/cmount/fs.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,9 @@ func (fsys *FS) Readdir(dirPath string,
221221
return -fuse.ESPIPE
222222
}
223223

224-
nodes, err := dir.ReadDirAll()
224+
// POSIX/FUSE readdir does not require sorted output, so use MapReadDir
225+
// directly to avoid ReadDirAll sorting overhead in mount paths.
226+
nodes, err := vfs.MapReadDir[vfs.Node](dir, func(n vfs.Node) (vfs.Node, error) { return n, nil }, 0)
225227
if err != nil {
226228
return translateError(err)
227229
}

cmd/mount/dir.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,9 @@ var _ fusefs.HandleReadDirAller = (*Dir)(nil)
105105
func (d *Dir) ReadDirAll(ctx context.Context) (dirents []fuse.Dirent, err error) {
106106
itemsRead := -1
107107
defer log.Trace(d, "")("item=%d, err=%v", &itemsRead, &err)
108-
items, err := d.Dir.ReadDirAll()
108+
// POSIX/FUSE readdir does not require sorted output, so use MapReadDir
109+
// directly to avoid ReadDirAll sorting overhead in mount paths.
110+
items, err := vfs.MapReadDir[vfs.Node](d.Dir, func(n vfs.Node) (vfs.Node, error) { return n, nil }, 0)
109111
if err != nil {
110112
return nil, translateError(err)
111113
}

cmd/mount2/node.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import (
66
"context"
77
"os"
88
"path"
9-
"slices"
10-
"strings"
119
"syscall"
1210

1311
fusefs "github.com/hanwen/go-fuse/v2/fs"
@@ -292,9 +290,13 @@ func (n *Node) Readdir(ctx context.Context) (ds fusefs.DirStream, errno syscall.
292290
Name: "..",
293291
Ino: 0, // FIXME
294292
}
295-
slices.SortFunc(items, func(a, b fuse.DirEntry) int {
296-
return strings.Compare(a.Name, b.Name)
297-
})
293+
// Sort removed: Linux/POSIX readdir does not require sorted output.
294+
// Previously needed to work around an Emby metadata refresh bug
295+
// where unsorted listings caused spurious subtitle change detection.
296+
// Fixed in Emby: https://emby.media/community/topic/136349
297+
// slices.SortFunc(items, func(a, b fuse.DirEntry) int {
298+
// return strings.Compare(a.Name, b.Name)
299+
// })
298300
return fusefs.NewListDirStream(items), 0
299301
}
300302

vfs/dir.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,14 +1163,16 @@ func (d *Dir) Stat(name string) (node Node, err error) {
11631163
return node, nil
11641164
}
11651165

1166-
// ReadDirAll reads the contents of the directory sorted
1166+
// ReadDirAll reads the contents of the directory sorted by name.
11671167
func (d *Dir) ReadDirAll() (items Nodes, err error) {
11681168
items, err = MapReadDir(d, func(n Node) (Node, error) { return n, nil }, 0)
11691169
if err != nil {
11701170
fs.Debugf(d.Path(), "Dir.ReadDirAll error: %v", err)
11711171
return nil, err
11721172
}
1173-
// Compare only the leaf strings of the nodes
1173+
// POSIX/FUSE readdir does not require sorted output, but ReadDirAll keeps
1174+
// deterministic ordering for general callers. Mount paths that need to skip
1175+
// this O(n log n) sort should call MapReadDir directly.
11741176
slices.SortFunc(items, func(a, b Node) int {
11751177
return strings.Compare(a.Name(), b.Name())
11761178
})

vfs/dir_handle_test.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,17 @@ func TestDirHandleReaddir(t *testing.T) {
7676
assert.False(t, fis[0].IsDir())
7777
assert.False(t, fis[1].IsDir())
7878

79-
fis, err = fh.Readdir(2)
79+
fis2, err := fh.Readdir(2)
8080
require.NoError(t, err)
81-
require.Equal(t, 1, len(fis))
82-
assert.Equal(t, "subdir", fis[0].Name())
83-
assert.True(t, fis[0].IsDir())
81+
require.Equal(t, 1, len(fis2))
82+
assert.Equal(t, "subdir", fis2[0].Name())
83+
assert.True(t, fis2[0].IsDir())
8484

85-
fis, err = fh.Readdir(2)
85+
fis3, err := fh.Readdir(2)
8686
assert.Equal(t, io.EOF, err)
87-
require.Equal(t, 0, len(fis))
87+
require.Equal(t, 0, len(fis3))
8888

8989
require.NoError(t, fh.Close())
90-
9190
}
9291

9392
func TestDirHandleReaddirnames(t *testing.T) {

0 commit comments

Comments
 (0)