rbd: __rbd_init_snaps_header() bug

There is a bug in the way __rbd_init_snaps_header() handles newly-
discovered snapshots, in the unusual case where the new snapshot id
is less than an existing rbd snapshot id.


When a new snapshot for an rbd image is created it is assigned a new
snapshot id.  The client requests the id from a monitor, and later
updates the osds with information about the snapshot.  The sequence
of snapshot ids is monotonically increasing, which guarantees each
is unique.  And typically all new snapshots will have higher ids
than any others a client has encountered.

Because of the delay between getting assigned a snapshot id and
recording the snapshot, there is a possible race between two clients
requesting new snapshots on the same rbd image.  It's possible in
this case for the client granted a higher id to be the first to
update the set of snapshots for the rbd image.  This leaves a sort
of gap in the set of snapshots until the other client's update gets
recorded.

This is an unlikely scenario, but it appears to be possible.  I'm
not sure whether we even support multiple concurrent clients for the
same rbd image.  However there is code in place to handle this case
and it's wrong, so it needs to be fixed.


The job of __rbd_init_snaps_header() is to compare an rbd's existing
list of snapshots to a new set, and remove any existing snapshots
that are not present in the new set and create any new ones not
present in the existing set.

If any new snapshots exist after the entire list of existing ones
has been examined, all the new ones that remain need to be created.
The logic for handling these last snapshots correct.

However, if a new snapshot is found whose id is less than an
existing one, the logic for handling this is wrong.  The basic
problem is that the name and current id used here are taken from
a place one position beyond where they should be.  In the event
this block of code is executed the first pass through the outer
loop, for example, these values will refer to invalid memory.

The fix is to make this block of code more closely match the
block that handles adding new snapshots at the end.  There are
three differences:
    - we use a do..while loop because we know we initially have an
      entry to process.
    - we insert the new entry at a position within the list instead
      of at the beginning
    - because we use it in the loop condition, we need to update
      our notion of "current id" each pass through.

Signed-off-by: Alex Elder <elder@inktank.com>
rbd: assign header name later

Move the assignment of the header name for an rbd image a bit later,
outside rbd_add_parse_args() and into its caller.

Signed-off-by: Alex Elder <elder@inktank.com>
rbd: do some header initialization earlier

Move some of the code that initializes an rbd header out of
rbd_init_disk and into its caller.  In order to do this we need
to supply the disk size (either the size of the base image or
the size of the snapshot) to rbd_init_disk().

Signed-off-by: Alex Elder <elder@inktank.com>
rbd: register device after header init

Now move registration of the device with the system down, after
doing all of the rbd header initialization.

This was done in steps in hopes it would make reviewing the change a
little easier.

Signed-off-by: Alex Elder <elder@inktank.com>
rbd: rearrange rbd_header_from_disk()

This just moves code around for the most part.  It was pulled out as
a separate patch to avoid cluttering up some upcoming patches which
are more substantive.  The point is basically to group everything
related to initializing the snapshot context together.

The only functional change is that rbd_read_header() now ensures
the header it passes is zero-filled.  This allows a simpler
error handling path.

Signed-off-by: Alex Elder <elder@inktank.com>
rbd: define struct snap_context

Currently a ceph snapshot context stores an array of ceph snapshot
ids.  This is consistent with how they're stored in the rbd image
header.  But there's no reason the in-core representation of a
snapshot has to match what's on disk.

Define a new struct type to hold the snapshot id, and eventually
hold other information we know about the snapshot.  This is
motivated by upcoming changes to support rbd image format 2.

Signed-off-by: Alex Elder <elder@inktank.com>
rbd: incorporate snapshot sizes in snap context

Rather than allocating a separate array of sizes to record each
snapshot's size, just include each snapshot's size in its
rbd_snap structure that's incorporated in the snapshot context.

Signed-off-by: Alex Elder <elder@inktank.com>
rbd: incorporate snapshot names in snap context

Rather than allocating a copy of the on-disk chunk of snapshot
names, allocate individual name strings for each snapshot and
include each snapshot's size in its rbd_snap structure that's
incorporated in the snapshot context.

This requires a bit more work than was needed for the snapshot id
and snapshot size.  rbd_header_from_disk() now makes the copy of
each snapshot name, and to protect from possible corruption it
also now takes and end pointer to ensure we don't overrun the
(source) names buffer in the process of copying.

In addition, snap_by_name() now just indexes the snaphot array to
get at the name rather than having to traverse the snap_names block.

Finally, 

Signed-off-by: Alex Elder <elder@inktank.com>