void calc_snap_set_diff(CephContext *cct, const librados::snap_set_t& snap_set,
librados::snap_t start, librados::snap_t end,
interval_set<uint64_t> *diff, uint64_t *end_size,
- bool *end_exists)
+ bool *end_exists, librados::snap_t *clone_end_snap_id)
{
ldout(cct, 10) << "calc_snap_set_diff start " << start << " end " << end
<< ", snap_set seq " << snap_set.seq << dendl;
diff->clear();
*end_size = 0;
*end_exists = false;
+ *clone_end_snap_id = 0;
for (vector<librados::clone_info_t>::const_iterator r = snap_set.clones.begin();
r != snap_set.clones.end();
if (end <= b) {
ldout(cct, 20) << " end" << dendl;
*end_exists = true;
+ *clone_end_snap_id = b;
break;
}
assert(!sync_ops.empty());
// map the sync op start snap id back to the necessary read snap id
- librados::snap_t remote_snap_seq = m_snap_sync_ops.begin()->first;
+ librados::snap_t remote_snap_seq = m_snap_sync_ops.begin()->first.second;
m_remote_io_ctx.snap_set_read(remote_snap_seq);
bool read_required = false;
// retrieve the local snap context for the op
SnapIds local_snap_ids;
librados::snap_t local_snap_seq = 0;
- librados::snap_t remote_snap_seq = m_snap_sync_ops.begin()->first;
+ librados::snap_t remote_snap_seq = m_snap_sync_ops.begin()->first.first;
if (remote_snap_seq != 0) {
auto snap_map_it = m_snap_map->find(remote_snap_seq);
assert(snap_map_it != m_snap_map->end());
void ObjectCopyRequest<I>::compute_diffs() {
CephContext *cct = m_local_image_ctx->cct;
+ librados::snap_t remote_sync_pont_snap_id = m_snap_map->rbegin()->first;
uint64_t prev_end_size = 0;
bool prev_exists = false;
librados::snap_t start_remote_snap_id = 0;
interval_set<uint64_t> diff;
uint64_t end_size;
bool exists;
+ librados::snap_t clone_end_snap_id;
calc_snap_set_diff(cct, m_snap_set, start_remote_snap_id,
- end_remote_snap_id, &diff, &end_size, &exists);
+ end_remote_snap_id, &diff, &end_size, &exists,
+ &clone_end_snap_id);
dout(20) << ": "
<< "start_remote_snap=" << start_remote_snap_id << ", "
<< "end_remote_snap_id=" << end_remote_snap_id << ", "
+ << "clone_end_snap_id=" << clone_end_snap_id << ", "
<< "end_local_snap_id=" << end_local_snap_id << ", "
<< "diff=" << diff << ", "
<< "end_size=" << end_size << ", "
uint8_t object_state = OBJECT_EXISTS;
if (m_local_image_ctx->test_features(RBD_FEATURE_FAST_DIFF,
m_local_image_ctx->snap_lock) &&
- diff.empty() && end_size == prev_end_size) {
+ prev_exists && diff.empty() && end_size == prev_end_size) {
object_state = OBJECT_EXISTS_CLEAN;
}
m_snap_object_states[end_local_snap_id] = object_state;
}
+ // reads should be issued against the newest (existing) snapshot within
+ // the associated snapshot object clone. writes should be issued
+ // against the oldest snapshot in the snap_map.
+ assert(clone_end_snap_id >= end_remote_snap_id);
+ if (clone_end_snap_id > remote_sync_pont_snap_id) {
+ // do not read past the sync point snapshot
+ clone_end_snap_id = remote_sync_pont_snap_id;
+ }
+
// object write/zero, or truncate
+ // NOTE: a single snapshot clone might represent multiple snapshots, but
+ // the write/zero and truncate ops will only be associated with the first
+ // snapshot encountered within the clone since the diff will be empty for
+ // subsequent snapshots and the size will remain constant for a clone.
for (auto it = diff.begin(); it != diff.end(); ++it) {
dout(20) << ": read/write op: " << it.get_start() << "~"
<< it.get_len() << dendl;
- m_snap_sync_ops[end_remote_snap_id].emplace_back(SYNC_OP_TYPE_WRITE,
- it.get_start(),
- it.get_len());
+ m_snap_sync_ops[{end_remote_snap_id, clone_end_snap_id}].emplace_back(
+ SYNC_OP_TYPE_WRITE, it.get_start(), it.get_len());
}
if (end_size < prev_end_size) {
dout(20) << ": trunc op: " << end_size << dendl;
- m_snap_sync_ops[end_remote_snap_id].emplace_back(SYNC_OP_TYPE_TRUNC,
- end_size, 0U);
+ m_snap_sync_ops[{end_remote_snap_id, clone_end_snap_id}].emplace_back(
+ SYNC_OP_TYPE_TRUNC, end_size, 0U);
}
m_snap_object_sizes[end_remote_snap_id] = end_size;
} else {
if (prev_exists) {
// object remove
dout(20) << ": remove op" << dendl;
- m_snap_sync_ops[end_remote_snap_id].emplace_back(SYNC_OP_TYPE_REMOVE,
- 0U, 0U);
+ m_snap_sync_ops[{end_remote_snap_id, end_remote_snap_id}].emplace_back(
+ SYNC_OP_TYPE_REMOVE, 0U, 0U);
}
}