mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-10-20 21:14:25 +02:00
refactor(filer): remove the inode->path index and the NFS gateway (#9724)
* fix(filer): derive inodes by hash instead of a snowflake sequencer
Compute the same inode the FUSE mount would: non-hard-linked entries hash path + crtime, hard links hash their shared HardLinkId so every link resolves to one inode. Removes the snowflake inodeSequencer and the SEAWEEDFS_FILER_SNOWFLAKE_ID knob; inodes are now deterministic across filers.
* chore: remove the experimental NFS gateway
The NFS frontend ('weed nfs') was the only consumer of the inode->path index. Remove the weed/server/nfs package, the command and its registration, the integration test harness, and the CI workflow; go mod tidy drops the willscott/go-nfs and go-nfs-client dependencies.
* refactor(filer): drop the inode->path index
With the NFS gateway gone, nothing reads it. A regular file's inode is a pure hash of its path and a hard link's is a hash of its shared HardLinkId -- both derivable on demand -- so the secondary KV index and its write/remove hooks are dead. Removes filer_inode_index.go and the recordInodeIndex hooks from the store wrapper.
This commit is contained in:
1 parent
3537312045
commit
dfd05d14cb
37 files changed
+64
-9247
No files matched your search
@@ -48,7 +48,6 @@ var Commands = []*Command{
|
||||
cmdVolume,
|
||||
cmdWebDav,
|
||||
cmdSftp,
|
||||
cmdNfs,
|
||||
cmdWorker,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/seaweedfs/seaweedfs/weed/glog"
|
||||
"github.com/seaweedfs/seaweedfs/weed/pb"
|
||||
"github.com/seaweedfs/seaweedfs/weed/security"
|
||||
weed_server_nfs "github.com/seaweedfs/seaweedfs/weed/server/nfs"
|
||||
"github.com/seaweedfs/seaweedfs/weed/util"
|
||||
"github.com/seaweedfs/seaweedfs/weed/util/version"
|
||||
)
|
||||
|
||||
var (
|
||||
nfsStandaloneOptions NfsOptions
|
||||
)
|
||||
|
||||
type NfsOptions struct {
|
||||
filer *string
|
||||
ipBind *string
|
||||
port *int
|
||||
filerRootPath *string
|
||||
readOnly *bool
|
||||
allowedClients *string
|
||||
volumeServerAccess *string
|
||||
portmapBind *string
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdNfs.Run = runNfs // break init cycle
|
||||
nfsStandaloneOptions.filer = cmdNfs.Flag.String("filer", "localhost:8888", "filer server address")
|
||||
nfsStandaloneOptions.ipBind = cmdNfs.Flag.String("ip.bind", "127.0.0.1", "ip address to bind to. Defaults to loopback; override explicitly to expose the experimental server to the network.")
|
||||
nfsStandaloneOptions.port = cmdNfs.Flag.Int("port", 2049, "NFS server listen port")
|
||||
nfsStandaloneOptions.filerRootPath = cmdNfs.Flag.String("filer.path", "", "remote path from filer server to export. Required: no default is provided so operators must opt in to exporting a namespace subtree.")
|
||||
nfsStandaloneOptions.readOnly = cmdNfs.Flag.Bool("readOnly", false, "export the filer path as read only")
|
||||
nfsStandaloneOptions.allowedClients = cmdNfs.Flag.String("allowedClients", "", "comma-separated client IPs, hostnames, or CIDRs allowed to connect")
|
||||
nfsStandaloneOptions.volumeServerAccess = cmdNfs.Flag.String("volumeServerAccess", "direct", "access volume servers by [direct|publicUrl|filerProxy]")
|
||||
nfsStandaloneOptions.portmapBind = cmdNfs.Flag.String("portmap.bind", "", "when set, bind a built-in portmap v2 responder on <ip>:111 so plain `mount -t nfs` works without client-side portmap bypass. Empty disables it. Binding port 111 requires root or CAP_NET_BIND_SERVICE and must not conflict with a system rpcbind.")
|
||||
}
|
||||
|
||||
var cmdNfs = &Command{
|
||||
UsageLine: "nfs -port=2049 -filer=<ip:port> -filer.path=<exported subtree>",
|
||||
Short: "start an experimental NFSv3 server backed by a filer",
|
||||
Long: `start an experimental NFSv3 server backed by a filer.
|
||||
|
||||
This command serves an experimental filer-native NFSv3 frontend with
|
||||
deterministic filehandles, filer-backed metadata operations, and direct
|
||||
volume-server data access for chunk reads and buffered writes.
|
||||
|
||||
Safer defaults (since export ACLs are still not implemented):
|
||||
|
||||
- ip.bind defaults to 127.0.0.1, so the server is not reachable from
|
||||
other hosts unless you override it explicitly.
|
||||
- filer.path has no default; you must pick the subtree to export.
|
||||
|
||||
Override -ip.bind to a routable address only after you have reviewed
|
||||
-allowedClients and the readiness of the rest of your deployment.
|
||||
|
||||
Mounting from a Linux client
|
||||
----------------------------
|
||||
The server does not run portmap/rpcbind by default. That means Linux
|
||||
mount.nfs, which queries portmap on port 111 first, will fail with
|
||||
"portmap query failed" against the plain form:
|
||||
|
||||
mount -t nfs -o nfsvers=3,nolock <host>:/export /mnt
|
||||
|
||||
Either tell the client to bypass portmap:
|
||||
|
||||
mount -t nfs -o nfsvers=3,nolock,port=2049,mountport=2049,\
|
||||
proto=tcp,mountproto=tcp <host>:/export /mnt
|
||||
|
||||
or enable the built-in portmap responder on the server:
|
||||
|
||||
weed nfs ... -portmap.bind=0.0.0.0
|
||||
|
||||
With the responder enabled MOUNT v3 is answered over both TCP and UDP,
|
||||
so the plain mount form above just works — no mountproto override is
|
||||
required even on clients whose default mountproto is UDP.
|
||||
|
||||
Binding port 111 requires root or CAP_NET_BIND_SERVICE and must not
|
||||
collide with a system rpcbind.
|
||||
`,
|
||||
}
|
||||
|
||||
func runNfs(cmd *Command, args []string) bool {
|
||||
util.LoadSecurityConfiguration()
|
||||
|
||||
if *nfsStandaloneOptions.ipBind == "" {
|
||||
*nfsStandaloneOptions.ipBind = "127.0.0.1"
|
||||
}
|
||||
|
||||
if *nfsStandaloneOptions.filerRootPath == "" {
|
||||
glog.Errorf("-filer.path is required: pick an explicit subtree to export; exporting \"/\" is not a default")
|
||||
return false
|
||||
}
|
||||
if *nfsStandaloneOptions.filerRootPath == "/" {
|
||||
glog.Warningf("-filer.path=/ exports the entire filer namespace; ensure -allowedClients or -ip.bind constrains access")
|
||||
}
|
||||
|
||||
listenAddress := fmt.Sprintf("%s:%d", *nfsStandaloneOptions.ipBind, *nfsStandaloneOptions.port)
|
||||
glog.V(0).Infof("Starting Seaweed NFS Server %s at %s", version.Version(), listenAddress)
|
||||
|
||||
grpcDialOption := security.LoadClientTLS(util.GetViper(), "grpc.client")
|
||||
|
||||
nfsServer, err := weed_server_nfs.NewServer(&weed_server_nfs.Option{
|
||||
Filer: pb.ServerAddress(*nfsStandaloneOptions.filer),
|
||||
BindIp: *nfsStandaloneOptions.ipBind,
|
||||
Port: *nfsStandaloneOptions.port,
|
||||
FilerRootPath: *nfsStandaloneOptions.filerRootPath,
|
||||
ReadOnly: *nfsStandaloneOptions.readOnly,
|
||||
AllowedClients: util.StringSplit(*nfsStandaloneOptions.allowedClients, ","),
|
||||
VolumeServerAccess: *nfsStandaloneOptions.volumeServerAccess,
|
||||
GrpcDialOption: grpcDialOption,
|
||||
PortmapBind: *nfsStandaloneOptions.portmapBind,
|
||||
})
|
||||
if err != nil {
|
||||
glog.Errorf("NFS Server startup error: %v", err)
|
||||
return false
|
||||
}
|
||||
|
||||
if err := nfsServer.Start(); err != nil {
|
||||
glog.Errorf("NFS Server startup error: %v", err)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
Reference in new issue
Block a user