osd/ReplicatedPG: make find_object_context() pass missing_oid

Prevoiusly we would return a snapid that we are blocked on if it is
missing.  This is necessary because the missing clone does not always
match the logical snap we are trying to read.

Extend this to return a full hobject_t that is the missing object we want.
For the missing clone case, this cleans things up slightly.  More
importantly, it lets find_object_context also tell us which on-disk
object is missing that, if it could be promoted, would help.

Signed-off-by: Sage Weil <sage@inktank.com>
osd/ReplicatedPG: using missing_oid to decide which object to promote

find_object_context() now tells us which object it could use if it
doesn't find it on disk.  Promote that one.

Signed-off-by: Sage Weil <sage@inktank.com>
osd/ReplicatedPG: include snaps in copy-get results

When promoting a snapped object, we need to also get the set of snaps over
which the clone is defined.  This is not strictly available except via the
list-snaps rados call, but that is only used on the snapdir object much
earlier when the head (whiteout) is promoted, and is not conveniently
available now.  Adding it to the internal copy-get is not exposed via
librados (copy-get is not exposed at all) so I don't think this is a
problem.

Signed-off-by: Sage Weil <sage@inktank.com>
osd/ReplicatedPG: adjust clone stats when promoting clones

Signed-off-by: Sage Weil <sage@inktank.com>
osd/ReplicatedPG: add PROMOTE log entry type

This is an alternative to MODIFY that indicates the object was just
promoted from another tier.  Thanksfully, is_modify() is used in very
few places!

Signed-off-by: Sage Weil <sage@inktank.com>
osd/osd_types: SnapSet::from_snap_set

Signed-off-by: Sage Weil <sage@inktank.com>
osd/ReplicatedPG: mirror SnapSet info when promoting head

When we promote the head for an object, get the list of snaps from the
backend pool and construct an appropriate SnapSet.  Note that this is
always placed on the head in the cache pool, since we will have a
whiteout object in this case.

Also note that the SnapSet's list of snapids will not include any snaps
for which there were no clones.  This is fine, since it is only used for
creating clones, and we've already done that.

Signed-off-by: Sage Weil <sage@inktank.com>
osd/ReplicatedPG: always encode snaps in finish_ctx

On promote we use finish_ctx to build the final log entries, and need to
encode the snaps vector in that case.  (Normally this is done by
make_writeable or explicitly by the snap trimmer.)

Signed-off-by: Sage Weil <sage@inktank.com>
osd/ReplicatedPG: only encode SnapSet on head objects in finish_ctx

Signed-off-by: Sage Weil <sage@inktank.com>
osd/ReplicatedPG: update snap_mapper for promoted clones

A clone that comes into existence via promotion takes an entirely
different path than a typical clone (which comes into existence via a
CLONE op in make_writeable()).  Make sure snap_mapper is updated
accordingly.

Signed-off-by: Sage Weil <sage@inktank.com>
ceph_test_rados_api_tier: test promotion of clones

Signed-off-by: Sage Weil <sage@inktank.com>
osd: add rados CACHE mode (different from RD and WR)

It is useful to distinguish cache operations from read and modify
operations.  Specifically, we will allow cache ops to be sent for
snaps and also allow those ops to result in a write.

Signed-off-by: Sage Weil <sage@inktank.com>
osd/ReplicatedPG: allow cache-evict on snaps

We do three things here:

 - make cache-evict a CACHE instead of WR op, allowing us to submit it
   on snaps (not just head)
 - allow eviction of a snap
 - verify that all snaps are missing before evicting a head

Signed-off-by: Sage Weil <sage@inktank.com>
osd/ReplicatedPG: make cache-[try-]flush CACHE instead of WR ops

This will allow us to send a flush op on a snap.

Signed-off-by: Sage Weil <sage@inktank.com>
vstart.sh: allow MDS=0

Signed-off-by: Sage Weil <sage@inktank.com>
osd/ReplicatedPG: refuse to flush when older dirty clones are present

If the next oldest clone is dirty, we cannot flush.  That is, we must
always flush starting with the oldest dirty clone.

Note that we can never have a sequence like dirty -> clean -> dirty,
because clones are only dirty on creation, are created in order, and cannot
be flushed (cleaned) out of order.  Thus checking the previous clone is
sufficient (and thankfully cheap).

Signed-off-by: Sage Weil <sage@inktank.com>
osd: add pg_log_entry_t event type CLEAN

Signed-off-by: Sage Weil <sage@inktank.com>
osd/ReplicatedPG: construct appropriate snapc for flush/writeback

Construct a snap context that will trigger the appropriate cloning (if any)
on the base pool.

Signed-off-by: Sage Weil <sage@inktank.com>
ceph_test_rados_api_tier: test flush on snaps/clones

Signed-off-by: Sage Weil <sage@inktank.com>
ceph_test_rados: don't update any state on successful cache-evict

- we didn't touch the user_version
- we didn't change the clean/dirty state

Signed-off-by: Sage Weil <sage@inktank.com>