Document the vldb (ubik) file format
authorMichael Meffie <mmeffie@sinenomine.net>
Wed, 29 Oct 2014 21:25:29 +0000 (17:25 -0400)
committerD Brashear <shadow@your-file-system.com>
Wed, 5 Nov 2014 13:22:35 +0000 (08:22 -0500)
Briefly document the vldb version 4 file format.  Describe the vl
header, the vl entry, and mh extensions.

Thanks to Marcio Barbosa for an initial draft, comments, and review.

Thanks to Ben Kaduk the prdb.txt, and for an initial review and comments.

Change-Id: If3ca85419027a218b7bb1585f5d5cd4763ad5b26
Reviewed-on: http://gerrit.openafs.org/11564
Reviewed-by: Nathaniel Filardo <nwfilardo@gmail.com>
Reviewed-by: D Brashear <shadow@your-file-system.com>
Tested-by: D Brashear <shadow@your-file-system.com>

doc/txt/vldb.txt [new file with mode: 0644]

diff --git a/doc/txt/vldb.txt b/doc/txt/vldb.txt
new file mode 100644 (file)
index 0000000..9e8d9dd
--- /dev/null
@@ -0,0 +1,565 @@
+
+This document describes version 4 of the OpenAFS Volume Location Database
+(VLDB) file format.
+
+
+VLDB file layout
+
+The vldb.DB0 file consists of 64 octet ubik header, followed by a 132,120 octet
+vldb header, followed a variable number of vldb records.  Records are either a
+148 octet volume location (vl) entry or a 8192 octet multi-homed (mh) extension
+block.  A bit flag at a fixed offset of each record specifies the record type.
+A field in the vldb header indicates the location of the last record. Any data
+in the file following the last record is ignored.
+
+
+Ubik header
+
+The vldb.DB0 file begins with a 64 octet ubik header.  All fields are in
+network byte order.  Only the first 16 octets of the ubik header are used.  The
+unused fields should always be zero.  The first 16 octets of the ubik header
+contain the representation of a struct ubik_hdr, with all the fields in network
+byte order:
+
+       0                   1                   2                   3
+       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |                           ubik_magic                          |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |            padding            |          header_size          |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |                             epoch                             |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |                            counter                            |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |                            [unused]                           |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |                            [unused]                           |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |                            [unused]                           |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |                            [unused]                           |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |                            [unused]                           |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |                            [unused]                           |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |                            [unused]                           |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |                            [unused]                           |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |                            [unused]                           |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |                            [unused]                           |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |                            [unused]                           |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |                            [unused]                           |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+       0                   1                   2                   3
+
+magic is the ubik file identification. It should always be 0x00354545.
+
+pad1 is unused, should always be 0
+
+header_size is the size of the ubik header (including unused space), should always
+be 0x40
+
+epoch is the ubik quorum epoch value.
+
+counter is the ubik counter for transactions and updates.
+
+unused space should always be zero.
+
+
+The ubik header is not exposed through the VL_ RPC package, and as such is not
+considered to be part of the logical VLDB database.
+
+Subsequent discussion will refer to VLDB addresses, or simply addresses.  A
+VLDB address is a logical offset to a data within the VLDB.  The physical file
+offset of data referenced by a VLDB address is the VLDB address plus the size
+of the ubik header (64 octets).
+
+
+VLDB header
+
+The VLDB header follows the ubik_header. It is the logical beginning of the
+VLDB.  The VLDB header is 132120 octets in size. The majority of this space
+contains four hash tables enabling quick lookups of volumes by name and id.
+All integer fields are stored in network byte order.
+
+The layout of the VLDB header is:
+
+        0                   1                   2                   3
+        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+octets +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     0 |                            version                            |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     4 |                          headersize                           |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     8 |                            freePtr                            |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    12 |                            eofPtr                             |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    16 |                            allocs                             |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    20 |                             frees                             |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    24 |                          MaxVolumeId                          |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    28 |                         TotalEntries[0] (rw)                  |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    32 |                         TotalEntries[1] (ro)                  |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    36 |                         TotalEntries[2] (bk)                  |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    40 |                          IpMappedAddr                         |
+       ~                              ...                              ~
+  1056 |                                                               |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  1060 |                          VolnameHash                          |
+       ~                              ...                              ~
+ 33820 |                                                               |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ 33824 |                          VolidHash[0] (rw)                    |
+       ~                              ...                              ~
+       |                                                               |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |                          VolidHash[1] (ro)                    |
+       ~                              ...                              ~
+       |                                                               |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |                          VolidHash[2] (bk)                    |
+       ~                              ...                              ~
+132112 |                                                               |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+132116 |                              SIT                              |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+        0                   1                   2                   3
+
+vldbversion is the vldb disk format version number. This document describes
+version 4.
+
+   Note: The OpenAFS vlserver creates empty vldb files as version 3, and
+         converts the vldb to version 4 in place the first time a fileserver
+         UUID is registered.
+
+headersize is the size in octets of the vldb header, currently 0x020418 (132120)
+
+freePtr is the logical address in octets of the first in a linked list of
+unused vldb entries in the vldb database file (that is the first logical hole
+in the database file). This value is zero if the database is densely packed.
+The physical file offset to the first free entry is the freePtr value plus the
+size of the ubik header (64 octets).
+
+eofPtr is the logical address in octets of the end of the database file. When a
+new entry is created that extends the database file, it will be created at this
+logical index.The physical file offset to the end of the database file eofPtr
+value plus the size of the ubik header (64 octets).
+
+allocs is the number of calls to AllocBlock(), for statistical purposes.
+
+frees is the number of calls to FreeBlock(), for statistical purposes.
+
+MaxVolumeId is the largest volume id allocated. It is incremented every time
+a volume is created.
+
+TotalEntries[0] is the number of read-write volume entries.
+
+TotalEntries[1] is the number of read/only volume entries.
+
+TotalEntries[2] is the number of backup volume entries.
+
+IpMappedAddr maps vl entry serverNumbers to file server information.  The vl
+entry serverNumber field is used as an offset into the IpMappedAddr table.  The
+IpMappedaddr is a table of 255 records, one for each possible serverNumber,
+from 0 to 254.  Each record is a 32 bit integer in network byte order.  Empty
+records should be zero filled.
+
+IpMappedAddr records hold either a reference to a mh entry or a single IPv4
+address.  Records which contain 0xFF in the first octet are references to mh
+entries. Non-zero records which do not contain 0xFF in the first octet hold a
+single IPv4 address in network byte order.
+
+The format of a reference to a mh entry is:
+
+        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |      0xFF     |     base      |            index              |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+0xFF in the first octet indicates the record contains a multi-homed entry
+reference, instead of an IPv4 address.
+
+base is the mh extension block number; supported range is 0 to 3.
+
+index is the index to the mh entry within the mh extension block; supported range
+is 1 to 63. (Index of 0 is reserved for the mh extension block header.)
+
+Following the index are four hash tables, each containing 8191 (a prime number)
+32-bit entries in network byte order. Each entry represents a hash bucket and
+holds the address of the vl entry at the head of the hash chain, or zero to
+indicate an empty hash bucket.
+
+VolnameHash is the hash table for searches by volume name.  The nextNameHash
+field at the head of the chain holds the address of the next vl entry in the
+hash chain.
+
+The NameHash hash function is targetted for ASCII text and is similar to the
+PRDB name hash function.  Each octet of the volume name is treated as an
+unsigned integer from which 63 (decimal) is subtracted, and the resulting
+stream of integers is used as the coefficients of a power series with base 63
+(decimal), with the least significant coefficient appearing first.
+
+For example, for a volume name string string of "abc", which is the stream
+of octets (in decimal):
+
+   97 98 99
+
+then the power series used in the hash function calculation would be
+(all numbers in decimal):
+
+  34 + (35 * 63) + (36 * 63**2)
+
+The value of this power series is stored in an unsigned 32-bit integer, and as
+such is implicitly computed modulo 2**32.  The remainder modulo 8191 (the size
+of the hash table) of this 32-bit value is used as the index into the hash
+table for this name entry.  (This hash function can be easily implemented
+iteratively.)
+
+
+VolidHash[0] is the hash table for searches by read-write volume ID. The
+nextIdHash[0] field at the head of the chain holds the address of the next vl
+entry in the hash chain.
+
+VolidHash[1] is the read-only volume ID to vldb entry hash table. The
+nextIdHash[1] field at the head of the chain holds the address of the next vl
+entry in the hash chain.
+
+VolidHash[2] is the backup volume ID to vldb entry hash table. The
+nextIdHash[2] field at the head of the chain holds the address of the next vl
+entry in the hash chain.
+
+The VolidHash hash function the remainder modulo 8191 (the size of the hash
+table) of the absolute value of the volume id.
+
+
+SIT holds the logical address of the first multi-homed extension block in the
+vldb. Each multi-homed extension block holds 4 logical addresses to additional
+multi-homed extension blocks.
+
+
+VLDB Records
+
+VLDB Records follow immediately after the VLDB header. Each record is either a
+148 octet sized volume location (vl) entry or a 8192 octet sized multi-homed
+(mh) extension block.  A bit flag at a fixed offset specifies the record type.
+
+    Note: The mh extension block size is *not* a multiple of the
+          vl entry size.
+
+The only invariant field is the single bit field which indicates the
+record type:
+
+        0                   1                   2                   3
+        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+octets +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     0 |                       [record-specific]                       |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |                       [record-specific]                       |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |                       [record-specific]                       |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    12 |              [record-specific-flags]                  |C| ... |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |                       [record-specific]                       |
+       ~                            ...                                ~
+       |                                                               |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+C is the continuation block flag (VLCONTBLOCK). A value of 0 indicates the
+record is a 148 octet vl entry. A value of 1 indicates the record is a 8192
+octet mh extension block.
+
+
+VL Entry
+
+The 148 octet vl entry maps a volume group to a set of file server locations
+for each volume in the volume group.  A volume group consists of a single
+read-write volume, zero or one backup volumes, zero or more read-only volumes,
+and zero or one temporary clone volumes.
+
+The vl entry also holds information for volume administration.
+
+All integer fields are in network byte order.
+
+The layout of the vl entry is:
+
+        0                   1                   2                   3
+        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+octets +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     0 |                         volumeId[0] (rw)                      |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |                         volumeId[1] (ro)                      |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |                         volumeId[2] (bk)                      |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    12 |                             flags                             |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |                           LockAfsId                           |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |                        LockAfsTimestamp                       |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |                            cloneId                            |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |                        nextIdHash[0] (rw)                     |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |                        nextIdHash[1] (ro)                     |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |                        nextIdHash[2] (bk)                     |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    40 |                         nextNameHash                          |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    44 |                             name                              |
+       +                                                               +
+       |                                                               |
+       ~                              ...                              ~
+       |                                                               |
+       +               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   108 |               |      serverNumber table                       |
+       +-+-+-+-+-+-+-+-+                                               +
+   112 |                                                               |
+       +                                                               +
+       |                                                               |
+       +                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   120 |                               |                               |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+   124 |                      serverPartition table                    |
+       +                                                               +
+       |                                                               |
+       +                                               +-+-+-+-+-+-+-+-+
+   132 |                                               |               |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+               +
+   136 |                      serverFlags table                        |
+       +                                                               +
+       |                                                               |
+       +                                                               +
+   144 |                                                               |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+
+
+volumeId[0] is the volume id allocated for the read-write volume in this volume
+group.  (The VLF_RWEXITS flag is set when the read-write volume is created.)
+
+volumeId[1] is the volume id allocated for read-only volumes in this volume
+group.  This number is allocated when the entry is created. (The VLF_ROEXISTS
+flag is set when a read-only volume is created.)
+
+volumeId[2] is the volume id allocated for the backup volume in this volume
+group, if one.  This number is allocated when the entry is created. (The
+VLF_BACKEXISTS flag is set when a backup volume is created.)
+
+flags is a bitmap which indicates the vl entry state:
+
+0x0001  VLFREE          indicates this entry is on the free list
+0x0002  VLDELETE        indicates this entry is deleted
+0x0004  VLLOCKED        not used; always zero
+0x0008  VLCONTBLOCK     always zero in vl entries
+0x0010  VLOP_MOVE       locked for a move operation
+0x0020  VLOP_RELEASE    locked for a release operation
+0x0040  VLOP_BACKUP     locked for a backup clone operation
+0x0080  VLOP_DELETE     locked for a delete or addsite operation
+0x0100  VLOP_DUMP       locked for a dump or restore operation
+0x1000  VLF_RWEXISTS    this group has a read-write volume
+0x2000  VLF_ROEXISTS    this group has at least one read-only volume
+0x4000  VLF_BACKEXISTS  this group has a backup clone
+0x8000  VLF_DFSFILESET  not used; always cleared
+
+High order bits of the flags field are reserved and should always be zero.
+
+LockAfsId is not used. This field is reserved to hold the id of the operator
+who locked the entry for a volume operation.
+
+LockTimestamp is the time stamp on the entry lock.
+
+cloneId is the volume id of the temporary clone volume, which may be
+created during volume operations.
+
+nextIdHash[0] is the logical address of the next vl entry on the
+read-write volume id hash chain.
+
+nextIdHash[1] is the logical address of the next vl entry on the
+read-only volume id hash chain.
+
+nextIdHash[2] is the logical address of the next vl entry on the backup
+volume id hash chain.
+
+nextNameHash the logical address of the next vl entry on the volume name
+hash chain.
+
+name is a 65 octet field which holds the volume name, as a null
+terminated string.
+
+serverNumber, serverPartition, and serverFlags fields form a 13 row by 3
+column table. Each row describes a volume site. Empty rows are filled with
+0xFF instead of zero.
+
+serverNumber is a number from 0 to 254. The IpMappedAddr record at the
+serverNumber offset has a reference to a multi-homed (mh) entry. The mh entry
+holds the fileserver uuid and one or more IPv4 addresses of the fileserver.
+
+serverPartition is a number from 0 to 255 which represents a file server
+partition, from /vicepa to /vicepih.
+
+serverFlags indicates the state of the volume site:
+
+0x01  VLSF_NEWREPSITE    read-only volume added to vldb, but not released yet
+0x02  VLSF_ROVOL         a read-only volume is present at this location (see Notes)
+0x04  VLSF_RWVOL         a read-write volume is present at this location (see Notes)
+0x08  VLSF_BACKVOL       a backup volume is present at this location (see Notes)
+0x10  VLSF_UUID          not used in the vldb; always zero
+0x20  VLSF_DONTUSE       out of date read-only volume
+0x40  VLSF_RWREPLICA     reserved for volume is a read-write replica
+
+Notes:
+
+1. In practice, one, and only one, of the VLSF_ROVOL, VLSF_RWVOL, VLSF_BACKVOL
+   flags are set per table row.
+
+2. In practice, the VLSF_BACKVOL flag is not used. Instead the VLF_BACKEXISTS
+   is set in the vl entry to indicate a backup clone is present on the same
+   fileserver and partition as the read-write volume. This saves an entry
+   in the table to allow for more read-only sites.
+
+
+Multi-homed Extension Block
+
+Multi-homed extension blocks are 8192 octets in size. The first 128 octets hold
+a header, which is mostly unused.  The header is immediately followed by 63 mh
+entry slots, each 128 octets in size.
+
+Up to 4 blocks may be present in the vldb. The address of the first block is
+held in the SIT field of the vldb header.  Addresses of the first and
+additional blocks are held in the contaddr field of the first block.
+
+Note: In the current format, the vldb is limited to 4 blocks, and 63 mh entries
+per block, which means the vldb is limited to 252 different mh servers, which
+is three less than the maximum number of server numbers (255).
+
+
+Multi-homed Extension Block Header
+
+The layout of the mh extension block is:
+
+        0                   1                   2                   3
+        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+octets +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     0 |                             count                             |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     4 |                           reserved[0]                         |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     8 |                           reserved[1]                         |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    12 |                             flags                             |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    16 |                           contaddr[0]                         |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    20 |                           contaddr[1]                         |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    24 |                           contaddr[2]                         |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    28 |                           contaddr[3]                         |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    32 |                            reserved                           |
+       +                                                               +
+       |                                                               |
+       ~                              ...                              ~
+   124 |                                                               |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+count is not used.
+
+reserved[0], reserved[1] should always be zero.
+
+flags must have the VLCONTBLOCK bit set to indicate this is a 8192 octet
+mh extension block. All other bits in this field should be zero.
+
+contaddrs is a table of the addresses of the mh extension blocks, including
+the first block.
+
+reserved should always be zero.
+
+
+Multi-homed Entry
+
+The mh entry contains information for a single file server. Each mh entry
+is 128 octets in size.
+
+        0                   1                   2                   3
+        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+octets +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     0 |                         uuid.time_low                         |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     4 |         uuid.time_mid         |   uuid.time_hi_and_version    |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     8 | uuid.clock_hi | uuid.clock_lo |          uuid.node            |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
+    12 |                                                               |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    16 |                           uniquifier                          |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    20 |                            addrs[0]                           |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    24 |                            addrs[1]                           |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    28 |                            addrs[2]                           |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    32 |                            addrs[3]                           |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    36 |                            addrs[4]                           |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    40 |                            addrs[5]                           |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    44 |                            addrs[6]                           |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    48 |                            addrs[7]                           |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    52 |                            addrs[8]                           |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    56 |                            addrs[9]                           |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    60 |                            addrs[10]                          |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    64 |                            addrs[11]                          |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    68 |                            addrs[12]                          |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    72 |                            addrs[13]                          |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    76 |                            addrs[14]                          |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    80 |                             flags                             |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    84 |                            reserved                           |
+       ~                               ...                             ~
+   124 |                                                               |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+uuid is the universal unique id the fileserver used when registering
+with the vldb.
+
+uniquifier is a serial number of the mh entry. The first mh entry is assigned a
+uniquifier of 1.  The uniquifier is incremented each time its containing entry
+is modified.
+
+addrs[0..14] holds a list of IPv4 addresses for this fileserver, each in
+network byte order.  Zero indicates an empty slot.
+
+flags is reserved and should always be zero.
+
+reserved should always be zero.
+