Skip to content

proposal: io/fs: track, list, interrupt pending ops #41249

@networkimprov

Description

@networkimprov

Operations by a filesystem (esp one using a network) must be interrupted if they stall. Herein is a way to do so without adding context.Context arguments to all functions of io/fs.

Mandating Context arguments would force them into third party package APIs that invoke any io/fs method. Code that depends on those packages would then be broken. If a package author did not amend its API, the callers would have to manage stalled ops some other way, and likely leak resources on every op retry.

However, we can define interfaces that support Context; see below.

The stdlib os filesystem would implement the PendingFS and PendingFile interfaces. Linux CIFS & FUSE and Windows I/O all support interruption of pending ops; Linux NFS does not. So interruption isn't assured for every deployment environment.

package fs

type PendingFS interface {
   FS
   TrackPending(on bool)               // turn on/off tracking; callable by multiple packages
   ListPending(kind uint) []PendingOp  // return recently pending ops
                                       // takes a set of |'d values, e.g. OpKindTop | OpKindFile
   Interrupt(op ...PendingOp) error    // interrupt one or more ops, if still pending
}

type PendingFile interface {
   File
   ListPending() []PendingOp           // return recently pending ops on the file
}

type PendingOp interface {
   Fn() string                         // "Open" etc
   Params() []interface{}              // all arguments
   Pathname() string                   // empty if not applicable
   String() string                     // summary suitable for logging
}

type InterruptError struct {...}       // returned by interrupted ops

const (
   OpKindFile uint = 1 << iota
   ...
)
package context // elsewhere?

type FS interface {
   fs.PendingFS
   WithContext(c Context, kind uint)   // cancellation interrupts all ops of 'kind'
}

type File interface {
   fs.PendingFile
   WithContext(c Context)              // cancellation interrupts all ops on the File
                                       // the context is preset if FS.WithContext got fs.OpKindFile | ...
}

Typical usage

afs := NewMyFs()
afs.TrackPending(true)
...
afl, err := afs.Open("myfile")
...
if problems {
   afs.Interrupt(afl.ListPending()...)
}

Related: #41054 - runtime: allow termination of blocked syscalls
Branched from #41190 (comment) - io/fs: add file system interfaces

cc @robpike @rsc

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions