@@ -31,7 +31,7 @@ void *MotrGC::GCWorker::entry() {
3131 do {
3232 std::string gc_log_prefix = " [" + gc_thread_prefix
3333 + std::to_string (worker_id) + " ] " ;
34- ldpp_dout (dpp, 10 ) << gc_log_prefix << __func__ << " Iteration Started " << dendl;
34+ ldpp_dout (dpp, 10 ) << gc_log_prefix << __func__ << " : iteration started " << dendl;
3535
3636 std::string iname = " " ;
3737 // Get lock on an GC index
@@ -49,20 +49,20 @@ void *MotrGC::GCWorker::entry() {
4949 // form the index name
5050 iname = motr_gc->index_names [my_index];
5151 ldpp_dout (dpp, 10 ) << gc_log_prefix
52- << __func__ << " : Working on GC Queue : " << iname << dendl;
53-
52+ << __func__ << " : working on GC queue : " << iname << dendl;
53+
5454 bufferlist bl;
5555 std::vector<std::string> keys (motr_gc->max_count + 1 );
5656 std::vector<bufferlist> vals (motr_gc->max_count + 1 );
5757 uint32_t rgw_gc_obj_min_wait = cct->_conf ->rgw_gc_obj_min_wait ;
5858 keys[0 ] = obj_exp_time_prefix;
5959 rc = motr_gc->store ->next_query_by_name (iname,
6060 keys, vals, obj_exp_time_prefix);
61- ldpp_dout (dpp, 0 ) << gc_log_prefix
61+ ldpp_dout (dpp, 0 ) << gc_log_prefix
6262 << __func__ <<" : next_query_by_name() rc=" << rc << dendl;
6363 if (rc < 0 ) {
6464 // In case of failure, worker will keep retrying till end_time
65- ldpp_dout (dpp, 0 ) << gc_log_prefix
65+ ldpp_dout (dpp, 0 ) << gc_log_prefix
6666 << __func__ <<" : ERROR: NEXT query failed. rc=" << rc << dendl;
6767 continue ;
6868 }
@@ -81,33 +81,48 @@ void *MotrGC::GCWorker::entry() {
8181 // delete motr object
8282 if (ginfo.is_multipart ) {
8383 // handle multipart object deletion
84+ // with large number of parts, a gc thread may exhaust its alloted
85+ // time, in that case it will be preempted and remaining parts will
86+ // be processed in next cycle
87+ rc = motr_gc->process_parts (ginfo, end_time);
88+ if (rc < 0 ) {
89+ ldpp_dout (dpp, 0 ) << gc_log_prefix << __func__
90+ << " : ERROR: failed to distribute multipart object "
91+ << ginfo.name << " with tag " << ginfo.tag << " rc: " << rc << dendl;
92+ continue ; // should continue deletion for next objects
93+ }
8494 }
8595 else {
8696 // simple object
87- rc = motr_gc->delete_motr_obj_from_gc (ginfo);
97+ rc = motr_gc->delete_obj_from_gc (ginfo);
8898 if (rc < 0 ) {
8999 ldpp_dout (dpp, 0 ) << gc_log_prefix
90- << __func__ <<" ERROR: Motr obj deletion failed for "
100+ << __func__ <<" : ERROR: motr obj deletion failed for "
91101 << ginfo.tag << " with rc: " << rc << dendl;
92102 continue ; // should continue deletion for next objects
93103 }
94104 }
95105 // delete entry from GC queue
96106 rc = motr_gc->dequeue (iname, ginfo);
107+ if (rc == 0 ) {
108+ ldpp_dout (dpp, 20 ) << gc_log_prefix << __func__
109+ << " : successfully deleted object " << ginfo.name
110+ << " with tag " << ginfo.tag << dendl;
111+ }
97112 processed_count++;
98-
113+
99114 // Update current time
100115 current_time = std::time (nullptr );
101116 // Exit the loop if required work is complete
102- if (processed_count >= motr_gc->max_count
117+ if (processed_count >= motr_gc->max_count
103118 || current_time > end_time || motr_gc->going_down ())
104119 break ;
105120 }
106121 // unlock the GC queue
107122 motr_gc->un_lock_gc_index (my_index);
108123 } else {
109124 ldpp_dout (dpp, 0 ) << gc_log_prefix
110- << __func__ << " ERROR: No GC index is available for locking."
125+ << __func__ << " : ERROR: no GC index is available for locking."
111126 << " Skipping GC processing" << " rc = " << rc << dendl;
112127 }
113128 my_index = (my_index + 1 ) % motr_gc->max_indices ;
@@ -119,7 +134,7 @@ void *MotrGC::GCWorker::entry() {
119134 }
120135 } while (!motr_gc->going_down ());
121136
122- ldpp_dout (dpp, 0 ) << __func__ << " : Stop signal called for "
137+ ldpp_dout (dpp, 0 ) << __func__ << " : stop signal called for "
123138 << gc_thread_prefix << worker_id << dendl;
124139 return nullptr ;
125140}
@@ -133,7 +148,7 @@ int MotrGC::initialize() {
133148 std::string iname = gc_index_prefix + " ." + std::to_string (ind_suf);
134149 rc = store->create_motr_idx_by_name (iname);
135150 if (rc < 0 && rc != -EEXIST){
136- ldout (cct, 0 ) << " ERROR: GC index creation failed with rc: " << rc << dendl;
151+ ldout (cct, 0 ) << " : ERROR: GC index creation failed with rc: " << rc << dendl;
137152 break ;
138153 }
139154 if (rc == -EEXIST) rc = 0 ;
@@ -154,7 +169,7 @@ int MotrGC::initialize() {
154169 rc = kv_lock_provider->initialize (
155170 this , store, global_lock_table);
156171 if (rc < 0 ) {
157- ldout (cct, 0 ) << " ERROR: Failed to initialize lock provider: "
172+ ldout (cct, 0 ) << " ERROR: failed to initialize lock provider: "
158173 << rc << dendl;
159174 return rc;
160175 }
@@ -223,27 +238,97 @@ uint32_t MotrGC::get_max_indices() {
223238 return gc_max_indices;
224239}
225240
226- int MotrGC::delete_motr_obj_from_gc (motr_gc_obj_info ginfo) {
241+ int MotrGC::delete_obj_from_gc (motr_gc_obj_info ginfo) {
242+ int rc = delete_motr_obj (ginfo.mobj );
243+ return rc;
244+ }
245+
246+ int MotrGC::process_parts (motr_gc_obj_info ginfo, std::time_t end_time) {
247+ int rc = 0 ;
248+ int max_entries = 10000 ;
249+ int number_of_parts = 0 ;
250+ int processed_parts = 0 ;
251+ std::vector<std::string> keys (max_entries + 1 );
252+ std::vector<bufferlist> vals (max_entries + 1 );
253+
254+ keys[0 ].clear ();
255+ keys[0 ] = " part." ;
256+ char buf[32 ];
257+ snprintf (buf, sizeof (buf), " %08d" , 1 );
258+ keys[0 ].append (buf);
259+ rc = store->next_query_by_name (ginfo.multipart_iname , keys, vals);
260+ if (rc < 0 ) {
261+ ldout (cct, 0 ) <<__func__<<" : ERROR: next query failed. rc="
262+ << rc << dendl;
263+ return rc;
264+ }
265+ number_of_parts = rc;
266+ for (const auto & bl: vals) {
267+ if (bl.length () == 0 )
268+ break ;
269+ RGWUploadPartInfo info;
270+ auto iter = bl.cbegin ();
271+ info.decode (iter);
272+ Meta mobj;
273+ mobj.decode (iter);
274+ ldout (cct, 20 ) <<__func__<< " : part_num=" << info.num
275+ << " part_size=" << info.size << dendl;
276+ std::string tag = PRIx64 + std::to_string (mobj.oid .u_hi ) + " :" +
277+ PRIx64 + std::to_string (mobj.oid .u_lo );
278+ std::string obj_fqdn = ginfo.name + " .part" + std::to_string (info.num );
279+ motr_gc_obj_info gc_obj (tag, obj_fqdn, mobj, ginfo.deletion_time ,
280+ info.size , info.size_rounded , false , " " );
281+ rc = enqueue (gc_obj);
282+ if (rc < 0 ) {
283+ ldout (cct, 0 ) <<__func__<< " : ERROR: failed to push "
284+ << obj_fqdn << " into GC queue " << dendl;
285+ continue ;
286+ }
287+ processed_parts++;
288+ std::string p = " part." ;
289+ char buff[32 ];
290+ snprintf (buff, sizeof (buff), " %08d" , (int )info.num );
291+ p.append (buff);
292+ bufferlist bl_del;
293+ rc = store->do_idx_op_by_name (ginfo.multipart_iname , M0_IC_DEL, p, bl_del);
294+ if (rc < 0 ) {
295+ ldout (cct, 0 ) <<__func__<< " : ERROR: failed to remove part " << p
296+ << " from part index " << ginfo.multipart_iname << dendl;
297+ }
298+ if (std::time (nullptr ) > end_time) {
299+ // processing time's up, so return now
300+ return 0 ;
301+ }
302+ }
303+
304+ if (processed_parts == number_of_parts) {
305+ store->delete_motr_idx_by_name (ginfo.multipart_iname );
306+ }
307+
308+ return rc;
309+ }
310+
311+ int MotrGC::delete_motr_obj (Meta motr_obj) {
227312 int rc;
228313 struct m0_op *op = nullptr ;
229314 char fid_str[M0_FID_STR_LEN];
230- snprintf (fid_str, ARRAY_SIZE (fid_str), U128X_F, U128_P (&ginfo. mobj .oid ));
315+ snprintf (fid_str, ARRAY_SIZE (fid_str), U128X_F, U128_P (&motr_obj .oid ));
231316
232- if (!ginfo. mobj . oid .u_hi || !ginfo. mobj .oid .u_lo ) {
317+ if (!motr_obj. oid .u_hi || !motr_obj .oid .u_lo ) {
233318 ldout (cct, 0 ) <<__func__<< " : invalid motr object oid=" << fid_str << dendl;
234319 return -EINVAL;
235320 }
236321 ldout (cct, 10 ) <<__func__<< " : deleting motr object oid=" << fid_str << dendl;
237322
238323 // Open the object.
239- if (ginfo. mobj .layout_id == 0 ) {
324+ if (motr_obj .layout_id == 0 ) {
240325 return -ENOENT;
241326 }
242327 auto mobj = new m0_obj ();
243328 memset (mobj, 0 , sizeof *mobj);
244- m0_obj_init (mobj, &store->container .co_realm , &ginfo. mobj .oid , store->conf .mc_layout_id );
245- mobj->ob_attr .oa_layout_id = ginfo. mobj .layout_id ;
246- mobj->ob_attr .oa_pver = ginfo. mobj .pver ;
329+ m0_obj_init (mobj, &store->container .co_realm , &motr_obj .oid , store->conf .mc_layout_id );
330+ mobj->ob_attr .oa_layout_id = motr_obj .layout_id ;
331+ mobj->ob_attr .oa_pver = motr_obj .pver ;
247332 mobj->ob_entity .en_flags |= M0_ENF_META;
248333 rc = m0_entity_open (&mobj->ob_entity , &op);
249334 if (rc != 0 ) {
@@ -293,8 +378,6 @@ int MotrGC::delete_motr_obj_from_gc(motr_gc_obj_info ginfo) {
293378 m0_obj_fini (mobj);
294379 delete mobj; mobj = nullptr ;
295380 }
296- ldout (cct, 10 ) <<__func__<< " : deleted motr object oid="
297- << fid_str << " for tag=" << ginfo.tag << dendl;
298381 return 0 ;
299382}
300383
@@ -340,16 +423,17 @@ int MotrGC::dequeue(std::string iname, motr_gc_obj_info obj) {
340423 std::to_string (obj.deletion_time + cct->_conf ->rgw_gc_obj_min_wait );
341424 rc = store->do_idx_op_by_name (iname, M0_IC_DEL, tag_key, bl);
342425 if (rc < 0 ) {
343- ldout (cct, 0 ) << " ERROR: failed to delete tag entry "
426+ ldout (cct, 0 ) << __func__ << " : ERROR: failed to delete tag entry "
344427 << tag_key << " rc: " << rc << dendl;
345428 }
346- ldout (cct, 10 ) << " Deleted tag entry " << tag_key << dendl;
429+ ldout (cct, 10 ) << __func__ << " : deleted tag entry " << tag_key << dendl;
347430 rc = store->do_idx_op_by_name (iname, M0_IC_DEL, expiry_time_key, bl);
348431 if (rc < 0 && rc != -EEXIST) {
349- ldout (cct, 0 ) << " ERROR: failed to delete time entry "
432+ ldout (cct, 0 ) << __func__ << " : ERROR: failed to delete time entry "
350433 << expiry_time_key << " rc: " << rc << dendl;
351434 }
352- ldout (cct, 10 ) << " Deleted time entry " << expiry_time_key << dendl;
435+ ldout (cct, 10 ) << __func__ << " : deleted time entry "
436+ << expiry_time_key << dendl;
353437 return rc;
354438}
355439
@@ -372,10 +456,11 @@ int MotrGC::get_locked_gc_index(uint32_t& rand_ind,
372456 rc = gc_lock->lock (iname, MotrLockType::EXCLUSIVE,
373457 gc_lease_duration, caller_id);
374458 if (rc < 0 ) {
375- ldout (cct, 10 ) << " Failed to acquire lock: GC Queue =[ " << iname << " ] "
376- << " caller_id =[" << caller_id << " ]" << " rc = " << rc << dendl;
459+ ldout (cct, 10 ) << __func__ << " : failed to acquire lock: GC queue = [ " << iname
460+ << " ] " << " caller_id =[" << caller_id << " ]" << " rc = " << rc << dendl;
377461 } else {
378- ldout (cct, 10 ) << " Acquired lock for GC Queue =[" << iname << " ]" << dendl;
462+ ldout (cct, 10 ) << __func__ << " : acquired lock for GC queue = ["
463+ << iname << " ]" << dendl;
379464 }
380465 }
381466 if (rc == 0 )
@@ -413,15 +498,15 @@ int MotrGC::list(std::vector<std::unordered_map<std::string, std::string>> &gc_e
413498 }
414499 rc = store->next_query_by_name (iname, keys, vals, obj_tag_prefix);
415500 if (rc < 0 ) {
416- ldout (cct, 0 ) <<__func__<< " : ERROR: NEXT query failed. rc= "
417- << rc << dendl;
501+ ldout (cct, 0 ) << __func__ << " : ERROR: next query failed for " << iname
502+ << " with rc= " << rc << dendl;
418503 return rc;
419504 }
420505 if (rc == max_entries + 1 ) {
421506 truncated = true ;
422507 marker = keys.back ();
423508 }
424- for (int j = 0 ; j < max_entries &&
509+ for (int j = 0 ; j < max_entries &&
425510 !keys[j].empty () && keys[j] != obj_tag_prefix; j++) {
426511 bufferlist::const_iterator blitr = vals[j].cbegin ();
427512 motr_gc_obj_info ginfo;
0 commit comments