Documentation
¶
Overview ¶
Package nfsv4 implements a read-only NFSv4.1 server for virtual filesystems.
The server speaks NFSv4 minor versions 1 and 2 (RFC 8881, RFC 7862) over TCP, which the Linux and macOS (since macOS 26) kernels can mount directly on any port, with no portmapper, mountd, or root privileges on the server side. Write operations fail with ErrROFS.
Layers ¶
The FS interface is close to the protocol: it deals in opaque, caller-chosen filehandles (up to 128 bytes), NFSv4 attributes, READDIR cookies, and NFSv4 status codes. Callers that want full control over filehandle encoding implement it directly.
Callers that don't want to think about filehandles use package nodefs, which implements FS on top of a tree of directory, file, and symlink nodes, deriving filehandles from paths so that they survive server restarts without any persistent state. Package memfs (in-memory) and package osfs (a local directory) are built on nodefs.
Cache control ¶
NFSv4 has no notion of "cache this for N seconds" or "valid forever" on the wire. Clients cache attributes and directory entries for a time set by their own mount options (acregmin, acregmax, acdirmin, acdirmax, actimeo) and revalidate using the change attribute (Attrs.Change).
The server-side lever is delegations: an FS implementing Delegator can grant clients read delegations on files (when they're opened) and on directories (when the client asks for a directory delegation). A delegation is a promise that the object won't change without the client being told first. While holding one, the Linux client doesn't revalidate at all: no GETATTR, LOOKUP, ACCESS, or READDIR for delegated directories and their entries, and no GETATTR or OPEN round trips for delegated files. That makes delegations the way to mark immutable subtrees as valid forever.
For objects that can change, either don't grant delegations (clients then revalidate on their own schedule), or grant them and use Server.Recall around changes. Delegation.MaxAge bounds how long a delegation lives.
Client behavior worth knowing about:
- The Linux client (as of 7.0) asks for directory delegations when it revalidates a directory it has checked access to (the nfs4.directory_delegations module parameter, on by default), and holds them until they're recalled or the directory's inode is evicted from its cache.
- The Linux client returns file delegations for files it hasn't used in a while (about one to two lease periods after the last close), and returns the least recently used ones when it holds more than the nfs.delegation_watermark module parameter (5000 by default). Reopening a file whose delegation was returned costs one OPEN round trip, which also revalidates it.
- The macOS client (as of macOS 26) doesn't use directory delegations, and file delegations only extend its attribute cache lifetime to acregmax. Long-lived caching on macOS mostly comes from mount options. After a recall, it may serve one more read from its cache before noticing a change.
- Delegations need a callback channel. NFSv4.1 clients run it over their own TCP connection to the server, so it works through NAT and userspace networking. Delegations aren't granted to clients without one.
A recall releases the delegation before a change. It does not disable ordinary client caching after the delegation is returned. On Linux 7.0, an already-open file can still return old data after a local change until its attributes are revalidated. A cached name can also remain visible for a short time after removal. The client mount options affect these delays.
Filehandles and restarts ¶
The server advertises persistent filehandles. Clients keep using filehandles across server restarts (the server's client state is lost, and clients transparently reclaim it). Opens are always reclaimable, since read-only opens can't conflict. A filehandle the FS no longer recognizes should get ErrStale, from which the Linux and macOS clients recover by looking names up again from the parent directory, but that doesn't work for open files or processes whose working directory is in the mount, and never for the root filehandle. The Linux client recovers transparently for path-based system calls; the macOS client (as of macOS 26) returns ESTALE to the application once before looking names up again. FileIDs must be as stable as filehandles: clients consider an object whose FileID changed to be gone.
Not supported ¶
Not supported: writes, NFSv4.0, Kerberos (only AUTH_SYS and AUTH_NONE are accepted, and credentials are passed to the FS for its own checks), ACLs, named attributes and extended attributes, pNFS, referrals, and directory change notifications (directory delegations are recalled instead). Byte-range locks are always granted, since locks on read-only files never conflict.
Index ¶
- Constants
- Variables
- type Accesser
- type Attr
- type AttrMask
- func (m AttrMask) All() []Attr
- func (m AttrMask) And(o AttrMask) AttrMask
- func (m AttrMask) AndNot(o AttrMask) AttrMask
- func (m *AttrMask) Clear(a Attr)
- func (m AttrMask) ContainsAll(o AttrMask) bool
- func (m AttrMask) Has(a Attr) bool
- func (m AttrMask) IsEmpty() bool
- func (m AttrMask) Or(o AttrMask) AttrMask
- func (m *AttrMask) Set(a Attr)
- func (m AttrMask) String() string
- type Attrs
- type CBOp
- type ClientInfo
- type Cred
- type Delegation
- type Delegator
- type Device
- type DirEntry
- type FS
- type FSID
- type FSStat
- type FileHandle
- type FileType
- type Op
- type Opener
- type ReadDirArgs
- type ReadDirResult
- type Request
- type Server
- type StatFSer
- type Stats
- type Status
Constants ¶
const ( AccessRead uint32 = 0x01 // read data or list directory AccessLookup uint32 = 0x02 // look up names in a directory AccessModify uint32 = 0x04 // rewrite data or modify directory entries AccessExtend uint32 = 0x08 // append data or add directory entries AccessDelete uint32 = 0x10 // delete directory entries AccessExecute uint32 = 0x20 // execute a file )
Access bits, as used by the ACCESS operation (ACCESS4_*).
const ( FHPersistent uint32 = 0x00 FHNoExpireWithOpen uint32 = 0x01 FHVolatileAny uint32 = 0x02 FHVolMigration uint32 = 0x04 FHVolRename uint32 = 0x08 )
Filehandle expiration types, as reported by the fh_expire_type attribute (FH4_*).
const (
// MaxFileHandleSize is the maximum length of a filehandle (NFS4_FHSIZE).
MaxFileHandleSize = 128
)
Protocol limits.
Variables ¶
var ErrServerClosed = errors.New("nfsv4: server closed")
ErrServerClosed is returned by Serve after Close is called.
Functions ¶
This section is empty.
Types ¶
type Accesser ¶
type Accesser interface {
// Access returns which of the requested access bits (AccessRead
// etc.) are allowed for fh.
Access(r *Request, fh FileHandle, attrs *Attrs, requested uint32) (allowed uint32, err error)
}
Accesser is an optional interface an FS can implement to decide the results of ACCESS operations, which clients use for permission checks.
Without it, the server computes access from the Mode, UID, and GID attributes and the request's credential, never granting AccessModify, AccessExtend, or AccessDelete.
type Attr ¶
type Attr uint32
Attr is an NFSv4 file attribute number (FATTR4_*).
const ( AttrSupportedAttrs Attr = 0 AttrType Attr = 1 AttrFHExpireType Attr = 2 AttrChange Attr = 3 AttrSize Attr = 4 AttrLinkSupport Attr = 5 AttrSymlinkSupport Attr = 6 AttrNamedAttr Attr = 7 AttrFSID Attr = 8 AttrUniqueHandles Attr = 9 AttrLeaseTime Attr = 10 AttrRdAttrError Attr = 11 AttrACL Attr = 12 AttrACLSupport Attr = 13 AttrArchive Attr = 14 AttrCanSetTime Attr = 15 AttrCaseInsensitive Attr = 16 AttrCasePreserving Attr = 17 AttrChownRestricted Attr = 18 AttrFileHandle Attr = 19 AttrFileID Attr = 20 AttrFilesAvail Attr = 21 AttrFilesFree Attr = 22 AttrFilesTotal Attr = 23 AttrFSLocations Attr = 24 AttrHidden Attr = 25 AttrHomogeneous Attr = 26 AttrMaxFileSize Attr = 27 AttrMaxLink Attr = 28 AttrMaxName Attr = 29 AttrMaxRead Attr = 30 AttrMaxWrite Attr = 31 AttrMIMEType Attr = 32 AttrMode Attr = 33 AttrNoTrunc Attr = 34 AttrNumLinks Attr = 35 AttrOwner Attr = 36 AttrOwnerGroup Attr = 37 AttrQuotaAvailHard Attr = 38 AttrQuotaAvailSoft Attr = 39 AttrQuotaUsed Attr = 40 AttrRawDev Attr = 41 AttrSpaceAvail Attr = 42 AttrSpaceFree Attr = 43 AttrSpaceTotal Attr = 44 AttrSpaceUsed Attr = 45 AttrSystem Attr = 46 AttrTimeAccess Attr = 47 AttrTimeAccessSet Attr = 48 AttrTimeBackup Attr = 49 AttrTimeCreate Attr = 50 AttrTimeDelta Attr = 51 AttrTimeMetadata Attr = 52 AttrTimeModify Attr = 53 AttrTimeModifySet Attr = 54 AttrMountedOnFileID Attr = 55 AttrDirNotifDelay Attr = 56 AttrDirentNotifDelay Attr = 57 AttrDACL Attr = 58 AttrSACL Attr = 59 AttrChangePolicy Attr = 60 AttrFSStatus Attr = 61 AttrFSLayoutTypes Attr = 62 AttrLayoutHint Attr = 63 AttrLayoutTypes Attr = 64 AttrLayoutBlkSize Attr = 65 AttrLayoutAlignment Attr = 66 AttrFSLocationsInfo Attr = 67 AttrMDSThreshold Attr = 68 AttrRetentionGet Attr = 69 AttrRetentionSet Attr = 70 AttrRetentEvtGet Attr = 71 AttrRetentEvtSet Attr = 72 AttrRetentionHold Attr = 73 AttrModeSetMasked Attr = 74 AttrSuppAttrExclCreat Attr = 75 AttrFSCharsetCap Attr = 76 AttrCloneBlkSize Attr = 77 AttrSpaceFreed Attr = 78 AttrChangeAttrType Attr = 79 AttrSecLabel Attr = 80 )
NFSv4 attribute numbers (FATTR4_*).
type AttrMask ¶
type AttrMask struct {
// contains filtered or unexported fields
}
AttrMask is a set of attributes (an NFSv4 bitmap4).
func MakeAttrMask ¶
MakeAttrMask returns an AttrMask containing attrs.
func (AttrMask) ContainsAll ¶
ContainsAll reports whether every attribute in o is also in m.
type Attrs ¶
type Attrs struct {
// Type is the object's type. It's required.
Type FileType
// Change is the change attribute: an opaque value that must change
// whenever the object's contents or attributes change (for
// directories: whenever entries are added, removed, or renamed).
// Clients compare it to decide whether their cached data is still
// valid, so an object that never changes should keep a constant
// Change, and a live object should always report a new value after
// changing, even if its size and modification time are unchanged.
Change uint64
// Size is the size in bytes. For symlinks, it should be the length of
// the target.
Size uint64
// SpaceUsed is the number of bytes of storage used. If zero, the
// server reports Size.
SpaceUsed uint64
// FileID is the object's unique number within its filesystem (its
// "inode number"). It must be unique, and as stable as the object's
// filehandle: clients that see a different FileID for a filehandle
// they know (such as after a server restart) consider the object
// gone and return ESTALE to applications.
FileID uint64
// MountedOnFileID is the mounted_on_fileid attribute. If zero, the
// server reports FileID, which is what's wanted unless the object is
// the root of a filesystem mounted on another object (see FSID).
MountedOnFileID uint64
// Mode holds the permission bits (0o7777). Type bits are ignored.
Mode uint32
// NumLinks is the number of hard links. If zero, the server reports
// 1 (or 2 for directories).
NumLinks uint32
// UID and GID are the numeric owner and group. They're sent as
// decimal strings, which both the Linux and macOS clients accept with
// AUTH_SYS.
UID, GID uint32
// Owner and Group, if non-empty, are sent as the owner and
// owner_group attributes verbatim instead of UID and GID (for
// instance "alice@example.com").
Owner, Group string
// RawDev is the device number for block and character devices.
RawDev Device
// ModTime is the time of the last modification of the contents.
ModTime time.Time
// ChangeTime is the time of the last change of contents or
// attributes (time_metadata, ctime). If zero, ModTime is reported.
ChangeTime time.Time
// AccessTime is the time of last access. If zero, ModTime is
// reported.
AccessTime time.Time
// BirthTime is the creation time. If zero, it's omitted.
BirthTime time.Time
// FSID, if non-nil, is the identifier of the filesystem containing
// this object. If nil, the Server's FSID is reported.
//
// Clients treat a directory whose FSID differs from its parent's as
// the root of a different filesystem and make it a separate
// (automatic) mount point. Most FS implementations should leave this
// nil.
FSID *FSID
}
Attrs are the per-object attributes of a file, directory, or other filesystem object.
Attributes that describe the filesystem as a whole (such as maxname or lease_time) are not here; they come from the Server configuration, and space and file counts come from the optional StatFSer interface.
type CBOp ¶
type CBOp uint32
CBOp is an NFSv4 callback operation number (nfs_cb_opnum4).
const ( CBOpGetAttr CBOp = 3 CBOpRecall CBOp = 4 CBOpLayoutRecall CBOp = 5 CBOpNotify CBOp = 6 CBOpPushDeleg CBOp = 7 CBOpRecallAny CBOp = 8 CBOpRecallableObjAvail CBOp = 9 CBOpRecallSlot CBOp = 10 CBOpSequence CBOp = 11 CBOpWantsCancelled CBOp = 12 CBOpNotifyLock CBOp = 13 CBOpNotifyDeviceID CBOp = 14 CBOpOffload CBOp = 15 CBOpIllegal CBOp = 10044 )
NFSv4 callback operation numbers (nfs_cb_opnum4).
type ClientInfo ¶
type ClientInfo struct {
// ID is the server-assigned client ID.
ID uint64
// OwnerID is the client's self-chosen unique identifier
// (co_ownerid). The Linux client uses a string like
// "Linux NFSv4.1 hostname".
OwnerID []byte
// ImplDomain, ImplName, and ImplDate describe the client
// implementation (such as "kernel.org" and "Linux 7.0.0 ..."), if the
// client sent them.
ImplDomain string
ImplName string
ImplDate time.Time
}
ClientInfo describes an NFSv4 client, as identified by the EXCHANGE_ID operation.
type Cred ¶
type Cred struct {
// Flavor is the RPC auth flavor: 0 (AUTH_NONE) or 1 (AUTH_SYS).
Flavor uint32
// UID, GID, and GIDs are the user's numeric identity for AUTH_SYS.
// For AUTH_NONE they're 65534 ("nobody") and nil.
UID, GID uint32
GIDs []uint32
// MachineName is the AUTH_SYS machine name (usually the client's
// hostname).
MachineName string
}
Cred is an RPC credential.
type Delegation ¶
type Delegation struct {
// Grant says whether to grant a read delegation.
Grant bool
// MaxAge, if non-zero, limits how long a delegation may be held. The
// server recalls it after this long. Zero means the delegation is
// held until it's recalled with Server.Recall (for immutable
// objects: forever) or the client returns it voluntarily.
MaxAge time.Duration
}
Delegation is a cache-control decision made by a Delegator.
An NFSv4 read delegation is a promise from the server that an object won't change without the client being told first (with a recall). While a client holds a delegation it can cache the object without revalidating: the Linux client stops sending GETATTR, LOOKUP, and ACCESS revalidations for delegated files and directories, and for a delegated directory also trusts its cached directory listing and child names. The macOS client uses delegations to extend its attribute cache lifetime to the acregmax mount option's value and doesn't use directory delegations.
The zero value grants no delegation; the client then revalidates on its own schedule (governed by its acregmin/acregmax/acdirmin/acdirmax mount options).
type Delegator ¶
type Delegator interface {
// Delegate decides whether to grant a read delegation for fh, a
// regular file being opened or a directory for which the client asked
// for a directory delegation. attrs are the object's current
// attributes.
Delegate(r *Request, fh FileHandle, attrs *Attrs) Delegation
}
Delegator is an optional interface an FS can implement to control client caching by granting delegations.
Delegations require a working callback channel to the client, which NFSv4.1 clients normally establish over their own connection. The server only consults the Delegator when one exists.
An FS that grants delegations for an object that can change must change it only while its delegations are recalled; see Server.Recall. For immutable objects there's nothing to do.
type Device ¶
type Device struct {
Major, Minor uint32
}
Device is a block or character device number.
type DirEntry ¶
type DirEntry struct {
// Name is the entry's name.
Name string
// Cookie identifies the entry's position, such that listing again
// with ReadDirArgs.Cookie set to this value resumes with the next
// entry. Cookies must be at least 3; the values 0, 1, and 2 are
// reserved by the protocol.
Cookie uint64
// Handle is the entry's filehandle. It's required if the client asked
// for any attributes (ReadDirArgs.Want is non-empty).
Handle FileHandle
// Attrs are the entry's attributes, if already known. If nil and the
// client wants attributes, the server calls FS.GetAttr(Handle).
Attrs *Attrs
}
DirEntry is a directory entry returned by FS.ReadDir.
type FS ¶
type FS interface {
// Root returns the root filehandle. It's called for each PUTROOTFH
// operation, so it should be cheap. It must return the same filehandle
// for the lifetime of the filesystem, including across restarts.
Root(r *Request) (FileHandle, error)
// GetAttr returns the attributes of fh.
//
// The want mask says which attributes the client asked for. It's a
// hint: implementations may use it to skip expensive work, but may
// also return attributes that weren't asked for. It always includes
// the basic attributes (type, change, size, fileid, mode, numlinks,
// owner, owner_group, and the times), so it's mostly useful for
// skipping work for clients that only want those. Attributes the
// server computes itself (such as lease_time) are never in want.
GetAttr(r *Request, fh FileHandle, want AttrMask) (*Attrs, error)
// Lookup looks up name in the directory dir and returns its
// filehandle. If convenient, it may also return the child's
// attributes, saving a subsequent GetAttr call; otherwise attrs may be
// nil.
//
// Lookup must return ErrNoEnt if the name doesn't exist and ErrNotDir
// if dir isn't a directory (or ErrSymlink if it's a symlink). The
// names "." and ".." are never passed to Lookup.
Lookup(r *Request, dir FileHandle, name string) (fh FileHandle, attrs *Attrs, err error)
// LookupParent returns the parent directory of the directory dir.
// It's never called for the root. Implementations that can't
// determine parents may return ErrNotSupp, but some client
// operations (such as resolving ".." from an open-by-handle
// directory, or NFS re-exports) won't work.
LookupParent(r *Request, dir FileHandle) (FileHandle, error)
// ReadDir lists the directory dir, calling emit for each entry in
// order, starting after the position described by args.Cookie. It
// stops early, returning nil, if emit returns false, which means the
// client's reply buffer is full. Not returning "." or ".." entries is
// the FS's responsibility.
//
// See ReadDirArgs and DirEntry for the cookie and verifier rules.
ReadDir(r *Request, dir FileHandle, args ReadDirArgs, emit func(DirEntry) bool) (ReadDirResult, error)
// Read reads up to len(p) bytes of the regular file fh starting at
// offset off into p, returning the number of bytes read and whether
// the read reached the end of the file. Reading at or past the end
// of the file returns 0, true, nil. Returning fewer bytes than
// requested without eof is allowed; the client will issue another
// read.
//
// p is the server's reply buffer, so data is written directly into
// the reply with no extra copy. Read must return ErrIsDir for
// directories and ErrInval for other non-regular files.
Read(r *Request, fh FileHandle, off uint64, p []byte) (n int, eof bool, err error)
// ReadLink returns the target of the symlink fh. It must return
// ErrInval if fh isn't a symlink (ErrIsDir for directories).
ReadLink(r *Request, fh FileHandle) (string, error)
}
FS is a read-only filesystem served over NFSv4 by a Server.
Methods are called concurrently. Methods that operate on a filehandle should return ErrStale or ErrBadHandle for unknown filehandles. Errors may be Status values (such as ErrNoEnt) or other errors that are mapped to a Status (see Server.Logf for errors that have no natural mapping). PUTFH uses GetAttr to validate handles and returns ErrServerFault if the mapped error is not valid for that operation.
Optional behavior is provided by implementing additional interfaces: Delegator (cache control), Opener, Accesser, and StatFSer.
type FSID ¶
type FSID struct {
Major, Minor uint64
}
FSID is a filesystem identifier (the fsid attribute).
type FSStat ¶
type FSStat struct {
SpaceTotal, SpaceFree, SpaceAvail uint64 // bytes
FilesTotal, FilesFree, FilesAvail uint64
}
FSStat holds filesystem-wide space and file counts.
type FileHandle ¶
type FileHandle []byte
FileHandle is an NFSv4 filehandle: opaque bytes, at most MaxFileHandleSize (128) bytes long, chosen by the FS implementation.
Clients treat filehandles as opaque identifiers and hold onto them indefinitely, including across server restarts. The server advertises its filehandles as persistent (FH4_PERSISTENT, unless configured otherwise), so an FS should be able to resolve any filehandle it ever handed out for as long as the object exists, even after the process restarts. Return ErrStale for filehandles that no longer resolve; clients recover from that by looking the name up again from the parent directory. The root filehandle must never become stale: neither the Linux nor the macOS client can recover a mount whose root filehandle stops working.
FS implementations that don't want to think about any of this can use the nodefs package, which manages filehandles itself.
type FileType ¶
type FileType uint32
FileType is an NFSv4 file type (nfs_ftype4).
const ( TypeReg FileType = 1 // NF4REG: regular file TypeDir FileType = 2 // NF4DIR: directory TypeBlock FileType = 3 // NF4BLK: block device TypeChar FileType = 4 // NF4CHR: character device TypeSymlink FileType = 5 // NF4LNK: symbolic link TypeSocket FileType = 6 // NF4SOCK: socket TypeFIFO FileType = 7 // NF4FIFO: named pipe TypeAttrDir FileType = 8 // NF4ATTRDIR: named attribute directory (unused) TypeNamedAttr FileType = 9 // NF4NAMEDATTR: named attribute (unused) )
File types.
type Op ¶
type Op uint32
Op is an NFSv4 COMPOUND operation number (nfs_opnum4).
const ( OpAccess Op = 3 OpClose Op = 4 OpCommit Op = 5 OpCreate Op = 6 OpDelegPurge Op = 7 OpDelegReturn Op = 8 OpGetAttr Op = 9 OpGetFH Op = 10 OpLink Op = 11 OpLock Op = 12 OpLockT Op = 13 OpLockU Op = 14 OpLookup Op = 15 OpLookupp Op = 16 OpNVerify Op = 17 OpOpen Op = 18 OpOpenAttr Op = 19 OpOpenConfirm Op = 20 OpOpenDowngrade Op = 21 OpPutFH Op = 22 OpPutPubFH Op = 23 OpPutRootFH Op = 24 OpRead Op = 25 OpReadDir Op = 26 OpReadLink Op = 27 OpRemove Op = 28 OpRename Op = 29 OpRenew Op = 30 OpRestoreFH Op = 31 OpSaveFH Op = 32 OpSecInfo Op = 33 OpSetAttr Op = 34 OpSetClientID Op = 35 OpSetClientIDConfirm Op = 36 OpVerify Op = 37 OpWrite Op = 38 OpReleaseLockOwner Op = 39 OpBackchannelCtl Op = 40 OpBindConnToSession Op = 41 OpExchangeID Op = 42 OpCreateSession Op = 43 OpDestroySession Op = 44 OpFreeStateID Op = 45 OpGetDirDelegation Op = 46 OpGetDeviceInfo Op = 47 OpGetDeviceList Op = 48 OpLayoutCommit Op = 49 OpLayoutGet Op = 50 OpLayoutReturn Op = 51 OpSecInfoNoName Op = 52 OpSequence Op = 53 OpSetSSV Op = 54 OpTestStateID Op = 55 OpWantDelegation Op = 56 OpDestroyClientID Op = 57 OpReclaimComplete Op = 58 OpAllocate Op = 59 OpCopy Op = 60 OpCopyNotify Op = 61 OpDeallocate Op = 62 OpIOAdvise Op = 63 OpLayoutError Op = 64 OpLayoutStats Op = 65 OpOffloadCancel Op = 66 OpOffloadStatus Op = 67 OpReadPlus Op = 68 OpSeek Op = 69 OpWriteSame Op = 70 OpClone Op = 71 OpIllegal Op = 10044 OpGetXattr Op = 72 OpSetXattr Op = 73 OpListXattrs Op = 74 OpRemoveXattr Op = 75 )
NFSv4 COMPOUND operation numbers (nfs_opnum4). Numbers 72 through 75 are the extended attribute operations from RFC 8276.
type Opener ¶
type Opener interface {
// Open is called when a client opens fh, a regular file, for
// reading. Returning an error fails the open.
Open(r *Request, fh FileHandle, attrs *Attrs) error
// Close is called when the client closes the open state for fh,
// or when the server discards it (such as when a client's lease
// expires).
Close(fh FileHandle)
}
Opener is an optional interface an FS can implement to observe or veto opens of regular files.
Clients open files before reading them, but may also read without an open (using special stateids), and clients holding a delegation open files locally without telling the server, so Open and Close are not a reliable way to track file usage.
type ReadDirArgs ¶
type ReadDirArgs struct {
// Cookie is where to resume listing. Zero means the beginning of the
// directory. Otherwise it's a DirEntry.Cookie value the FS returned
// earlier, and listing resumes with the entry after that one.
Cookie uint64
// Verifier is the ReadDirResult.Verifier value the FS returned along
// with Cookie, or zero when Cookie is zero. An FS whose cookies can be
// invalidated by directory changes uses the verifier to detect stale
// cookies, returning ErrNotSame (or ErrBadCookie) for them.
Verifier uint64
// Want is the set of attributes the client wants for each entry, as
// in FS.GetAttr. If it includes AttrFileHandle, the client wants
// each entry's filehandle. If it is empty, the client wants only
// names and cookies.
Want AttrMask
}
ReadDirArgs are the arguments to FS.ReadDir.
type ReadDirResult ¶
type ReadDirResult struct {
// Verifier is the cookie verifier the client should send back with
// future cookies from this listing. Zero is fine for FSes with
// stable cookies.
Verifier uint64
}
ReadDirResult is the result of FS.ReadDir.
type Request ¶
type Request struct {
// Cred is the RPC credential of the caller.
Cred Cred
// RemoteAddr and LocalAddr are the connection's addresses.
RemoteAddr, LocalAddr net.Addr
// Client is the client that sent the request. It's nil only for
// requests that aren't part of a session, which never reach an FS.
Client *ClientInfo
// MinorVersion is the NFSv4 minor version (1 or 2) of the request.
MinorVersion uint32
// contains filtered or unexported fields
}
Request describes the context of an FS method call: one COMPOUND procedure from a client.
type Server ¶
type Server struct {
// FS is the filesystem to serve. It's required.
FS FS
// Logf, if non-nil, is used to log errors and unusual events. If
// nil, log.Printf is used.
Logf func(format string, args ...any)
// Debugf, if non-nil, logs every operation. It's very verbose.
Debugf func(format string, args ...any)
// LeaseTime is the lease time clients must renew their state within.
// Clients send a SEQUENCE heartbeat at least this often, and the
// Linux client returns idle file delegations it isn't using after one
// or two thirds of it. If zero, 90 seconds is used.
LeaseTime time.Duration
// ClientExpiry is how long after a client stops renewing its lease
// that the server discards the client's state. Read-only state never
// conflicts with other clients, so the server is "courteous" and
// keeps the state of unresponsive clients (such as laptops that went
// to sleep) much longer than the lease time, so they can resume
// seamlessly. If zero, one hour is used.
ClientExpiry time.Duration
// MaxIO is the maximum READ size (the maxread attribute) and the
// basis for the session request and response size limits. If zero,
// 1 MiB is used.
MaxIO int
// FSID is the default fsid attribute, used for objects whose
// Attrs.FSID is nil. The zero value is fine.
FSID FSID
// FHExpireType is the value of the fh_expire_type attribute. The
// zero value, FHPersistent, is the right choice for filehandles that
// survive server restarts.
FHExpireType uint32
// ChangeIsMonotonic promises that every object's Attrs.Change value
// only ever increases. It's reported to NFSv4.2 clients in the
// change_attr_type attribute, and the Linux client then uses Change
// values to order concurrent attribute updates. Leave it false if
// Change values are arbitrary (such as hashes).
ChangeIsMonotonic bool
// ServerScope identifies the server for the purposes of client
// state (eir_server_scope). Servers sharing a scope (and a
// ServerOwner) are considered the same server by clients. If empty,
// "github.com/tailscale/nfsv4" is used.
ServerScope string
// ServerOwner is the server owner major ID (so_major_id), used by
// clients for trunking detection. If empty, a random value is chosen
// at startup.
ServerOwner string
// contains filtered or unexported fields
}
Server is an NFSv4.1 server serving an FS read-only.
It speaks NFSv4 minor versions 1 and 2 over TCP. Clients mount it directly on whatever port it listens on, with no portmapper or mountd:
Linux: mount -t nfs4 -o vers=4.2,port=N,ro HOST:/ /mnt macOS: mount -t nfs -o vers=4.1,port=N,rdonly,rsize=1048576 HOST:/ /mnt
The exported fields must not be changed after the first call to Serve or ServeConn.
func (*Server) Close ¶
Close stops all listeners and closes all connections. Client state is discarded. It waits for in-progress requests to finish.
func (*Server) Recall ¶
func (s *Server) Recall(ctx context.Context, fhs ...FileHandle) (release func(), err error)
Recall recalls the delegations clients hold for the objects fhs and prevents new delegations for them from being granted until release is called. An FS that grants delegations for objects that can change must change them only between Recall and release:
release, err := srv.Recall(ctx, fileFH, dirFH)
if err != nil {
return err
}
defer release()
// ... change the file, and the directory's entries ...
The order matters. Clients send their final GETATTR for a delegated object when returning the delegation and, still trusting their delegation at that moment, record the new change attribute without discarding their cached data. So clients must return their delegations before the object changes; after release, they notice the new change attribute (which the FS must report) and discard their stale caches.
Recall returns once all delegations for fhs have been returned by their clients, or revoked from clients that didn't return them within the lease time. If ctx is done first, Recall returns ctx's error, and delegations aren't blocked; the caller should retry before changing anything.
Objects with no delegations outstanding (including all objects of an FS that doesn't implement Delegator) are handled quickly, without contacting any clients.
func (*Server) Serve ¶
Serve accepts connections on ln and serves them until ln fails or Close is called, in which case it returns ErrServerClosed.
type StatFSer ¶
type StatFSer interface {
StatFS(r *Request, fh FileHandle) (*FSStat, error)
}
StatFSer is an optional interface an FS can implement to report filesystem space and file counts (the attributes behind df(1)). Without it, all values are reported as zero.
type Stats ¶
type Stats struct {
// Ops counts the operations processed, by operation.
Ops map[Op]uint64
// Compounds is the number of COMPOUND procedures processed.
Compounds uint64
// Clients and Sessions are the current numbers of clients and
// sessions.
Clients, Sessions int
// Opens, Locks, and Delegations are the current numbers of open,
// lock, and delegation stateids.
Opens, Locks, Delegations int
// Recalls is the number of delegation recalls sent. Revocations is
// the number of delegations revoked because the client failed to
// return them in time.
Recalls, Revocations uint64
}
Stats are server statistics, as returned by Server.Stats.
type Status ¶
type Status uint32
Status is an NFSv4 status code (nfsstat4).
Status implements error, so FS implementations can return Status values such as ErrNoEnt directly to control exactly what the client sees. OK should not be returned as an error.
const ( OK Status = 0 // NFS4_OK ErrPerm Status = 1 // NFS4ERR_PERM ErrNoEnt Status = 2 // NFS4ERR_NOENT ErrIO Status = 5 // NFS4ERR_IO ErrNXIO Status = 6 // NFS4ERR_NXIO ErrAccess Status = 13 // NFS4ERR_ACCESS ErrExist Status = 17 // NFS4ERR_EXIST ErrXDev Status = 18 // NFS4ERR_XDEV ErrNotDir Status = 20 // NFS4ERR_NOTDIR ErrIsDir Status = 21 // NFS4ERR_ISDIR ErrInval Status = 22 // NFS4ERR_INVAL ErrFBig Status = 27 // NFS4ERR_FBIG ErrNoSpc Status = 28 // NFS4ERR_NOSPC ErrROFS Status = 30 // NFS4ERR_ROFS ErrMLink Status = 31 // NFS4ERR_MLINK ErrNameTooLong Status = 63 // NFS4ERR_NAMETOOLONG ErrNotEmpty Status = 66 // NFS4ERR_NOTEMPTY ErrDQuot Status = 69 // NFS4ERR_DQUOT ErrStale Status = 70 // NFS4ERR_STALE ErrBadHandle Status = 10001 // NFS4ERR_BADHANDLE ErrBadCookie Status = 10003 // NFS4ERR_BAD_COOKIE ErrNotSupp Status = 10004 // NFS4ERR_NOTSUPP ErrTooSmall Status = 10005 // NFS4ERR_TOOSMALL ErrServerFault Status = 10006 // NFS4ERR_SERVERFAULT ErrBadType Status = 10007 // NFS4ERR_BADTYPE ErrDelay Status = 10008 // NFS4ERR_DELAY ErrSame Status = 10009 // NFS4ERR_SAME ErrDenied Status = 10010 // NFS4ERR_DENIED ErrExpired Status = 10011 // NFS4ERR_EXPIRED ErrLocked Status = 10012 // NFS4ERR_LOCKED ErrGrace Status = 10013 // NFS4ERR_GRACE ErrFHExpired Status = 10014 // NFS4ERR_FHEXPIRED ErrWrongSec Status = 10016 // NFS4ERR_WRONGSEC ErrClidInUse Status = 10017 // NFS4ERR_CLID_INUSE ErrResource Status = 10018 // NFS4ERR_RESOURCE ErrMoved Status = 10019 // NFS4ERR_MOVED ErrNoFileHandle Status = 10020 // NFS4ERR_NOFILEHANDLE ErrMinorVersMismatch Status = 10021 // NFS4ERR_MINOR_VERS_MISMATCH ErrStaleClientID Status = 10022 // NFS4ERR_STALE_CLIENTID ErrStaleStateID Status = 10023 // NFS4ERR_STALE_STATEID ErrOldStateID Status = 10024 // NFS4ERR_OLD_STATEID ErrBadStateID Status = 10025 // NFS4ERR_BAD_STATEID ErrBadSeqID Status = 10026 // NFS4ERR_BAD_SEQID ErrNotSame Status = 10027 // NFS4ERR_NOT_SAME ErrLockRange Status = 10028 // NFS4ERR_LOCK_RANGE ErrSymlink Status = 10029 // NFS4ERR_SYMLINK ErrRestoreFH Status = 10030 // NFS4ERR_RESTOREFH ErrLeaseMoved Status = 10031 // NFS4ERR_LEASE_MOVED ErrAttrNotSupp Status = 10032 // NFS4ERR_ATTRNOTSUPP ErrNoGrace Status = 10033 // NFS4ERR_NO_GRACE ErrReclaimBad Status = 10034 // NFS4ERR_RECLAIM_BAD ErrReclaimConflict Status = 10035 // NFS4ERR_RECLAIM_CONFLICT ErrBadXDR Status = 10036 // NFS4ERR_BADXDR ErrLocksHeld Status = 10037 // NFS4ERR_LOCKS_HELD ErrOpenMode Status = 10038 // NFS4ERR_OPENMODE ErrBadOwner Status = 10039 // NFS4ERR_BADOWNER ErrBadChar Status = 10040 // NFS4ERR_BADCHAR ErrBadName Status = 10041 // NFS4ERR_BADNAME ErrBadRange Status = 10042 // NFS4ERR_BAD_RANGE ErrLockNotSupp Status = 10043 // NFS4ERR_LOCK_NOTSUPP ErrOpIllegal Status = 10044 // NFS4ERR_OP_ILLEGAL ErrDeadlock Status = 10045 // NFS4ERR_DEADLOCK ErrFileOpen Status = 10046 // NFS4ERR_FILE_OPEN ErrAdminRevoked Status = 10047 // NFS4ERR_ADMIN_REVOKED ErrCBPathDown Status = 10048 // NFS4ERR_CB_PATH_DOWN ErrBadIOMode Status = 10049 // NFS4ERR_BADIOMODE ErrBadLayout Status = 10050 // NFS4ERR_BADLAYOUT ErrBadSessionDigest Status = 10051 // NFS4ERR_BAD_SESSION_DIGEST ErrBadSession Status = 10052 // NFS4ERR_BADSESSION ErrBadSlot Status = 10053 // NFS4ERR_BADSLOT ErrCompleteAlready Status = 10054 // NFS4ERR_COMPLETE_ALREADY ErrConnNotBoundToSession Status = 10055 // NFS4ERR_CONN_NOT_BOUND_TO_SESSION ErrDelegAlreadyWanted Status = 10056 // NFS4ERR_DELEG_ALREADY_WANTED ErrBackChanBusy Status = 10057 // NFS4ERR_BACK_CHAN_BUSY ErrLayoutTryLater Status = 10058 // NFS4ERR_LAYOUTTRYLATER ErrNoMatchingLayout Status = 10060 // NFS4ERR_NOMATCHING_LAYOUT ErrRecallConflict Status = 10061 // NFS4ERR_RECALLCONFLICT ErrUnknownLayoutType Status = 10062 // NFS4ERR_UNKNOWN_LAYOUTTYPE ErrSeqMisordered Status = 10063 // NFS4ERR_SEQ_MISORDERED ErrSequencePos Status = 10064 // NFS4ERR_SEQUENCE_POS ErrReqTooBig Status = 10065 // NFS4ERR_REQ_TOO_BIG ErrRepTooBig Status = 10066 // NFS4ERR_REP_TOO_BIG ErrRepTooBigToCache Status = 10067 // NFS4ERR_REP_TOO_BIG_TO_CACHE ErrRetryUncachedRep Status = 10068 // NFS4ERR_RETRY_UNCACHED_REP ErrUnsafeCompound Status = 10069 // NFS4ERR_UNSAFE_COMPOUND ErrTooManyOps Status = 10070 // NFS4ERR_TOO_MANY_OPS ErrOpNotInSession Status = 10071 // NFS4ERR_OP_NOT_IN_SESSION ErrHashAlgUnsupp Status = 10072 // NFS4ERR_HASH_ALG_UNSUPP ErrClientIDBusy Status = 10074 // NFS4ERR_CLIENTID_BUSY ErrPNFSIOHole Status = 10075 // NFS4ERR_PNFS_IO_HOLE ErrSeqFalseRetry Status = 10076 // NFS4ERR_SEQ_FALSE_RETRY ErrBadHighSlot Status = 10077 // NFS4ERR_BAD_HIGH_SLOT ErrDeadSession Status = 10078 // NFS4ERR_DEADSESSION ErrEncrAlgUnsupp Status = 10079 // NFS4ERR_ENCR_ALG_UNSUPP ErrPNFSNoLayout Status = 10080 // NFS4ERR_PNFS_NO_LAYOUT ErrNotOnlyOp Status = 10081 // NFS4ERR_NOT_ONLY_OP ErrWrongCred Status = 10082 // NFS4ERR_WRONG_CRED ErrWrongType Status = 10083 // NFS4ERR_WRONG_TYPE ErrRejectDeleg Status = 10085 // NFS4ERR_REJECT_DELEG ErrReturnConflict Status = 10086 // NFS4ERR_RETURNCONFLICT ErrDelegRevoked Status = 10087 // NFS4ERR_DELEG_REVOKED ErrPartnerNotSupp Status = 10088 // NFS4ERR_PARTNER_NOTSUPP ErrPartnerNoAuth Status = 10089 // NFS4ERR_PARTNER_NO_AUTH ErrUnionNotSupp Status = 10090 // NFS4ERR_UNION_NOTSUPP ErrOffloadDenied Status = 10091 // NFS4ERR_OFFLOAD_DENIED ErrWrongLFS Status = 10092 // NFS4ERR_WRONG_LFS ErrBadLabel Status = 10093 // NFS4ERR_BADLABEL ErrOffloadNoReqs Status = 10094 // NFS4ERR_OFFLOAD_NO_REQS )
NFSv4 status codes (nfsstat4).
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
nfs4serve
command
The nfs4serve command serves a local directory, or a demo in-memory filesystem, read-only over NFSv4.1.
|
The nfs4serve command serves a local directory, or a demo in-memory filesystem, read-only over NFSv4.1. |
|
internal
|
|
|
nfs4client
Package nfs4client is a minimal NFSv4.1 client for testing the server at the protocol level.
|
Package nfs4client is a minimal NFSv4.1 client for testing the server at the protocol level. |
|
oncrpc
Package oncrpc implements the parts of ONC RPC version 2 (RFC 5531) needed by an NFSv4 server: TCP record marking, call and reply headers, and the AUTH_NONE and AUTH_SYS credential flavors.
|
Package oncrpc implements the parts of ONC RPC version 2 (RFC 5531) needed by an NFSv4 server: TCP record marking, call and reply headers, and the AUTH_NONE and AUTH_SYS credential flavors. |
|
testfs
Package testfs is a simple in-memory nfsv4.FS using raw filehandles (the 8-byte inode number), for tests.
|
Package testfs is a simple in-memory nfsv4.FS using raw filehandles (the 8-byte inode number), for tests. |
|
xdr
Package xdr implements the subset of XDR (RFC 4506) encoding and decoding needed by ONC RPC and NFSv4.
|
Package xdr implements the subset of XDR (RFC 4506) encoding and decoding needed by ONC RPC and NFSv4. |
|
Package memfs is an in-memory filesystem served with nodefs.
|
Package memfs is an in-memory filesystem served with nodefs. |
|
Package nodefs adapts a tree of nodes to an nfsv4.FS, managing NFSv4 filehandles so that implementations don't have to think about them.
|
Package nodefs adapts a tree of nodes to an nfsv4.FS, managing NFSv4 filehandles so that implementations don't have to think about them. |
|
Package osfs serves a local directory tree read-only, using nodefs.
|
Package osfs serves a local directory tree read-only, using nodefs. |
|
tests
|
|
|
conformance/cmd/nfstestserve
command
The nfstestserve command serves test data and a local control socket.
|
The nfstestserve command serves test data and a local control socket. |