All packets have a common header:
typedef struct { __u32 magic; __u16 command; __u16 length; } Drbd_Packet;The command fields decides the nature of the packet, the length field holds the length of the data part of the packet, which is 0 for all other packets than data packets.
The data packet ships a block over the wire:
typedef struct { __u64 block_nr; __u64 block_id; } Drbd_Data_P;This header is followed by the actual data.
This is a write barrier packet.
typedef struct { __u32 barrier; __u32 _fill; } Drbd_Barrier_P;barrier Is used to ship a number around. This number is used to identify the barrier.
At first I want to introduce you into the different execution contexts, that are used in DRBD:
The transfer_log is a circular buffer, which holds references to
recently sent blocks and write barriers. The blocks and write barriers
are put into the trasfer_log in the same order as they are sent over the
socket.
The transfer_log is used to analyse the dependencies between blocks, and
to decide if it is neccessary to issue a write barrier. If a
write-barrier-acknowledge packet is received the oldest epch set is released
from the transfer_log.
The epoch_set is used on the receiver's side to hold references to the blocks of the current epoch set. When a block is received, an entry is put into the epoch_set. Entries are remove from the epoch set when the according acknowledge packet is sent back. On receiption of a write-barrier packet, the drbdd thread must wait until all blocks of the current epoch_set are on the disk, before it may continue to receive further data blocks.
The sync_log is quite simmilar to the epoch_set, but only blocks sent by the drbd_syncer_X thread are going into the sync_log.
back