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, librados::snap_t *clone_end_snap_id)
+ bool *end_exists, librados::snap_t *clone_end_snap_id,
+ bool *whole_object)
{
ldout(cct, 10) << "calc_snap_set_diff start " << start << " end " << end
<< ", snap_set seq " << snap_set.seq << dendl;
*end_size = 0;
*end_exists = false;
*clone_end_snap_id = 0;
+ *whole_object = false;
for (vector<librados::clone_info_t>::const_iterator r = snap_set.clones.begin();
r != snap_set.clones.end();
// head is valid starting from right after the last seen seq
a = snap_set.seq + 1;
b = librados::SNAP_HEAD;
+ } else if (r->snaps.empty()) {
+ ldout(cct, 1) << "clone " << r->cloneid
+ << ": empty snaps, return whole object" << dendl;
+ *whole_object = true;
+ return;
} else {
a = r->snaps[0];
// note: b might be < r->cloneid if a snap has been trimmed.
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, librados::snap_t *clone_end_snap_id);
+ bool *end_exists, librados::snap_t *clone_end_snap_id,
+ bool *whole_object);
#endif
uint64_t end_size;
bool end_exists;
librados::snap_t clone_end_snap_id;
+ bool whole_object;
calc_snap_set_diff(cct, m_snap_set, m_diff_context.from_snap_id,
m_diff_context.end_snap_id, &diff, &end_size,
- &end_exists, &clone_end_snap_id);
+ &end_exists, &clone_end_snap_id, &whole_object);
+ if (whole_object) {
+ ldout(cct, 1) << "object " << m_oid << ": need to provide full object"
+ << dendl;
+ }
ldout(cct, 20) << " diff " << diff << " end_exists=" << end_exists
<< dendl;
- if (diff.empty()) {
+ if (diff.empty() && !whole_object) {
if (m_diff_context.from_snap_id == 0 && !end_exists) {
compute_parent_overlap(diffs);
}
return;
- } else if (m_diff_context.whole_object) {
+ } else if (m_diff_context.whole_object || whole_object) {
// provide the full object extents to the callback
for (vector<ObjectExtent>::iterator q = m_object_extents.begin();
q != m_object_extents.end(); ++q) {
void ObjectCopyRequest<I>::handle_read_object(int r) {
dout(20) << ": r=" << r << dendl;
+ auto snap_seq = m_snap_sync_ops.begin()->first.second;
+ if (r == -ENOENT && m_read_whole_object[snap_seq]) {
+ dout(5) << ": object missing when forced to read whole object"
+ << dendl;
+ r = 0;
+ }
+
if (r == -ENOENT) {
m_retry_snap_set = m_snap_set;
m_retry_missing_read = true;
uint64_t end_size;
bool exists;
librados::snap_t clone_end_snap_id;
+ bool read_whole_object;
calc_snap_set_diff(cct, m_snap_set, start_remote_snap_id,
end_remote_snap_id, &diff, &end_size, &exists,
- &clone_end_snap_id);
+ &clone_end_snap_id, &read_whole_object);
+
+ if (read_whole_object) {
+ dout(1) << ": need to read full object" << dendl;
+ diff.insert(0, m_remote_image_ctx->layout.object_size);
+ exists = true;
+ end_size = m_remote_image_ctx->layout.object_size;
+ clone_end_snap_id = end_remote_snap_id;
+ }
dout(20) << ": "
<< "start_remote_snap=" << start_remote_snap_id << ", "
// do not read past the sync point snapshot
clone_end_snap_id = remote_sync_pont_snap_id;
}
+ m_read_whole_object[clone_end_snap_id] = read_whole_object;
// object write/zero, or truncate
// NOTE: a single snapshot clone might represent multiple snapshots, but
bool m_retry_missing_read = false;
librados::snap_set_t m_retry_snap_set;
+ std::map<librados::snap_t, bool> m_read_whole_object;
SnapSyncOps m_snap_sync_ops;
SnapObjectStates m_snap_object_states;