new kv, ctx in nfs handler
This commit is contained in:
parent
609d69fb5a
commit
bc4b39b1c1
41 changed files with 270 additions and 222 deletions
pkg/go-nfs
conn.gohandler.go
helpers
mount.gonfs_onaccess.gonfs_oncommit.gonfs_oncreate.gonfs_onfsinfo.gonfs_onfsstat.gonfs_ongetattr.gonfs_onlink.gonfs_onlookup.gonfs_onmkdir.gonfs_onmknod.gonfs_onpathconf.gonfs_onread.gonfs_onreaddir.gonfs_onreaddirplus.gonfs_onreadlink.gonfs_onremove.gonfs_onrename.gonfs_onsetattr.gonfs_onsymlink.gonfs_onwrite.go
|
@ -117,9 +117,16 @@ func (c *conn) serializeWrites(ctx context.Context) {
|
|||
|
||||
// Handle a request. errors from this method indicate a failure to read or
|
||||
// write on the network stream, and trigger a disconnection of the connection.
|
||||
func (c *conn) handle(ctx context.Context, w *response) error {
|
||||
func (c *conn) handle(ctx context.Context, w *response) (err error) {
|
||||
ctx, span := tracer.Start(ctx, fmt.Sprintf("nfs.handle.%s", NFSProcedure(w.req.Header.Proc).String()))
|
||||
defer span.End()
|
||||
defer func() {
|
||||
if err != nil {
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
} else {
|
||||
span.SetStatus(codes.Ok, "")
|
||||
}
|
||||
}()
|
||||
|
||||
handler := c.Server.handlerFor(w.req.Header.Prog, w.req.Header.Proc)
|
||||
if handler == nil {
|
||||
|
@ -146,7 +153,6 @@ func (c *conn) handle(ctx context.Context, w *response) error {
|
|||
}
|
||||
}
|
||||
|
||||
span.SetStatus(codes.Ok, "")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -25,9 +25,9 @@ type Handler interface {
|
|||
|
||||
// represent file objects as opaque references
|
||||
// Can be safely implemented via helpers/cachinghandler.
|
||||
ToHandle(fs Filesystem, path []string) []byte
|
||||
FromHandle(fh []byte) (Filesystem, []string, error)
|
||||
InvalidateHandle(Filesystem, []byte) error
|
||||
ToHandle(ctx context.Context, fs Filesystem, path []string) []byte
|
||||
FromHandle(ctx context.Context, fh []byte) (Filesystem, []string, error)
|
||||
InvalidateHandle(context.Context, Filesystem, []byte) error
|
||||
|
||||
// How many handles can be safely maintained by the handler.
|
||||
HandleLimit() int
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package helpers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"io/fs"
|
||||
|
@ -51,7 +52,7 @@ type entry struct {
|
|||
// ToHandle takes a file and represents it with an opaque handle to reference it.
|
||||
// In stateless nfs (when it's serving a unix fs) this can be the device + inode
|
||||
// but we can generalize with a stateful local cache of handed out IDs.
|
||||
func (c *CachingHandler) ToHandle(f nfs.Filesystem, path []string) []byte {
|
||||
func (c *CachingHandler) ToHandle(ctx context.Context, f nfs.Filesystem, path []string) []byte {
|
||||
joinedPath := f.Join(path...)
|
||||
|
||||
if handle := c.searchReverseCache(f, joinedPath); handle != nil {
|
||||
|
@ -79,7 +80,7 @@ func (c *CachingHandler) ToHandle(f nfs.Filesystem, path []string) []byte {
|
|||
}
|
||||
|
||||
// FromHandle converts from an opaque handle to the file it represents
|
||||
func (c *CachingHandler) FromHandle(fh []byte) (nfs.Filesystem, []string, error) {
|
||||
func (c *CachingHandler) FromHandle(ctx context.Context, fh []byte) (nfs.Filesystem, []string, error) {
|
||||
id, err := uuid.FromBytes(fh)
|
||||
if err != nil {
|
||||
return nil, []string{}, err
|
||||
|
@ -134,7 +135,7 @@ func (c *CachingHandler) evictReverseCache(path string, handle uuid.UUID) {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *CachingHandler) InvalidateHandle(fs nfs.Filesystem, handle []byte) error {
|
||||
func (c *CachingHandler) InvalidateHandle(ctx context.Context, fs nfs.Filesystem, handle []byte) error {
|
||||
//Remove from cache
|
||||
id, _ := uuid.FromBytes(handle)
|
||||
entry, ok := c.activeHandles.Get(id)
|
||||
|
|
|
@ -35,21 +35,21 @@ func (h *NullAuthHandler) Change(fs nfs.Filesystem) nfs.Change {
|
|||
}
|
||||
|
||||
// FSStat provides information about a filesystem.
|
||||
func (h *NullAuthHandler) FSStat(ctx context.Context, f nfs.Filesystem, s *nfs.FSStat) error {
|
||||
func (h *NullAuthHandler) FSStat(context.Context, nfs.Filesystem, *nfs.FSStat) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToHandle handled by CachingHandler
|
||||
func (h *NullAuthHandler) ToHandle(f nfs.Filesystem, s []string) []byte {
|
||||
func (h *NullAuthHandler) ToHandle(context.Context, nfs.Filesystem, []string) []byte {
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
// FromHandle handled by CachingHandler
|
||||
func (h *NullAuthHandler) FromHandle([]byte) (nfs.Filesystem, []string, error) {
|
||||
func (h *NullAuthHandler) FromHandle(context.Context, []byte) (nfs.Filesystem, []string, error) {
|
||||
return nil, []string{}, nil
|
||||
}
|
||||
|
||||
func (c *NullAuthHandler) InvalidateHandle(nfs.Filesystem, []byte) error {
|
||||
func (c *NullAuthHandler) InvalidateHandle(context.Context, nfs.Filesystem, []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ func onMount(ctx context.Context, w *response, userHandle Handler) error {
|
|||
return err
|
||||
}
|
||||
|
||||
rootHndl := userHandle.ToHandle(handle, []string{})
|
||||
rootHndl := userHandle.ToHandle(ctx, handle, []string{})
|
||||
|
||||
if status == MountStatusOk {
|
||||
_ = xdr.Write(writer, rootHndl)
|
||||
|
|
|
@ -14,7 +14,7 @@ func onAccess(ctx context.Context, w *response, userHandle Handler) error {
|
|||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusInval, err}
|
||||
}
|
||||
fs, path, err := userHandle.FromHandle(roothandle)
|
||||
fs, path, err := userHandle.FromHandle(ctx, roothandle)
|
||||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusStale, err}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ func onCommit(ctx context.Context, w *response, userHandle Handler) error {
|
|||
}
|
||||
// The conn will drain the unread offset and count arguments.
|
||||
|
||||
fs, path, err := userHandle.FromHandle(handle)
|
||||
fs, path, err := userHandle.FromHandle(ctx, handle)
|
||||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusStale, err}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ func onCreate(ctx context.Context, w *response, userHandle Handler) error {
|
|||
return &NFSStatusError{NFSStatusNotSupp, os.ErrInvalid}
|
||||
}
|
||||
|
||||
fs, path, err := userHandle.FromHandle(obj.Handle)
|
||||
fs, path, err := userHandle.FromHandle(ctx, obj.Handle)
|
||||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusStale, err}
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ func onCreate(ctx context.Context, w *response, userHandle Handler) error {
|
|||
return &NFSStatusError{NFSStatusAccess, err}
|
||||
}
|
||||
|
||||
fp := userHandle.ToHandle(fs, newFile)
|
||||
fp := userHandle.ToHandle(ctx, fs, newFile)
|
||||
changer := userHandle.Change(fs)
|
||||
if err := attrs.Apply(ctx, changer, fs, newFilePath); err != nil {
|
||||
Log.Errorf("Error applying attributes: %v\n", err)
|
||||
|
|
|
@ -24,7 +24,7 @@ func onFSInfo(ctx context.Context, w *response, userHandle Handler) error {
|
|||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusInval, err}
|
||||
}
|
||||
fs, path, err := userHandle.FromHandle(roothandle)
|
||||
fs, path, err := userHandle.FromHandle(ctx, roothandle)
|
||||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusStale, err}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ func onFSStat(ctx context.Context, w *response, userHandle Handler) error {
|
|||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusInval, err}
|
||||
}
|
||||
fs, path, err := userHandle.FromHandle(roothandle)
|
||||
fs, path, err := userHandle.FromHandle(ctx, roothandle)
|
||||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusStale, err}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ func onGetAttr(ctx context.Context, w *response, userHandle Handler) error {
|
|||
return &NFSStatusError{NFSStatusInval, err}
|
||||
}
|
||||
|
||||
fs, path, err := userHandle.FromHandle(handle)
|
||||
fs, path, err := userHandle.FromHandle(ctx, handle)
|
||||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusStale, err}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ func onLink(ctx context.Context, w *response, userHandle Handler) error {
|
|||
return &NFSStatusError{NFSStatusInval, err}
|
||||
}
|
||||
|
||||
fs, path, err := userHandle.FromHandle(obj.Handle)
|
||||
fs, path, err := userHandle.FromHandle(ctx, obj.Handle)
|
||||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusStale, err}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ func onLink(ctx context.Context, w *response, userHandle Handler) error {
|
|||
return &NFSStatusError{NFSStatusNotDir, nil}
|
||||
}
|
||||
|
||||
fp := userHandle.ToHandle(fs, append(path, string(obj.Filename)))
|
||||
fp := userHandle.ToHandle(ctx, fs, append(path, string(obj.Filename)))
|
||||
changer := userHandle.Change(fs)
|
||||
if changer == nil {
|
||||
return &NFSStatusError{NFSStatusAccess, err}
|
||||
|
|
|
@ -33,7 +33,7 @@ func onLookup(ctx context.Context, w *response, userHandle Handler) error {
|
|||
return &NFSStatusError{NFSStatusInval, err}
|
||||
}
|
||||
|
||||
fs, p, err := userHandle.FromHandle(obj.Handle)
|
||||
fs, p, err := userHandle.FromHandle(ctx, obj.Handle)
|
||||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusStale, err}
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ func onLookup(ctx context.Context, w *response, userHandle Handler) error {
|
|||
return &NFSStatusError{NFSStatusAccess, os.ErrPermission}
|
||||
}
|
||||
pPath := p[0 : len(p)-1]
|
||||
pHandle := userHandle.ToHandle(fs, pPath)
|
||||
pHandle := userHandle.ToHandle(ctx, fs, pPath)
|
||||
resp, err := lookupSuccessResponse(ctx, pHandle, pPath, p, fs)
|
||||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusServerFault, err}
|
||||
|
@ -74,7 +74,7 @@ func onLookup(ctx context.Context, w *response, userHandle Handler) error {
|
|||
return &NFSStatusError{NFSStatusNoEnt, os.ErrNotExist}
|
||||
}
|
||||
|
||||
newHandle := userHandle.ToHandle(fs, reqPath)
|
||||
newHandle := userHandle.ToHandle(ctx, fs, reqPath)
|
||||
resp, err := lookupSuccessResponse(ctx, newHandle, reqPath, p, fs)
|
||||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusServerFault, err}
|
||||
|
|
|
@ -26,7 +26,7 @@ func onMkdir(ctx context.Context, w *response, userHandle Handler) error {
|
|||
return &NFSStatusError{NFSStatusInval, err}
|
||||
}
|
||||
|
||||
fs, path, err := userHandle.FromHandle(obj.Handle)
|
||||
fs, path, err := userHandle.FromHandle(ctx, obj.Handle)
|
||||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusStale, err}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ func onMkdir(ctx context.Context, w *response, userHandle Handler) error {
|
|||
return &NFSStatusError{NFSStatusAccess, err}
|
||||
}
|
||||
|
||||
fp := userHandle.ToHandle(fs, newFolder)
|
||||
fp := userHandle.ToHandle(ctx, fs, newFolder)
|
||||
changer := userHandle.Change(fs)
|
||||
if changer != nil {
|
||||
if err := attrs.Apply(ctx, changer, fs, newFolderPath); err != nil {
|
||||
|
|
|
@ -37,7 +37,7 @@ func onMknod(ctx context.Context, w *response, userHandle Handler) error {
|
|||
}
|
||||
|
||||
// see if the filesystem supports mknod
|
||||
fs, path, err := userHandle.FromHandle(obj.Handle)
|
||||
fs, path, err := userHandle.FromHandle(ctx, obj.Handle)
|
||||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusStale, err}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ func onMknod(ctx context.Context, w *response, userHandle Handler) error {
|
|||
} else if !parent.IsDir() {
|
||||
return &NFSStatusError{NFSStatusNotDir, nil}
|
||||
}
|
||||
fp := userHandle.ToHandle(fs, append(path, string(obj.Filename)))
|
||||
fp := userHandle.ToHandle(ctx, fs, append(path, string(obj.Filename)))
|
||||
|
||||
switch nfs_ftype(ftype) {
|
||||
case FTYPE_NF3CHR:
|
||||
|
|
|
@ -15,7 +15,7 @@ func onPathConf(ctx context.Context, w *response, userHandle Handler) error {
|
|||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusInval, err}
|
||||
}
|
||||
fs, path, err := userHandle.FromHandle(roothandle)
|
||||
fs, path, err := userHandle.FromHandle(ctx, roothandle)
|
||||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusStale, err}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ func onRead(ctx context.Context, w *response, userHandle Handler) error {
|
|||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusInval, err}
|
||||
}
|
||||
fs, path, err := userHandle.FromHandle(obj.Handle)
|
||||
fs, path, err := userHandle.FromHandle(ctx, obj.Handle)
|
||||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusStale, err}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ func onReadDir(ctx context.Context, w *response, userHandle Handler) error {
|
|||
return &NFSStatusError{NFSStatusTooSmall, io.ErrShortBuffer}
|
||||
}
|
||||
|
||||
fs, p, err := userHandle.FromHandle(obj.Handle)
|
||||
fs, p, err := userHandle.FromHandle(ctx, obj.Handle)
|
||||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusStale, err}
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ func onReadDir(ctx context.Context, w *response, userHandle Handler) error {
|
|||
|
||||
func getDirListingWithVerifier(ctx context.Context, userHandle Handler, fsHandle []byte, verifier uint64) ([]fs.FileInfo, uint64, error) {
|
||||
// figure out what directory it is.
|
||||
fs, p, err := userHandle.FromHandle(fsHandle)
|
||||
fs, p, err := userHandle.FromHandle(ctx, fsHandle)
|
||||
if err != nil {
|
||||
return nil, 0, &NFSStatusError{NFSStatusStale, err}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ func onReadDirPlus(ctx context.Context, w *response, userHandle Handler) error {
|
|||
return &NFSStatusError{NFSStatusTooSmall, nil}
|
||||
}
|
||||
|
||||
fs, p, err := userHandle.FromHandle(obj.Handle)
|
||||
fs, p, err := userHandle.FromHandle(ctx, obj.Handle)
|
||||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusStale, err}
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ func onReadDirPlus(ctx context.Context, w *response, userHandle Handler) error {
|
|||
}
|
||||
|
||||
filePath := joinPath(p, c.Name())
|
||||
handle := userHandle.ToHandle(fs, filePath)
|
||||
handle := userHandle.ToHandle(ctx, fs, filePath)
|
||||
attrs := ToFileAttribute(c, path.Join(filePath...))
|
||||
entities = append(entities, readDirPlusEntity{
|
||||
FileID: attrs.Fileid,
|
||||
|
|
|
@ -15,7 +15,7 @@ func onReadLink(ctx context.Context, w *response, userHandle Handler) error {
|
|||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusInval, err}
|
||||
}
|
||||
fs, path, err := userHandle.FromHandle(handle)
|
||||
fs, path, err := userHandle.FromHandle(ctx, handle)
|
||||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusStale, err}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ func onRemove(ctx context.Context, w *response, userHandle Handler) error {
|
|||
if err := xdr.Read(w.req.Body, &obj); err != nil {
|
||||
return &NFSStatusError{NFSStatusInval, err}
|
||||
}
|
||||
fs, path, err := userHandle.FromHandle(obj.Handle)
|
||||
fs, path, err := userHandle.FromHandle(ctx, obj.Handle)
|
||||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusStale, err}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ func onRemove(ctx context.Context, w *response, userHandle Handler) error {
|
|||
preCacheData := ToFileAttribute(dirInfo, fullPath).AsCache()
|
||||
|
||||
toDelete := fs.Join(append(path, string(obj.Filename))...)
|
||||
toDeleteHandle := userHandle.ToHandle(fs, append(path, string(obj.Filename)))
|
||||
toDeleteHandle := userHandle.ToHandle(ctx, fs, append(path, string(obj.Filename)))
|
||||
|
||||
err = fs.Remove(ctx, toDelete)
|
||||
if err != nil {
|
||||
|
@ -65,7 +65,7 @@ func onRemove(ctx context.Context, w *response, userHandle Handler) error {
|
|||
return &NFSStatusError{NFSStatusIO, err}
|
||||
}
|
||||
|
||||
if err := userHandle.InvalidateHandle(fs, toDeleteHandle); err != nil {
|
||||
if err := userHandle.InvalidateHandle(ctx, fs, toDeleteHandle); err != nil {
|
||||
return &NFSStatusError{NFSStatusServerFault, err}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ func onRename(ctx context.Context, w *response, userHandle Handler) error {
|
|||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusInval, err}
|
||||
}
|
||||
fs, fromPath, err := userHandle.FromHandle(from.Handle)
|
||||
fs, fromPath, err := userHandle.FromHandle(ctx, from.Handle)
|
||||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusStale, err}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ func onRename(ctx context.Context, w *response, userHandle Handler) error {
|
|||
if err = xdr.Read(w.req.Body, &to); err != nil {
|
||||
return &NFSStatusError{NFSStatusInval, err}
|
||||
}
|
||||
fs2, toPath, err := userHandle.FromHandle(to.Handle)
|
||||
fs2, toPath, err := userHandle.FromHandle(ctx, to.Handle)
|
||||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusStale, err}
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ func onRename(ctx context.Context, w *response, userHandle Handler) error {
|
|||
}
|
||||
preDestData := ToFileAttribute(toDirInfo, toDirPath).AsCache()
|
||||
|
||||
oldHandle := userHandle.ToHandle(fs, append(fromPath, string(from.Filename)))
|
||||
oldHandle := userHandle.ToHandle(ctx, fs, append(fromPath, string(from.Filename)))
|
||||
|
||||
fromLoc := fs.Join(append(fromPath, string(from.Filename))...)
|
||||
toLoc := fs.Join(append(toPath, string(to.Filename))...)
|
||||
|
@ -97,7 +97,7 @@ func onRename(ctx context.Context, w *response, userHandle Handler) error {
|
|||
return &NFSStatusError{NFSStatusIO, err}
|
||||
}
|
||||
|
||||
if err := userHandle.InvalidateHandle(fs, oldHandle); err != nil {
|
||||
if err := userHandle.InvalidateHandle(ctx, fs, oldHandle); err != nil {
|
||||
return &NFSStatusError{NFSStatusServerFault, err}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ func onSetAttr(ctx context.Context, w *response, userHandle Handler) error {
|
|||
return &NFSStatusError{NFSStatusInval, err}
|
||||
}
|
||||
|
||||
fs, path, err := userHandle.FromHandle(handle)
|
||||
fs, path, err := userHandle.FromHandle(ctx, handle)
|
||||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusStale, err}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ func onSymlink(ctx context.Context, w *response, userHandle Handler) error {
|
|||
return &NFSStatusError{NFSStatusInval, err}
|
||||
}
|
||||
|
||||
fs, path, err := userHandle.FromHandle(obj.Handle)
|
||||
fs, path, err := userHandle.FromHandle(ctx, obj.Handle)
|
||||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusStale, err}
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ func onSymlink(ctx context.Context, w *response, userHandle Handler) error {
|
|||
return &NFSStatusError{NFSStatusAccess, err}
|
||||
}
|
||||
|
||||
fp := userHandle.ToHandle(fs, append(path, string(obj.Filename)))
|
||||
fp := userHandle.ToHandle(ctx, fs, append(path, string(obj.Filename)))
|
||||
changer := userHandle.Change(fs)
|
||||
if changer != nil {
|
||||
if err := attrs.Apply(ctx, changer, fs, newFilePath); err != nil {
|
||||
|
|
|
@ -35,7 +35,7 @@ func onWrite(ctx context.Context, w *response, userHandle Handler) error {
|
|||
return &NFSStatusError{NFSStatusInval, err}
|
||||
}
|
||||
|
||||
fs, path, err := userHandle.FromHandle(req.Handle)
|
||||
fs, path, err := userHandle.FromHandle(ctx, req.Handle)
|
||||
if err != nil {
|
||||
return &NFSStatusError{NFSStatusStale, err}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue