Instead treat the diff as a full-object delta.
Signed-off-by: Mykola Golub <mgolub@suse.com>
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) {
ldout(m_cct, 20) << "r=" << r << dendl;
+ if (r == -ENOENT && m_read_whole_object) {
+ ldout(m_cct, 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;
librados::snap_t clone_end_snap_id;
calc_snap_set_diff(m_cct, m_snap_set, start_src_snap_id,
end_src_snap_id, &diff, &end_size, &exists,
- &clone_end_snap_id);
+ &clone_end_snap_id, &m_read_whole_object);
+
+ if (m_read_whole_object) {
+ ldout(m_cct, 1) << "need to read full object" << dendl;
+ diff.insert(0, m_src_image_ctx->layout.object_size);
+ exists = true;
+ end_size = m_src_image_ctx->layout.object_size;
+ clone_end_snap_id = end_src_snap_id;
+ }
+
if (!exists) {
end_size = 0;
}
int m_snap_ret = 0;
bool m_retry_missing_read = false;
librados::snap_set_t m_retry_snap_set;
+ bool m_read_whole_object = false;
std::map<WriteReadSnapIds, CopyOps> m_read_ops;
std::list<WriteReadSnapIds> m_read_snaps;