string oid = image_ctx.get_object_name(m_object_no);
ldout(image_ctx.cct, 10) << "removing (with copyup) " << oid << dendl;
- auto req = new io::ObjectTrimRequest(&image_ctx, oid, m_object_no,
- m_snapc, false, this);
+ auto req = io::ObjectRequest<I>::create_trim(&image_ctx, oid, m_object_no,
+ m_snapc, false, this);
req->send();
return 0;
}
template <typename I>
class C_RemoveObject : public C_AsyncObjectThrottle<I> {
public:
- C_RemoveObject(AsyncObjectThrottle<I> &throttle, ImageCtx *image_ctx,
+ C_RemoveObject(AsyncObjectThrottle<I> &throttle, I *image_ctx,
uint64_t object_no)
: C_AsyncObjectThrottle<I>(throttle, *image_ctx), m_object_no(object_no)
{
m_delete_off = MIN(new_num_periods * period, original_size);
// first object we can delete free and clear
m_delete_start = new_num_periods * image_ctx.get_stripe_count();
+ m_delete_start_min = m_delete_start;
m_num_objects = Striper::get_num_objects(image_ctx.layout, original_size);
CephContext *cct = image_ctx.cct;
RWLock::RLocker owner_lock(image_ctx.owner_lock);
switch (m_state) {
- case STATE_PRE_COPYUP:
- ldout(cct, 5) << " PRE_COPYUP" << dendl;
+ case STATE_PRE_TRIM:
+ ldout(cct, 5) << " PRE_TRIM" << dendl;
send_copyup_objects();
break;
case STATE_COPYUP_OBJECTS:
ldout(cct, 5) << " COPYUP_OBJECTS" << dendl;
- send_post_copyup();
- break;
-
- case STATE_POST_COPYUP:
- ldout(cct, 5) << " POST_COPYUP" << dendl;
- send_pre_remove();
- break;
-
- case STATE_PRE_REMOVE:
- ldout(cct, 5) << " PRE_REMOVE" << dendl;
send_remove_objects();
break;
case STATE_REMOVE_OBJECTS:
ldout(cct, 5) << " REMOVE_OBJECTS" << dendl;
- send_post_remove();
+ send_post_trim();
break;
- case STATE_POST_REMOVE:
- ldout(cct, 5) << " POST_OBJECTS" << dendl;
+ case STATE_POST_TRIM:
+ ldout(cct, 5) << " POST_TRIM" << dendl;
send_clean_boundary();
break;
template <typename I>
void TrimRequest<I>::send() {
- send_pre_copyup();
+ send_pre_trim();
}
template<typename I>
-void TrimRequest<I>::send_copyup_objects() {
+void TrimRequest<I>::send_pre_trim() {
I &image_ctx = this->m_image_ctx;
assert(image_ctx.owner_lock.is_locked());
- ldout(image_ctx.cct, 5) << this << " send_copyup_objects: "
- << " start object=" << m_copyup_start << ", "
- << " end object=" << m_copyup_end << dendl;
- m_state = STATE_COPYUP_OBJECTS;
+ if (m_delete_start >= m_num_objects) {
+ send_clean_boundary();
+ return;
+ }
- ::SnapContext snapc;
{
RWLock::RLocker snap_locker(image_ctx.snap_lock);
- RWLock::RLocker parent_locker(image_ctx.parent_lock);
- snapc = image_ctx.snapc;
- }
-
- Context *ctx = this->create_callback_context();
- typename AsyncObjectThrottle<I>::ContextFactory context_factory(
- boost::lambda::bind(boost::lambda::new_ptr<C_CopyupObject<I> >(),
- boost::lambda::_1, &image_ctx, snapc, boost::lambda::_2));
- AsyncObjectThrottle<I> *throttle = new AsyncObjectThrottle<I>(
- this, image_ctx, context_factory, ctx, &m_prog_ctx, m_copyup_start,
- m_copyup_end);
- throttle->start_ops(image_ctx.concurrent_management_ops);
-}
+ if (image_ctx.object_map != nullptr) {
+ ldout(image_ctx.cct, 5) << this << " send_pre_trim: "
+ << " delete_start_min=" << m_delete_start_min
+ << " num_objects=" << m_num_objects << dendl;
+ m_state = STATE_PRE_TRIM;
-template <typename I>
-void TrimRequest<I>::send_remove_objects() {
- I &image_ctx = this->m_image_ctx;
- assert(image_ctx.owner_lock.is_locked());
+ assert(image_ctx.exclusive_lock->is_lock_owner());
- ldout(image_ctx.cct, 5) << this << " send_remove_objects: "
- << " delete_start=" << m_delete_start
- << " num_objects=" << m_num_objects << dendl;
- m_state = STATE_REMOVE_OBJECTS;
+ RWLock::WLocker object_map_locker(image_ctx.object_map_lock);
+ if (image_ctx.object_map->template aio_update<AsyncRequest<I> >(
+ CEPH_NOSNAP, m_delete_start_min, m_num_objects, OBJECT_PENDING,
+ OBJECT_EXISTS, {}, this)) {
+ return;
+ }
+ }
+ }
- Context *ctx = this->create_callback_context();
- typename AsyncObjectThrottle<I>::ContextFactory context_factory(
- boost::lambda::bind(boost::lambda::new_ptr<C_RemoveObject<I> >(),
- boost::lambda::_1, &image_ctx, boost::lambda::_2));
- AsyncObjectThrottle<I> *throttle = new AsyncObjectThrottle<I>(
- this, image_ctx, context_factory, ctx, &m_prog_ctx, m_delete_start,
- m_num_objects);
- throttle->start_ops(image_ctx.concurrent_management_ops);
+ send_copyup_objects();
}
template<typename I>
-void TrimRequest<I>::send_pre_copyup() {
+void TrimRequest<I>::send_copyup_objects() {
I &image_ctx = this->m_image_ctx;
assert(image_ctx.owner_lock.is_locked());
- if (m_delete_start >= m_num_objects) {
- send_clean_boundary();
- return;
- }
-
+ ::SnapContext snapc;
bool has_snapshots;
uint64_t parent_overlap;
{
RWLock::RLocker snap_locker(image_ctx.snap_lock);
RWLock::RLocker parent_locker(image_ctx.parent_lock);
+ snapc = image_ctx.snapc;
has_snapshots = !image_ctx.snaps.empty();
int r = image_ctx.get_parent_overlap(CEPH_NOSNAP, &parent_overlap);
assert(r == 0);
}
// copyup is only required for portion of image that overlaps parent
- m_copyup_end = Striper::get_num_objects(image_ctx.layout, parent_overlap);
+ uint64_t copyup_end = Striper::get_num_objects(image_ctx.layout,
+ parent_overlap);
// TODO: protect against concurrent shrink and snap create?
// skip to remove if no copyup is required.
- if (m_copyup_end <= m_delete_start || !has_snapshots) {
- send_pre_remove();
+ if (copyup_end <= m_delete_start || !has_snapshots) {
+ send_remove_objects();
return;
}
- m_copyup_start = m_delete_start;
- m_delete_start = m_copyup_end;
-
- {
- RWLock::RLocker snap_locker(image_ctx.snap_lock);
- if (image_ctx.object_map != nullptr) {
- ldout(image_ctx.cct, 5) << this << " send_pre_copyup: "
- << " copyup_start=" << m_copyup_start
- << " copyup_end=" << m_copyup_end << dendl;
- m_state = STATE_PRE_COPYUP;
-
- assert(image_ctx.exclusive_lock->is_lock_owner());
+ uint64_t copyup_start = m_delete_start;
+ m_delete_start = copyup_end;
- RWLock::WLocker object_map_locker(image_ctx.object_map_lock);
- if (image_ctx.object_map->template aio_update<AsyncRequest<I> >(
- CEPH_NOSNAP, m_copyup_start, m_copyup_end, OBJECT_PENDING,
- OBJECT_EXISTS, {}, this)) {
- return;
- }
- }
- }
+ ldout(image_ctx.cct, 5) << this << " send_copyup_objects: "
+ << " start object=" << copyup_start << ", "
+ << " end object=" << copyup_end << dendl;
+ m_state = STATE_COPYUP_OBJECTS;
- send_copyup_objects();
+ Context *ctx = this->create_callback_context();
+ typename AsyncObjectThrottle<I>::ContextFactory context_factory(
+ boost::lambda::bind(boost::lambda::new_ptr<C_CopyupObject<I> >(),
+ boost::lambda::_1, &image_ctx, snapc, boost::lambda::_2));
+ AsyncObjectThrottle<I> *throttle = new AsyncObjectThrottle<I>(
+ this, image_ctx, context_factory, ctx, &m_prog_ctx, copyup_start,
+ copyup_end);
+ throttle->start_ops(image_ctx.concurrent_management_ops);
}
template <typename I>
-void TrimRequest<I>::send_pre_remove() {
+void TrimRequest<I>::send_remove_objects() {
I &image_ctx = this->m_image_ctx;
assert(image_ctx.owner_lock.is_locked());
- if (m_delete_start >= m_num_objects) {
- send_clean_boundary();
- return;
- }
-
- {
- RWLock::RLocker snap_locker(image_ctx.snap_lock);
- if (image_ctx.object_map != nullptr) {
- ldout(image_ctx.cct, 5) << this << " send_pre_remove: "
- << " delete_start=" << m_delete_start
- << " num_objects=" << m_num_objects << dendl;
- m_state = STATE_PRE_REMOVE;
-
- assert(image_ctx.exclusive_lock->is_lock_owner());
- // flag the objects as pending deletion
- RWLock::WLocker object_map_locker(image_ctx.object_map_lock);
- if (image_ctx.object_map->template aio_update<AsyncRequest<I> >(
- CEPH_NOSNAP, m_delete_start, m_num_objects, OBJECT_PENDING,
- OBJECT_EXISTS, {}, this)) {
- return;
- }
- }
- }
+ ldout(image_ctx.cct, 5) << this << " send_remove_objects: "
+ << " delete_start=" << m_delete_start
+ << " num_objects=" << m_num_objects << dendl;
+ m_state = STATE_REMOVE_OBJECTS;
- // no object map update required
- send_remove_objects();
+ Context *ctx = this->create_callback_context();
+ typename AsyncObjectThrottle<I>::ContextFactory context_factory(
+ boost::lambda::bind(boost::lambda::new_ptr<C_RemoveObject<I> >(),
+ boost::lambda::_1, &image_ctx, boost::lambda::_2));
+ AsyncObjectThrottle<I> *throttle = new AsyncObjectThrottle<I>(
+ this, image_ctx, context_factory, ctx, &m_prog_ctx, m_delete_start,
+ m_num_objects);
+ throttle->start_ops(image_ctx.concurrent_management_ops);
}
template<typename I>
-void TrimRequest<I>::send_post_copyup() {
- I &image_ctx = this->m_image_ctx;
- assert(image_ctx.owner_lock.is_locked());
-
- {
- RWLock::RLocker snap_locker(image_ctx.snap_lock);
- if (image_ctx.object_map != nullptr) {
- ldout(image_ctx.cct, 5) << this << " send_post_copyup:"
- << " copyup_start=" << m_copyup_start
- << " copyup_end=" << m_copyup_end << dendl;
- m_state = STATE_POST_COPYUP;
-
- assert(image_ctx.exclusive_lock->is_lock_owner());
-
- RWLock::WLocker object_map_locker(image_ctx.object_map_lock);
- if (image_ctx.object_map->template aio_update<AsyncRequest<I> >(
- CEPH_NOSNAP, m_copyup_start, m_copyup_end, OBJECT_NONEXISTENT,
- OBJECT_PENDING, {}, this)) {
- return;
- }
- }
- }
-
- send_pre_remove();
-}
-
-template <typename I>
-void TrimRequest<I>::send_post_remove() {
+void TrimRequest<I>::send_post_trim() {
I &image_ctx = this->m_image_ctx;
assert(image_ctx.owner_lock.is_locked());
{
RWLock::RLocker snap_locker(image_ctx.snap_lock);
if (image_ctx.object_map != nullptr) {
- ldout(image_ctx.cct, 5) << this << " send_post_remove: "
- << " delete_start=" << m_delete_start
- << " num_objects=" << m_num_objects << dendl;
- m_state = STATE_POST_REMOVE;
+ ldout(image_ctx.cct, 5) << this << " send_post_trim:"
+ << " delete_start_min=" << m_delete_start_min
+ << " num_objects=" << m_num_objects << dendl;
+ m_state = STATE_POST_TRIM;
assert(image_ctx.exclusive_lock->is_lock_owner());
- // flag the pending objects as removed
RWLock::WLocker object_map_locker(image_ctx.object_map_lock);
if (image_ctx.object_map->template aio_update<AsyncRequest<I> >(
- CEPH_NOSNAP, m_delete_start, m_num_objects, OBJECT_NONEXISTENT,
+ CEPH_NOSNAP, m_delete_start_min, m_num_objects, OBJECT_NONEXISTENT,
OBJECT_PENDING, {}, this)) {
return;
}
}
}
- // no object map update required
send_clean_boundary();
}
ldout(cct, 20) << " ex " << *p << dendl;
Context *req_comp = new C_ContextCompletion(*completion);
- io::ObjectRequest<> *req;
+ io::ObjectRequest<I> *req;
if (p->offset == 0) {
- req = new io::ObjectTrimRequest(&image_ctx, p->oid.name, p->objectno,
- snapc, true, req_comp);
+ req = io::ObjectRequest<I>::create_trim(&image_ctx, p->oid.name,
+ p->objectno, snapc, true,
+ req_comp);
} else {
- req = new io::ObjectTruncateRequest(&image_ctx, p->oid.name, p->objectno,
- p->offset, snapc, {}, req_comp);
+ req = io::ObjectRequest<I>::create_truncate(&image_ctx, p->oid.name,
+ p->objectno, p->offset, snapc,
+ {}, req_comp);
}
req->send();
}