Commit fb9b7327 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

fuse: support RENAME2 in RawFileSystem

In practice, this only triggers for RENAME_EXCHANGE, as the kernel
issues the RENAME opcode in case of a normal rename or a
RENAME_NOREPLACE.

We have always advertised rename2 support (protocol v23), but it returned
ENOSYS always. Instead, rename RenameIn => Rename1In, and add Flags to
RenameIn.

For raw filesystems that want to support rename2 should examine
RenameIn.Flags and check for syscall.RENAME_XXX.

For fuse/nodefs, we return ENOSYS in case of Rename2, since we lack
API surface to propagate the flags.
parent afa3a28f
...@@ -305,6 +305,9 @@ func (c *rawBridge) Symlink(header *fuse.InHeader, pointedTo string, linkName st ...@@ -305,6 +305,9 @@ func (c *rawBridge) Symlink(header *fuse.InHeader, pointedTo string, linkName st
} }
func (c *rawBridge) Rename(input *fuse.RenameIn, oldName string, newName string) (code fuse.Status) { func (c *rawBridge) Rename(input *fuse.RenameIn, oldName string, newName string) (code fuse.Status) {
if input.Flags != 0 {
return fuse.ENOSYS
}
oldParent := c.toInode(input.NodeId) oldParent := c.toInode(input.NodeId)
child := oldParent.GetChild(oldName) child := oldParent.GetChild(oldName)
......
...@@ -56,7 +56,7 @@ const ( ...@@ -56,7 +56,7 @@ const (
_OP_BATCH_FORGET = int32(42) _OP_BATCH_FORGET = int32(42)
_OP_FALLOCATE = int32(43) // protocol version 19. _OP_FALLOCATE = int32(43) // protocol version 19.
_OP_READDIRPLUS = int32(44) // protocol version 21. _OP_READDIRPLUS = int32(44) // protocol version 21.
_OP_FUSE_RENAME2 = int32(45) // protocol version 23. _OP_RENAME2 = int32(45) // protocol version 23.
// The following entries don't have to be compatible across Go-FUSE versions. // The following entries don't have to be compatible across Go-FUSE versions.
_OP_NOTIFY_INVAL_ENTRY = int32(100) _OP_NOTIFY_INVAL_ENTRY = int32(100)
...@@ -410,6 +410,15 @@ func doSymlink(server *Server, req *request) { ...@@ -410,6 +410,15 @@ func doSymlink(server *Server, req *request) {
} }
func doRename(server *Server, req *request) { func doRename(server *Server, req *request) {
in1 := (*Rename1In)(req.inData)
in := RenameIn{
InHeader: in1.InHeader,
Newdir: in1.Newdir,
}
req.status = server.fileSystem.Rename(&in, req.filenames[0], req.filenames[1])
}
func doRename2(server *Server, req *request) {
req.status = server.fileSystem.Rename((*RenameIn)(req.inData), req.filenames[0], req.filenames[1]) req.status = server.fileSystem.Rename((*RenameIn)(req.inData), req.filenames[0], req.filenames[1])
} }
...@@ -499,7 +508,7 @@ func init() { ...@@ -499,7 +508,7 @@ func init() {
_OP_SETATTR: unsafe.Sizeof(SetAttrIn{}), _OP_SETATTR: unsafe.Sizeof(SetAttrIn{}),
_OP_MKNOD: unsafe.Sizeof(MknodIn{}), _OP_MKNOD: unsafe.Sizeof(MknodIn{}),
_OP_MKDIR: unsafe.Sizeof(MkdirIn{}), _OP_MKDIR: unsafe.Sizeof(MkdirIn{}),
_OP_RENAME: unsafe.Sizeof(RenameIn{}), _OP_RENAME: unsafe.Sizeof(Rename1In{}),
_OP_LINK: unsafe.Sizeof(LinkIn{}), _OP_LINK: unsafe.Sizeof(LinkIn{}),
_OP_OPEN: unsafe.Sizeof(OpenIn{}), _OP_OPEN: unsafe.Sizeof(OpenIn{}),
_OP_READ: unsafe.Sizeof(ReadIn{}), _OP_READ: unsafe.Sizeof(ReadIn{}),
...@@ -527,6 +536,7 @@ func init() { ...@@ -527,6 +536,7 @@ func init() {
_OP_NOTIFY_REPLY: unsafe.Sizeof(NotifyRetrieveIn{}), _OP_NOTIFY_REPLY: unsafe.Sizeof(NotifyRetrieveIn{}),
_OP_FALLOCATE: unsafe.Sizeof(FallocateIn{}), _OP_FALLOCATE: unsafe.Sizeof(FallocateIn{}),
_OP_READDIRPLUS: unsafe.Sizeof(ReadIn{}), _OP_READDIRPLUS: unsafe.Sizeof(ReadIn{}),
_OP_RENAME2: unsafe.Sizeof(RenameIn{}),
} { } {
operationHandlers[op].InputSize = sz operationHandlers[op].InputSize = sz
} }
...@@ -608,6 +618,7 @@ func init() { ...@@ -608,6 +618,7 @@ func init() {
_OP_NOTIFY_DELETE: "NOTIFY_DELETE", _OP_NOTIFY_DELETE: "NOTIFY_DELETE",
_OP_FALLOCATE: "FALLOCATE", _OP_FALLOCATE: "FALLOCATE",
_OP_READDIRPLUS: "READDIRPLUS", _OP_READDIRPLUS: "READDIRPLUS",
_OP_RENAME2: "RENAME2",
} { } {
operationHandlers[op].Name = v operationHandlers[op].Name = v
} }
...@@ -652,6 +663,7 @@ func init() { ...@@ -652,6 +663,7 @@ func init() {
_OP_NOTIFY_REPLY: doNotifyReply, _OP_NOTIFY_REPLY: doNotifyReply,
_OP_FALLOCATE: doFallocate, _OP_FALLOCATE: doFallocate,
_OP_READDIRPLUS: doReadDirPlus, _OP_READDIRPLUS: doReadDirPlus,
_OP_RENAME2: doRename2,
} { } {
operationHandlers[op].Func = v operationHandlers[op].Func = v
} }
...@@ -704,10 +716,11 @@ func init() { ...@@ -704,10 +716,11 @@ func init() {
_OP_FALLOCATE: func(ptr unsafe.Pointer) interface{} { return (*FallocateIn)(ptr) }, _OP_FALLOCATE: func(ptr unsafe.Pointer) interface{} { return (*FallocateIn)(ptr) },
_OP_NOTIFY_REPLY: func(ptr unsafe.Pointer) interface{} { return (*NotifyRetrieveIn)(ptr) }, _OP_NOTIFY_REPLY: func(ptr unsafe.Pointer) interface{} { return (*NotifyRetrieveIn)(ptr) },
_OP_READDIRPLUS: func(ptr unsafe.Pointer) interface{} { return (*ReadIn)(ptr) }, _OP_READDIRPLUS: func(ptr unsafe.Pointer) interface{} { return (*ReadIn)(ptr) },
_OP_RENAME: func(ptr unsafe.Pointer) interface{} { return (*RenameIn)(ptr) }, _OP_RENAME: func(ptr unsafe.Pointer) interface{} { return (*Rename1In)(ptr) },
_OP_GETLK: func(ptr unsafe.Pointer) interface{} { return (*LkIn)(ptr) }, _OP_GETLK: func(ptr unsafe.Pointer) interface{} { return (*LkIn)(ptr) },
_OP_SETLK: func(ptr unsafe.Pointer) interface{} { return (*LkIn)(ptr) }, _OP_SETLK: func(ptr unsafe.Pointer) interface{} { return (*LkIn)(ptr) },
_OP_SETLKW: func(ptr unsafe.Pointer) interface{} { return (*LkIn)(ptr) }, _OP_SETLKW: func(ptr unsafe.Pointer) interface{} { return (*LkIn)(ptr) },
_OP_RENAME2: func(ptr unsafe.Pointer) interface{} { return (*RenameIn)(ptr) },
} { } {
operationHandlers[op].DecodeIn = f operationHandlers[op].DecodeIn = f
} }
...@@ -723,6 +736,7 @@ func init() { ...@@ -723,6 +736,7 @@ func init() {
_OP_MKNOD: 1, _OP_MKNOD: 1,
_OP_REMOVEXATTR: 1, _OP_REMOVEXATTR: 1,
_OP_RENAME: 2, _OP_RENAME: 2,
_OP_RENAME2: 2,
_OP_RMDIR: 1, _OP_RMDIR: 1,
_OP_SYMLINK: 2, _OP_SYMLINK: 2,
_OP_UNLINK: 1, _OP_UNLINK: 1,
......
...@@ -115,8 +115,12 @@ func (me *MkdirIn) string() string { ...@@ -115,8 +115,12 @@ func (me *MkdirIn) string() string {
return fmt.Sprintf("{0%o (0%o)}", me.Mode, me.Umask) return fmt.Sprintf("{0%o (0%o)}", me.Mode, me.Umask)
} }
func (me *Rename1In) string() string {
return fmt.Sprintf("{i%d}", me.Newdir)
}
func (me *RenameIn) string() string { func (me *RenameIn) string() string {
return fmt.Sprintf("{%d}", me.Newdir) return fmt.Sprintf("{i%d %x}", me.Newdir, me.Flags)
} }
func (me *SetAttrIn) string() string { func (me *SetAttrIn) string() string {
......
...@@ -97,12 +97,12 @@ type MkdirIn struct { ...@@ -97,12 +97,12 @@ type MkdirIn struct {
Umask uint32 Umask uint32
} }
type RenameIn struct { type Rename1In struct {
InHeader InHeader
Newdir uint64 Newdir uint64
} }
type Rename2In struct { type RenameIn struct {
InHeader InHeader
Newdir uint64 Newdir uint64
Flags uint32 Flags uint32
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment