Skip to content
This repository was archived by the owner on Feb 8, 2024. It is now read-only.

Commit 524eb3b

Browse files
committed
rgw: [CORTX-32694] Motr GC Implementation for Multipart Objects
Motr GC producer and consumer module implementation for multipart objects Signed-off-by: Jeet Jain <[email protected]>
1 parent 5c7a38b commit 524eb3b

File tree

3 files changed

+146
-34
lines changed

3 files changed

+146
-34
lines changed

src/rgw/motr/gc/gc.cc

Lines changed: 117 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -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;

src/rgw/motr/gc/gc.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,9 @@ class MotrGC : public DoutPrefixProvider {
172172
int dequeue(std::string iname, motr_gc_obj_info obj);
173173

174174
int list(std::vector<std::unordered_map<std::string, std::string>> &gc_entries);
175-
int delete_motr_obj_from_gc(motr_gc_obj_info ginfo);
175+
int delete_obj_from_gc(motr_gc_obj_info ginfo);
176+
int process_parts(motr_gc_obj_info ginfo, std::time_t end_time);
177+
int delete_motr_obj(Meta motr_obj);
176178
int get_locked_gc_index(uint32_t& rand_ind, uint32_t& lease_duration);
177179
int un_lock_gc_index(uint32_t& index);
178180

src/rgw/rgw_sal_motr.cc

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2215,7 +2215,32 @@ int MotrObject::remove_mobj_and_index_entry(
22152215
if (ent.meta.size != 0) {
22162216
if (ent.meta.category == RGWObjCategory::MultiMeta) {
22172217
this->set_category(RGWObjCategory::MultiMeta);
2218-
rc = this->delete_part_objs(dpp, &size_rounded);
2218+
if (store->gc_enabled()) {
2219+
ldpp_dout(dpp, 0) <<__func__<< ": trying to put obj into GC=" << dendl;
2220+
std::string upload_id = "";
2221+
rc = store->get_upload_id(bucket_name, delete_key, upload_id);
2222+
if (rc < 0) {
2223+
ldpp_dout(dpp, 0) <<__func__<< ": ERROR: get_upload_id failed. rc=" << rc << dendl;
2224+
}
2225+
else {
2226+
std::string obj_fqdn = bucket_name + "/" + delete_key;
2227+
std::string obj_part_iname = "motr.rgw.object." + bucket_name + "." + delete_key +
2228+
"." + upload_id + ".parts";
2229+
ldpp_dout(dpp, 20) << __func__ << ": object part index=" << obj_part_iname << dendl;
2230+
::Meta *mobj = reinterpret_cast<::Meta*>(&this->meta);
2231+
motr_gc_obj_info gc_obj(upload_id, obj_fqdn, *mobj, std::time(nullptr),
2232+
ent.meta.size, size_rounded, true, obj_part_iname);
2233+
rc = store->get_gc()->enqueue(gc_obj);
2234+
if (rc == 0) {
2235+
pushed_to_gc = true;
2236+
ldpp_dout(dpp, 20) << __func__ << ": Pushed the delete req with tag="
2237+
<< upload_id << " to the motr garbage collector." << dendl;
2238+
}
2239+
}
2240+
}
2241+
if (!pushed_to_gc) {
2242+
rc = this->delete_part_objs(dpp, &size_rounded);
2243+
}
22192244
} else {
22202245
// Handling Simple Object Deletion
22212246
// Open the object if not already open.

0 commit comments

Comments
 (0)