mount: build the package on windows

Windows has no fcntl lock types, no O_ACCMODE and no x/sys/unix, so a
handful of constants kept weed/mount pinned to unix even though the code
using them is portable in-memory logic. Route them through per-OS shims
and give setBlksize a windows no-op.

The POSIX lock table now compiles on windows but stays unreachable:
WinFsp resolves byte-range locks in its own kernel driver, so nothing
will feed it there.

go.mod points at a go-fuse branch commit and needs repinning to a release
tag once that lands.
This commit is contained in:
Chris Lu
2026-08-03 00:50:25 -07:00
parent e768c45f79
commit b2e53d8035
10 changed files with 62 additions and 22 deletions
+1 -1
View File
@@ -148,7 +148,7 @@ require (
github.com/rdleal/intervalst v1.5.0
github.com/redis/go-redis/v9 v9.21.0
github.com/schollz/progressbar/v3 v3.19.1
github.com/seaweedfs/go-fuse/v2 v2.9.3
github.com/seaweedfs/go-fuse/v2 v2.9.4-0.20260803074752-bd46d45ccb3b
github.com/shirou/gopsutil/v4 v4.26.6
github.com/tarantool/go-option v1.1.0
github.com/tarantool/go-tarantool/v3 v3.0.0
+4
View File
@@ -1810,6 +1810,10 @@ github.com/seaweedfs/cockroachdb-parser v0.0.0-20260225204133-2f342c5ea564 h1:Tg
github.com/seaweedfs/cockroachdb-parser v0.0.0-20260225204133-2f342c5ea564/go.mod h1:JSKCh6uCHBz91lQYFYHCyTrSVIPge4SUFVn28iwMNB0=
github.com/seaweedfs/go-fuse/v2 v2.9.3 h1:rJufGrHImTx7yoGUmetUi+To4LrmTQJROJnBHWt92ic=
github.com/seaweedfs/go-fuse/v2 v2.9.3/go.mod h1:zABdmWEa6A0bwaBeEOBUeUkGIZlxUhcdv+V1Dcc/U/I=
github.com/seaweedfs/go-fuse/v2 v2.9.4-0.20260803073934-cb95bfebced6 h1:Kn79NPV77uc3bEat4RWi6vpNYNacYfjXcWBLNv3RZ2A=
github.com/seaweedfs/go-fuse/v2 v2.9.4-0.20260803073934-cb95bfebced6/go.mod h1:zABdmWEa6A0bwaBeEOBUeUkGIZlxUhcdv+V1Dcc/U/I=
github.com/seaweedfs/go-fuse/v2 v2.9.4-0.20260803074752-bd46d45ccb3b h1:ECjScJHzIATk8CTdlP+yfPY4W5bLxeoy1Mma8rd0dRA=
github.com/seaweedfs/go-fuse/v2 v2.9.4-0.20260803074752-bd46d45ccb3b/go.mod h1:zABdmWEa6A0bwaBeEOBUeUkGIZlxUhcdv+V1Dcc/U/I=
github.com/seaweedfs/goexif v1.0.3 h1:ve/OjI7dxPW8X9YQsv3JuVMaxEyF9Rvfd04ouL+Bz30=
github.com/seaweedfs/goexif v1.0.3/go.mod h1:Oni780Z236sXpIQzk1XoJlTwqrJ02smEin9zQeff7Fk=
github.com/seaweedfs/raft v1.2.0 h1:Ez4Hw9ifBbTT7wg54DvGHBjw1vRlTb4roH0TKl0Oj9Y=
+6 -7
View File
@@ -4,7 +4,6 @@ import (
"math"
"sort"
"sync"
"syscall"
"github.com/seaweedfs/go-fuse/v2/fuse"
)
@@ -13,7 +12,7 @@ import (
type lockRange struct {
Start uint64 // inclusive byte offset
End uint64 // inclusive; math.MaxUint64 means "to EOF"
Typ uint32 // syscall.F_RDLCK or syscall.F_WRLCK
Typ uint32 // f_RDLCK or f_WRLCK
Owner uint64 // FUSE lock owner (from LkIn.Owner)
Pid uint32 // PID of lock holder (for GetLk reporting)
// flock and fcntl locks have different ownership and close semantics.
@@ -127,7 +126,7 @@ func findConflict(locks []lockRange, proposed lockRange) (lockRange, bool) {
if !rangesOverlap(h.Start, h.End, proposed.Start, proposed.End) {
continue
}
if h.Typ == syscall.F_RDLCK && proposed.Typ == syscall.F_RDLCK {
if h.Typ == f_RDLCK && proposed.Typ == f_RDLCK {
continue
}
return h, true
@@ -304,7 +303,7 @@ func (plt *PosixLockTable) GetLk(inode uint64, proposed lockRange, out *fuse.LkO
for {
il := plt.getInodeLocks(inode)
if il == nil {
out.Lk.Typ = syscall.F_UNLCK
out.Lk.Typ = f_UNLCK
return
}
il.mu.Lock()
@@ -324,7 +323,7 @@ func (plt *PosixLockTable) GetLk(inode uint64, proposed lockRange, out *fuse.LkO
out.Lk.Typ = conflict.Typ
out.Lk.Pid = conflict.Pid
} else {
out.Lk.Typ = syscall.F_UNLCK
out.Lk.Typ = f_UNLCK
}
return
}
@@ -334,7 +333,7 @@ func (plt *PosixLockTable) GetLk(inode uint64, proposed lockRange, out *fuse.LkO
// For unlock (F_UNLCK): removes locks in the given range for the owner.
// For lock: returns fuse.EAGAIN if a conflict exists, fuse.OK on success.
func (plt *PosixLockTable) SetLk(inode uint64, lk lockRange) fuse.Status {
if lk.Typ == syscall.F_UNLCK {
if lk.Typ == f_UNLCK {
il := plt.getInodeLocks(inode)
if il == nil {
return fuse.OK
@@ -376,7 +375,7 @@ func (plt *PosixLockTable) SetLk(inode uint64, lk lockRange) fuse.Status {
// SetLkw attempts a blocking lock. It waits until the lock can be acquired
// or the cancel channel is closed.
func (plt *PosixLockTable) SetLkw(inode uint64, lk lockRange, cancel <-chan struct{}) fuse.Status {
if lk.Typ == syscall.F_UNLCK {
if lk.Typ == f_UNLCK {
return plt.SetLk(inode, lk)
}
+19
View File
@@ -0,0 +1,19 @@
//go:build !windows
package mount
import (
"syscall"
sys "golang.org/x/sys/unix"
)
const (
f_RDLCK = syscall.F_RDLCK
f_WRLCK = syscall.F_WRLCK
f_UNLCK = syscall.F_UNLCK
o_ACCMODE = syscall.O_ACCMODE
xattr_CREATE = sys.XATTR_CREATE
xattr_REPLACE = sys.XATTR_REPLACE
)
+14
View File
@@ -0,0 +1,14 @@
package mount
// Windows has no fcntl lock types and no access-mode mask. The Linux values
// stand in: nothing on Windows feeds these, and the lock table only ever
// compares them against each other.
const (
f_RDLCK = 0
f_WRLCK = 1
f_UNLCK = 2
o_ACCMODE = 0x3
xattr_CREATE = 1
xattr_REPLACE = 2
)
+1 -1
View File
@@ -155,7 +155,7 @@ func checkStickyBit(dirMode, dirUid, targetUid, callerUid uint32) fuse.Status {
// openFlagsToAccessMask converts open(2) flags to an access permission mask.
func openFlagsToAccessMask(flags uint32) uint32 {
switch flags & uint32(syscall.O_ACCMODE) {
switch flags & uint32(o_ACCMODE) {
case syscall.O_WRONLY:
return fuse.W_OK
case syscall.O_RDWR:
+8
View File
@@ -0,0 +1,8 @@
package mount
import (
"github.com/seaweedfs/go-fuse/v2/fuse"
)
func setBlksize(out *fuse.Attr, size uint32) {
}
+1 -3
View File
@@ -1,8 +1,6 @@
package mount
import (
"syscall"
"github.com/seaweedfs/go-fuse/v2/fuse"
)
@@ -56,7 +54,7 @@ func (wfs *WFS) SetLkw(cancel <-chan struct{}, in *fuse.LkIn) fuse.Status {
Pid: in.Lk.Pid,
IsFlock: in.LkFlags&fuse.FUSE_LK_FLOCK != 0,
}
if lk.Typ == syscall.F_UNLCK {
if lk.Typ == f_UNLCK {
return wfs.posixLocks.SetLk(in.NodeId, lk)
}
return wfs.posixLocks.SetLkw(in.NodeId, lk, cancel)
+6 -7
View File
@@ -6,7 +6,6 @@ import (
"encoding/hex"
"math/rand/v2"
"sync"
"syscall"
"time"
"github.com/seaweedfs/go-fuse/v2/fuse"
@@ -103,9 +102,9 @@ func (wfs *WFS) posixLockKeyForInode(inode uint64) (string, bool) {
func posixLockTypeToWire(typ uint32) uint32 {
switch typ {
case syscall.F_RDLCK:
case f_RDLCK:
return posixlock.Read
case syscall.F_WRLCK:
case f_WRLCK:
return posixlock.Write
default:
return posixlock.Unlock
@@ -115,11 +114,11 @@ func posixLockTypeToWire(typ uint32) uint32 {
func posixLockTypeFromWire(typ uint32) uint32 {
switch typ {
case posixlock.Read:
return syscall.F_RDLCK
return f_RDLCK
case posixlock.Write:
return syscall.F_WRLCK
return f_WRLCK
default:
return syscall.F_UNLCK
return f_UNLCK
}
}
@@ -186,7 +185,7 @@ func (wfs *WFS) routedGetLk(cancel <-chan struct{}, in *fuse.LkIn, out *fuse.LkO
out.Lk.Start, out.Lk.End, out.Lk.Pid = c.GetStart(), c.GetEnd(), c.GetPid()
out.Lk.Typ = posixLockTypeFromWire(c.GetType())
} else {
out.Lk.Typ = syscall.F_UNLCK
out.Lk.Typ = f_UNLCK
}
return fuse.OK
}
+2 -3
View File
@@ -8,7 +8,6 @@ import (
"syscall"
"github.com/seaweedfs/go-fuse/v2/fuse"
sys "golang.org/x/sys/unix"
)
const (
@@ -123,11 +122,11 @@ func (wfs *WFS) SetXAttr(cancel <-chan struct{}, input *fuse.SetXAttrIn, attr st
}
_, exists := entry.Extended[XATTR_PREFIX+attr]
switch input.Flags {
case sys.XATTR_CREATE:
case xattr_CREATE:
if exists {
return fuse.Status(syscall.EEXIST)
}
case sys.XATTR_REPLACE:
case xattr_REPLACE:
if !exists {
return fuse.ENODATA
}