@@ -6266,9 +6266,13 @@ struct tombstone_entry {
62666266 * Delete an object.
62676267 * bucket: name of the bucket storing the object
62686268 * obj: name of the object to delete
6269+ * force: if b.i. entry exists but head object does not, still remove entry
62696270 * Returns: 0 on success, -ERR# otherwise.
62706271 */
6271- int RGWRados::Object::Delete::delete_obj (optional_yield y, const DoutPrefixProvider *dpp, bool log_op)
6272+ int RGWRados::Object::Delete::delete_obj (optional_yield y,
6273+ const DoutPrefixProvider* dpp,
6274+ bool log_op,
6275+ const bool force)
62726276{
62736277 RGWRados *store = target->get_store ();
62746278 const rgw_obj& src_obj = target->get_obj ();
@@ -6297,8 +6301,9 @@ int RGWRados::Object::Delete::delete_obj(optional_yield y, const DoutPrefixProvi
62976301 }
62986302
62996303 result.version_id = marker.key .instance ;
6300- if (result.version_id .empty ())
6304+ if (result.version_id .empty ()) {
63016305 result.version_id = " null" ;
6306+ }
63026307 result.delete_marker = true ;
63036308
63046309 struct rgw_bucket_dir_entry_meta meta;
@@ -6326,8 +6331,10 @@ int RGWRados::Object::Delete::delete_obj(optional_yield y, const DoutPrefixProvi
63266331 return r;
63276332 }
63286333 result.delete_marker = dirent.is_delete_marker ();
6329- r = store->unlink_obj_instance (dpp, target->get_ctx (), target->get_bucket_info (), obj, params.olh_epoch ,
6330- y, params.bilog_flags , params.null_verid , params.zones_trace , add_log);
6334+ r = store->unlink_obj_instance (
6335+ dpp, target->get_ctx (), target->get_bucket_info (), obj,
6336+ params.olh_epoch , y, params.bilog_flags ,
6337+ params.null_verid , params.zones_trace , add_log, force);
63316338 if (r < 0 ) {
63326339 return r;
63336340 }
@@ -6349,7 +6356,7 @@ int RGWRados::Object::Delete::delete_obj(optional_yield y, const DoutPrefixProvi
63496356 }
63506357
63516358 return 0 ;
6352- }
6359+ } // if versioned bucket
63536360
63546361 rgw_rados_ref ref;
63556362 int r = store->get_obj_head_ref (dpp, target->get_bucket_info (), obj, &ref);
@@ -6360,8 +6367,9 @@ int RGWRados::Object::Delete::delete_obj(optional_yield y, const DoutPrefixProvi
63606367 RGWObjState *state;
63616368 RGWObjManifest *manifest = nullptr ;
63626369 r = target->get_state (dpp, &state, &manifest, false , y);
6363- if (r < 0 )
6370+ if (r < 0 ) {
63646371 return r;
6372+ }
63656373
63666374 ObjectWriteOperation op;
63676375
@@ -6383,7 +6391,7 @@ int RGWRados::Object::Delete::delete_obj(optional_yield y, const DoutPrefixProvi
63836391 }
63846392 uint64_t obj_accounted_size = state->accounted_size ;
63856393
6386- if (params.abortmp ) {
6394+ if (params.abortmp ) {
63876395 obj_accounted_size = params.parts_accounted_size ;
63886396 }
63896397
@@ -6409,13 +6417,20 @@ int RGWRados::Object::Delete::delete_obj(optional_yield y, const DoutPrefixProvi
64096417 }
64106418
64116419 if (!state->exists ) {
6412- target->invalidate_state ();
6413- return -ENOENT;
6420+ if (!force) {
6421+ target->invalidate_state ();
6422+ return -ENOENT;
6423+ } else {
6424+ ldpp_dout (dpp, 5 ) << " WARNING: head for \" " << src_obj <<
6425+ " \" does not exist; will continue with deleting bucket "
6426+ " index entry(ies)" << dendl;
6427+ }
64146428 }
64156429
64166430 r = target->prepare_atomic_modification (dpp, op, false , NULL , NULL , NULL , true , false , y);
6417- if (r < 0 )
6431+ if (r < 0 ) {
64186432 return r;
6433+ }
64196434
64206435 RGWBucketInfo& bucket_info = target->get_bucket_info ();
64216436
@@ -6429,10 +6444,10 @@ int RGWRados::Object::Delete::delete_obj(optional_yield y, const DoutPrefixProvi
64296444 index_op.set_bilog_flags (params.bilog_flags | RGW_BILOG_NULL_VERSION);
64306445 }
64316446
6432-
64336447 r = index_op.prepare (dpp, CLS_RGW_OP_DEL, &state->write_tag , y);
6434- if (r < 0 )
6448+ if (r < 0 ) {
64356449 return r;
6450+ }
64366451
64376452 store->remove_rgw_head_obj (op);
64386453
@@ -6477,8 +6492,9 @@ int RGWRados::Object::Delete::delete_obj(optional_yield y, const DoutPrefixProvi
64776492 target->invalidate_state ();
64786493 }
64796494
6480- if (r < 0 )
6495+ if (r < 0 ) {
64816496 return r;
6497+ }
64826498
64836499 /* update quota cache */
64846500 store->quota_handler ->update_stats (params.bucket_owner , obj.bucket , -1 , 0 , obj_accounted_size);
@@ -6495,7 +6511,8 @@ int RGWRados::delete_obj(const DoutPrefixProvider *dpp,
64956511 uint16_t bilog_flags,
64966512 const real_time& expiration_time,
64976513 rgw_zone_set *zones_trace,
6498- bool log_op)
6514+ bool log_op,
6515+ const bool force) // force removal even if head object is broken
64996516{
65006517 RGWRados::Object del_target (this , bucket_info, obj_ctx, obj);
65016518 RGWRados::Object::Delete del_op (&del_target);
@@ -6507,7 +6524,7 @@ int RGWRados::delete_obj(const DoutPrefixProvider *dpp,
65076524 del_op.params .zones_trace = zones_trace;
65086525 del_op.params .null_verid = null_verid;
65096526
6510- return del_op.delete_obj (y, dpp, log_op ? rgw::sal::FLAG_LOG_OP : 0 );
6527+ return del_op.delete_obj (y, dpp, log_op, force );
65116528}
65126529
65136530int RGWRados::delete_raw_obj (const DoutPrefixProvider *dpp, const rgw_raw_obj& obj, optional_yield y)
@@ -8618,7 +8635,7 @@ int RGWRados::bucket_index_unlink_instance(const DoutPrefixProvider *dpp,
86188635 }
86198636
86208637 return 0 ;
8621- }
8638+ } // bucket_index_unlink_instance
86228639
86238640int RGWRados::bucket_index_read_olh_log (const DoutPrefixProvider *dpp,
86248641 RGWBucketInfo& bucket_info, RGWObjState& state,
@@ -8813,9 +8830,10 @@ int RGWRados::apply_olh_log(const DoutPrefixProvider *dpp,
88138830 std::map<uint64_t , std::vector<rgw_bucket_olh_log_entry> >& log,
88148831 uint64_t *plast_ver,
88158832 optional_yield y,
8816- bool null_verid,
8817- rgw_zone_set* zones_trace,
8818- bool log_op)
8833+ bool null_verid,
8834+ rgw_zone_set* zones_trace,
8835+ bool log_op,
8836+ const bool force)
88198837{
88208838 if (log.empty ()) {
88218839 return 0 ;
@@ -8928,7 +8946,9 @@ int RGWRados::apply_olh_log(const DoutPrefixProvider *dpp,
89288946 liter != remove_instances.end (); ++liter) {
89298947 cls_rgw_obj_key& key = *liter;
89308948 rgw_obj obj_instance (bucket, key);
8931- int ret = delete_obj (dpp, obj_ctx, bucket_info, obj_instance, 0 , y, null_verid, RGW_BILOG_FLAG_VERSIONED_OP, ceph::real_time (), zones_trace, log_op);
8949+ int ret = delete_obj (dpp, obj_ctx, bucket_info, obj_instance, 0 , y,
8950+ null_verid, RGW_BILOG_FLAG_VERSIONED_OP,
8951+ ceph::real_time (), zones_trace, log_op, force);
89328952 if (ret < 0 && ret != -ENOENT) {
89338953 ldpp_dout (dpp, 0 ) << " ERROR: delete_obj() returned " << ret << " obj_instance=" << obj_instance << dendl;
89348954 return ret;
@@ -8942,7 +8962,6 @@ int RGWRados::apply_olh_log(const DoutPrefixProvider *dpp,
89428962 return r;
89438963 }
89448964
8945-
89468965 if (need_to_remove) {
89478966 string olh_tag (state.olh_tag .c_str (), state.olh_tag .length ());
89488967 r = clear_olh (dpp, obj_ctx, obj, bucket_info, ref, olh_tag, last_ver, y);
@@ -9032,7 +9051,15 @@ int RGWRados::clear_olh(const DoutPrefixProvider *dpp,
90329051/*
90339052 * read olh log and apply it
90349053 */
9035- int RGWRados::update_olh (const DoutPrefixProvider *dpp, RGWObjectCtx& obj_ctx, RGWObjState *state, RGWBucketInfo& bucket_info, const rgw_obj& obj, optional_yield y, rgw_zone_set *zones_trace, bool null_verid, bool log_op)
9054+ int RGWRados::update_olh (const DoutPrefixProvider* dpp,
9055+ RGWObjectCtx& obj_ctx,
9056+ RGWObjState* state,
9057+ RGWBucketInfo& bucket_info,
9058+ const rgw_obj& obj, optional_yield y,
9059+ rgw_zone_set* zones_trace,
9060+ bool null_verid,
9061+ bool log_op,
9062+ const bool force)
90369063{
90379064 map<uint64_t , vector<rgw_bucket_olh_log_entry> > log;
90389065 bool is_truncated;
@@ -9043,7 +9070,9 @@ int RGWRados::update_olh(const DoutPrefixProvider *dpp, RGWObjectCtx& obj_ctx, R
90439070 if (ret < 0 ) {
90449071 return ret;
90459072 }
9046- ret = apply_olh_log (dpp, obj_ctx, *state, bucket_info, obj, state->olh_tag , log, &ver_marker, y, null_verid, zones_trace, log_op);
9073+ ret = apply_olh_log (dpp, obj_ctx, *state, bucket_info, obj,
9074+ state->olh_tag , log, &ver_marker, y,
9075+ null_verid, zones_trace, log_op, force);
90479076 if (ret < 0 ) {
90489077 return ret;
90499078 }
@@ -9144,8 +9173,17 @@ int RGWRados::set_olh(const DoutPrefixProvider *dpp, RGWObjectCtx& obj_ctx,
91449173 return 0 ;
91459174}
91469175
9147- int RGWRados::unlink_obj_instance (const DoutPrefixProvider *dpp, RGWObjectCtx& obj_ctx, RGWBucketInfo& bucket_info, const rgw_obj& target_obj,
9148- uint64_t olh_epoch, optional_yield y, uint16_t bilog_flags, bool null_verid, rgw_zone_set *zones_trace, bool log_op)
9176+ int RGWRados::unlink_obj_instance (const DoutPrefixProvider* dpp,
9177+ RGWObjectCtx& obj_ctx,
9178+ RGWBucketInfo& bucket_info,
9179+ const rgw_obj& target_obj,
9180+ uint64_t olh_epoch,
9181+ optional_yield y,
9182+ uint16_t bilog_flags,
9183+ bool null_verid,
9184+ rgw_zone_set* zones_trace,
9185+ bool log_op,
9186+ const bool force)
91499187{
91509188 string op_tag;
91519189
@@ -9190,31 +9228,36 @@ int RGWRados::unlink_obj_instance(const DoutPrefixProvider *dpp, RGWObjectCtx& o
91909228 bilog_flags = bilog_flags | RGW_BILOG_FLAG_VERSIONED_OP;
91919229 }
91929230
9193- ret = bucket_index_unlink_instance (dpp, bucket_info, target_obj, op_tag, olh_tag, olh_epoch, y, bilog_flags, zones_trace, log_op);
9231+ ret = bucket_index_unlink_instance (dpp, bucket_info, target_obj,
9232+ op_tag, olh_tag, olh_epoch, y,
9233+ bilog_flags, zones_trace, log_op);
91949234 if (ret < 0 ) {
91959235 olh_cancel_modification (dpp, bucket_info, *state, olh_obj, op_tag, y);
9196- ldpp_dout (dpp, 20 ) << " bucket_index_unlink_instance() target_obj=" << target_obj << " returned " << ret << dendl;
9236+ ldpp_dout (dpp, 20 ) << " bucket_index_unlink_instance() target_obj=" <<
9237+ target_obj << " returned " << ret << dendl;
91979238 if (ret == -ECANCELED) {
91989239 continue ;
91999240 }
92009241 // it's possible that the pending xattr from this op prevented the olh
92019242 // object from being cleaned by another thread that was deleting the last
92029243 // existing version. We invoke a best-effort update_olh here to handle this case.
9203- int r = update_olh (dpp, obj_ctx, state, bucket_info, olh_obj, y, zones_trace, null_verid, log_op);
9244+ int r = update_olh (dpp, obj_ctx, state, bucket_info, olh_obj, y,
9245+ zones_trace, null_verid, log_op, force);
92049246 if (r < 0 && r != -ECANCELED) {
92059247 ldpp_dout (dpp, 20 ) << " update_olh() target_obj=" << olh_obj << " returned " << r << dendl;
92069248 }
92079249 return ret;
9208- }
9250+ } // if error in bucket_index_unlink_instance call
92099251 break ;
9210- }
9252+ } // cancel retry loop
92119253
92129254 if (i == MAX_ECANCELED_RETRY) {
92139255 ldpp_dout (dpp, 0 ) << " ERROR: exceeded max ECANCELED retries, aborting (EIO)" << dendl;
92149256 return -EIO;
92159257 }
92169258
9217- ret = update_olh (dpp, obj_ctx, state, bucket_info, olh_obj, y, zones_trace, null_verid, log_op);
9259+ ret = update_olh (dpp, obj_ctx, state, bucket_info, olh_obj, y,
9260+ zones_trace, null_verid, log_op, force);
92189261 if (ret == -ECANCELED) { /* already did what we needed, no need to retry, raced with another user */
92199262 return 0 ;
92209263 }
@@ -11322,7 +11365,7 @@ int RGWRados::delete_obj_aio(const DoutPrefixProvider *dpp, const rgw_obj& obj,
1132211365 }
1132311366 }
1132411367 return ret;
11325- }
11368+ } // delete_obj_aio
1132611369
1132711370void objexp_hint_entry::generate_test_instances (list<objexp_hint_entry*>& o)
1132811371{
0 commit comments