Module Mkernel.Block

type t

The type of block devices.

val pagesize : t -> int

pagesize t returns the number of bytes in a memory page, where "page" is a fixed length block, the unit for memory allocation and block-device mapping performed by the functions above.

val length : t -> int

length t returns the length of the block device (in bytes).

val atomic_read : t -> src_off:int -> ?dst_off:int -> bigstring -> unit

atomic_read t ~src_off ?dst_off bstr reads data of pagesize t bytes into the buffer bstr (starting at byte dst_off) from the block device t at byte src_off. Always reads the full amount of pagesize t bytes ("short reads" are not possible).

This operation is called atomic, meaning that it is indivisible and irreducible. What's more, Miou can't do anything else (such as execute other tasks) until this operation has been completed.

The advantage of this type of operation is that you can assume a precise state, not only of the memory but also of the block-device, which cannot change during the read.

The disadvantage is that this operation can take a long time (and make your unikernel unavailable to all events for the duration of the operation) depending on the file system used by the host and the hardware used to store the block-device.

  • raises Invalid_argument

    if src_off is not a multiple of pagesize t or if the length of bstr is not equal to pagesize t.

val atomic_write : t -> ?src_off:int -> dst_off:int -> bigstring -> unit

atomic_write t ~src_off ?dst_off bstr writes data pagesize t bytes from the buffer bstr (at byte dst_off) to the block device identified by t, starting at byte src_off. Data is either written in it's entirety or not at all ("short writes" are not possible).

This operation is called atomic, meaning that it is indivisible and irreducible. What's more, Miou can't do anything else (such as execute other tasks) until this operation has been completed.

  • raises Invalid_argument

    if dst_off is not a multiple of pagesize t or if the length of bstr is not equal to pagesize t.

Scheduled operations on block-devices.

As far as operations on scheduled block-devices are concerned, here's a description of when Miou performs these operations.

As soon as Miou tries to observe possible events (such as the reception of a packet - see Net.read), it also performs a (single) block-device operation. If Miou still has time (such as waiting for the end of a sleep), it can perform several operations on the block-devices until it runs out of time.

In short, operations on scheduled block-devices have the lowest priority. A unikernel can't go faster than the operations on waiting block-devices, so it's said to be I/O-bound on block-devices.

val read : t -> src_off:int -> ?dst_off:int -> bigstring -> unit

Like atomic_read, but the operation is scheduled. That is, it's not actually done, but will be as soon as Miou gets the chance.

val write : t -> ?src_off:int -> dst_off:int -> bigstring -> unit

Like atomic_write, but the operation is scheduled. That is, it's not actually done, but will be as soon as Miou gets the chance.

val connect : string -> (t, [> `Msg of string ]) result

connect name returns a block device according to the given name. It must correspond to the name given as an argument to the Solo5 tender. For example, if the invocation of our unikernel with Solo5 corresponds to:

  $ solo5-hvt --block:disk=file.txt -- unikernel.hvt

The name of the block would be: "disk".