With the new queue-based GC code, when a GC defer operation is
performed, it adds an "urgent" record to prevent GC from removing
objects that are still being read. It does not check whether the
objects are on the GC queue or not and that's OK for the urgent
record.
The code *also* adds a new GC entry to the queue to cause GC to occur
at a later time. This would be incorrect if there was no GC entry to
begin with, however. In such a case this would cause GC to delete tail
objects when no user-initiated remove has happend. In other words a
READ could cause a DELETE of tail objects and therefore data loss.
This fix prevents such a new GC entry from being enqueued, thus
preventing the data loss in this rare case. There is a new risk that
tail object orphans to be created, but as an immediate fix to prevent
data loss, this is appropriate and it is a rare event. A follow-on PR
that will handle these cases is likely.
This PR adds a level 0 log entry as a way to potentially confirm this
case is being triggered in real-world cases. In time, this log entry
should be deleted.
Signed-off-by: J. Eric Ivancich <ivancich@redhat.com>
return -ENOSPC;
}
+ // Due to Tracker 47866 we are no longer executing this code, as it
+ // appears to possibly create a GC entry for an object that has not
+ // been deleted. Instead we will log at level 0 to perhaps confirm
+ // that when and how often this bug would otherwise be hit.
+#if 0
cls_queue_enqueue_op enqueue_op;
bufferlist bl_data;
encode(op.info, bl_data);
if (ret < 0) {
return ret;
}
+#else
+ std::string first_chain = "<empty-chain>";
+ if (! op.info.chain.objs.empty()) {
+ first_chain = op.info.chain.objs.cbegin()->key.name;
+ }
+ CLS_LOG(0,
+ "INFO: refrained from enqueueing GC entry during GC defer"
+ " tag=%s, first_chain=%s\n",
+ op.info.tag.c_str(), first_chain.c_str());
+#endif
if (has_urgent_data) {
head.bl_urgent_data.clear();