Documentation
¶
Overview ¶
Package nbd implements both sides of the Network Block Device (NBD) protocol over the fixed-newstyle handshake. Server exports a go-volumes volume.Device so a remote client (the Linux kernel nbd-client, qemu-nbd, libnbd/nbdinfo/nbdcopy, or this package's own Client) can read and write a block volume across a network connection; Client dials a remote NBD server and exposes the negotiated export as a volume.Device, so a remote volume is consumed exactly like a local one.
The wire protocol follows github.com/NetworkBlockDevice/nbd doc/proto.md. All multi-byte integers are big-endian (network byte order); both sides are therefore exercised on big-endian targets (s390x) in CI.
The implementation is pure Go, CGO-free, and depends only on the standard library and github.com/go-volumes/interface.
Index ¶
- Variables
- type Client
- func (c *Client) Close() error
- func (c *Client) Discard(off, length int64) error
- func (c *Client) ReadAt(p []byte, off int64) (int, error)
- func (c *Client) ReadOnly() bool
- func (c *Client) Size() (int64, error)
- func (c *Client) Sync() error
- func (c *Client) TrimSupported() bool
- func (c *Client) WriteAt(p []byte, off int64) (int, error)
- type ClientOption
- type Export
- type Logger
- type Server
Constants ¶
This section is empty.
Variables ¶
var ( ErrEPERM = errors.New("nbd: operation not permitted") ErrEIO = errors.New("nbd: input/output error") ErrEINVAL = errors.New("nbd: invalid argument") ErrENOSPC = errors.New("nbd: no space left on device") ErrEOVERFLOW = errors.New("nbd: value too large") )
Exported NBD errno sentinels for errors.Is matching on server-returned codes.
var ErrNoSpace = errNoSpace
ErrNoSpace is the sentinel a volume.Device may wrap from WriteAt to have the server report NBD ENOSPC to the client instead of the generic EIO.
var ErrReadOnly = errReadOnly
ErrReadOnly is returned by WriteAt/Discard when the negotiated export is read-only (it is the same sentinel the server adapter uses).
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is an NBD client: it dials a fixed-newstyle NBD server, negotiates an export, and exposes it as a volume.Device. ReadAt/WriteAt/Sync/Discard issue NBD_CMD_READ/WRITE/FLUSH/TRIM and Close sends NBD_CMD_DISC before closing the connection.
A Client is safe for concurrent use: a single background goroutine owns all reads from the connection and demultiplexes replies to waiting callers by request handle, while callers serialize their request writes under a mutex. This lets the replication engine in github.com/go-volumes/replica issue concurrent ReadAt/WriteAt/Sync against one Client.
func Dial ¶
Dial connects to an NBD server at addr (tcp) and negotiates the default export via the fixed-newstyle handshake, returning a Client over it.
func DialExport ¶
func DialExport(ctx context.Context, addr, exportName string, opts ...ClientOption) (*Client, error)
DialExport is Dial with an explicit export name (equivalent to Dial(ctx, addr, WithExportName(name), opts...)).
func NewClient ¶
func NewClient(conn net.Conn, opts ...ClientOption) (*Client, error)
NewClient negotiates over an already-connected net.Conn (e.g. one end of a net.Pipe), taking ownership of conn. It is the seam tests drive against the in-repo Server.
func (*Client) Close ¶
Close sends NBD_CMD_DISC (best effort) and closes the connection. It is safe to call more than once.
func (*Client) Discard ¶
Discard issues NBD_CMD_TRIM for [off, off+length), letting a thin backing reclaim the space. It is only available when the server advertised SEND_TRIM (see TrimSupported); otherwise it returns an error. Discard satisfies volume.Discarder.
func (*Client) ReadAt ¶
ReadAt issues NBD_CMD_READ and copies the returned data into p. It reads len(p) bytes at off; a short server reply is reported as io.ErrUnexpectedEOF.
func (*Client) TrimSupported ¶
TrimSupported reports whether the negotiated export advertised SEND_TRIM, so callers can decide whether to type-assert for volume.Discarder.
type ClientOption ¶
type ClientOption func(*clientConfig)
ClientOption configures a Client during Dial.
func WithExportName ¶
func WithExportName(name string) ClientOption
WithExportName selects the export to negotiate (empty = the default export).
func WithExportNameOpt ¶
func WithExportNameOpt() ClientOption
WithExportNameOpt forces the legacy NBD_OPT_EXPORT_NAME negotiation instead of the preferred NBD_OPT_GO. It exists mainly to exercise and support servers that do not implement NBD_OPT_GO.
func WithTimeout ¶
func WithTimeout(d time.Duration) ClientOption
WithTimeout sets a read/write deadline applied to the connection for every handshake and transmission operation. Zero (the default) means no deadline.
type Export ¶
type Export struct {
// Name is the export name a client selects during negotiation. Empty means
// the default export.
Name string
// Device is the backing block device.
Device volume.Device
// ReadOnly forces the export read-only even if Device can write. An export
// is also read-only when Device only satisfies volume.ReadOnly (see
// ReadOnlyExport).
ReadOnly bool
}
Export is a single named block device offered to clients. An export with an empty Name is the default export, served when a client requests the empty export name (e.g. nbd-client without -N, or qemu-nbd's default).
type Logger ¶
Logger is the minimal logging sink the server writes connection-level errors to. The standard library's *log.Logger satisfies it. It is injectable so the package keeps no global state; a nil logger discards everything.
type Server ¶
type Server struct {
// Exports lists the devices offered to clients. The first export whose
// Name matches the client's request is used; an export with an empty Name
// is the default.
Exports []Export
// Log receives connection-level errors. Nil discards them.
Log Logger
}
Server exports one or more block devices over NBD. The zero value is not usable; populate Exports. Server is safe for concurrent use and serves one goroutine per connection.
func (*Server) Handle ¶
Handle runs the full NBD lifecycle (fixed-newstyle handshake, option haggling, transmission) on a single connection and closes it on return. It is exported so callers can drive it over a net.Pipe or a custom listener. A clean client disconnect (NBD_CMD_DISC or EOF after negotiation) returns nil.
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
nbd-serve
command
Command nbd-serve exports a file as an NBD device on a TCP port so a real external NBD client (the Linux kernel nbd-client, qemu-nbd, nbdcopy, …) can connect to it.
|
Command nbd-serve exports a file as an NBD device on a TCP port so a real external NBD client (the Linux kernel nbd-client, qemu-nbd, nbdcopy, …) can connect to it. |