From bfcd4113c31bbde4ffd3bfa9fc0c1de228f9e6c0 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Thu, 29 Oct 2020 15:12:36 +0000 Subject: [PATCH] mount: implement mknod to make NFS file creation work - fixes #2115 It turns out that NFS calls mknod in FUSE even though we have create defined. This was causing EIO errors when creating files. This patch fixes it by implementing mknod. The way it is implemented means that to write to an NFS file system you'll need --vfs-cache-mode writes. --- cmd/mount/dir.go | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/cmd/mount/dir.go b/cmd/mount/dir.go index a178c0f23..16263cf40 100644 --- a/cmd/mount/dir.go +++ b/cmd/mount/dir.go @@ -4,6 +4,7 @@ package mount import ( "context" + "io" "os" "time" @@ -214,3 +215,33 @@ func (d *Dir) Link(ctx context.Context, req *fuse.LinkRequest, old fusefs.Node) defer log.Trace(d, "req=%v, old=%v", req, old)("new=%v, err=%v", &newNode, &err) return nil, fuse.ENOSYS } + +// Check interface satisfied +var _ fusefs.NodeMknoder = (*Dir)(nil) + +// Mknod is called to create a file. Since we define create this will +// be called in preference, however NFS likes to call it for some +// reason. We don't actually create a file here just the Node. +func (d *Dir) Mknod(ctx context.Context, req *fuse.MknodRequest) (node fusefs.Node, err error) { + defer log.Trace(d, "name=%v, mode=%d, rdev=%d", req.Name, req.Mode, req.Rdev)("node=%v, err=%v", &node, &err) + if req.Rdev != 0 { + fs.Errorf(d, "Can't create device node %q", req.Name) + return nil, fuse.EIO + } + var cReq = fuse.CreateRequest{ + Name: req.Name, + Flags: fuse.OpenFlags(os.O_CREATE | os.O_WRONLY), + Mode: req.Mode, + Umask: req.Umask, + } + var cResp fuse.CreateResponse + node, handle, err := d.Create(ctx, &cReq, &cResp) + if err != nil { + return nil, err + } + err = handle.(io.Closer).Close() + if err != nil { + return nil, err + } + return node, nil +}