summaryrefslogtreecommitdiffhomepage
path: root/pkg/lisafs
diff options
context:
space:
mode:
authorgVisor bot <gvisor-bot@google.com>2021-09-21 21:14:05 +0000
committergVisor bot <gvisor-bot@google.com>2021-09-21 21:14:05 +0000
commit11acecfe692f6de652ed94343618dfcd9324af94 (patch)
treee47a8c367e67beb77a1068503e50157776fa8718 /pkg/lisafs
parent88c6c5d6df320b543ac3c1355f5b0c0b4bd3eb8e (diff)
parent6fccc185609e37b0e3346f8df91bdcb37bc990db (diff)
Merge release-20210906.0-52-g6fccc1856 (automated)
Diffstat (limited to 'pkg/lisafs')
-rw-r--r--pkg/lisafs/client.go55
-rw-r--r--pkg/lisafs/client_file.go475
-rw-r--r--pkg/lisafs/connection.go16
-rw-r--r--pkg/lisafs/fd.go28
-rw-r--r--pkg/lisafs/handlers.go650
-rw-r--r--pkg/lisafs/lisafs_abi_autogen_unsafe.go2680
-rw-r--r--pkg/lisafs/message.go993
7 files changed, 4893 insertions, 4 deletions
diff --git a/pkg/lisafs/client.go b/pkg/lisafs/client.go
index c99f8c73d..ccf1b9f72 100644
--- a/pkg/lisafs/client.go
+++ b/pkg/lisafs/client.go
@@ -20,12 +20,19 @@ import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/cleanup"
+ "gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/flipcall"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sync"
"gvisor.dev/gvisor/pkg/unet"
)
+const (
+ // fdsToCloseBatchSize is the number of closed FDs batched before an Close
+ // RPC is made to close them all. fdsToCloseBatchSize is immutable.
+ fdsToCloseBatchSize = 100
+)
+
// Client helps manage a connection to the lisafs server and pass messages
// efficiently. There is a 1:1 mapping between a Connection and a Client.
type Client struct {
@@ -53,6 +60,12 @@ type Client struct {
// maxMessageSize is the maximum payload length (in bytes) that can be sent.
// It is initialized on Mount and is immutable.
maxMessageSize uint32
+
+ // fdsToClose tracks the FDs to close. It caches the FDs no longer being used
+ // by the client and closes them in one shot. It is not preserved across
+ // checkpoint/restore as FDIDs are not preserved.
+ fdsMu sync.Mutex
+ fdsToClose []FDID
}
// NewClient creates a new client for communication with the server. It mounts
@@ -66,6 +79,7 @@ func NewClient(sock *unet.Socket, mountPath string) (*Client, *Inode, error) {
channels: make([]*channel, 0, maxChans),
availableChannels: make([]*channel, 0, maxChans),
maxMessageSize: 1 << 20, // 1 MB for now.
+ fdsToClose: make([]FDID, 0, fdsToCloseBatchSize),
}
// Start a goroutine to check socket health. This goroutine is also
@@ -245,6 +259,47 @@ func (c *Client) IsSupported(m MID) bool {
return int(m) < len(c.supported) && c.supported[m]
}
+// CloseFDBatched either queues the passed FD to be closed or makes a batch
+// RPC to close all the accumulated FDs-to-close.
+func (c *Client) CloseFDBatched(ctx context.Context, fd FDID) {
+ c.fdsMu.Lock()
+ c.fdsToClose = append(c.fdsToClose, fd)
+ if len(c.fdsToClose) < fdsToCloseBatchSize {
+ c.fdsMu.Unlock()
+ return
+ }
+
+ // Flush the cache. We should not hold fdsMu while making an RPC, so be sure
+ // to copy the fdsToClose to another buffer before unlocking fdsMu.
+ var toCloseArr [fdsToCloseBatchSize]FDID
+ toClose := toCloseArr[:len(c.fdsToClose)]
+ copy(toClose, c.fdsToClose)
+
+ // Clear fdsToClose so other FDIDs can be appended.
+ c.fdsToClose = c.fdsToClose[:0]
+ c.fdsMu.Unlock()
+
+ req := CloseReq{FDs: toClose}
+ ctx.UninterruptibleSleepStart(false)
+ err := c.SndRcvMessage(Close, uint32(req.SizeBytes()), req.MarshalBytes, NoopUnmarshal, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ if err != nil {
+ log.Warningf("lisafs: batch closing FDs returned error: %v", err)
+ }
+}
+
+// SyncFDs makes a Fsync RPC to sync multiple FDs.
+func (c *Client) SyncFDs(ctx context.Context, fds []FDID) error {
+ if len(fds) == 0 {
+ return nil
+ }
+ req := FsyncReq{FDs: fds}
+ ctx.UninterruptibleSleepStart(false)
+ err := c.SndRcvMessage(FSync, uint32(req.SizeBytes()), req.MarshalBytes, NoopUnmarshal, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return err
+}
+
// SndRcvMessage invokes reqMarshal to marshal the request onto the payload
// buffer, wakes up the server to process the request, waits for the response
// and invokes respUnmarshal with the response payload. respFDs is populated
diff --git a/pkg/lisafs/client_file.go b/pkg/lisafs/client_file.go
new file mode 100644
index 000000000..0f8788f3b
--- /dev/null
+++ b/pkg/lisafs/client_file.go
@@ -0,0 +1,475 @@
+// Copyright 2021 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package lisafs
+
+import (
+ "golang.org/x/sys/unix"
+ "gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/log"
+ "gvisor.dev/gvisor/pkg/marshal/primitive"
+)
+
+// ClientFD is a wrapper around FDID that provides client-side utilities
+// so that RPC making is easier.
+type ClientFD struct {
+ fd FDID
+ client *Client
+}
+
+// ID returns the underlying FDID.
+func (f *ClientFD) ID() FDID {
+ return f.fd
+}
+
+// Client returns the backing Client.
+func (f *ClientFD) Client() *Client {
+ return f.client
+}
+
+// NewFD initializes a new ClientFD.
+func (c *Client) NewFD(fd FDID) ClientFD {
+ return ClientFD{
+ client: c,
+ fd: fd,
+ }
+}
+
+// Ok returns true if the underlying FD is ok.
+func (f *ClientFD) Ok() bool {
+ return f.fd.Ok()
+}
+
+// CloseBatched queues this FD to be closed on the server and resets f.fd.
+// This maybe invoke the Close RPC if the queue is full.
+func (f *ClientFD) CloseBatched(ctx context.Context) {
+ f.client.CloseFDBatched(ctx, f.fd)
+ f.fd = InvalidFDID
+}
+
+// Close closes this FD immediately (invoking a Close RPC). Consider using
+// CloseBatched if closing this FD on remote right away is not critical.
+func (f *ClientFD) Close(ctx context.Context) error {
+ fdArr := [1]FDID{f.fd}
+ req := CloseReq{FDs: fdArr[:]}
+
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(Close, uint32(req.SizeBytes()), req.MarshalBytes, NoopUnmarshal, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return err
+}
+
+// OpenAt makes the OpenAt RPC.
+func (f *ClientFD) OpenAt(ctx context.Context, flags uint32) (FDID, int, error) {
+ req := OpenAtReq{
+ FD: f.fd,
+ Flags: flags,
+ }
+ var respFD [1]int
+ var resp OpenAtResp
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(OpenAt, uint32(req.SizeBytes()), req.MarshalUnsafe, resp.UnmarshalUnsafe, respFD[:])
+ ctx.UninterruptibleSleepFinish(false)
+ return resp.NewFD, respFD[0], err
+}
+
+// OpenCreateAt makes the OpenCreateAt RPC.
+func (f *ClientFD) OpenCreateAt(ctx context.Context, name string, flags uint32, mode linux.FileMode, uid UID, gid GID) (Inode, FDID, int, error) {
+ var req OpenCreateAtReq
+ req.DirFD = f.fd
+ req.Name = SizedString(name)
+ req.Flags = primitive.Uint32(flags)
+ req.Mode = mode
+ req.UID = uid
+ req.GID = gid
+
+ var respFD [1]int
+ var resp OpenCreateAtResp
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(OpenCreateAt, uint32(req.SizeBytes()), req.MarshalBytes, resp.UnmarshalUnsafe, respFD[:])
+ ctx.UninterruptibleSleepFinish(false)
+ return resp.Child, resp.NewFD, respFD[0], err
+}
+
+// StatTo makes the Fstat RPC and populates stat with the result.
+func (f *ClientFD) StatTo(ctx context.Context, stat *linux.Statx) error {
+ req := StatReq{FD: f.fd}
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(FStat, uint32(req.SizeBytes()), req.MarshalUnsafe, stat.UnmarshalUnsafe, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return err
+}
+
+// Sync makes the Fsync RPC.
+func (f *ClientFD) Sync(ctx context.Context) error {
+ req := FsyncReq{FDs: []FDID{f.fd}}
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(FSync, uint32(req.SizeBytes()), req.MarshalBytes, NoopUnmarshal, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return err
+}
+
+// Read makes the PRead RPC.
+func (f *ClientFD) Read(ctx context.Context, dst []byte, offset uint64) (uint64, error) {
+ req := PReadReq{
+ Offset: offset,
+ FD: f.fd,
+ Count: uint32(len(dst)),
+ }
+
+ resp := PReadResp{
+ // This will be unmarshalled into. Already set Buf so that we don't need to
+ // allocate a temporary buffer during unmarshalling.
+ // PReadResp.UnmarshalBytes expects this to be set.
+ Buf: dst,
+ }
+
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(PRead, uint32(req.SizeBytes()), req.MarshalUnsafe, resp.UnmarshalBytes, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return uint64(resp.NumBytes), err
+}
+
+// Write makes the PWrite RPC.
+func (f *ClientFD) Write(ctx context.Context, src []byte, offset uint64) (uint64, error) {
+ req := PWriteReq{
+ Offset: primitive.Uint64(offset),
+ FD: f.fd,
+ NumBytes: primitive.Uint32(len(src)),
+ Buf: src,
+ }
+
+ var resp PWriteResp
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(PWrite, uint32(req.SizeBytes()), req.MarshalBytes, resp.UnmarshalUnsafe, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return resp.Count, err
+}
+
+// MkdirAt makes the MkdirAt RPC.
+func (f *ClientFD) MkdirAt(ctx context.Context, name string, mode linux.FileMode, uid UID, gid GID) (*Inode, error) {
+ var req MkdirAtReq
+ req.DirFD = f.fd
+ req.Name = SizedString(name)
+ req.Mode = mode
+ req.UID = uid
+ req.GID = gid
+
+ var resp MkdirAtResp
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(MkdirAt, uint32(req.SizeBytes()), req.MarshalBytes, resp.UnmarshalUnsafe, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return &resp.ChildDir, err
+}
+
+// SymlinkAt makes the SymlinkAt RPC.
+func (f *ClientFD) SymlinkAt(ctx context.Context, name, target string, uid UID, gid GID) (*Inode, error) {
+ req := SymlinkAtReq{
+ DirFD: f.fd,
+ Name: SizedString(name),
+ Target: SizedString(target),
+ UID: uid,
+ GID: gid,
+ }
+
+ var resp SymlinkAtResp
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(SymlinkAt, uint32(req.SizeBytes()), req.MarshalBytes, resp.UnmarshalUnsafe, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return &resp.Symlink, err
+}
+
+// LinkAt makes the LinkAt RPC.
+func (f *ClientFD) LinkAt(ctx context.Context, targetFD FDID, name string) (*Inode, error) {
+ req := LinkAtReq{
+ DirFD: f.fd,
+ Target: targetFD,
+ Name: SizedString(name),
+ }
+
+ var resp LinkAtResp
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(LinkAt, uint32(req.SizeBytes()), req.MarshalBytes, resp.UnmarshalUnsafe, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return &resp.Link, err
+}
+
+// MknodAt makes the MknodAt RPC.
+func (f *ClientFD) MknodAt(ctx context.Context, name string, mode linux.FileMode, uid UID, gid GID, minor, major uint32) (*Inode, error) {
+ var req MknodAtReq
+ req.DirFD = f.fd
+ req.Name = SizedString(name)
+ req.Mode = mode
+ req.UID = uid
+ req.GID = gid
+ req.Minor = primitive.Uint32(minor)
+ req.Major = primitive.Uint32(major)
+
+ var resp MknodAtResp
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(MknodAt, uint32(req.SizeBytes()), req.MarshalBytes, resp.UnmarshalUnsafe, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return &resp.Child, err
+}
+
+// SetStat makes the SetStat RPC.
+func (f *ClientFD) SetStat(ctx context.Context, stat *linux.Statx) (uint32, error, error) {
+ req := SetStatReq{
+ FD: f.fd,
+ Mask: stat.Mask,
+ Mode: uint32(stat.Mode),
+ UID: UID(stat.UID),
+ GID: GID(stat.GID),
+ Size: stat.Size,
+ Atime: linux.Timespec{
+ Sec: stat.Atime.Sec,
+ Nsec: int64(stat.Atime.Nsec),
+ },
+ Mtime: linux.Timespec{
+ Sec: stat.Mtime.Sec,
+ Nsec: int64(stat.Mtime.Nsec),
+ },
+ }
+
+ var resp SetStatResp
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(SetStat, uint32(req.SizeBytes()), req.MarshalUnsafe, resp.UnmarshalUnsafe, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return resp.FailureMask, unix.Errno(resp.FailureErrNo), err
+}
+
+// WalkMultiple makes the Walk RPC with multiple path components.
+func (f *ClientFD) WalkMultiple(ctx context.Context, names []string) (WalkStatus, []Inode, error) {
+ req := WalkReq{
+ DirFD: f.fd,
+ Path: StringArray(names),
+ }
+
+ var resp WalkResp
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(Walk, uint32(req.SizeBytes()), req.MarshalBytes, resp.UnmarshalBytes, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return resp.Status, resp.Inodes, err
+}
+
+// Walk makes the Walk RPC with just one path component to walk.
+func (f *ClientFD) Walk(ctx context.Context, name string) (*Inode, error) {
+ req := WalkReq{
+ DirFD: f.fd,
+ Path: []string{name},
+ }
+
+ var inode [1]Inode
+ resp := WalkResp{Inodes: inode[:]}
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(Walk, uint32(req.SizeBytes()), req.MarshalBytes, resp.UnmarshalBytes, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ if err != nil {
+ return nil, err
+ }
+
+ switch resp.Status {
+ case WalkComponentDoesNotExist:
+ return nil, unix.ENOENT
+ case WalkComponentSymlink:
+ // f is not a directory which can be walked on.
+ return nil, unix.ENOTDIR
+ }
+
+ if n := len(resp.Inodes); n > 1 {
+ for i := range resp.Inodes {
+ f.client.CloseFDBatched(ctx, resp.Inodes[i].ControlFD)
+ }
+ log.Warningf("requested to walk one component, but got %d results", n)
+ return nil, unix.EIO
+ } else if n == 0 {
+ log.Warningf("walk has success status but no results returned")
+ return nil, unix.ENOENT
+ }
+ return &inode[0], err
+}
+
+// WalkStat makes the WalkStat RPC with multiple path components to walk.
+func (f *ClientFD) WalkStat(ctx context.Context, names []string) ([]linux.Statx, error) {
+ req := WalkReq{
+ DirFD: f.fd,
+ Path: StringArray(names),
+ }
+
+ var resp WalkStatResp
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(WalkStat, uint32(req.SizeBytes()), req.MarshalBytes, resp.UnmarshalBytes, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return resp.Stats, err
+}
+
+// StatFSTo makes the FStatFS RPC and populates statFS with the result.
+func (f *ClientFD) StatFSTo(ctx context.Context, statFS *StatFS) error {
+ req := FStatFSReq{FD: f.fd}
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(FStatFS, uint32(req.SizeBytes()), req.MarshalUnsafe, statFS.UnmarshalUnsafe, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return err
+}
+
+// Allocate makes the FAllocate RPC.
+func (f *ClientFD) Allocate(ctx context.Context, mode, offset, length uint64) error {
+ req := FAllocateReq{
+ FD: f.fd,
+ Mode: mode,
+ Offset: offset,
+ Length: length,
+ }
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(FAllocate, uint32(req.SizeBytes()), req.MarshalUnsafe, NoopUnmarshal, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return err
+}
+
+// ReadLinkAt makes the ReadLinkAt RPC.
+func (f *ClientFD) ReadLinkAt(ctx context.Context) (string, error) {
+ req := ReadLinkAtReq{FD: f.fd}
+ var resp ReadLinkAtResp
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(ReadLinkAt, uint32(req.SizeBytes()), req.MarshalUnsafe, resp.UnmarshalBytes, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return string(resp.Target), err
+}
+
+// Flush makes the Flush RPC.
+func (f *ClientFD) Flush(ctx context.Context) error {
+ if !f.client.IsSupported(Flush) {
+ // If Flush is not supported, it probably means that it would be a noop.
+ return nil
+ }
+ req := FlushReq{FD: f.fd}
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(Flush, uint32(req.SizeBytes()), req.MarshalUnsafe, NoopUnmarshal, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return err
+}
+
+// Connect makes the Connect RPC.
+func (f *ClientFD) Connect(ctx context.Context, sockType linux.SockType) (int, error) {
+ req := ConnectReq{FD: f.fd, SockType: uint32(sockType)}
+ var sockFD [1]int
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(Connect, uint32(req.SizeBytes()), req.MarshalUnsafe, NoopUnmarshal, sockFD[:])
+ ctx.UninterruptibleSleepFinish(false)
+ if err == nil && sockFD[0] < 0 {
+ err = unix.EBADF
+ }
+ return sockFD[0], err
+}
+
+// UnlinkAt makes the UnlinkAt RPC.
+func (f *ClientFD) UnlinkAt(ctx context.Context, name string, flags uint32) error {
+ req := UnlinkAtReq{
+ DirFD: f.fd,
+ Name: SizedString(name),
+ Flags: primitive.Uint32(flags),
+ }
+
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(UnlinkAt, uint32(req.SizeBytes()), req.MarshalBytes, NoopUnmarshal, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return err
+}
+
+// RenameTo makes the RenameAt RPC which renames f to newDirFD directory with
+// name newName.
+func (f *ClientFD) RenameTo(ctx context.Context, newDirFD FDID, newName string) error {
+ req := RenameAtReq{
+ Renamed: f.fd,
+ NewDir: newDirFD,
+ NewName: SizedString(newName),
+ }
+
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(RenameAt, uint32(req.SizeBytes()), req.MarshalBytes, NoopUnmarshal, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return err
+}
+
+// Getdents64 makes the Getdents64 RPC.
+func (f *ClientFD) Getdents64(ctx context.Context, count int32) ([]Dirent64, error) {
+ req := Getdents64Req{
+ DirFD: f.fd,
+ Count: count,
+ }
+
+ var resp Getdents64Resp
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(Getdents64, uint32(req.SizeBytes()), req.MarshalUnsafe, resp.UnmarshalBytes, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return resp.Dirents, err
+}
+
+// ListXattr makes the FListXattr RPC.
+func (f *ClientFD) ListXattr(ctx context.Context, size uint64) ([]string, error) {
+ req := FListXattrReq{
+ FD: f.fd,
+ Size: size,
+ }
+
+ var resp FListXattrResp
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(FListXattr, uint32(req.SizeBytes()), req.MarshalUnsafe, resp.UnmarshalBytes, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return resp.Xattrs, err
+}
+
+// GetXattr makes the FGetXattr RPC.
+func (f *ClientFD) GetXattr(ctx context.Context, name string, size uint64) (string, error) {
+ req := FGetXattrReq{
+ FD: f.fd,
+ Name: SizedString(name),
+ BufSize: primitive.Uint32(size),
+ }
+
+ var resp FGetXattrResp
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(FGetXattr, uint32(req.SizeBytes()), req.MarshalBytes, resp.UnmarshalBytes, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return string(resp.Value), err
+}
+
+// SetXattr makes the FSetXattr RPC.
+func (f *ClientFD) SetXattr(ctx context.Context, name string, value string, flags uint32) error {
+ req := FSetXattrReq{
+ FD: f.fd,
+ Name: SizedString(name),
+ Value: SizedString(value),
+ Flags: primitive.Uint32(flags),
+ }
+
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(FSetXattr, uint32(req.SizeBytes()), req.MarshalBytes, NoopUnmarshal, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return err
+}
+
+// RemoveXattr makes the FRemoveXattr RPC.
+func (f *ClientFD) RemoveXattr(ctx context.Context, name string) error {
+ req := FRemoveXattrReq{
+ FD: f.fd,
+ Name: SizedString(name),
+ }
+
+ ctx.UninterruptibleSleepStart(false)
+ err := f.client.SndRcvMessage(FRemoveXattr, uint32(req.SizeBytes()), req.MarshalBytes, NoopUnmarshal, nil)
+ ctx.UninterruptibleSleepFinish(false)
+ return err
+}
diff --git a/pkg/lisafs/connection.go b/pkg/lisafs/connection.go
index 8dba4805f..f6e5ecb4f 100644
--- a/pkg/lisafs/connection.go
+++ b/pkg/lisafs/connection.go
@@ -289,6 +289,22 @@ func (c *Connection) RemoveFD(id FDID) {
}
}
+// RemoveControlFDLocked is the same as RemoveFD with added preconditions.
+//
+// Preconditions:
+// * server's rename mutex must at least be read locked.
+// * id must be pointing to a control FD.
+func (c *Connection) RemoveControlFDLocked(id FDID) {
+ c.fdsMu.Lock()
+ fd := c.removeFDLocked(id)
+ c.fdsMu.Unlock()
+ if fd != nil {
+ // Drop the ref held by c. This can take arbitrarily long. So do not hold
+ // c.fdsMu while calling it.
+ fd.(*ControlFD).DecRefLocked()
+ }
+}
+
// removeFDLocked makes c stop tracking the passed FDID. Note that the caller
// must drop ref on the returned fd (preferably without holding c.fdsMu).
//
diff --git a/pkg/lisafs/fd.go b/pkg/lisafs/fd.go
index 9dd8ba384..cc6919a1b 100644
--- a/pkg/lisafs/fd.go
+++ b/pkg/lisafs/fd.go
@@ -231,7 +231,7 @@ func (fd *ControlFD) FilePath() string {
return fd.FilePathLocked()
}
-// FilePathLocked is the same as FilePath with the additonal precondition.
+// FilePathLocked is the same as FilePath with the additional precondition.
//
// Precondition: server's rename mutex must be at least read locked.
func (fd *ControlFD) FilePathLocked() string {
@@ -333,6 +333,25 @@ func (fd *OpenFD) Init(cfd *ControlFD, flags uint32, impl OpenFDImpl) {
type ControlFDImpl interface {
FD() *ControlFD
Close(c *Connection)
+ Stat(c *Connection, comm Communicator) (uint32, error)
+ SetStat(c *Connection, comm Communicator, stat SetStatReq) (uint32, error)
+ Walk(c *Connection, comm Communicator, path StringArray) (uint32, error)
+ WalkStat(c *Connection, comm Communicator, path StringArray) (uint32, error)
+ Open(c *Connection, comm Communicator, flags uint32) (uint32, error)
+ OpenCreate(c *Connection, comm Communicator, mode linux.FileMode, uid UID, gid GID, name string, flags uint32) (uint32, error)
+ Mkdir(c *Connection, comm Communicator, mode linux.FileMode, uid UID, gid GID, name string) (uint32, error)
+ Mknod(c *Connection, comm Communicator, mode linux.FileMode, uid UID, gid GID, name string, minor uint32, major uint32) (uint32, error)
+ Symlink(c *Connection, comm Communicator, name string, target string, uid UID, gid GID) (uint32, error)
+ Link(c *Connection, comm Communicator, dir ControlFDImpl, name string) (uint32, error)
+ StatFS(c *Connection, comm Communicator) (uint32, error)
+ Readlink(c *Connection, comm Communicator) (uint32, error)
+ Connect(c *Connection, comm Communicator, sockType uint32) error
+ Unlink(c *Connection, name string, flags uint32) error
+ RenameLocked(c *Connection, newDir ControlFDImpl, newName string) (func(ControlFDImpl), func(), error)
+ GetXattr(c *Connection, comm Communicator, name string, size uint32) (uint32, error)
+ SetXattr(c *Connection, name string, value string, flags uint32) error
+ ListXattr(c *Connection, comm Communicator, size uint64) (uint32, error)
+ RemoveXattr(c *Connection, comm Communicator, name string) error
}
// OpenFDImpl contains implementation details for a OpenFD. Implementations of
@@ -345,4 +364,11 @@ type ControlFDImpl interface {
type OpenFDImpl interface {
FD() *OpenFD
Close(c *Connection)
+ Stat(c *Connection, comm Communicator) (uint32, error)
+ Sync(c *Connection) error
+ Write(c *Connection, comm Communicator, buf []byte, off uint64) (uint32, error)
+ Read(c *Connection, comm Communicator, off uint64, count uint32) (uint32, error)
+ Allocate(c *Connection, mode, off, length uint64) error
+ Flush(c *Connection) error
+ Getdent64(c *Connection, comm Communicator, count uint32, seek0 bool) (uint32, error)
}
diff --git a/pkg/lisafs/handlers.go b/pkg/lisafs/handlers.go
index 9b8d8164a..82807734d 100644
--- a/pkg/lisafs/handlers.go
+++ b/pkg/lisafs/handlers.go
@@ -15,15 +15,23 @@
package lisafs
import (
+ "fmt"
"path"
"path/filepath"
+ "strings"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/flipcall"
+ "gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/marshal/primitive"
)
+const (
+ allowedOpenFlags = unix.O_ACCMODE | unix.O_TRUNC
+ setStatSupportedMask = unix.STATX_MODE | unix.STATX_UID | unix.STATX_GID | unix.STATX_SIZE | unix.STATX_ATIME | unix.STATX_MTIME
+)
+
// RPCHandler defines a handler that is invoked when the associated message is
// received. The handler is responsible for:
//
@@ -34,9 +42,35 @@ import (
type RPCHandler func(c *Connection, comm Communicator, payloadLen uint32) (uint32, error)
var handlers = [...]RPCHandler{
- Error: ErrorHandler,
- Mount: MountHandler,
- Channel: ChannelHandler,
+ Error: ErrorHandler,
+ Mount: MountHandler,
+ Channel: ChannelHandler,
+ FStat: FStatHandler,
+ SetStat: SetStatHandler,
+ Walk: WalkHandler,
+ WalkStat: WalkStatHandler,
+ OpenAt: OpenAtHandler,
+ OpenCreateAt: OpenCreateAtHandler,
+ Close: CloseHandler,
+ FSync: FSyncHandler,
+ PWrite: PWriteHandler,
+ PRead: PReadHandler,
+ MkdirAt: MkdirAtHandler,
+ MknodAt: MknodAtHandler,
+ SymlinkAt: SymlinkAtHandler,
+ LinkAt: LinkAtHandler,
+ FStatFS: FStatFSHandler,
+ FAllocate: FAllocateHandler,
+ ReadLinkAt: ReadLinkAtHandler,
+ Flush: FlushHandler,
+ Connect: ConnectHandler,
+ UnlinkAt: UnlinkAtHandler,
+ RenameAt: RenameAtHandler,
+ Getdents64: Getdents64Handler,
+ FGetXattr: FGetXattrHandler,
+ FSetXattr: FSetXattrHandler,
+ FListXattr: FListXattrHandler,
+ FRemoveXattr: FRemoveXattrHandler,
}
// ErrorHandler handles Error message.
@@ -122,3 +156,613 @@ func ChannelHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32
resp.MarshalUnsafe(comm.PayloadBuf(respLen))
return respLen, nil
}
+
+// FStatHandler handles the FStat RPC.
+func FStatHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ var req StatReq
+ req.UnmarshalUnsafe(comm.PayloadBuf(payloadLen))
+
+ fd, err := c.lookupFD(req.FD)
+ if err != nil {
+ return 0, err
+ }
+ defer fd.DecRef(nil)
+
+ switch t := fd.(type) {
+ case *ControlFD:
+ return t.impl.Stat(c, comm)
+ case *OpenFD:
+ return t.impl.Stat(c, comm)
+ default:
+ panic(fmt.Sprintf("unknown fd type %T", t))
+ }
+}
+
+// SetStatHandler handles the SetStat RPC.
+func SetStatHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ if c.readonly {
+ return 0, unix.EROFS
+ }
+
+ var req SetStatReq
+ req.UnmarshalUnsafe(comm.PayloadBuf(payloadLen))
+
+ fd, err := c.LookupControlFD(req.FD)
+ if err != nil {
+ return 0, err
+ }
+ defer fd.DecRef(nil)
+
+ if req.Mask&^setStatSupportedMask != 0 {
+ return 0, unix.EPERM
+ }
+
+ return fd.impl.SetStat(c, comm, req)
+}
+
+// WalkHandler handles the Walk RPC.
+func WalkHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ var req WalkReq
+ req.UnmarshalBytes(comm.PayloadBuf(payloadLen))
+
+ fd, err := c.LookupControlFD(req.DirFD)
+ if err != nil {
+ return 0, err
+ }
+ defer fd.DecRef(nil)
+ if !fd.IsDir() {
+ return 0, unix.ENOTDIR
+ }
+ for _, name := range req.Path {
+ if err := checkSafeName(name); err != nil {
+ return 0, err
+ }
+ }
+
+ return fd.impl.Walk(c, comm, req.Path)
+}
+
+// WalkStatHandler handles the WalkStat RPC.
+func WalkStatHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ var req WalkReq
+ req.UnmarshalBytes(comm.PayloadBuf(payloadLen))
+
+ fd, err := c.LookupControlFD(req.DirFD)
+ if err != nil {
+ return 0, err
+ }
+ defer fd.DecRef(nil)
+
+ // Note that this fd is allowed to not actually be a directory when the
+ // only path component to walk is "" (self).
+ if !fd.IsDir() {
+ if len(req.Path) > 1 || (len(req.Path) == 1 && len(req.Path[0]) > 0) {
+ return 0, unix.ENOTDIR
+ }
+ }
+ for i, name := range req.Path {
+ // First component is allowed to be "".
+ if i == 0 && len(name) == 0 {
+ continue
+ }
+ if err := checkSafeName(name); err != nil {
+ return 0, err
+ }
+ }
+
+ return fd.impl.WalkStat(c, comm, req.Path)
+}
+
+// OpenAtHandler handles the OpenAt RPC.
+func OpenAtHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ var req OpenAtReq
+ req.UnmarshalUnsafe(comm.PayloadBuf(payloadLen))
+
+ // Only keep allowed open flags.
+ if allowedFlags := req.Flags & allowedOpenFlags; allowedFlags != req.Flags {
+ log.Debugf("discarding open flags that are not allowed: old open flags = %d, new open flags = %d", req.Flags, allowedFlags)
+ req.Flags = allowedFlags
+ }
+
+ accessMode := req.Flags & unix.O_ACCMODE
+ trunc := req.Flags&unix.O_TRUNC != 0
+ if c.readonly && (accessMode != unix.O_RDONLY || trunc) {
+ return 0, unix.EROFS
+ }
+
+ fd, err := c.LookupControlFD(req.FD)
+ if err != nil {
+ return 0, err
+ }
+ defer fd.DecRef(nil)
+ if fd.IsDir() {
+ // Directory is not truncatable and must be opened with O_RDONLY.
+ if accessMode != unix.O_RDONLY || trunc {
+ return 0, unix.EISDIR
+ }
+ }
+
+ return fd.impl.Open(c, comm, req.Flags)
+}
+
+// OpenCreateAtHandler handles the OpenCreateAt RPC.
+func OpenCreateAtHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ if c.readonly {
+ return 0, unix.EROFS
+ }
+ var req OpenCreateAtReq
+ req.UnmarshalBytes(comm.PayloadBuf(payloadLen))
+
+ // Only keep allowed open flags.
+ if allowedFlags := req.Flags & allowedOpenFlags; allowedFlags != req.Flags {
+ log.Debugf("discarding open flags that are not allowed: old open flags = %d, new open flags = %d", req.Flags, allowedFlags)
+ req.Flags = allowedFlags
+ }
+
+ name := string(req.Name)
+ if err := checkSafeName(name); err != nil {
+ return 0, err
+ }
+
+ fd, err := c.LookupControlFD(req.DirFD)
+ if err != nil {
+ return 0, err
+ }
+ defer fd.DecRef(nil)
+ if !fd.IsDir() {
+ return 0, unix.ENOTDIR
+ }
+
+ return fd.impl.OpenCreate(c, comm, req.Mode, req.UID, req.GID, name, uint32(req.Flags))
+}
+
+// CloseHandler handles the Close RPC.
+func CloseHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ var req CloseReq
+ req.UnmarshalBytes(comm.PayloadBuf(payloadLen))
+ for _, fd := range req.FDs {
+ c.RemoveFD(fd)
+ }
+
+ // There is no response message for this.
+ return 0, nil
+}
+
+// FSyncHandler handles the FSync RPC.
+func FSyncHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ var req FsyncReq
+ req.UnmarshalBytes(comm.PayloadBuf(payloadLen))
+
+ // Return the first error we encounter, but sync everything we can
+ // regardless.
+ var retErr error
+ for _, fdid := range req.FDs {
+ if err := c.fsyncFD(fdid); err != nil && retErr == nil {
+ retErr = err
+ }
+ }
+
+ // There is no response message for this.
+ return 0, retErr
+}
+
+func (c *Connection) fsyncFD(id FDID) error {
+ fd, err := c.LookupOpenFD(id)
+ if err != nil {
+ return err
+ }
+ return fd.impl.Sync(c)
+}
+
+// PWriteHandler handles the PWrite RPC.
+func PWriteHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ if c.readonly {
+ return 0, unix.EROFS
+ }
+ var req PWriteReq
+ // Note that it is an optimized Unmarshal operation which avoids any buffer
+ // allocation and copying. req.Buf just points to payload. This is safe to do
+ // as the handler owns payload and req's lifetime is limited to the handler.
+ req.UnmarshalBytes(comm.PayloadBuf(payloadLen))
+ fd, err := c.LookupOpenFD(req.FD)
+ if err != nil {
+ return 0, err
+ }
+ if !fd.writable {
+ return 0, unix.EBADF
+ }
+ return fd.impl.Write(c, comm, req.Buf, uint64(req.Offset))
+}
+
+// PReadHandler handles the PRead RPC.
+func PReadHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ var req PReadReq
+ req.UnmarshalUnsafe(comm.PayloadBuf(payloadLen))
+
+ fd, err := c.LookupOpenFD(req.FD)
+ if err != nil {
+ return 0, err
+ }
+ defer fd.DecRef(nil)
+ if !fd.readable {
+ return 0, unix.EBADF
+ }
+ return fd.impl.Read(c, comm, req.Offset, req.Count)
+}
+
+// MkdirAtHandler handles the MkdirAt RPC.
+func MkdirAtHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ if c.readonly {
+ return 0, unix.EROFS
+ }
+ var req MkdirAtReq
+ req.UnmarshalBytes(comm.PayloadBuf(payloadLen))
+
+ name := string(req.Name)
+ if err := checkSafeName(name); err != nil {
+ return 0, err
+ }
+
+ fd, err := c.LookupControlFD(req.DirFD)
+ if err != nil {
+ return 0, err
+ }
+ defer fd.DecRef(nil)
+ if !fd.IsDir() {
+ return 0, unix.ENOTDIR
+ }
+ return fd.impl.Mkdir(c, comm, req.Mode, req.UID, req.GID, name)
+}
+
+// MknodAtHandler handles the MknodAt RPC.
+func MknodAtHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ if c.readonly {
+ return 0, unix.EROFS
+ }
+ var req MknodAtReq
+ req.UnmarshalBytes(comm.PayloadBuf(payloadLen))
+
+ name := string(req.Name)
+ if err := checkSafeName(name); err != nil {
+ return 0, err
+ }
+
+ fd, err := c.LookupControlFD(req.DirFD)
+ if err != nil {
+ return 0, err
+ }
+ defer fd.DecRef(nil)
+ if !fd.IsDir() {
+ return 0, unix.ENOTDIR
+ }
+ return fd.impl.Mknod(c, comm, req.Mode, req.UID, req.GID, name, uint32(req.Minor), uint32(req.Major))
+}
+
+// SymlinkAtHandler handles the SymlinkAt RPC.
+func SymlinkAtHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ if c.readonly {
+ return 0, unix.EROFS
+ }
+ var req SymlinkAtReq
+ req.UnmarshalBytes(comm.PayloadBuf(payloadLen))
+
+ name := string(req.Name)
+ if err := checkSafeName(name); err != nil {
+ return 0, err
+ }
+
+ fd, err := c.LookupControlFD(req.DirFD)
+ if err != nil {
+ return 0, err
+ }
+ defer fd.DecRef(nil)
+ if !fd.IsDir() {
+ return 0, unix.ENOTDIR
+ }
+ return fd.impl.Symlink(c, comm, name, string(req.Target), req.UID, req.GID)
+}
+
+// LinkAtHandler handles the LinkAt RPC.
+func LinkAtHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ if c.readonly {
+ return 0, unix.EROFS
+ }
+ var req LinkAtReq
+ req.UnmarshalBytes(comm.PayloadBuf(payloadLen))
+
+ name := string(req.Name)
+ if err := checkSafeName(name); err != nil {
+ return 0, err
+ }
+
+ fd, err := c.LookupControlFD(req.DirFD)
+ if err != nil {
+ return 0, err
+ }
+ defer fd.DecRef(nil)
+ if !fd.IsDir() {
+ return 0, unix.ENOTDIR
+ }
+
+ targetFD, err := c.LookupControlFD(req.Target)
+ if err != nil {
+ return 0, err
+ }
+ return targetFD.impl.Link(c, comm, fd.impl, name)
+}
+
+// FStatFSHandler handles the FStatFS RPC.
+func FStatFSHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ var req FStatFSReq
+ req.UnmarshalUnsafe(comm.PayloadBuf(payloadLen))
+
+ fd, err := c.LookupControlFD(req.FD)
+ if err != nil {
+ return 0, err
+ }
+ defer fd.DecRef(nil)
+ return fd.impl.StatFS(c, comm)
+}
+
+// FAllocateHandler handles the FAllocate RPC.
+func FAllocateHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ if c.readonly {
+ return 0, unix.EROFS
+ }
+ var req FAllocateReq
+ req.UnmarshalUnsafe(comm.PayloadBuf(payloadLen))
+
+ fd, err := c.LookupOpenFD(req.FD)
+ if err != nil {
+ return 0, err
+ }
+ defer fd.DecRef(nil)
+ if !fd.writable {
+ return 0, unix.EBADF
+ }
+ return 0, fd.impl.Allocate(c, req.Mode, req.Offset, req.Length)
+}
+
+// ReadLinkAtHandler handles the ReadLinkAt RPC.
+func ReadLinkAtHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ var req ReadLinkAtReq
+ req.UnmarshalUnsafe(comm.PayloadBuf(payloadLen))
+
+ fd, err := c.LookupControlFD(req.FD)
+ if err != nil {
+ return 0, err
+ }
+ defer fd.DecRef(nil)
+ if !fd.IsSymlink() {
+ return 0, unix.EINVAL
+ }
+ return fd.impl.Readlink(c, comm)
+}
+
+// FlushHandler handles the Flush RPC.
+func FlushHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ var req FlushReq
+ req.UnmarshalUnsafe(comm.PayloadBuf(payloadLen))
+
+ fd, err := c.LookupOpenFD(req.FD)
+ if err != nil {
+ return 0, err
+ }
+ defer fd.DecRef(nil)
+
+ return 0, fd.impl.Flush(c)
+}
+
+// ConnectHandler handles the Connect RPC.
+func ConnectHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ var req ConnectReq
+ req.UnmarshalUnsafe(comm.PayloadBuf(payloadLen))
+
+ fd, err := c.LookupControlFD(req.FD)
+ if err != nil {
+ return 0, err
+ }
+ defer fd.DecRef(nil)
+ if !fd.IsSocket() {
+ return 0, unix.ENOTSOCK
+ }
+ return 0, fd.impl.Connect(c, comm, req.SockType)
+}
+
+// UnlinkAtHandler handles the UnlinkAt RPC.
+func UnlinkAtHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ if c.readonly {
+ return 0, unix.EROFS
+ }
+ var req UnlinkAtReq
+ req.UnmarshalBytes(comm.PayloadBuf(payloadLen))
+
+ name := string(req.Name)
+ if err := checkSafeName(name); err != nil {
+ return 0, err
+ }
+
+ fd, err := c.LookupControlFD(req.DirFD)
+ if err != nil {
+ return 0, err
+ }
+ defer fd.DecRef(nil)
+ if !fd.IsDir() {
+ return 0, unix.ENOTDIR
+ }
+ return 0, fd.impl.Unlink(c, name, uint32(req.Flags))
+}
+
+// RenameAtHandler handles the RenameAt RPC.
+func RenameAtHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ if c.readonly {
+ return 0, unix.EROFS
+ }
+ var req RenameAtReq
+ req.UnmarshalBytes(comm.PayloadBuf(payloadLen))
+
+ newName := string(req.NewName)
+ if err := checkSafeName(newName); err != nil {
+ return 0, err
+ }
+
+ renamed, err := c.LookupControlFD(req.Renamed)
+ if err != nil {
+ return 0, err
+ }
+ defer renamed.DecRef(nil)
+
+ newDir, err := c.LookupControlFD(req.NewDir)
+ if err != nil {
+ return 0, err
+ }
+ defer newDir.DecRef(nil)
+ if !newDir.IsDir() {
+ return 0, unix.ENOTDIR
+ }
+
+ // Hold RenameMu for writing during rename, this is important.
+ c.server.RenameMu.Lock()
+ defer c.server.RenameMu.Unlock()
+
+ if renamed.parent == nil {
+ // renamed is root.
+ return 0, unix.EBUSY
+ }
+
+ oldParentPath := renamed.parent.FilePathLocked()
+ oldPath := oldParentPath + "/" + renamed.name
+ if newName == renamed.name && oldParentPath == newDir.FilePathLocked() {
+ // Nothing to do.
+ return 0, nil
+ }
+
+ updateControlFD, cleanUp, err := renamed.impl.RenameLocked(c, newDir.impl, newName)
+ if err != nil {
+ return 0, err
+ }
+
+ c.server.forEachMountPoint(func(root *ControlFD) {
+ if !strings.HasPrefix(oldPath, root.name) {
+ return
+ }
+ pit := fspath.Parse(oldPath[len(root.name):]).Begin
+ root.renameRecursiveLocked(newDir, newName, pit, updateControlFD)
+ })
+
+ if cleanUp != nil {
+ cleanUp()
+ }
+ return 0, nil
+}
+
+// Precondition: rename mutex must be locked for writing.
+func (fd *ControlFD) renameRecursiveLocked(newDir *ControlFD, newName string, pit fspath.Iterator, updateControlFD func(ControlFDImpl)) {
+ if !pit.Ok() {
+ // fd should be renamed.
+ fd.clearParentLocked()
+ fd.setParentLocked(newDir)
+ fd.name = newName
+ if updateControlFD != nil {
+ updateControlFD(fd.impl)
+ }
+ return
+ }
+
+ cur := pit.String()
+ next := pit.Next()
+ // No need to hold fd.childrenMu because RenameMu is locked for writing.
+ for child := fd.children.Front(); child != nil; child = child.Next() {
+ if child.name == cur {
+ child.renameRecursiveLocked(newDir, newName, next, updateControlFD)
+ }
+ }
+}
+
+// Getdents64Handler handles the Getdents64 RPC.
+func Getdents64Handler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ var req Getdents64Req
+ req.UnmarshalUnsafe(comm.PayloadBuf(payloadLen))
+
+ fd, err := c.LookupOpenFD(req.DirFD)
+ if err != nil {
+ return 0, err
+ }
+ defer fd.DecRef(nil)
+ if !fd.controlFD.IsDir() {
+ return 0, unix.ENOTDIR
+ }
+
+ seek0 := false
+ if req.Count < 0 {
+ seek0 = true
+ req.Count = -req.Count
+ }
+ return fd.impl.Getdent64(c, comm, uint32(req.Count), seek0)
+}
+
+// FGetXattrHandler handles the FGetXattr RPC.
+func FGetXattrHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ var req FGetXattrReq
+ req.UnmarshalBytes(comm.PayloadBuf(payloadLen))
+
+ fd, err := c.LookupControlFD(req.FD)
+ if err != nil {
+ return 0, err
+ }
+ defer fd.DecRef(nil)
+ return fd.impl.GetXattr(c, comm, string(req.Name), uint32(req.BufSize))
+}
+
+// FSetXattrHandler handles the FSetXattr RPC.
+func FSetXattrHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ if c.readonly {
+ return 0, unix.EROFS
+ }
+ var req FSetXattrReq
+ req.UnmarshalBytes(comm.PayloadBuf(payloadLen))
+
+ fd, err := c.LookupControlFD(req.FD)
+ if err != nil {
+ return 0, err
+ }
+ defer fd.DecRef(nil)
+ return 0, fd.impl.SetXattr(c, string(req.Name), string(req.Value), uint32(req.Flags))
+}
+
+// FListXattrHandler handles the FListXattr RPC.
+func FListXattrHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ var req FListXattrReq
+ req.UnmarshalUnsafe(comm.PayloadBuf(payloadLen))
+
+ fd, err := c.LookupControlFD(req.FD)
+ if err != nil {
+ return 0, err
+ }
+ defer fd.DecRef(nil)
+ return fd.impl.ListXattr(c, comm, req.Size)
+}
+
+// FRemoveXattrHandler handles the FRemoveXattr RPC.
+func FRemoveXattrHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
+ if c.readonly {
+ return 0, unix.EROFS
+ }
+ var req FRemoveXattrReq
+ req.UnmarshalBytes(comm.PayloadBuf(payloadLen))
+
+ fd, err := c.LookupControlFD(req.FD)
+ if err != nil {
+ return 0, err
+ }
+ defer fd.DecRef(nil)
+ return 0, fd.impl.RemoveXattr(c, comm, string(req.Name))
+}
+
+// checkSafeName validates the name and returns nil or returns an error.
+func checkSafeName(name string) error {
+ if name != "" && !strings.Contains(name, "/") && name != "." && name != ".." {
+ return nil
+ }
+ return unix.EINVAL
+}
diff --git a/pkg/lisafs/lisafs_abi_autogen_unsafe.go b/pkg/lisafs/lisafs_abi_autogen_unsafe.go
index ece422578..828c75a4e 100644
--- a/pkg/lisafs/lisafs_abi_autogen_unsafe.go
+++ b/pkg/lisafs/lisafs_abi_autogen_unsafe.go
@@ -15,17 +15,40 @@ import (
// Marshallable types used by this file.
var _ marshal.Marshallable = (*ChannelResp)(nil)
+var _ marshal.Marshallable = (*ConnectReq)(nil)
var _ marshal.Marshallable = (*ErrorResp)(nil)
+var _ marshal.Marshallable = (*FAllocateReq)(nil)
var _ marshal.Marshallable = (*FDID)(nil)
+var _ marshal.Marshallable = (*FListXattrReq)(nil)
+var _ marshal.Marshallable = (*FStatFSReq)(nil)
+var _ marshal.Marshallable = (*FlushReq)(nil)
var _ marshal.Marshallable = (*GID)(nil)
+var _ marshal.Marshallable = (*Getdents64Req)(nil)
var _ marshal.Marshallable = (*Inode)(nil)
+var _ marshal.Marshallable = (*LinkAtResp)(nil)
var _ marshal.Marshallable = (*MID)(nil)
+var _ marshal.Marshallable = (*MkdirAtResp)(nil)
+var _ marshal.Marshallable = (*MknodAtResp)(nil)
var _ marshal.Marshallable = (*MsgDynamic)(nil)
var _ marshal.Marshallable = (*MsgSimple)(nil)
+var _ marshal.Marshallable = (*OpenAtReq)(nil)
+var _ marshal.Marshallable = (*OpenAtResp)(nil)
+var _ marshal.Marshallable = (*OpenCreateAtResp)(nil)
var _ marshal.Marshallable = (*P9Version)(nil)
+var _ marshal.Marshallable = (*PReadReq)(nil)
+var _ marshal.Marshallable = (*PWriteResp)(nil)
+var _ marshal.Marshallable = (*ReadLinkAtReq)(nil)
+var _ marshal.Marshallable = (*SetStatReq)(nil)
+var _ marshal.Marshallable = (*SetStatResp)(nil)
+var _ marshal.Marshallable = (*StatFS)(nil)
+var _ marshal.Marshallable = (*StatReq)(nil)
+var _ marshal.Marshallable = (*SymlinkAtResp)(nil)
var _ marshal.Marshallable = (*UID)(nil)
var _ marshal.Marshallable = (*channelHeader)(nil)
+var _ marshal.Marshallable = (*createCommon)(nil)
+var _ marshal.Marshallable = (*linux.FileMode)(nil)
var _ marshal.Marshallable = (*linux.Statx)(nil)
+var _ marshal.Marshallable = (*linux.Timespec)(nil)
var _ marshal.Marshallable = (*sockHeader)(nil)
// SizeBytes implements marshal.Marshallable.SizeBytes.
@@ -422,6 +445,135 @@ func (c *ChannelResp) WriteTo(writer io.Writer) (int64, error) {
}
// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (c *ConnectReq) SizeBytes() int {
+ return 4 +
+ (*FDID)(nil).SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (c *ConnectReq) MarshalBytes(dst []byte) {
+ c.FD.MarshalBytes(dst[:c.FD.SizeBytes()])
+ dst = dst[c.FD.SizeBytes():]
+ hostarch.ByteOrder.PutUint32(dst[:4], uint32(c.SockType))
+ dst = dst[4:]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (c *ConnectReq) UnmarshalBytes(src []byte) {
+ c.FD.UnmarshalBytes(src[:c.FD.SizeBytes()])
+ src = src[c.FD.SizeBytes():]
+ c.SockType = uint32(hostarch.ByteOrder.Uint32(src[:4]))
+ src = src[4:]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (c *ConnectReq) Packed() bool {
+ return c.FD.Packed()
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (c *ConnectReq) MarshalUnsafe(dst []byte) {
+ if c.FD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(c), uintptr(c.SizeBytes()))
+ } else {
+ // Type ConnectReq doesn't have a packed layout in memory, fallback to MarshalBytes.
+ c.MarshalBytes(dst)
+ }
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (c *ConnectReq) UnmarshalUnsafe(src []byte) {
+ if c.FD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(c), unsafe.Pointer(&src[0]), uintptr(c.SizeBytes()))
+ } else {
+ // Type ConnectReq doesn't have a packed layout in memory, fallback to UnmarshalBytes.
+ c.UnmarshalBytes(src)
+ }
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (c *ConnectReq) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ if !c.FD.Packed() {
+ // Type ConnectReq doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := cc.CopyScratchBuffer(c.SizeBytes()) // escapes: okay.
+ c.MarshalBytes(buf) // escapes: fallback.
+ return cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(c)))
+ hdr.Len = c.SizeBytes()
+ hdr.Cap = c.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that c
+ // must live until the use above.
+ runtime.KeepAlive(c) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (c *ConnectReq) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return c.CopyOutN(cc, addr, c.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (c *ConnectReq) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ if !c.FD.Packed() {
+ // Type ConnectReq doesn't have a packed layout in memory, fall back to UnmarshalBytes.
+ buf := cc.CopyScratchBuffer(c.SizeBytes()) // escapes: okay.
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Unmarshal unconditionally. If we had a short copy-in, this results in a
+ // partially unmarshalled struct.
+ c.UnmarshalBytes(buf) // escapes: fallback.
+ return length, err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(c)))
+ hdr.Len = c.SizeBytes()
+ hdr.Cap = c.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that c
+ // must live until the use above.
+ runtime.KeepAlive(c) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (c *ConnectReq) WriteTo(writer io.Writer) (int64, error) {
+ if !c.FD.Packed() {
+ // Type ConnectReq doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := make([]byte, c.SizeBytes())
+ c.MarshalBytes(buf)
+ length, err := writer.Write(buf)
+ return int64(length), err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(c)))
+ hdr.Len = c.SizeBytes()
+ hdr.Cap = c.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that c
+ // must live until the use above.
+ runtime.KeepAlive(c) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
func (e *ErrorResp) SizeBytes() int {
return 4
}
@@ -511,6 +663,530 @@ func (e *ErrorResp) WriteTo(writer io.Writer) (int64, error) {
}
// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (f *FAllocateReq) SizeBytes() int {
+ return 28 +
+ (*FDID)(nil).SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (f *FAllocateReq) MarshalBytes(dst []byte) {
+ f.FD.MarshalBytes(dst[:f.FD.SizeBytes()])
+ dst = dst[f.FD.SizeBytes():]
+ // Padding: dst[:sizeof(uint32)] ~= uint32(0)
+ dst = dst[4:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(f.Mode))
+ dst = dst[8:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(f.Offset))
+ dst = dst[8:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(f.Length))
+ dst = dst[8:]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (f *FAllocateReq) UnmarshalBytes(src []byte) {
+ f.FD.UnmarshalBytes(src[:f.FD.SizeBytes()])
+ src = src[f.FD.SizeBytes():]
+ // Padding: var _ uint32 ~= src[:sizeof(uint32)]
+ src = src[4:]
+ f.Mode = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ f.Offset = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ f.Length = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (f *FAllocateReq) Packed() bool {
+ return f.FD.Packed()
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (f *FAllocateReq) MarshalUnsafe(dst []byte) {
+ if f.FD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(f), uintptr(f.SizeBytes()))
+ } else {
+ // Type FAllocateReq doesn't have a packed layout in memory, fallback to MarshalBytes.
+ f.MarshalBytes(dst)
+ }
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (f *FAllocateReq) UnmarshalUnsafe(src []byte) {
+ if f.FD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(f), unsafe.Pointer(&src[0]), uintptr(f.SizeBytes()))
+ } else {
+ // Type FAllocateReq doesn't have a packed layout in memory, fallback to UnmarshalBytes.
+ f.UnmarshalBytes(src)
+ }
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (f *FAllocateReq) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ if !f.FD.Packed() {
+ // Type FAllocateReq doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := cc.CopyScratchBuffer(f.SizeBytes()) // escapes: okay.
+ f.MarshalBytes(buf) // escapes: fallback.
+ return cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(f)))
+ hdr.Len = f.SizeBytes()
+ hdr.Cap = f.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that f
+ // must live until the use above.
+ runtime.KeepAlive(f) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (f *FAllocateReq) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return f.CopyOutN(cc, addr, f.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (f *FAllocateReq) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ if !f.FD.Packed() {
+ // Type FAllocateReq doesn't have a packed layout in memory, fall back to UnmarshalBytes.
+ buf := cc.CopyScratchBuffer(f.SizeBytes()) // escapes: okay.
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Unmarshal unconditionally. If we had a short copy-in, this results in a
+ // partially unmarshalled struct.
+ f.UnmarshalBytes(buf) // escapes: fallback.
+ return length, err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(f)))
+ hdr.Len = f.SizeBytes()
+ hdr.Cap = f.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that f
+ // must live until the use above.
+ runtime.KeepAlive(f) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (f *FAllocateReq) WriteTo(writer io.Writer) (int64, error) {
+ if !f.FD.Packed() {
+ // Type FAllocateReq doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := make([]byte, f.SizeBytes())
+ f.MarshalBytes(buf)
+ length, err := writer.Write(buf)
+ return int64(length), err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(f)))
+ hdr.Len = f.SizeBytes()
+ hdr.Cap = f.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that f
+ // must live until the use above.
+ runtime.KeepAlive(f) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (f *FListXattrReq) SizeBytes() int {
+ return 12 +
+ (*FDID)(nil).SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (f *FListXattrReq) MarshalBytes(dst []byte) {
+ f.FD.MarshalBytes(dst[:f.FD.SizeBytes()])
+ dst = dst[f.FD.SizeBytes():]
+ // Padding: dst[:sizeof(uint32)] ~= uint32(0)
+ dst = dst[4:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(f.Size))
+ dst = dst[8:]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (f *FListXattrReq) UnmarshalBytes(src []byte) {
+ f.FD.UnmarshalBytes(src[:f.FD.SizeBytes()])
+ src = src[f.FD.SizeBytes():]
+ // Padding: var _ uint32 ~= src[:sizeof(uint32)]
+ src = src[4:]
+ f.Size = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (f *FListXattrReq) Packed() bool {
+ return f.FD.Packed()
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (f *FListXattrReq) MarshalUnsafe(dst []byte) {
+ if f.FD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(f), uintptr(f.SizeBytes()))
+ } else {
+ // Type FListXattrReq doesn't have a packed layout in memory, fallback to MarshalBytes.
+ f.MarshalBytes(dst)
+ }
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (f *FListXattrReq) UnmarshalUnsafe(src []byte) {
+ if f.FD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(f), unsafe.Pointer(&src[0]), uintptr(f.SizeBytes()))
+ } else {
+ // Type FListXattrReq doesn't have a packed layout in memory, fallback to UnmarshalBytes.
+ f.UnmarshalBytes(src)
+ }
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (f *FListXattrReq) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ if !f.FD.Packed() {
+ // Type FListXattrReq doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := cc.CopyScratchBuffer(f.SizeBytes()) // escapes: okay.
+ f.MarshalBytes(buf) // escapes: fallback.
+ return cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(f)))
+ hdr.Len = f.SizeBytes()
+ hdr.Cap = f.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that f
+ // must live until the use above.
+ runtime.KeepAlive(f) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (f *FListXattrReq) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return f.CopyOutN(cc, addr, f.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (f *FListXattrReq) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ if !f.FD.Packed() {
+ // Type FListXattrReq doesn't have a packed layout in memory, fall back to UnmarshalBytes.
+ buf := cc.CopyScratchBuffer(f.SizeBytes()) // escapes: okay.
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Unmarshal unconditionally. If we had a short copy-in, this results in a
+ // partially unmarshalled struct.
+ f.UnmarshalBytes(buf) // escapes: fallback.
+ return length, err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(f)))
+ hdr.Len = f.SizeBytes()
+ hdr.Cap = f.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that f
+ // must live until the use above.
+ runtime.KeepAlive(f) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (f *FListXattrReq) WriteTo(writer io.Writer) (int64, error) {
+ if !f.FD.Packed() {
+ // Type FListXattrReq doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := make([]byte, f.SizeBytes())
+ f.MarshalBytes(buf)
+ length, err := writer.Write(buf)
+ return int64(length), err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(f)))
+ hdr.Len = f.SizeBytes()
+ hdr.Cap = f.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that f
+ // must live until the use above.
+ runtime.KeepAlive(f) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (f *FStatFSReq) SizeBytes() int {
+ return 0 +
+ (*FDID)(nil).SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (f *FStatFSReq) MarshalBytes(dst []byte) {
+ f.FD.MarshalBytes(dst[:f.FD.SizeBytes()])
+ dst = dst[f.FD.SizeBytes():]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (f *FStatFSReq) UnmarshalBytes(src []byte) {
+ f.FD.UnmarshalBytes(src[:f.FD.SizeBytes()])
+ src = src[f.FD.SizeBytes():]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (f *FStatFSReq) Packed() bool {
+ return f.FD.Packed()
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (f *FStatFSReq) MarshalUnsafe(dst []byte) {
+ if f.FD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(f), uintptr(f.SizeBytes()))
+ } else {
+ // Type FStatFSReq doesn't have a packed layout in memory, fallback to MarshalBytes.
+ f.MarshalBytes(dst)
+ }
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (f *FStatFSReq) UnmarshalUnsafe(src []byte) {
+ if f.FD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(f), unsafe.Pointer(&src[0]), uintptr(f.SizeBytes()))
+ } else {
+ // Type FStatFSReq doesn't have a packed layout in memory, fallback to UnmarshalBytes.
+ f.UnmarshalBytes(src)
+ }
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (f *FStatFSReq) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ if !f.FD.Packed() {
+ // Type FStatFSReq doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := cc.CopyScratchBuffer(f.SizeBytes()) // escapes: okay.
+ f.MarshalBytes(buf) // escapes: fallback.
+ return cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(f)))
+ hdr.Len = f.SizeBytes()
+ hdr.Cap = f.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that f
+ // must live until the use above.
+ runtime.KeepAlive(f) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (f *FStatFSReq) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return f.CopyOutN(cc, addr, f.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (f *FStatFSReq) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ if !f.FD.Packed() {
+ // Type FStatFSReq doesn't have a packed layout in memory, fall back to UnmarshalBytes.
+ buf := cc.CopyScratchBuffer(f.SizeBytes()) // escapes: okay.
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Unmarshal unconditionally. If we had a short copy-in, this results in a
+ // partially unmarshalled struct.
+ f.UnmarshalBytes(buf) // escapes: fallback.
+ return length, err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(f)))
+ hdr.Len = f.SizeBytes()
+ hdr.Cap = f.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that f
+ // must live until the use above.
+ runtime.KeepAlive(f) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (f *FStatFSReq) WriteTo(writer io.Writer) (int64, error) {
+ if !f.FD.Packed() {
+ // Type FStatFSReq doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := make([]byte, f.SizeBytes())
+ f.MarshalBytes(buf)
+ length, err := writer.Write(buf)
+ return int64(length), err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(f)))
+ hdr.Len = f.SizeBytes()
+ hdr.Cap = f.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that f
+ // must live until the use above.
+ runtime.KeepAlive(f) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (f *FlushReq) SizeBytes() int {
+ return 0 +
+ (*FDID)(nil).SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (f *FlushReq) MarshalBytes(dst []byte) {
+ f.FD.MarshalBytes(dst[:f.FD.SizeBytes()])
+ dst = dst[f.FD.SizeBytes():]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (f *FlushReq) UnmarshalBytes(src []byte) {
+ f.FD.UnmarshalBytes(src[:f.FD.SizeBytes()])
+ src = src[f.FD.SizeBytes():]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (f *FlushReq) Packed() bool {
+ return f.FD.Packed()
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (f *FlushReq) MarshalUnsafe(dst []byte) {
+ if f.FD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(f), uintptr(f.SizeBytes()))
+ } else {
+ // Type FlushReq doesn't have a packed layout in memory, fallback to MarshalBytes.
+ f.MarshalBytes(dst)
+ }
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (f *FlushReq) UnmarshalUnsafe(src []byte) {
+ if f.FD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(f), unsafe.Pointer(&src[0]), uintptr(f.SizeBytes()))
+ } else {
+ // Type FlushReq doesn't have a packed layout in memory, fallback to UnmarshalBytes.
+ f.UnmarshalBytes(src)
+ }
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (f *FlushReq) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ if !f.FD.Packed() {
+ // Type FlushReq doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := cc.CopyScratchBuffer(f.SizeBytes()) // escapes: okay.
+ f.MarshalBytes(buf) // escapes: fallback.
+ return cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(f)))
+ hdr.Len = f.SizeBytes()
+ hdr.Cap = f.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that f
+ // must live until the use above.
+ runtime.KeepAlive(f) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (f *FlushReq) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return f.CopyOutN(cc, addr, f.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (f *FlushReq) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ if !f.FD.Packed() {
+ // Type FlushReq doesn't have a packed layout in memory, fall back to UnmarshalBytes.
+ buf := cc.CopyScratchBuffer(f.SizeBytes()) // escapes: okay.
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Unmarshal unconditionally. If we had a short copy-in, this results in a
+ // partially unmarshalled struct.
+ f.UnmarshalBytes(buf) // escapes: fallback.
+ return length, err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(f)))
+ hdr.Len = f.SizeBytes()
+ hdr.Cap = f.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that f
+ // must live until the use above.
+ runtime.KeepAlive(f) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (f *FlushReq) WriteTo(writer io.Writer) (int64, error) {
+ if !f.FD.Packed() {
+ // Type FlushReq doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := make([]byte, f.SizeBytes())
+ f.MarshalBytes(buf)
+ length, err := writer.Write(buf)
+ return int64(length), err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(f)))
+ hdr.Len = f.SizeBytes()
+ hdr.Cap = f.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that f
+ // must live until the use above.
+ runtime.KeepAlive(f) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
//go:nosplit
func (gid *GID) SizeBytes() int {
return 4
@@ -600,6 +1276,135 @@ func (gid *GID) WriteTo(w io.Writer) (int64, error) {
}
// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (g *Getdents64Req) SizeBytes() int {
+ return 4 +
+ (*FDID)(nil).SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (g *Getdents64Req) MarshalBytes(dst []byte) {
+ g.DirFD.MarshalBytes(dst[:g.DirFD.SizeBytes()])
+ dst = dst[g.DirFD.SizeBytes():]
+ hostarch.ByteOrder.PutUint32(dst[:4], uint32(g.Count))
+ dst = dst[4:]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (g *Getdents64Req) UnmarshalBytes(src []byte) {
+ g.DirFD.UnmarshalBytes(src[:g.DirFD.SizeBytes()])
+ src = src[g.DirFD.SizeBytes():]
+ g.Count = int32(hostarch.ByteOrder.Uint32(src[:4]))
+ src = src[4:]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (g *Getdents64Req) Packed() bool {
+ return g.DirFD.Packed()
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (g *Getdents64Req) MarshalUnsafe(dst []byte) {
+ if g.DirFD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(g), uintptr(g.SizeBytes()))
+ } else {
+ // Type Getdents64Req doesn't have a packed layout in memory, fallback to MarshalBytes.
+ g.MarshalBytes(dst)
+ }
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (g *Getdents64Req) UnmarshalUnsafe(src []byte) {
+ if g.DirFD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(g), unsafe.Pointer(&src[0]), uintptr(g.SizeBytes()))
+ } else {
+ // Type Getdents64Req doesn't have a packed layout in memory, fallback to UnmarshalBytes.
+ g.UnmarshalBytes(src)
+ }
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (g *Getdents64Req) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ if !g.DirFD.Packed() {
+ // Type Getdents64Req doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := cc.CopyScratchBuffer(g.SizeBytes()) // escapes: okay.
+ g.MarshalBytes(buf) // escapes: fallback.
+ return cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(g)))
+ hdr.Len = g.SizeBytes()
+ hdr.Cap = g.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that g
+ // must live until the use above.
+ runtime.KeepAlive(g) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (g *Getdents64Req) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return g.CopyOutN(cc, addr, g.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (g *Getdents64Req) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ if !g.DirFD.Packed() {
+ // Type Getdents64Req doesn't have a packed layout in memory, fall back to UnmarshalBytes.
+ buf := cc.CopyScratchBuffer(g.SizeBytes()) // escapes: okay.
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Unmarshal unconditionally. If we had a short copy-in, this results in a
+ // partially unmarshalled struct.
+ g.UnmarshalBytes(buf) // escapes: fallback.
+ return length, err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(g)))
+ hdr.Len = g.SizeBytes()
+ hdr.Cap = g.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that g
+ // must live until the use above.
+ runtime.KeepAlive(g) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (g *Getdents64Req) WriteTo(writer io.Writer) (int64, error) {
+ if !g.DirFD.Packed() {
+ // Type Getdents64Req doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := make([]byte, g.SizeBytes())
+ g.MarshalBytes(buf)
+ length, err := writer.Write(buf)
+ return int64(length), err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(g)))
+ hdr.Len = g.SizeBytes()
+ hdr.Cap = g.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that g
+ // must live until the use above.
+ runtime.KeepAlive(g) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
func (i *Inode) SizeBytes() int {
return 4 +
(*FDID)(nil).SizeBytes() +
@@ -857,6 +1662,131 @@ func UnmarshalUnsafeInodeSlice(dst []Inode, src []byte) (int, error) {
}
// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (l *LinkAtResp) SizeBytes() int {
+ return 0 +
+ (*Inode)(nil).SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (l *LinkAtResp) MarshalBytes(dst []byte) {
+ l.Link.MarshalBytes(dst[:l.Link.SizeBytes()])
+ dst = dst[l.Link.SizeBytes():]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (l *LinkAtResp) UnmarshalBytes(src []byte) {
+ l.Link.UnmarshalBytes(src[:l.Link.SizeBytes()])
+ src = src[l.Link.SizeBytes():]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (l *LinkAtResp) Packed() bool {
+ return l.Link.Packed()
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (l *LinkAtResp) MarshalUnsafe(dst []byte) {
+ if l.Link.Packed() {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(l), uintptr(l.SizeBytes()))
+ } else {
+ // Type LinkAtResp doesn't have a packed layout in memory, fallback to MarshalBytes.
+ l.MarshalBytes(dst)
+ }
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (l *LinkAtResp) UnmarshalUnsafe(src []byte) {
+ if l.Link.Packed() {
+ gohacks.Memmove(unsafe.Pointer(l), unsafe.Pointer(&src[0]), uintptr(l.SizeBytes()))
+ } else {
+ // Type LinkAtResp doesn't have a packed layout in memory, fallback to UnmarshalBytes.
+ l.UnmarshalBytes(src)
+ }
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (l *LinkAtResp) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ if !l.Link.Packed() {
+ // Type LinkAtResp doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := cc.CopyScratchBuffer(l.SizeBytes()) // escapes: okay.
+ l.MarshalBytes(buf) // escapes: fallback.
+ return cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(l)))
+ hdr.Len = l.SizeBytes()
+ hdr.Cap = l.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that l
+ // must live until the use above.
+ runtime.KeepAlive(l) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (l *LinkAtResp) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return l.CopyOutN(cc, addr, l.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (l *LinkAtResp) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ if !l.Link.Packed() {
+ // Type LinkAtResp doesn't have a packed layout in memory, fall back to UnmarshalBytes.
+ buf := cc.CopyScratchBuffer(l.SizeBytes()) // escapes: okay.
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Unmarshal unconditionally. If we had a short copy-in, this results in a
+ // partially unmarshalled struct.
+ l.UnmarshalBytes(buf) // escapes: fallback.
+ return length, err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(l)))
+ hdr.Len = l.SizeBytes()
+ hdr.Cap = l.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that l
+ // must live until the use above.
+ runtime.KeepAlive(l) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (l *LinkAtResp) WriteTo(writer io.Writer) (int64, error) {
+ if !l.Link.Packed() {
+ // Type LinkAtResp doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := make([]byte, l.SizeBytes())
+ l.MarshalBytes(buf)
+ length, err := writer.Write(buf)
+ return int64(length), err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(l)))
+ hdr.Len = l.SizeBytes()
+ hdr.Cap = l.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that l
+ // must live until the use above.
+ runtime.KeepAlive(l) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
//go:nosplit
func (m *MID) SizeBytes() int {
return 2
@@ -1024,6 +1954,1612 @@ func UnmarshalUnsafeMIDSlice(dst []MID, src []byte) (int, error) {
}
// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (m *MkdirAtResp) SizeBytes() int {
+ return 0 +
+ (*Inode)(nil).SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (m *MkdirAtResp) MarshalBytes(dst []byte) {
+ m.ChildDir.MarshalBytes(dst[:m.ChildDir.SizeBytes()])
+ dst = dst[m.ChildDir.SizeBytes():]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (m *MkdirAtResp) UnmarshalBytes(src []byte) {
+ m.ChildDir.UnmarshalBytes(src[:m.ChildDir.SizeBytes()])
+ src = src[m.ChildDir.SizeBytes():]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (m *MkdirAtResp) Packed() bool {
+ return m.ChildDir.Packed()
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (m *MkdirAtResp) MarshalUnsafe(dst []byte) {
+ if m.ChildDir.Packed() {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(m), uintptr(m.SizeBytes()))
+ } else {
+ // Type MkdirAtResp doesn't have a packed layout in memory, fallback to MarshalBytes.
+ m.MarshalBytes(dst)
+ }
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (m *MkdirAtResp) UnmarshalUnsafe(src []byte) {
+ if m.ChildDir.Packed() {
+ gohacks.Memmove(unsafe.Pointer(m), unsafe.Pointer(&src[0]), uintptr(m.SizeBytes()))
+ } else {
+ // Type MkdirAtResp doesn't have a packed layout in memory, fallback to UnmarshalBytes.
+ m.UnmarshalBytes(src)
+ }
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (m *MkdirAtResp) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ if !m.ChildDir.Packed() {
+ // Type MkdirAtResp doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := cc.CopyScratchBuffer(m.SizeBytes()) // escapes: okay.
+ m.MarshalBytes(buf) // escapes: fallback.
+ return cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(m)))
+ hdr.Len = m.SizeBytes()
+ hdr.Cap = m.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that m
+ // must live until the use above.
+ runtime.KeepAlive(m) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (m *MkdirAtResp) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return m.CopyOutN(cc, addr, m.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (m *MkdirAtResp) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ if !m.ChildDir.Packed() {
+ // Type MkdirAtResp doesn't have a packed layout in memory, fall back to UnmarshalBytes.
+ buf := cc.CopyScratchBuffer(m.SizeBytes()) // escapes: okay.
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Unmarshal unconditionally. If we had a short copy-in, this results in a
+ // partially unmarshalled struct.
+ m.UnmarshalBytes(buf) // escapes: fallback.
+ return length, err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(m)))
+ hdr.Len = m.SizeBytes()
+ hdr.Cap = m.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that m
+ // must live until the use above.
+ runtime.KeepAlive(m) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (m *MkdirAtResp) WriteTo(writer io.Writer) (int64, error) {
+ if !m.ChildDir.Packed() {
+ // Type MkdirAtResp doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := make([]byte, m.SizeBytes())
+ m.MarshalBytes(buf)
+ length, err := writer.Write(buf)
+ return int64(length), err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(m)))
+ hdr.Len = m.SizeBytes()
+ hdr.Cap = m.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that m
+ // must live until the use above.
+ runtime.KeepAlive(m) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (m *MknodAtResp) SizeBytes() int {
+ return 0 +
+ (*Inode)(nil).SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (m *MknodAtResp) MarshalBytes(dst []byte) {
+ m.Child.MarshalBytes(dst[:m.Child.SizeBytes()])
+ dst = dst[m.Child.SizeBytes():]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (m *MknodAtResp) UnmarshalBytes(src []byte) {
+ m.Child.UnmarshalBytes(src[:m.Child.SizeBytes()])
+ src = src[m.Child.SizeBytes():]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (m *MknodAtResp) Packed() bool {
+ return m.Child.Packed()
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (m *MknodAtResp) MarshalUnsafe(dst []byte) {
+ if m.Child.Packed() {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(m), uintptr(m.SizeBytes()))
+ } else {
+ // Type MknodAtResp doesn't have a packed layout in memory, fallback to MarshalBytes.
+ m.MarshalBytes(dst)
+ }
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (m *MknodAtResp) UnmarshalUnsafe(src []byte) {
+ if m.Child.Packed() {
+ gohacks.Memmove(unsafe.Pointer(m), unsafe.Pointer(&src[0]), uintptr(m.SizeBytes()))
+ } else {
+ // Type MknodAtResp doesn't have a packed layout in memory, fallback to UnmarshalBytes.
+ m.UnmarshalBytes(src)
+ }
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (m *MknodAtResp) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ if !m.Child.Packed() {
+ // Type MknodAtResp doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := cc.CopyScratchBuffer(m.SizeBytes()) // escapes: okay.
+ m.MarshalBytes(buf) // escapes: fallback.
+ return cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(m)))
+ hdr.Len = m.SizeBytes()
+ hdr.Cap = m.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that m
+ // must live until the use above.
+ runtime.KeepAlive(m) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (m *MknodAtResp) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return m.CopyOutN(cc, addr, m.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (m *MknodAtResp) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ if !m.Child.Packed() {
+ // Type MknodAtResp doesn't have a packed layout in memory, fall back to UnmarshalBytes.
+ buf := cc.CopyScratchBuffer(m.SizeBytes()) // escapes: okay.
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Unmarshal unconditionally. If we had a short copy-in, this results in a
+ // partially unmarshalled struct.
+ m.UnmarshalBytes(buf) // escapes: fallback.
+ return length, err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(m)))
+ hdr.Len = m.SizeBytes()
+ hdr.Cap = m.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that m
+ // must live until the use above.
+ runtime.KeepAlive(m) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (m *MknodAtResp) WriteTo(writer io.Writer) (int64, error) {
+ if !m.Child.Packed() {
+ // Type MknodAtResp doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := make([]byte, m.SizeBytes())
+ m.MarshalBytes(buf)
+ length, err := writer.Write(buf)
+ return int64(length), err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(m)))
+ hdr.Len = m.SizeBytes()
+ hdr.Cap = m.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that m
+ // must live until the use above.
+ runtime.KeepAlive(m) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (o *OpenAtReq) SizeBytes() int {
+ return 4 +
+ (*FDID)(nil).SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (o *OpenAtReq) MarshalBytes(dst []byte) {
+ o.FD.MarshalBytes(dst[:o.FD.SizeBytes()])
+ dst = dst[o.FD.SizeBytes():]
+ hostarch.ByteOrder.PutUint32(dst[:4], uint32(o.Flags))
+ dst = dst[4:]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (o *OpenAtReq) UnmarshalBytes(src []byte) {
+ o.FD.UnmarshalBytes(src[:o.FD.SizeBytes()])
+ src = src[o.FD.SizeBytes():]
+ o.Flags = uint32(hostarch.ByteOrder.Uint32(src[:4]))
+ src = src[4:]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (o *OpenAtReq) Packed() bool {
+ return o.FD.Packed()
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (o *OpenAtReq) MarshalUnsafe(dst []byte) {
+ if o.FD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(o), uintptr(o.SizeBytes()))
+ } else {
+ // Type OpenAtReq doesn't have a packed layout in memory, fallback to MarshalBytes.
+ o.MarshalBytes(dst)
+ }
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (o *OpenAtReq) UnmarshalUnsafe(src []byte) {
+ if o.FD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(o), unsafe.Pointer(&src[0]), uintptr(o.SizeBytes()))
+ } else {
+ // Type OpenAtReq doesn't have a packed layout in memory, fallback to UnmarshalBytes.
+ o.UnmarshalBytes(src)
+ }
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (o *OpenAtReq) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ if !o.FD.Packed() {
+ // Type OpenAtReq doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := cc.CopyScratchBuffer(o.SizeBytes()) // escapes: okay.
+ o.MarshalBytes(buf) // escapes: fallback.
+ return cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(o)))
+ hdr.Len = o.SizeBytes()
+ hdr.Cap = o.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that o
+ // must live until the use above.
+ runtime.KeepAlive(o) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (o *OpenAtReq) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return o.CopyOutN(cc, addr, o.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (o *OpenAtReq) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ if !o.FD.Packed() {
+ // Type OpenAtReq doesn't have a packed layout in memory, fall back to UnmarshalBytes.
+ buf := cc.CopyScratchBuffer(o.SizeBytes()) // escapes: okay.
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Unmarshal unconditionally. If we had a short copy-in, this results in a
+ // partially unmarshalled struct.
+ o.UnmarshalBytes(buf) // escapes: fallback.
+ return length, err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(o)))
+ hdr.Len = o.SizeBytes()
+ hdr.Cap = o.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that o
+ // must live until the use above.
+ runtime.KeepAlive(o) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (o *OpenAtReq) WriteTo(writer io.Writer) (int64, error) {
+ if !o.FD.Packed() {
+ // Type OpenAtReq doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := make([]byte, o.SizeBytes())
+ o.MarshalBytes(buf)
+ length, err := writer.Write(buf)
+ return int64(length), err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(o)))
+ hdr.Len = o.SizeBytes()
+ hdr.Cap = o.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that o
+ // must live until the use above.
+ runtime.KeepAlive(o) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (o *OpenAtResp) SizeBytes() int {
+ return 0 +
+ (*FDID)(nil).SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (o *OpenAtResp) MarshalBytes(dst []byte) {
+ o.NewFD.MarshalBytes(dst[:o.NewFD.SizeBytes()])
+ dst = dst[o.NewFD.SizeBytes():]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (o *OpenAtResp) UnmarshalBytes(src []byte) {
+ o.NewFD.UnmarshalBytes(src[:o.NewFD.SizeBytes()])
+ src = src[o.NewFD.SizeBytes():]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (o *OpenAtResp) Packed() bool {
+ return o.NewFD.Packed()
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (o *OpenAtResp) MarshalUnsafe(dst []byte) {
+ if o.NewFD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(o), uintptr(o.SizeBytes()))
+ } else {
+ // Type OpenAtResp doesn't have a packed layout in memory, fallback to MarshalBytes.
+ o.MarshalBytes(dst)
+ }
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (o *OpenAtResp) UnmarshalUnsafe(src []byte) {
+ if o.NewFD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(o), unsafe.Pointer(&src[0]), uintptr(o.SizeBytes()))
+ } else {
+ // Type OpenAtResp doesn't have a packed layout in memory, fallback to UnmarshalBytes.
+ o.UnmarshalBytes(src)
+ }
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (o *OpenAtResp) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ if !o.NewFD.Packed() {
+ // Type OpenAtResp doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := cc.CopyScratchBuffer(o.SizeBytes()) // escapes: okay.
+ o.MarshalBytes(buf) // escapes: fallback.
+ return cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(o)))
+ hdr.Len = o.SizeBytes()
+ hdr.Cap = o.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that o
+ // must live until the use above.
+ runtime.KeepAlive(o) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (o *OpenAtResp) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return o.CopyOutN(cc, addr, o.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (o *OpenAtResp) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ if !o.NewFD.Packed() {
+ // Type OpenAtResp doesn't have a packed layout in memory, fall back to UnmarshalBytes.
+ buf := cc.CopyScratchBuffer(o.SizeBytes()) // escapes: okay.
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Unmarshal unconditionally. If we had a short copy-in, this results in a
+ // partially unmarshalled struct.
+ o.UnmarshalBytes(buf) // escapes: fallback.
+ return length, err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(o)))
+ hdr.Len = o.SizeBytes()
+ hdr.Cap = o.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that o
+ // must live until the use above.
+ runtime.KeepAlive(o) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (o *OpenAtResp) WriteTo(writer io.Writer) (int64, error) {
+ if !o.NewFD.Packed() {
+ // Type OpenAtResp doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := make([]byte, o.SizeBytes())
+ o.MarshalBytes(buf)
+ length, err := writer.Write(buf)
+ return int64(length), err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(o)))
+ hdr.Len = o.SizeBytes()
+ hdr.Cap = o.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that o
+ // must live until the use above.
+ runtime.KeepAlive(o) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (o *OpenCreateAtResp) SizeBytes() int {
+ return 4 +
+ (*Inode)(nil).SizeBytes() +
+ (*FDID)(nil).SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (o *OpenCreateAtResp) MarshalBytes(dst []byte) {
+ o.Child.MarshalBytes(dst[:o.Child.SizeBytes()])
+ dst = dst[o.Child.SizeBytes():]
+ o.NewFD.MarshalBytes(dst[:o.NewFD.SizeBytes()])
+ dst = dst[o.NewFD.SizeBytes():]
+ // Padding: dst[:sizeof(uint32)] ~= uint32(0)
+ dst = dst[4:]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (o *OpenCreateAtResp) UnmarshalBytes(src []byte) {
+ o.Child.UnmarshalBytes(src[:o.Child.SizeBytes()])
+ src = src[o.Child.SizeBytes():]
+ o.NewFD.UnmarshalBytes(src[:o.NewFD.SizeBytes()])
+ src = src[o.NewFD.SizeBytes():]
+ // Padding: var _ uint32 ~= src[:sizeof(uint32)]
+ src = src[4:]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (o *OpenCreateAtResp) Packed() bool {
+ return o.Child.Packed() && o.NewFD.Packed()
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (o *OpenCreateAtResp) MarshalUnsafe(dst []byte) {
+ if o.Child.Packed() && o.NewFD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(o), uintptr(o.SizeBytes()))
+ } else {
+ // Type OpenCreateAtResp doesn't have a packed layout in memory, fallback to MarshalBytes.
+ o.MarshalBytes(dst)
+ }
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (o *OpenCreateAtResp) UnmarshalUnsafe(src []byte) {
+ if o.Child.Packed() && o.NewFD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(o), unsafe.Pointer(&src[0]), uintptr(o.SizeBytes()))
+ } else {
+ // Type OpenCreateAtResp doesn't have a packed layout in memory, fallback to UnmarshalBytes.
+ o.UnmarshalBytes(src)
+ }
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (o *OpenCreateAtResp) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ if !o.Child.Packed() && o.NewFD.Packed() {
+ // Type OpenCreateAtResp doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := cc.CopyScratchBuffer(o.SizeBytes()) // escapes: okay.
+ o.MarshalBytes(buf) // escapes: fallback.
+ return cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(o)))
+ hdr.Len = o.SizeBytes()
+ hdr.Cap = o.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that o
+ // must live until the use above.
+ runtime.KeepAlive(o) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (o *OpenCreateAtResp) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return o.CopyOutN(cc, addr, o.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (o *OpenCreateAtResp) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ if !o.Child.Packed() && o.NewFD.Packed() {
+ // Type OpenCreateAtResp doesn't have a packed layout in memory, fall back to UnmarshalBytes.
+ buf := cc.CopyScratchBuffer(o.SizeBytes()) // escapes: okay.
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Unmarshal unconditionally. If we had a short copy-in, this results in a
+ // partially unmarshalled struct.
+ o.UnmarshalBytes(buf) // escapes: fallback.
+ return length, err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(o)))
+ hdr.Len = o.SizeBytes()
+ hdr.Cap = o.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that o
+ // must live until the use above.
+ runtime.KeepAlive(o) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (o *OpenCreateAtResp) WriteTo(writer io.Writer) (int64, error) {
+ if !o.Child.Packed() && o.NewFD.Packed() {
+ // Type OpenCreateAtResp doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := make([]byte, o.SizeBytes())
+ o.MarshalBytes(buf)
+ length, err := writer.Write(buf)
+ return int64(length), err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(o)))
+ hdr.Len = o.SizeBytes()
+ hdr.Cap = o.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that o
+ // must live until the use above.
+ runtime.KeepAlive(o) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (p *PReadReq) SizeBytes() int {
+ return 12 +
+ (*FDID)(nil).SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (p *PReadReq) MarshalBytes(dst []byte) {
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(p.Offset))
+ dst = dst[8:]
+ p.FD.MarshalBytes(dst[:p.FD.SizeBytes()])
+ dst = dst[p.FD.SizeBytes():]
+ hostarch.ByteOrder.PutUint32(dst[:4], uint32(p.Count))
+ dst = dst[4:]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (p *PReadReq) UnmarshalBytes(src []byte) {
+ p.Offset = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ p.FD.UnmarshalBytes(src[:p.FD.SizeBytes()])
+ src = src[p.FD.SizeBytes():]
+ p.Count = uint32(hostarch.ByteOrder.Uint32(src[:4]))
+ src = src[4:]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (p *PReadReq) Packed() bool {
+ return p.FD.Packed()
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (p *PReadReq) MarshalUnsafe(dst []byte) {
+ if p.FD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(p), uintptr(p.SizeBytes()))
+ } else {
+ // Type PReadReq doesn't have a packed layout in memory, fallback to MarshalBytes.
+ p.MarshalBytes(dst)
+ }
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (p *PReadReq) UnmarshalUnsafe(src []byte) {
+ if p.FD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(p), unsafe.Pointer(&src[0]), uintptr(p.SizeBytes()))
+ } else {
+ // Type PReadReq doesn't have a packed layout in memory, fallback to UnmarshalBytes.
+ p.UnmarshalBytes(src)
+ }
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (p *PReadReq) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ if !p.FD.Packed() {
+ // Type PReadReq doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := cc.CopyScratchBuffer(p.SizeBytes()) // escapes: okay.
+ p.MarshalBytes(buf) // escapes: fallback.
+ return cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(p)))
+ hdr.Len = p.SizeBytes()
+ hdr.Cap = p.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that p
+ // must live until the use above.
+ runtime.KeepAlive(p) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (p *PReadReq) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return p.CopyOutN(cc, addr, p.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (p *PReadReq) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ if !p.FD.Packed() {
+ // Type PReadReq doesn't have a packed layout in memory, fall back to UnmarshalBytes.
+ buf := cc.CopyScratchBuffer(p.SizeBytes()) // escapes: okay.
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Unmarshal unconditionally. If we had a short copy-in, this results in a
+ // partially unmarshalled struct.
+ p.UnmarshalBytes(buf) // escapes: fallback.
+ return length, err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(p)))
+ hdr.Len = p.SizeBytes()
+ hdr.Cap = p.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that p
+ // must live until the use above.
+ runtime.KeepAlive(p) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (p *PReadReq) WriteTo(writer io.Writer) (int64, error) {
+ if !p.FD.Packed() {
+ // Type PReadReq doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := make([]byte, p.SizeBytes())
+ p.MarshalBytes(buf)
+ length, err := writer.Write(buf)
+ return int64(length), err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(p)))
+ hdr.Len = p.SizeBytes()
+ hdr.Cap = p.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that p
+ // must live until the use above.
+ runtime.KeepAlive(p) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (p *PWriteResp) SizeBytes() int {
+ return 8
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (p *PWriteResp) MarshalBytes(dst []byte) {
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(p.Count))
+ dst = dst[8:]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (p *PWriteResp) UnmarshalBytes(src []byte) {
+ p.Count = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (p *PWriteResp) Packed() bool {
+ return true
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (p *PWriteResp) MarshalUnsafe(dst []byte) {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(p), uintptr(p.SizeBytes()))
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (p *PWriteResp) UnmarshalUnsafe(src []byte) {
+ gohacks.Memmove(unsafe.Pointer(p), unsafe.Pointer(&src[0]), uintptr(p.SizeBytes()))
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (p *PWriteResp) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(p)))
+ hdr.Len = p.SizeBytes()
+ hdr.Cap = p.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that p
+ // must live until the use above.
+ runtime.KeepAlive(p) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (p *PWriteResp) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return p.CopyOutN(cc, addr, p.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (p *PWriteResp) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(p)))
+ hdr.Len = p.SizeBytes()
+ hdr.Cap = p.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that p
+ // must live until the use above.
+ runtime.KeepAlive(p) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (p *PWriteResp) WriteTo(writer io.Writer) (int64, error) {
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(p)))
+ hdr.Len = p.SizeBytes()
+ hdr.Cap = p.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that p
+ // must live until the use above.
+ runtime.KeepAlive(p) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (r *ReadLinkAtReq) SizeBytes() int {
+ return 0 +
+ (*FDID)(nil).SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (r *ReadLinkAtReq) MarshalBytes(dst []byte) {
+ r.FD.MarshalBytes(dst[:r.FD.SizeBytes()])
+ dst = dst[r.FD.SizeBytes():]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (r *ReadLinkAtReq) UnmarshalBytes(src []byte) {
+ r.FD.UnmarshalBytes(src[:r.FD.SizeBytes()])
+ src = src[r.FD.SizeBytes():]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (r *ReadLinkAtReq) Packed() bool {
+ return r.FD.Packed()
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (r *ReadLinkAtReq) MarshalUnsafe(dst []byte) {
+ if r.FD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(r), uintptr(r.SizeBytes()))
+ } else {
+ // Type ReadLinkAtReq doesn't have a packed layout in memory, fallback to MarshalBytes.
+ r.MarshalBytes(dst)
+ }
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (r *ReadLinkAtReq) UnmarshalUnsafe(src []byte) {
+ if r.FD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(r), unsafe.Pointer(&src[0]), uintptr(r.SizeBytes()))
+ } else {
+ // Type ReadLinkAtReq doesn't have a packed layout in memory, fallback to UnmarshalBytes.
+ r.UnmarshalBytes(src)
+ }
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (r *ReadLinkAtReq) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ if !r.FD.Packed() {
+ // Type ReadLinkAtReq doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := cc.CopyScratchBuffer(r.SizeBytes()) // escapes: okay.
+ r.MarshalBytes(buf) // escapes: fallback.
+ return cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(r)))
+ hdr.Len = r.SizeBytes()
+ hdr.Cap = r.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that r
+ // must live until the use above.
+ runtime.KeepAlive(r) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (r *ReadLinkAtReq) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return r.CopyOutN(cc, addr, r.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (r *ReadLinkAtReq) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ if !r.FD.Packed() {
+ // Type ReadLinkAtReq doesn't have a packed layout in memory, fall back to UnmarshalBytes.
+ buf := cc.CopyScratchBuffer(r.SizeBytes()) // escapes: okay.
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Unmarshal unconditionally. If we had a short copy-in, this results in a
+ // partially unmarshalled struct.
+ r.UnmarshalBytes(buf) // escapes: fallback.
+ return length, err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(r)))
+ hdr.Len = r.SizeBytes()
+ hdr.Cap = r.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that r
+ // must live until the use above.
+ runtime.KeepAlive(r) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (r *ReadLinkAtReq) WriteTo(writer io.Writer) (int64, error) {
+ if !r.FD.Packed() {
+ // Type ReadLinkAtReq doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := make([]byte, r.SizeBytes())
+ r.MarshalBytes(buf)
+ length, err := writer.Write(buf)
+ return int64(length), err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(r)))
+ hdr.Len = r.SizeBytes()
+ hdr.Cap = r.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that r
+ // must live until the use above.
+ runtime.KeepAlive(r) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (s *SetStatReq) SizeBytes() int {
+ return 20 +
+ (*FDID)(nil).SizeBytes() +
+ (*UID)(nil).SizeBytes() +
+ (*GID)(nil).SizeBytes() +
+ (*linux.Timespec)(nil).SizeBytes() +
+ (*linux.Timespec)(nil).SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (s *SetStatReq) MarshalBytes(dst []byte) {
+ s.FD.MarshalBytes(dst[:s.FD.SizeBytes()])
+ dst = dst[s.FD.SizeBytes():]
+ // Padding: dst[:sizeof(uint32)] ~= uint32(0)
+ dst = dst[4:]
+ hostarch.ByteOrder.PutUint32(dst[:4], uint32(s.Mask))
+ dst = dst[4:]
+ hostarch.ByteOrder.PutUint32(dst[:4], uint32(s.Mode))
+ dst = dst[4:]
+ s.UID.MarshalBytes(dst[:s.UID.SizeBytes()])
+ dst = dst[s.UID.SizeBytes():]
+ s.GID.MarshalBytes(dst[:s.GID.SizeBytes()])
+ dst = dst[s.GID.SizeBytes():]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(s.Size))
+ dst = dst[8:]
+ s.Atime.MarshalBytes(dst[:s.Atime.SizeBytes()])
+ dst = dst[s.Atime.SizeBytes():]
+ s.Mtime.MarshalBytes(dst[:s.Mtime.SizeBytes()])
+ dst = dst[s.Mtime.SizeBytes():]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (s *SetStatReq) UnmarshalBytes(src []byte) {
+ s.FD.UnmarshalBytes(src[:s.FD.SizeBytes()])
+ src = src[s.FD.SizeBytes():]
+ // Padding: var _ uint32 ~= src[:sizeof(uint32)]
+ src = src[4:]
+ s.Mask = uint32(hostarch.ByteOrder.Uint32(src[:4]))
+ src = src[4:]
+ s.Mode = uint32(hostarch.ByteOrder.Uint32(src[:4]))
+ src = src[4:]
+ s.UID.UnmarshalBytes(src[:s.UID.SizeBytes()])
+ src = src[s.UID.SizeBytes():]
+ s.GID.UnmarshalBytes(src[:s.GID.SizeBytes()])
+ src = src[s.GID.SizeBytes():]
+ s.Size = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ s.Atime.UnmarshalBytes(src[:s.Atime.SizeBytes()])
+ src = src[s.Atime.SizeBytes():]
+ s.Mtime.UnmarshalBytes(src[:s.Mtime.SizeBytes()])
+ src = src[s.Mtime.SizeBytes():]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (s *SetStatReq) Packed() bool {
+ return s.Atime.Packed() && s.FD.Packed() && s.GID.Packed() && s.Mtime.Packed() && s.UID.Packed()
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (s *SetStatReq) MarshalUnsafe(dst []byte) {
+ if s.Atime.Packed() && s.FD.Packed() && s.GID.Packed() && s.Mtime.Packed() && s.UID.Packed() {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(s), uintptr(s.SizeBytes()))
+ } else {
+ // Type SetStatReq doesn't have a packed layout in memory, fallback to MarshalBytes.
+ s.MarshalBytes(dst)
+ }
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (s *SetStatReq) UnmarshalUnsafe(src []byte) {
+ if s.Atime.Packed() && s.FD.Packed() && s.GID.Packed() && s.Mtime.Packed() && s.UID.Packed() {
+ gohacks.Memmove(unsafe.Pointer(s), unsafe.Pointer(&src[0]), uintptr(s.SizeBytes()))
+ } else {
+ // Type SetStatReq doesn't have a packed layout in memory, fallback to UnmarshalBytes.
+ s.UnmarshalBytes(src)
+ }
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (s *SetStatReq) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ if !s.Atime.Packed() && s.FD.Packed() && s.GID.Packed() && s.Mtime.Packed() && s.UID.Packed() {
+ // Type SetStatReq doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := cc.CopyScratchBuffer(s.SizeBytes()) // escapes: okay.
+ s.MarshalBytes(buf) // escapes: fallback.
+ return cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(s)))
+ hdr.Len = s.SizeBytes()
+ hdr.Cap = s.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that s
+ // must live until the use above.
+ runtime.KeepAlive(s) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (s *SetStatReq) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return s.CopyOutN(cc, addr, s.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (s *SetStatReq) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ if !s.Atime.Packed() && s.FD.Packed() && s.GID.Packed() && s.Mtime.Packed() && s.UID.Packed() {
+ // Type SetStatReq doesn't have a packed layout in memory, fall back to UnmarshalBytes.
+ buf := cc.CopyScratchBuffer(s.SizeBytes()) // escapes: okay.
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Unmarshal unconditionally. If we had a short copy-in, this results in a
+ // partially unmarshalled struct.
+ s.UnmarshalBytes(buf) // escapes: fallback.
+ return length, err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(s)))
+ hdr.Len = s.SizeBytes()
+ hdr.Cap = s.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that s
+ // must live until the use above.
+ runtime.KeepAlive(s) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (s *SetStatReq) WriteTo(writer io.Writer) (int64, error) {
+ if !s.Atime.Packed() && s.FD.Packed() && s.GID.Packed() && s.Mtime.Packed() && s.UID.Packed() {
+ // Type SetStatReq doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := make([]byte, s.SizeBytes())
+ s.MarshalBytes(buf)
+ length, err := writer.Write(buf)
+ return int64(length), err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(s)))
+ hdr.Len = s.SizeBytes()
+ hdr.Cap = s.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that s
+ // must live until the use above.
+ runtime.KeepAlive(s) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (s *SetStatResp) SizeBytes() int {
+ return 8
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (s *SetStatResp) MarshalBytes(dst []byte) {
+ hostarch.ByteOrder.PutUint32(dst[:4], uint32(s.FailureMask))
+ dst = dst[4:]
+ hostarch.ByteOrder.PutUint32(dst[:4], uint32(s.FailureErrNo))
+ dst = dst[4:]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (s *SetStatResp) UnmarshalBytes(src []byte) {
+ s.FailureMask = uint32(hostarch.ByteOrder.Uint32(src[:4]))
+ src = src[4:]
+ s.FailureErrNo = uint32(hostarch.ByteOrder.Uint32(src[:4]))
+ src = src[4:]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (s *SetStatResp) Packed() bool {
+ return true
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (s *SetStatResp) MarshalUnsafe(dst []byte) {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(s), uintptr(s.SizeBytes()))
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (s *SetStatResp) UnmarshalUnsafe(src []byte) {
+ gohacks.Memmove(unsafe.Pointer(s), unsafe.Pointer(&src[0]), uintptr(s.SizeBytes()))
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (s *SetStatResp) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(s)))
+ hdr.Len = s.SizeBytes()
+ hdr.Cap = s.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that s
+ // must live until the use above.
+ runtime.KeepAlive(s) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (s *SetStatResp) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return s.CopyOutN(cc, addr, s.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (s *SetStatResp) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(s)))
+ hdr.Len = s.SizeBytes()
+ hdr.Cap = s.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that s
+ // must live until the use above.
+ runtime.KeepAlive(s) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (s *SetStatResp) WriteTo(writer io.Writer) (int64, error) {
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(s)))
+ hdr.Len = s.SizeBytes()
+ hdr.Cap = s.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that s
+ // must live until the use above.
+ runtime.KeepAlive(s) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (s *StatFS) SizeBytes() int {
+ return 64
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (s *StatFS) MarshalBytes(dst []byte) {
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(s.Type))
+ dst = dst[8:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(s.BlockSize))
+ dst = dst[8:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(s.Blocks))
+ dst = dst[8:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(s.BlocksFree))
+ dst = dst[8:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(s.BlocksAvailable))
+ dst = dst[8:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(s.Files))
+ dst = dst[8:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(s.FilesFree))
+ dst = dst[8:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(s.NameLength))
+ dst = dst[8:]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (s *StatFS) UnmarshalBytes(src []byte) {
+ s.Type = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ s.BlockSize = int64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ s.Blocks = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ s.BlocksFree = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ s.BlocksAvailable = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ s.Files = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ s.FilesFree = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ s.NameLength = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (s *StatFS) Packed() bool {
+ return true
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (s *StatFS) MarshalUnsafe(dst []byte) {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(s), uintptr(s.SizeBytes()))
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (s *StatFS) UnmarshalUnsafe(src []byte) {
+ gohacks.Memmove(unsafe.Pointer(s), unsafe.Pointer(&src[0]), uintptr(s.SizeBytes()))
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (s *StatFS) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(s)))
+ hdr.Len = s.SizeBytes()
+ hdr.Cap = s.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that s
+ // must live until the use above.
+ runtime.KeepAlive(s) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (s *StatFS) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return s.CopyOutN(cc, addr, s.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (s *StatFS) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(s)))
+ hdr.Len = s.SizeBytes()
+ hdr.Cap = s.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that s
+ // must live until the use above.
+ runtime.KeepAlive(s) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (s *StatFS) WriteTo(writer io.Writer) (int64, error) {
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(s)))
+ hdr.Len = s.SizeBytes()
+ hdr.Cap = s.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that s
+ // must live until the use above.
+ runtime.KeepAlive(s) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (s *StatReq) SizeBytes() int {
+ return 0 +
+ (*FDID)(nil).SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (s *StatReq) MarshalBytes(dst []byte) {
+ s.FD.MarshalBytes(dst[:s.FD.SizeBytes()])
+ dst = dst[s.FD.SizeBytes():]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (s *StatReq) UnmarshalBytes(src []byte) {
+ s.FD.UnmarshalBytes(src[:s.FD.SizeBytes()])
+ src = src[s.FD.SizeBytes():]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (s *StatReq) Packed() bool {
+ return s.FD.Packed()
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (s *StatReq) MarshalUnsafe(dst []byte) {
+ if s.FD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(s), uintptr(s.SizeBytes()))
+ } else {
+ // Type StatReq doesn't have a packed layout in memory, fallback to MarshalBytes.
+ s.MarshalBytes(dst)
+ }
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (s *StatReq) UnmarshalUnsafe(src []byte) {
+ if s.FD.Packed() {
+ gohacks.Memmove(unsafe.Pointer(s), unsafe.Pointer(&src[0]), uintptr(s.SizeBytes()))
+ } else {
+ // Type StatReq doesn't have a packed layout in memory, fallback to UnmarshalBytes.
+ s.UnmarshalBytes(src)
+ }
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (s *StatReq) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ if !s.FD.Packed() {
+ // Type StatReq doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := cc.CopyScratchBuffer(s.SizeBytes()) // escapes: okay.
+ s.MarshalBytes(buf) // escapes: fallback.
+ return cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(s)))
+ hdr.Len = s.SizeBytes()
+ hdr.Cap = s.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that s
+ // must live until the use above.
+ runtime.KeepAlive(s) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (s *StatReq) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return s.CopyOutN(cc, addr, s.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (s *StatReq) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ if !s.FD.Packed() {
+ // Type StatReq doesn't have a packed layout in memory, fall back to UnmarshalBytes.
+ buf := cc.CopyScratchBuffer(s.SizeBytes()) // escapes: okay.
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Unmarshal unconditionally. If we had a short copy-in, this results in a
+ // partially unmarshalled struct.
+ s.UnmarshalBytes(buf) // escapes: fallback.
+ return length, err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(s)))
+ hdr.Len = s.SizeBytes()
+ hdr.Cap = s.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that s
+ // must live until the use above.
+ runtime.KeepAlive(s) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (s *StatReq) WriteTo(writer io.Writer) (int64, error) {
+ if !s.FD.Packed() {
+ // Type StatReq doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := make([]byte, s.SizeBytes())
+ s.MarshalBytes(buf)
+ length, err := writer.Write(buf)
+ return int64(length), err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(s)))
+ hdr.Len = s.SizeBytes()
+ hdr.Cap = s.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that s
+ // must live until the use above.
+ runtime.KeepAlive(s) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (s *SymlinkAtResp) SizeBytes() int {
+ return 0 +
+ (*Inode)(nil).SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (s *SymlinkAtResp) MarshalBytes(dst []byte) {
+ s.Symlink.MarshalBytes(dst[:s.Symlink.SizeBytes()])
+ dst = dst[s.Symlink.SizeBytes():]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (s *SymlinkAtResp) UnmarshalBytes(src []byte) {
+ s.Symlink.UnmarshalBytes(src[:s.Symlink.SizeBytes()])
+ src = src[s.Symlink.SizeBytes():]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (s *SymlinkAtResp) Packed() bool {
+ return s.Symlink.Packed()
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (s *SymlinkAtResp) MarshalUnsafe(dst []byte) {
+ if s.Symlink.Packed() {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(s), uintptr(s.SizeBytes()))
+ } else {
+ // Type SymlinkAtResp doesn't have a packed layout in memory, fallback to MarshalBytes.
+ s.MarshalBytes(dst)
+ }
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (s *SymlinkAtResp) UnmarshalUnsafe(src []byte) {
+ if s.Symlink.Packed() {
+ gohacks.Memmove(unsafe.Pointer(s), unsafe.Pointer(&src[0]), uintptr(s.SizeBytes()))
+ } else {
+ // Type SymlinkAtResp doesn't have a packed layout in memory, fallback to UnmarshalBytes.
+ s.UnmarshalBytes(src)
+ }
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (s *SymlinkAtResp) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ if !s.Symlink.Packed() {
+ // Type SymlinkAtResp doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := cc.CopyScratchBuffer(s.SizeBytes()) // escapes: okay.
+ s.MarshalBytes(buf) // escapes: fallback.
+ return cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(s)))
+ hdr.Len = s.SizeBytes()
+ hdr.Cap = s.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that s
+ // must live until the use above.
+ runtime.KeepAlive(s) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (s *SymlinkAtResp) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return s.CopyOutN(cc, addr, s.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (s *SymlinkAtResp) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ if !s.Symlink.Packed() {
+ // Type SymlinkAtResp doesn't have a packed layout in memory, fall back to UnmarshalBytes.
+ buf := cc.CopyScratchBuffer(s.SizeBytes()) // escapes: okay.
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Unmarshal unconditionally. If we had a short copy-in, this results in a
+ // partially unmarshalled struct.
+ s.UnmarshalBytes(buf) // escapes: fallback.
+ return length, err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(s)))
+ hdr.Len = s.SizeBytes()
+ hdr.Cap = s.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that s
+ // must live until the use above.
+ runtime.KeepAlive(s) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (s *SymlinkAtResp) WriteTo(writer io.Writer) (int64, error) {
+ if !s.Symlink.Packed() {
+ // Type SymlinkAtResp doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := make([]byte, s.SizeBytes())
+ s.MarshalBytes(buf)
+ length, err := writer.Write(buf)
+ return int64(length), err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(s)))
+ hdr.Len = s.SizeBytes()
+ hdr.Cap = s.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that s
+ // must live until the use above.
+ runtime.KeepAlive(s) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
//go:nosplit
func (uid *UID) SizeBytes() int {
return 4
@@ -1112,6 +3648,150 @@ func (uid *UID) WriteTo(w io.Writer) (int64, error) {
return int64(length), err
}
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (c *createCommon) SizeBytes() int {
+ return 2 +
+ (*FDID)(nil).SizeBytes() +
+ (*linux.FileMode)(nil).SizeBytes() +
+ (*UID)(nil).SizeBytes() +
+ (*GID)(nil).SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (c *createCommon) MarshalBytes(dst []byte) {
+ c.DirFD.MarshalBytes(dst[:c.DirFD.SizeBytes()])
+ dst = dst[c.DirFD.SizeBytes():]
+ c.Mode.MarshalBytes(dst[:c.Mode.SizeBytes()])
+ dst = dst[c.Mode.SizeBytes():]
+ // Padding: dst[:sizeof(uint16)] ~= uint16(0)
+ dst = dst[2:]
+ c.UID.MarshalBytes(dst[:c.UID.SizeBytes()])
+ dst = dst[c.UID.SizeBytes():]
+ c.GID.MarshalBytes(dst[:c.GID.SizeBytes()])
+ dst = dst[c.GID.SizeBytes():]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (c *createCommon) UnmarshalBytes(src []byte) {
+ c.DirFD.UnmarshalBytes(src[:c.DirFD.SizeBytes()])
+ src = src[c.DirFD.SizeBytes():]
+ c.Mode.UnmarshalBytes(src[:c.Mode.SizeBytes()])
+ src = src[c.Mode.SizeBytes():]
+ // Padding: var _ uint16 ~= src[:sizeof(uint16)]
+ src = src[2:]
+ c.UID.UnmarshalBytes(src[:c.UID.SizeBytes()])
+ src = src[c.UID.SizeBytes():]
+ c.GID.UnmarshalBytes(src[:c.GID.SizeBytes()])
+ src = src[c.GID.SizeBytes():]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (c *createCommon) Packed() bool {
+ return c.DirFD.Packed() && c.GID.Packed() && c.Mode.Packed() && c.UID.Packed()
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (c *createCommon) MarshalUnsafe(dst []byte) {
+ if c.DirFD.Packed() && c.GID.Packed() && c.Mode.Packed() && c.UID.Packed() {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(c), uintptr(c.SizeBytes()))
+ } else {
+ // Type createCommon doesn't have a packed layout in memory, fallback to MarshalBytes.
+ c.MarshalBytes(dst)
+ }
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (c *createCommon) UnmarshalUnsafe(src []byte) {
+ if c.DirFD.Packed() && c.GID.Packed() && c.Mode.Packed() && c.UID.Packed() {
+ gohacks.Memmove(unsafe.Pointer(c), unsafe.Pointer(&src[0]), uintptr(c.SizeBytes()))
+ } else {
+ // Type createCommon doesn't have a packed layout in memory, fallback to UnmarshalBytes.
+ c.UnmarshalBytes(src)
+ }
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (c *createCommon) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ if !c.DirFD.Packed() && c.GID.Packed() && c.Mode.Packed() && c.UID.Packed() {
+ // Type createCommon doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := cc.CopyScratchBuffer(c.SizeBytes()) // escapes: okay.
+ c.MarshalBytes(buf) // escapes: fallback.
+ return cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(c)))
+ hdr.Len = c.SizeBytes()
+ hdr.Cap = c.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that c
+ // must live until the use above.
+ runtime.KeepAlive(c) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (c *createCommon) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return c.CopyOutN(cc, addr, c.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (c *createCommon) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ if !c.DirFD.Packed() && c.GID.Packed() && c.Mode.Packed() && c.UID.Packed() {
+ // Type createCommon doesn't have a packed layout in memory, fall back to UnmarshalBytes.
+ buf := cc.CopyScratchBuffer(c.SizeBytes()) // escapes: okay.
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Unmarshal unconditionally. If we had a short copy-in, this results in a
+ // partially unmarshalled struct.
+ c.UnmarshalBytes(buf) // escapes: fallback.
+ return length, err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(c)))
+ hdr.Len = c.SizeBytes()
+ hdr.Cap = c.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that c
+ // must live until the use above.
+ runtime.KeepAlive(c) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (c *createCommon) WriteTo(writer io.Writer) (int64, error) {
+ if !c.DirFD.Packed() && c.GID.Packed() && c.Mode.Packed() && c.UID.Packed() {
+ // Type createCommon doesn't have a packed layout in memory, fall back to MarshalBytes.
+ buf := make([]byte, c.SizeBytes())
+ c.MarshalBytes(buf)
+ length, err := writer.Write(buf)
+ return int64(length), err
+ }
+
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(c)))
+ hdr.Len = c.SizeBytes()
+ hdr.Cap = c.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that c
+ // must live until the use above.
+ runtime.KeepAlive(c) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
// Packed implements marshal.Marshallable.Packed.
//go:nosplit
func (m *MsgDynamic) Packed() bool {
diff --git a/pkg/lisafs/message.go b/pkg/lisafs/message.go
index 55fd2c0b1..722afd0be 100644
--- a/pkg/lisafs/message.go
+++ b/pkg/lisafs/message.go
@@ -46,6 +46,94 @@ const (
// Channel requests to start a new communicational channel.
Channel MID = 2
+
+ // FStat requests the stat(2) results for a specified file.
+ FStat MID = 3
+
+ // SetStat requests to change file attributes. Note that there is no one
+ // corresponding Linux syscall. This is a conglomeration of fchmod(2),
+ // fchown(2), ftruncate(2) and futimesat(2).
+ SetStat MID = 4
+
+ // Walk requests to walk the specified path starting from the specified
+ // directory. Server-side path traversal is terminated preemptively on
+ // symlinks entries because they can cause non-linear traversal.
+ Walk MID = 5
+
+ // WalkStat is the same as Walk, except the following differences:
+ // * If the first path component is "", then it also returns stat results
+ // for the directory where the walk starts.
+ // * Does not return Inode, just the Stat results for each path component.
+ WalkStat MID = 6
+
+ // OpenAt is analogous to openat(2). It does not perform any walk. It merely
+ // duplicates the control FD with the open flags passed.
+ OpenAt MID = 7
+
+ // OpenCreateAt is analogous to openat(2) with O_CREAT|O_EXCL added to flags.
+ // It also returns the newly created file inode.
+ OpenCreateAt MID = 8
+
+ // Close is analogous to close(2) but can work on multiple FDs.
+ Close MID = 9
+
+ // FSync is analogous to fsync(2) but can work on multiple FDs.
+ FSync MID = 10
+
+ // PWrite is analogous to pwrite(2).
+ PWrite MID = 11
+
+ // PRead is analogous to pread(2).
+ PRead MID = 12
+
+ // MkdirAt is analogous to mkdirat(2).
+ MkdirAt MID = 13
+
+ // MknodAt is analogous to mknodat(2).
+ MknodAt MID = 14
+
+ // SymlinkAt is analogous to symlinkat(2).
+ SymlinkAt MID = 15
+
+ // LinkAt is analogous to linkat(2).
+ LinkAt MID = 16
+
+ // FStatFS is analogous to fstatfs(2).
+ FStatFS MID = 17
+
+ // FAllocate is analogous to fallocate(2).
+ FAllocate MID = 18
+
+ // ReadLinkAt is analogous to readlinkat(2).
+ ReadLinkAt MID = 19
+
+ // Flush cleans up the file state. Its behavior is implementation
+ // dependent and might not even be supported in server implementations.
+ Flush MID = 20
+
+ // Connect is loosely analogous to connect(2).
+ Connect MID = 21
+
+ // UnlinkAt is analogous to unlinkat(2).
+ UnlinkAt MID = 22
+
+ // RenameAt is loosely analogous to renameat(2).
+ RenameAt MID = 23
+
+ // Getdents64 is analogous to getdents64(2).
+ Getdents64 MID = 24
+
+ // FGetXattr is analogous to fgetxattr(2).
+ FGetXattr MID = 25
+
+ // FSetXattr is analogous to fsetxattr(2).
+ FSetXattr MID = 26
+
+ // FListXattr is analogous to flistxattr(2).
+ FListXattr MID = 27
+
+ // FRemoveXattr is analogous to fremovexattr(2).
+ FRemoveXattr MID = 28
)
const (
@@ -256,3 +344,908 @@ type ChannelResp struct {
type ErrorResp struct {
errno uint32
}
+
+// StatReq requests the stat results for the specified FD.
+//
+// +marshal
+type StatReq struct {
+ FD FDID
+}
+
+// SetStatReq is used to set attributeds on FDs.
+//
+// +marshal
+type SetStatReq struct {
+ FD FDID
+ _ uint32
+ Mask uint32
+ Mode uint32 // Only permissions part is settable.
+ UID UID
+ GID GID
+ Size uint64
+ Atime linux.Timespec
+ Mtime linux.Timespec
+}
+
+// SetStatResp is used to communicate SetStat results. It contains a mask
+// representing the failed changes. It also contains the errno of the failed
+// set attribute operation. If multiple operations failed then any of those
+// errnos can be returned.
+//
+// +marshal
+type SetStatResp struct {
+ FailureMask uint32
+ FailureErrNo uint32
+}
+
+// WalkReq is used to request to walk multiple path components at once. This
+// is used for both Walk and WalkStat.
+type WalkReq struct {
+ DirFD FDID
+ Path StringArray
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (w *WalkReq) SizeBytes() int {
+ return w.DirFD.SizeBytes() + w.Path.SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (w *WalkReq) MarshalBytes(dst []byte) {
+ w.DirFD.MarshalUnsafe(dst)
+ dst = dst[w.DirFD.SizeBytes():]
+ w.Path.MarshalBytes(dst)
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (w *WalkReq) UnmarshalBytes(src []byte) {
+ w.DirFD.UnmarshalUnsafe(src)
+ src = src[w.DirFD.SizeBytes():]
+ w.Path.UnmarshalBytes(src)
+}
+
+// WalkStatus is used to indicate the reason for partial/unsuccessful server
+// side Walk operations. Please note that partial/unsuccessful walk operations
+// do not necessarily fail the RPC. The RPC is successful with a failure hint
+// which can be used by the client to infer server-side state.
+type WalkStatus = primitive.Uint8
+
+const (
+ // WalkSuccess indicates that all path components were successfully walked.
+ WalkSuccess WalkStatus = iota
+
+ // WalkComponentDoesNotExist indicates that the walk was prematurely
+ // terminated because an intermediate path component does not exist on
+ // server. The results of all previous existing path components is returned.
+ WalkComponentDoesNotExist
+
+ // WalkComponentSymlink indicates that the walk was prematurely
+ // terminated because an intermediate path component was a symlink. It is not
+ // safe to resolve symlinks remotely (unaware of mount points).
+ WalkComponentSymlink
+)
+
+// WalkResp is used to communicate the inodes walked by the server.
+type WalkResp struct {
+ Status WalkStatus
+ Inodes []Inode
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (w *WalkResp) SizeBytes() int {
+ return w.Status.SizeBytes() +
+ (*primitive.Uint32)(nil).SizeBytes() + (len(w.Inodes) * (*Inode)(nil).SizeBytes())
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (w *WalkResp) MarshalBytes(dst []byte) {
+ w.Status.MarshalUnsafe(dst)
+ dst = dst[w.Status.SizeBytes():]
+
+ numInodes := primitive.Uint32(len(w.Inodes))
+ numInodes.MarshalUnsafe(dst)
+ dst = dst[numInodes.SizeBytes():]
+
+ MarshalUnsafeInodeSlice(w.Inodes, dst)
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (w *WalkResp) UnmarshalBytes(src []byte) {
+ w.Status.UnmarshalUnsafe(src)
+ src = src[w.Status.SizeBytes():]
+
+ var numInodes primitive.Uint32
+ numInodes.UnmarshalUnsafe(src)
+ src = src[numInodes.SizeBytes():]
+
+ if cap(w.Inodes) < int(numInodes) {
+ w.Inodes = make([]Inode, numInodes)
+ } else {
+ w.Inodes = w.Inodes[:numInodes]
+ }
+ UnmarshalUnsafeInodeSlice(w.Inodes, src)
+}
+
+// WalkStatResp is used to communicate stat results for WalkStat.
+type WalkStatResp struct {
+ Stats []linux.Statx
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (w *WalkStatResp) SizeBytes() int {
+ return (*primitive.Uint32)(nil).SizeBytes() + (len(w.Stats) * linux.SizeOfStatx)
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (w *WalkStatResp) MarshalBytes(dst []byte) {
+ numStats := primitive.Uint32(len(w.Stats))
+ numStats.MarshalUnsafe(dst)
+ dst = dst[numStats.SizeBytes():]
+
+ linux.MarshalUnsafeStatxSlice(w.Stats, dst)
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (w *WalkStatResp) UnmarshalBytes(src []byte) {
+ var numStats primitive.Uint32
+ numStats.UnmarshalUnsafe(src)
+ src = src[numStats.SizeBytes():]
+
+ if cap(w.Stats) < int(numStats) {
+ w.Stats = make([]linux.Statx, numStats)
+ } else {
+ w.Stats = w.Stats[:numStats]
+ }
+ linux.UnmarshalUnsafeStatxSlice(w.Stats, src)
+}
+
+// OpenAtReq is used to open existing FDs with the specified flags.
+//
+// +marshal
+type OpenAtReq struct {
+ FD FDID
+ Flags uint32
+}
+
+// OpenAtResp is used to communicate the newly created FD.
+//
+// +marshal
+type OpenAtResp struct {
+ NewFD FDID
+}
+
+// +marshal
+type createCommon struct {
+ DirFD FDID
+ Mode linux.FileMode
+ _ uint16 // Need to make struct packed.
+ UID UID
+ GID GID
+}
+
+// OpenCreateAtReq is used to make OpenCreateAt requests.
+type OpenCreateAtReq struct {
+ createCommon
+ Name SizedString
+ Flags primitive.Uint32
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (o *OpenCreateAtReq) SizeBytes() int {
+ return o.createCommon.SizeBytes() + o.Name.SizeBytes() + o.Flags.SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (o *OpenCreateAtReq) MarshalBytes(dst []byte) {
+ o.createCommon.MarshalUnsafe(dst)
+ dst = dst[o.createCommon.SizeBytes():]
+ o.Name.MarshalBytes(dst)
+ dst = dst[o.Name.SizeBytes():]
+ o.Flags.MarshalUnsafe(dst)
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (o *OpenCreateAtReq) UnmarshalBytes(src []byte) {
+ o.createCommon.UnmarshalUnsafe(src)
+ src = src[o.createCommon.SizeBytes():]
+ o.Name.UnmarshalBytes(src)
+ src = src[o.Name.SizeBytes():]
+ o.Flags.UnmarshalUnsafe(src)
+}
+
+// OpenCreateAtResp is used to communicate successful OpenCreateAt results.
+//
+// +marshal
+type OpenCreateAtResp struct {
+ Child Inode
+ NewFD FDID
+ _ uint32 // Need to make struct packed.
+}
+
+// FdArray is a utility struct which implements a marshallable type for
+// communicating an array of FDIDs. In memory, the array data is preceded by a
+// uint32 denoting the array length.
+type FdArray []FDID
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (f *FdArray) SizeBytes() int {
+ return (*primitive.Uint32)(nil).SizeBytes() + (len(*f) * (*FDID)(nil).SizeBytes())
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (f *FdArray) MarshalBytes(dst []byte) {
+ arrLen := primitive.Uint32(len(*f))
+ arrLen.MarshalUnsafe(dst)
+ dst = dst[arrLen.SizeBytes():]
+ MarshalUnsafeFDIDSlice(*f, dst)
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (f *FdArray) UnmarshalBytes(src []byte) {
+ var arrLen primitive.Uint32
+ arrLen.UnmarshalUnsafe(src)
+ src = src[arrLen.SizeBytes():]
+ if cap(*f) < int(arrLen) {
+ *f = make(FdArray, arrLen)
+ } else {
+ *f = (*f)[:arrLen]
+ }
+ UnmarshalUnsafeFDIDSlice(*f, src)
+}
+
+// CloseReq is used to close(2) FDs.
+type CloseReq struct {
+ FDs FdArray
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (c *CloseReq) SizeBytes() int {
+ return c.FDs.SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (c *CloseReq) MarshalBytes(dst []byte) {
+ c.FDs.MarshalBytes(dst)
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (c *CloseReq) UnmarshalBytes(src []byte) {
+ c.FDs.UnmarshalBytes(src)
+}
+
+// FsyncReq is used to fsync(2) FDs.
+type FsyncReq struct {
+ FDs FdArray
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (f *FsyncReq) SizeBytes() int {
+ return f.FDs.SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (f *FsyncReq) MarshalBytes(dst []byte) {
+ f.FDs.MarshalBytes(dst)
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (f *FsyncReq) UnmarshalBytes(src []byte) {
+ f.FDs.UnmarshalBytes(src)
+}
+
+// PReadReq is used to pread(2) on an FD.
+//
+// +marshal
+type PReadReq struct {
+ Offset uint64
+ FD FDID
+ Count uint32
+}
+
+// PReadResp is used to return the result of pread(2).
+type PReadResp struct {
+ NumBytes primitive.Uint32
+ Buf []byte
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (r *PReadResp) SizeBytes() int {
+ return r.NumBytes.SizeBytes() + int(r.NumBytes)
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (r *PReadResp) MarshalBytes(dst []byte) {
+ r.NumBytes.MarshalUnsafe(dst)
+ dst = dst[r.NumBytes.SizeBytes():]
+ copy(dst[:r.NumBytes], r.Buf[:r.NumBytes])
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (r *PReadResp) UnmarshalBytes(src []byte) {
+ r.NumBytes.UnmarshalUnsafe(src)
+ src = src[r.NumBytes.SizeBytes():]
+
+ // We expect the client to have already allocated r.Buf. r.Buf probably
+ // (optimally) points to usermem. Directly copy into that.
+ copy(r.Buf[:r.NumBytes], src[:r.NumBytes])
+}
+
+// PWriteReq is used to pwrite(2) on an FD.
+type PWriteReq struct {
+ Offset primitive.Uint64
+ FD FDID
+ NumBytes primitive.Uint32
+ Buf []byte
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (w *PWriteReq) SizeBytes() int {
+ return w.Offset.SizeBytes() + w.FD.SizeBytes() + w.NumBytes.SizeBytes() + int(w.NumBytes)
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (w *PWriteReq) MarshalBytes(dst []byte) {
+ w.Offset.MarshalUnsafe(dst)
+ dst = dst[w.Offset.SizeBytes():]
+ w.FD.MarshalUnsafe(dst)
+ dst = dst[w.FD.SizeBytes():]
+ w.NumBytes.MarshalUnsafe(dst)
+ dst = dst[w.NumBytes.SizeBytes():]
+ copy(dst[:w.NumBytes], w.Buf[:w.NumBytes])
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (w *PWriteReq) UnmarshalBytes(src []byte) {
+ w.Offset.UnmarshalUnsafe(src)
+ src = src[w.Offset.SizeBytes():]
+ w.FD.UnmarshalUnsafe(src)
+ src = src[w.FD.SizeBytes():]
+ w.NumBytes.UnmarshalUnsafe(src)
+ src = src[w.NumBytes.SizeBytes():]
+
+ // This is an optimization. Assuming that the server is making this call, it
+ // is safe to just point to src rather than allocating and copying.
+ w.Buf = src[:w.NumBytes]
+}
+
+// PWriteResp is used to return the result of pwrite(2).
+//
+// +marshal
+type PWriteResp struct {
+ Count uint64
+}
+
+// MkdirAtReq is used to make MkdirAt requests.
+type MkdirAtReq struct {
+ createCommon
+ Name SizedString
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (m *MkdirAtReq) SizeBytes() int {
+ return m.createCommon.SizeBytes() + m.Name.SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (m *MkdirAtReq) MarshalBytes(dst []byte) {
+ m.createCommon.MarshalUnsafe(dst)
+ dst = dst[m.createCommon.SizeBytes():]
+ m.Name.MarshalBytes(dst)
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (m *MkdirAtReq) UnmarshalBytes(src []byte) {
+ m.createCommon.UnmarshalUnsafe(src)
+ src = src[m.createCommon.SizeBytes():]
+ m.Name.UnmarshalBytes(src)
+}
+
+// MkdirAtResp is the response to a successful MkdirAt request.
+//
+// +marshal
+type MkdirAtResp struct {
+ ChildDir Inode
+}
+
+// MknodAtReq is used to make MknodAt requests.
+type MknodAtReq struct {
+ createCommon
+ Name SizedString
+ Minor primitive.Uint32
+ Major primitive.Uint32
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (m *MknodAtReq) SizeBytes() int {
+ return m.createCommon.SizeBytes() + m.Name.SizeBytes() + m.Minor.SizeBytes() + m.Major.SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (m *MknodAtReq) MarshalBytes(dst []byte) {
+ m.createCommon.MarshalUnsafe(dst)
+ dst = dst[m.createCommon.SizeBytes():]
+ m.Name.MarshalBytes(dst)
+ dst = dst[m.Name.SizeBytes():]
+ m.Minor.MarshalUnsafe(dst)
+ dst = dst[m.Minor.SizeBytes():]
+ m.Major.MarshalUnsafe(dst)
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (m *MknodAtReq) UnmarshalBytes(src []byte) {
+ m.createCommon.UnmarshalUnsafe(src)
+ src = src[m.createCommon.SizeBytes():]
+ m.Name.UnmarshalBytes(src)
+ src = src[m.Name.SizeBytes():]
+ m.Minor.UnmarshalUnsafe(src)
+ src = src[m.Minor.SizeBytes():]
+ m.Major.UnmarshalUnsafe(src)
+}
+
+// MknodAtResp is the response to a successful MknodAt request.
+//
+// +marshal
+type MknodAtResp struct {
+ Child Inode
+}
+
+// SymlinkAtReq is used to make SymlinkAt request.
+type SymlinkAtReq struct {
+ DirFD FDID
+ Name SizedString
+ Target SizedString
+ UID UID
+ GID GID
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (s *SymlinkAtReq) SizeBytes() int {
+ return s.DirFD.SizeBytes() + s.Name.SizeBytes() + s.Target.SizeBytes() + s.UID.SizeBytes() + s.GID.SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (s *SymlinkAtReq) MarshalBytes(dst []byte) {
+ s.DirFD.MarshalUnsafe(dst)
+ dst = dst[s.DirFD.SizeBytes():]
+ s.Name.MarshalBytes(dst)
+ dst = dst[s.Name.SizeBytes():]
+ s.Target.MarshalBytes(dst)
+ dst = dst[s.Target.SizeBytes():]
+ s.UID.MarshalUnsafe(dst)
+ dst = dst[s.UID.SizeBytes():]
+ s.GID.MarshalUnsafe(dst)
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (s *SymlinkAtReq) UnmarshalBytes(src []byte) {
+ s.DirFD.UnmarshalUnsafe(src)
+ src = src[s.DirFD.SizeBytes():]
+ s.Name.UnmarshalBytes(src)
+ src = src[s.Name.SizeBytes():]
+ s.Target.UnmarshalBytes(src)
+ src = src[s.Target.SizeBytes():]
+ s.UID.UnmarshalUnsafe(src)
+ src = src[s.UID.SizeBytes():]
+ s.GID.UnmarshalUnsafe(src)
+}
+
+// SymlinkAtResp is the response to a successful SymlinkAt request.
+//
+// +marshal
+type SymlinkAtResp struct {
+ Symlink Inode
+}
+
+// LinkAtReq is used to make LinkAt requests.
+type LinkAtReq struct {
+ DirFD FDID
+ Target FDID
+ Name SizedString
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (l *LinkAtReq) SizeBytes() int {
+ return l.DirFD.SizeBytes() + l.Target.SizeBytes() + l.Name.SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (l *LinkAtReq) MarshalBytes(dst []byte) {
+ l.DirFD.MarshalUnsafe(dst)
+ dst = dst[l.DirFD.SizeBytes():]
+ l.Target.MarshalUnsafe(dst)
+ dst = dst[l.Target.SizeBytes():]
+ l.Name.MarshalBytes(dst)
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (l *LinkAtReq) UnmarshalBytes(src []byte) {
+ l.DirFD.UnmarshalUnsafe(src)
+ src = src[l.DirFD.SizeBytes():]
+ l.Target.UnmarshalUnsafe(src)
+ src = src[l.Target.SizeBytes():]
+ l.Name.UnmarshalBytes(src)
+}
+
+// LinkAtResp is used to respond to a successful LinkAt request.
+//
+// +marshal
+type LinkAtResp struct {
+ Link Inode
+}
+
+// FStatFSReq is used to request StatFS results for the specified FD.
+//
+// +marshal
+type FStatFSReq struct {
+ FD FDID
+}
+
+// StatFS is responded to a successful FStatFS request.
+//
+// +marshal
+type StatFS struct {
+ Type uint64
+ BlockSize int64
+ Blocks uint64
+ BlocksFree uint64
+ BlocksAvailable uint64
+ Files uint64
+ FilesFree uint64
+ NameLength uint64
+}
+
+// FAllocateReq is used to request to fallocate(2) an FD. This has no response.
+//
+// +marshal
+type FAllocateReq struct {
+ FD FDID
+ _ uint32
+ Mode uint64
+ Offset uint64
+ Length uint64
+}
+
+// ReadLinkAtReq is used to readlinkat(2) at the specified FD.
+//
+// +marshal
+type ReadLinkAtReq struct {
+ FD FDID
+}
+
+// ReadLinkAtResp is used to communicate ReadLinkAt results.
+type ReadLinkAtResp struct {
+ Target SizedString
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (r *ReadLinkAtResp) SizeBytes() int {
+ return r.Target.SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (r *ReadLinkAtResp) MarshalBytes(dst []byte) {
+ r.Target.MarshalBytes(dst)
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (r *ReadLinkAtResp) UnmarshalBytes(src []byte) {
+ r.Target.UnmarshalBytes(src)
+}
+
+// FlushReq is used to make Flush requests.
+//
+// +marshal
+type FlushReq struct {
+ FD FDID
+}
+
+// ConnectReq is used to make a Connect request.
+//
+// +marshal
+type ConnectReq struct {
+ FD FDID
+ // SockType is used to specify the socket type to connect to. As a special
+ // case, SockType = 0 means that the socket type does not matter and the
+ // requester will accept any socket type.
+ SockType uint32
+}
+
+// UnlinkAtReq is used to make UnlinkAt request.
+type UnlinkAtReq struct {
+ DirFD FDID
+ Name SizedString
+ Flags primitive.Uint32
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (u *UnlinkAtReq) SizeBytes() int {
+ return u.DirFD.SizeBytes() + u.Name.SizeBytes() + u.Flags.SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (u *UnlinkAtReq) MarshalBytes(dst []byte) {
+ u.DirFD.MarshalUnsafe(dst)
+ dst = dst[u.DirFD.SizeBytes():]
+ u.Name.MarshalBytes(dst)
+ dst = dst[u.Name.SizeBytes():]
+ u.Flags.MarshalUnsafe(dst)
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (u *UnlinkAtReq) UnmarshalBytes(src []byte) {
+ u.DirFD.UnmarshalUnsafe(src)
+ src = src[u.DirFD.SizeBytes():]
+ u.Name.UnmarshalBytes(src)
+ src = src[u.Name.SizeBytes():]
+ u.Flags.UnmarshalUnsafe(src)
+}
+
+// RenameAtReq is used to make Rename requests. Note that the request takes in
+// the to-be-renamed file's FD instead of oldDir and oldName like renameat(2).
+type RenameAtReq struct {
+ Renamed FDID
+ NewDir FDID
+ NewName SizedString
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (r *RenameAtReq) SizeBytes() int {
+ return r.Renamed.SizeBytes() + r.NewDir.SizeBytes() + r.NewName.SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (r *RenameAtReq) MarshalBytes(dst []byte) {
+ r.Renamed.MarshalUnsafe(dst)
+ dst = dst[r.Renamed.SizeBytes():]
+ r.NewDir.MarshalUnsafe(dst)
+ dst = dst[r.NewDir.SizeBytes():]
+ r.NewName.MarshalBytes(dst)
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (r *RenameAtReq) UnmarshalBytes(src []byte) {
+ r.Renamed.UnmarshalUnsafe(src)
+ src = src[r.Renamed.SizeBytes():]
+ r.NewDir.UnmarshalUnsafe(src)
+ src = src[r.NewDir.SizeBytes():]
+ r.NewName.UnmarshalBytes(src)
+}
+
+// Getdents64Req is used to make Getdents64 requests.
+//
+// +marshal
+type Getdents64Req struct {
+ DirFD FDID
+ // Count is the number of bytes to read. A negative value of Count is used to
+ // indicate that the implementation must lseek(0, SEEK_SET) before calling
+ // getdents64(2). Implementations must use the absolute value of Count to
+ // determine the number of bytes to read.
+ Count int32
+}
+
+// Dirent64 is analogous to struct linux_dirent64.
+type Dirent64 struct {
+ Ino primitive.Uint64
+ DevMinor primitive.Uint32
+ DevMajor primitive.Uint32
+ Off primitive.Uint64
+ Type primitive.Uint8
+ Name SizedString
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (d *Dirent64) SizeBytes() int {
+ return d.Ino.SizeBytes() + d.DevMinor.SizeBytes() + d.DevMajor.SizeBytes() + d.Off.SizeBytes() + d.Type.SizeBytes() + d.Name.SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (d *Dirent64) MarshalBytes(dst []byte) {
+ d.Ino.MarshalUnsafe(dst)
+ dst = dst[d.Ino.SizeBytes():]
+ d.DevMinor.MarshalUnsafe(dst)
+ dst = dst[d.DevMinor.SizeBytes():]
+ d.DevMajor.MarshalUnsafe(dst)
+ dst = dst[d.DevMajor.SizeBytes():]
+ d.Off.MarshalUnsafe(dst)
+ dst = dst[d.Off.SizeBytes():]
+ d.Type.MarshalUnsafe(dst)
+ dst = dst[d.Type.SizeBytes():]
+ d.Name.MarshalBytes(dst)
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (d *Dirent64) UnmarshalBytes(src []byte) {
+ d.Ino.UnmarshalUnsafe(src)
+ src = src[d.Ino.SizeBytes():]
+ d.DevMinor.UnmarshalUnsafe(src)
+ src = src[d.DevMinor.SizeBytes():]
+ d.DevMajor.UnmarshalUnsafe(src)
+ src = src[d.DevMajor.SizeBytes():]
+ d.Off.UnmarshalUnsafe(src)
+ src = src[d.Off.SizeBytes():]
+ d.Type.UnmarshalUnsafe(src)
+ src = src[d.Type.SizeBytes():]
+ d.Name.UnmarshalBytes(src)
+}
+
+// Getdents64Resp is used to communicate getdents64 results.
+type Getdents64Resp struct {
+ Dirents []Dirent64
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (g *Getdents64Resp) SizeBytes() int {
+ ret := (*primitive.Uint32)(nil).SizeBytes()
+ for i := range g.Dirents {
+ ret += g.Dirents[i].SizeBytes()
+ }
+ return ret
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (g *Getdents64Resp) MarshalBytes(dst []byte) {
+ numDirents := primitive.Uint32(len(g.Dirents))
+ numDirents.MarshalUnsafe(dst)
+ dst = dst[numDirents.SizeBytes():]
+ for i := range g.Dirents {
+ g.Dirents[i].MarshalBytes(dst)
+ dst = dst[g.Dirents[i].SizeBytes():]
+ }
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (g *Getdents64Resp) UnmarshalBytes(src []byte) {
+ var numDirents primitive.Uint32
+ numDirents.UnmarshalUnsafe(src)
+ if cap(g.Dirents) < int(numDirents) {
+ g.Dirents = make([]Dirent64, numDirents)
+ } else {
+ g.Dirents = g.Dirents[:numDirents]
+ }
+
+ src = src[numDirents.SizeBytes():]
+ for i := range g.Dirents {
+ g.Dirents[i].UnmarshalBytes(src)
+ src = src[g.Dirents[i].SizeBytes():]
+ }
+}
+
+// FGetXattrReq is used to make FGetXattr requests. The response to this is
+// just a SizedString containing the xattr value.
+type FGetXattrReq struct {
+ FD FDID
+ BufSize primitive.Uint32
+ Name SizedString
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (g *FGetXattrReq) SizeBytes() int {
+ return g.FD.SizeBytes() + g.BufSize.SizeBytes() + g.Name.SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (g *FGetXattrReq) MarshalBytes(dst []byte) {
+ g.FD.MarshalUnsafe(dst)
+ dst = dst[g.FD.SizeBytes():]
+ g.BufSize.MarshalUnsafe(dst)
+ dst = dst[g.BufSize.SizeBytes():]
+ g.Name.MarshalBytes(dst)
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (g *FGetXattrReq) UnmarshalBytes(src []byte) {
+ g.FD.UnmarshalUnsafe(src)
+ src = src[g.FD.SizeBytes():]
+ g.BufSize.UnmarshalUnsafe(src)
+ src = src[g.BufSize.SizeBytes():]
+ g.Name.UnmarshalBytes(src)
+}
+
+// FGetXattrResp is used to respond to FGetXattr request.
+type FGetXattrResp struct {
+ Value SizedString
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (g *FGetXattrResp) SizeBytes() int {
+ return g.Value.SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (g *FGetXattrResp) MarshalBytes(dst []byte) {
+ g.Value.MarshalBytes(dst)
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (g *FGetXattrResp) UnmarshalBytes(src []byte) {
+ g.Value.UnmarshalBytes(src)
+}
+
+// FSetXattrReq is used to make FSetXattr requests. It has no response.
+type FSetXattrReq struct {
+ FD FDID
+ Flags primitive.Uint32
+ Name SizedString
+ Value SizedString
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (s *FSetXattrReq) SizeBytes() int {
+ return s.FD.SizeBytes() + s.Flags.SizeBytes() + s.Name.SizeBytes() + s.Value.SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (s *FSetXattrReq) MarshalBytes(dst []byte) {
+ s.FD.MarshalUnsafe(dst)
+ dst = dst[s.FD.SizeBytes():]
+ s.Flags.MarshalUnsafe(dst)
+ dst = dst[s.Flags.SizeBytes():]
+ s.Name.MarshalBytes(dst)
+ dst = dst[s.Name.SizeBytes():]
+ s.Value.MarshalBytes(dst)
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (s *FSetXattrReq) UnmarshalBytes(src []byte) {
+ s.FD.UnmarshalUnsafe(src)
+ src = src[s.FD.SizeBytes():]
+ s.Flags.UnmarshalUnsafe(src)
+ src = src[s.Flags.SizeBytes():]
+ s.Name.UnmarshalBytes(src)
+ src = src[s.Name.SizeBytes():]
+ s.Value.UnmarshalBytes(src)
+}
+
+// FRemoveXattrReq is used to make FRemoveXattr requests. It has no response.
+type FRemoveXattrReq struct {
+ FD FDID
+ Name SizedString
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (r *FRemoveXattrReq) SizeBytes() int {
+ return r.FD.SizeBytes() + r.Name.SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (r *FRemoveXattrReq) MarshalBytes(dst []byte) {
+ r.FD.MarshalUnsafe(dst)
+ dst = dst[r.FD.SizeBytes():]
+ r.Name.MarshalBytes(dst)
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (r *FRemoveXattrReq) UnmarshalBytes(src []byte) {
+ r.FD.UnmarshalUnsafe(src)
+ src = src[r.FD.SizeBytes():]
+ r.Name.UnmarshalBytes(src)
+}
+
+// FListXattrReq is used to make FListXattr requests.
+//
+// +marshal
+type FListXattrReq struct {
+ FD FDID
+ _ uint32
+ Size uint64
+}
+
+// FListXattrResp is used to respond to FListXattr requests.
+type FListXattrResp struct {
+ Xattrs StringArray
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (l *FListXattrResp) SizeBytes() int {
+ return l.Xattrs.SizeBytes()
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (l *FListXattrResp) MarshalBytes(dst []byte) {
+ l.Xattrs.MarshalBytes(dst)
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (l *FListXattrResp) UnmarshalBytes(src []byte) {
+ l.Xattrs.UnmarshalBytes(src)
+}