Index


NAME

Linux::NBD::Server - server (data provider) side of a network block device

SYNOPSIS

 use Linux::NBD::Server;

DESCRIPTION

You must subclass Linux::NBD::Server to get meaningful results. You should overwrite req_read and/or req_write. The default implementations just return EIO.

METHODS

$server = new Linux::NBD::Server socket => $fh, ...;

Create a new server. All arguments are put into a hashref which is blessed and returned. The only required argument is socket which should be connected to a Linux::NBD::Client.

$server->run

Enters a server loop, serving requests. Only returns when the socket is closed or a disconnect message is received.

If you need non-blocking access your best bet is to use $server->one_request after you detected readability on the file descriptor, but note that it still might block to read the write data from the socket.

$server->one_request

Waits for and handles a single request and returns, returning true if a request could be handled, false (but defined) if no full request could be received yet (in which case the partial request will be buffered), and undef if there was an error or eof.

On blockign sockets, this will read one full request and handle it. On non-blocking sockets it will try to do the same, but if not enough data is available, it will return false (but defined) and buffer th already-read data for the next invocation.

$server->format_reply ($handle[, $error, [, $read_data]])

Formats (and returns as a string) a reply message. If the request was a read request and $error is zero (or missing, both meaning no error), you should append the read data to it (or let the method do it by specifying the $read_data argument, which is automatically appended unless $error is true).

$server->reply ($handle[, $error[, $read_data]])

Formats and sends a reply to the server. Only works on blocking sockets. For non-blocking sockets, you have to use format_reply and manage the send buffer yourself.

$server->req_read ($handle, $offset, $length)

This callback is called for every read request. It should send back a reply and the requested number of bytes, e.g.:

  sub req_read {
     my ($self, $handle, $ofs, $len) = @_;
     $self->reply ($handle, 0, "\xff" x $len);
  }

The default implementation will reply with an error.

$server->req_write ($handle, $offset, $data)

Same as req_read, but is called for writes: instead of a length the write data is passed directly.

  sub req_write {
     my ($self, $handle, $ofs, $data) = @_;
     $self->reply ($handle, 0); # OK
  }

You can avoid copying the (potentially large) data argument by refering to it directly, e.g.:

  sub req_write {
     my ($self, $handle, $ofs) = @_;
     # do something with $_[3] directly
     $self->reply ($handle, 0); # OK
  }

The default implementation will reply with an error.

$server->req_disc

A disconnect request was received - what you do with it is up to you, the kernel driver is a bit confused - you can still have outstanding requests, and you can still receive further requests, so it's not clear what this request is intended to achieve, and it's probably best not to override it.

NBD TOOL NEGOTIATION PROTOCOL

Standard NBD tools add a handshake phase before starting to serve/send requests. The server-side implementation looks like this:

    $size = new Math::BigInt $size;
    my $size_hi = $size->copy->brsft(32)->blsft(32);
    my $size_lo = $size->copy->bsub($size_hi)->numify;
    $size_hi = $size_hi->brsft(32)->numify;

    $s->send ("NBDMAGIC\x00\x00\x42\x02\x81\x86\x12\x53");
    $s->send (pack "NN", $size_hi, $size_lo);
    $s->send ("\x00" x 128);

    # now serve
    my $server = new ServerClass socket => $s;
    $server->run;

AUTHOR

 Marc Lehmann <schmorp@schmorp.de>
 http://home.schmorp.de/