]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/services/svc_sys_obj_core.cc
import ceph pacific 16.2.5
[ceph.git] / ceph / src / rgw / services / svc_sys_obj_core.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
3
4 #include "svc_sys_obj_core.h"
5 #include "svc_rados.h"
6 #include "svc_zone.h"
7
8 #include "rgw/rgw_tools.h"
9
10 #define dout_subsys ceph_subsys_rgw
11
12 int RGWSI_SysObj_Core_GetObjState::get_rados_obj(const DoutPrefixProvider *dpp,
13 RGWSI_RADOS *rados_svc,
14 RGWSI_Zone *zone_svc,
15 const rgw_raw_obj& obj,
16 RGWSI_RADOS::Obj **pobj)
17 {
18 if (!has_rados_obj) {
19 if (obj.oid.empty()) {
20 ldpp_dout(dpp, 0) << "ERROR: obj.oid is empty" << dendl;
21 return -EINVAL;
22 }
23
24 rados_obj = rados_svc->obj(obj);
25 int r = rados_obj.open(dpp);
26 if (r < 0) {
27 return r;
28 }
29 has_rados_obj = true;
30 }
31 *pobj = &rados_obj;
32 return 0;
33 }
34
35 int RGWSI_SysObj_Core::get_rados_obj(const DoutPrefixProvider *dpp,
36 RGWSI_Zone *zone_svc,
37 const rgw_raw_obj& obj,
38 RGWSI_RADOS::Obj *pobj)
39 {
40 if (obj.oid.empty()) {
41 ldpp_dout(dpp, 0) << "ERROR: obj.oid is empty" << dendl;
42 return -EINVAL;
43 }
44
45 *pobj = rados_svc->obj(obj);
46 int r = pobj->open(dpp);
47 if (r < 0) {
48 return r;
49 }
50
51 return 0;
52 }
53
54 int RGWSI_SysObj_Core::get_system_obj_state_impl(RGWSysObjectCtxBase *rctx,
55 const rgw_raw_obj& obj,
56 RGWSysObjState **state,
57 RGWObjVersionTracker *objv_tracker,
58 optional_yield y,
59 const DoutPrefixProvider *dpp)
60 {
61 if (obj.empty()) {
62 return -EINVAL;
63 }
64
65 RGWSysObjState *s = rctx->get_state(obj);
66 ldpp_dout(dpp, 20) << "get_system_obj_state: rctx=" << (void *)rctx << " obj=" << obj << " state=" << (void *)s << " s->prefetch_data=" << s->prefetch_data << dendl;
67 *state = s;
68 if (s->has_attrs) {
69 return 0;
70 }
71
72 s->obj = obj;
73
74 int r = raw_stat(dpp, obj, &s->size, &s->mtime, &s->epoch, &s->attrset,
75 (s->prefetch_data ? &s->data : nullptr), objv_tracker, y);
76 if (r == -ENOENT) {
77 s->exists = false;
78 s->has_attrs = true;
79 s->mtime = real_time();
80 return 0;
81 }
82 if (r < 0)
83 return r;
84
85 s->exists = true;
86 s->has_attrs = true;
87 s->obj_tag = s->attrset[RGW_ATTR_ID_TAG];
88
89 if (s->obj_tag.length()) {
90 ldpp_dout(dpp, 20) << "get_system_obj_state: setting s->obj_tag to " << s->obj_tag.c_str() << dendl;
91 } else {
92 ldpp_dout(dpp, 20) << "get_system_obj_state: s->obj_tag was set empty" << dendl;
93 }
94
95 return 0;
96 }
97
98 int RGWSI_SysObj_Core::get_system_obj_state(RGWSysObjectCtxBase *rctx,
99 const rgw_raw_obj& obj,
100 RGWSysObjState **state,
101 RGWObjVersionTracker *objv_tracker,
102 optional_yield y,
103 const DoutPrefixProvider *dpp)
104 {
105 int ret;
106
107 do {
108 ret = get_system_obj_state_impl(rctx, obj, state, objv_tracker, y, dpp);
109 } while (ret == -EAGAIN);
110
111 return ret;
112 }
113
114 int RGWSI_SysObj_Core::raw_stat(const DoutPrefixProvider *dpp, const rgw_raw_obj& obj, uint64_t *psize, real_time *pmtime, uint64_t *epoch,
115 map<string, bufferlist> *attrs, bufferlist *first_chunk,
116 RGWObjVersionTracker *objv_tracker,
117 optional_yield y)
118 {
119 RGWSI_RADOS::Obj rados_obj;
120 int r = get_rados_obj(dpp, zone_svc, obj, &rados_obj);
121 if (r < 0) {
122 return r;
123 }
124
125 uint64_t size = 0;
126 struct timespec mtime_ts;
127
128 librados::ObjectReadOperation op;
129 if (objv_tracker) {
130 objv_tracker->prepare_op_for_read(&op);
131 }
132 op.getxattrs(attrs, nullptr);
133 if (psize || pmtime) {
134 op.stat2(&size, &mtime_ts, nullptr);
135 }
136 if (first_chunk) {
137 op.read(0, cct->_conf->rgw_max_chunk_size, first_chunk, nullptr);
138 }
139 bufferlist outbl;
140 r = rados_obj.operate(dpp, &op, &outbl, y);
141
142 if (epoch) {
143 *epoch = rados_obj.get_last_version();
144 }
145
146 if (r < 0)
147 return r;
148
149 if (psize)
150 *psize = size;
151 if (pmtime)
152 *pmtime = ceph::real_clock::from_timespec(mtime_ts);
153
154 return 0;
155 }
156
157 int RGWSI_SysObj_Core::stat(RGWSysObjectCtxBase& obj_ctx,
158 RGWSI_SysObj_Obj_GetObjState& _state,
159 const rgw_raw_obj& obj,
160 map<string, bufferlist> *attrs,
161 bool raw_attrs,
162 real_time *lastmod,
163 uint64_t *obj_size,
164 RGWObjVersionTracker *objv_tracker,
165 optional_yield y,
166 const DoutPrefixProvider *dpp)
167 {
168 RGWSysObjState *astate = nullptr;
169
170 int r = get_system_obj_state(&obj_ctx, obj, &astate, objv_tracker, y, dpp);
171 if (r < 0)
172 return r;
173
174 if (!astate->exists) {
175 return -ENOENT;
176 }
177
178 if (attrs) {
179 if (raw_attrs) {
180 *attrs = astate->attrset;
181 } else {
182 rgw_filter_attrset(astate->attrset, RGW_ATTR_PREFIX, attrs);
183 }
184 if (cct->_conf->subsys.should_gather<ceph_subsys_rgw, 20>()) {
185 map<string, bufferlist>::iterator iter;
186 for (iter = attrs->begin(); iter != attrs->end(); ++iter) {
187 ldpp_dout(dpp, 20) << "Read xattr: " << iter->first << dendl;
188 }
189 }
190 }
191
192 if (obj_size)
193 *obj_size = astate->size;
194 if (lastmod)
195 *lastmod = astate->mtime;
196
197 return 0;
198 }
199
200 int RGWSI_SysObj_Core::read(const DoutPrefixProvider *dpp,
201 RGWSysObjectCtxBase& obj_ctx,
202 RGWSI_SysObj_Obj_GetObjState& _read_state,
203 RGWObjVersionTracker *objv_tracker,
204 const rgw_raw_obj& obj,
205 bufferlist *bl, off_t ofs, off_t end,
206 map<string, bufferlist> *attrs,
207 bool raw_attrs,
208 rgw_cache_entry_info *cache_info,
209 boost::optional<obj_version>,
210 optional_yield y)
211 {
212 auto& read_state = static_cast<GetObjState&>(_read_state);
213
214 uint64_t len;
215 librados::ObjectReadOperation op;
216
217 if (end < 0)
218 len = 0;
219 else
220 len = end - ofs + 1;
221
222 if (objv_tracker) {
223 objv_tracker->prepare_op_for_read(&op);
224 }
225
226 ldpp_dout(dpp, 20) << "rados->read ofs=" << ofs << " len=" << len << dendl;
227 op.read(ofs, len, bl, nullptr);
228
229 map<string, bufferlist> unfiltered_attrset;
230
231 if (attrs) {
232 if (raw_attrs) {
233 op.getxattrs(attrs, nullptr);
234 } else {
235 op.getxattrs(&unfiltered_attrset, nullptr);
236 }
237 }
238
239 RGWSI_RADOS::Obj rados_obj;
240 int r = get_rados_obj(dpp, zone_svc, obj, &rados_obj);
241 if (r < 0) {
242 ldpp_dout(dpp, 20) << "get_rados_obj() on obj=" << obj << " returned " << r << dendl;
243 return r;
244 }
245 r = rados_obj.operate(dpp, &op, nullptr, y);
246 if (r < 0) {
247 ldpp_dout(dpp, 20) << "rados_obj.operate() r=" << r << " bl.length=" << bl->length() << dendl;
248 return r;
249 }
250 ldpp_dout(dpp, 20) << "rados_obj.operate() r=" << r << " bl.length=" << bl->length() << dendl;
251
252 uint64_t op_ver = rados_obj.get_last_version();
253
254 if (read_state.last_ver > 0 &&
255 read_state.last_ver != op_ver) {
256 ldpp_dout(dpp, 5) << "raced with an object write, abort" << dendl;
257 return -ECANCELED;
258 }
259
260 if (attrs && !raw_attrs) {
261 rgw_filter_attrset(unfiltered_attrset, RGW_ATTR_PREFIX, attrs);
262 }
263
264 read_state.last_ver = op_ver;
265
266 return bl->length();
267 }
268
269 /**
270 * Get an attribute for a system object.
271 * obj: the object to get attr
272 * name: name of the attr to retrieve
273 * dest: bufferlist to store the result in
274 * Returns: 0 on success, -ERR# otherwise.
275 */
276 int RGWSI_SysObj_Core::get_attr(const DoutPrefixProvider *dpp,
277 const rgw_raw_obj& obj,
278 const char *name,
279 bufferlist *dest,
280 optional_yield y)
281 {
282 RGWSI_RADOS::Obj rados_obj;
283 int r = get_rados_obj(dpp, zone_svc, obj, &rados_obj);
284 if (r < 0) {
285 ldpp_dout(dpp, 20) << "get_rados_obj() on obj=" << obj << " returned " << r << dendl;
286 return r;
287 }
288
289 librados::ObjectReadOperation op;
290
291 int rval;
292 op.getxattr(name, dest, &rval);
293
294 r = rados_obj.operate(dpp, &op, nullptr, y);
295 if (r < 0)
296 return r;
297
298 return 0;
299 }
300
301 int RGWSI_SysObj_Core::set_attrs(const DoutPrefixProvider *dpp,
302 const rgw_raw_obj& obj,
303 map<string, bufferlist>& attrs,
304 map<string, bufferlist> *rmattrs,
305 RGWObjVersionTracker *objv_tracker,
306 optional_yield y)
307 {
308 RGWSI_RADOS::Obj rados_obj;
309 int r = get_rados_obj(dpp, zone_svc, obj, &rados_obj);
310 if (r < 0) {
311 ldpp_dout(dpp, 20) << "get_rados_obj() on obj=" << obj << " returned " << r << dendl;
312 return r;
313 }
314
315 librados::ObjectWriteOperation op;
316
317 if (objv_tracker) {
318 objv_tracker->prepare_op_for_write(&op);
319 }
320
321 map<string, bufferlist>::iterator iter;
322 if (rmattrs) {
323 for (iter = rmattrs->begin(); iter != rmattrs->end(); ++iter) {
324 const string& name = iter->first;
325 op.rmxattr(name.c_str());
326 }
327 }
328
329 for (iter = attrs.begin(); iter != attrs.end(); ++iter) {
330 const string& name = iter->first;
331 bufferlist& bl = iter->second;
332
333 if (!bl.length())
334 continue;
335
336 op.setxattr(name.c_str(), bl);
337 }
338
339 if (!op.size())
340 return 0;
341
342 bufferlist bl;
343
344 r = rados_obj.operate(dpp, &op, y);
345 if (r < 0)
346 return r;
347
348 if (objv_tracker) {
349 objv_tracker->apply_write();
350 }
351 return 0;
352 }
353
354 int RGWSI_SysObj_Core::omap_get_vals(const DoutPrefixProvider *dpp,
355 const rgw_raw_obj& obj,
356 const string& marker,
357 uint64_t count,
358 std::map<string, bufferlist> *m,
359 bool *pmore,
360 optional_yield y)
361 {
362 RGWSI_RADOS::Obj rados_obj;
363 int r = get_rados_obj(dpp, zone_svc, obj, &rados_obj);
364 if (r < 0) {
365 ldpp_dout(dpp, 20) << "get_rados_obj() on obj=" << obj << " returned " << r << dendl;
366 return r;
367 }
368
369 string start_after = marker;
370 bool more;
371
372 do {
373 librados::ObjectReadOperation op;
374
375 std::map<string, bufferlist> t;
376 int rval;
377 op.omap_get_vals2(start_after, count, &t, &more, &rval);
378
379 r = rados_obj.operate(dpp, &op, nullptr, y);
380 if (r < 0) {
381 return r;
382 }
383 if (t.empty()) {
384 break;
385 }
386 count -= t.size();
387 start_after = t.rbegin()->first;
388 m->insert(t.begin(), t.end());
389 } while (more && count > 0);
390
391 if (pmore) {
392 *pmore = more;
393 }
394 return 0;
395 }
396
397 int RGWSI_SysObj_Core::omap_get_all(const DoutPrefixProvider *dpp,
398 const rgw_raw_obj& obj,
399 std::map<string, bufferlist> *m,
400 optional_yield y)
401 {
402 RGWSI_RADOS::Obj rados_obj;
403 int r = get_rados_obj(dpp, zone_svc, obj, &rados_obj);
404 if (r < 0) {
405 ldpp_dout(dpp, 20) << "get_rados_obj() on obj=" << obj << " returned " << r << dendl;
406 return r;
407 }
408
409 #define MAX_OMAP_GET_ENTRIES 1024
410 const int count = MAX_OMAP_GET_ENTRIES;
411 string start_after;
412 bool more;
413
414 do {
415 librados::ObjectReadOperation op;
416
417 std::map<string, bufferlist> t;
418 int rval;
419 op.omap_get_vals2(start_after, count, &t, &more, &rval);
420
421 r = rados_obj.operate(dpp, &op, nullptr, y);
422 if (r < 0) {
423 return r;
424 }
425 if (t.empty()) {
426 break;
427 }
428 start_after = t.rbegin()->first;
429 m->insert(t.begin(), t.end());
430 } while (more);
431 return 0;
432 }
433
434 int RGWSI_SysObj_Core::omap_set(const DoutPrefixProvider *dpp, const rgw_raw_obj& obj, const std::string& key,
435 bufferlist& bl, bool must_exist,
436 optional_yield y)
437 {
438 RGWSI_RADOS::Obj rados_obj;
439 int r = get_rados_obj(dpp, zone_svc, obj, &rados_obj);
440 if (r < 0) {
441 ldpp_dout(dpp, 20) << "get_rados_obj() on obj=" << obj << " returned " << r << dendl;
442 return r;
443 }
444
445 ldpp_dout(dpp, 15) << "omap_set obj=" << obj << " key=" << key << dendl;
446
447 map<string, bufferlist> m;
448 m[key] = bl;
449 librados::ObjectWriteOperation op;
450 if (must_exist)
451 op.assert_exists();
452 op.omap_set(m);
453 r = rados_obj.operate(dpp, &op, y);
454 return r;
455 }
456
457 int RGWSI_SysObj_Core::omap_set(const DoutPrefixProvider *dpp, const rgw_raw_obj& obj,
458 const std::map<std::string, bufferlist>& m,
459 bool must_exist, optional_yield y)
460 {
461 RGWSI_RADOS::Obj rados_obj;
462 int r = get_rados_obj(dpp, zone_svc, obj, &rados_obj);
463 if (r < 0) {
464 ldpp_dout(dpp, 20) << "get_rados_obj() on obj=" << obj << " returned " << r << dendl;
465 return r;
466 }
467
468 librados::ObjectWriteOperation op;
469 if (must_exist)
470 op.assert_exists();
471 op.omap_set(m);
472 r = rados_obj.operate(dpp, &op, y);
473 return r;
474 }
475
476 int RGWSI_SysObj_Core::omap_del(const DoutPrefixProvider *dpp, const rgw_raw_obj& obj, const std::string& key,
477 optional_yield y)
478 {
479 RGWSI_RADOS::Obj rados_obj;
480 int r = get_rados_obj(dpp, zone_svc, obj, &rados_obj);
481 if (r < 0) {
482 ldpp_dout(dpp, 20) << "get_rados_obj() on obj=" << obj << " returned " << r << dendl;
483 return r;
484 }
485
486 set<string> k;
487 k.insert(key);
488
489 librados::ObjectWriteOperation op;
490
491 op.omap_rm_keys(k);
492
493 r = rados_obj.operate(dpp, &op, y);
494 return r;
495 }
496
497 int RGWSI_SysObj_Core::notify(const DoutPrefixProvider *dpp, const rgw_raw_obj& obj, bufferlist& bl,
498 uint64_t timeout_ms, bufferlist *pbl,
499 optional_yield y)
500 {
501 RGWSI_RADOS::Obj rados_obj;
502 int r = get_rados_obj(dpp, zone_svc, obj, &rados_obj);
503 if (r < 0) {
504 ldpp_dout(dpp, 20) << "get_rados_obj() on obj=" << obj << " returned " << r << dendl;
505 return r;
506 }
507
508 r = rados_obj.notify(dpp, bl, timeout_ms, pbl, y);
509 return r;
510 }
511
512 int RGWSI_SysObj_Core::remove(const DoutPrefixProvider *dpp,
513 RGWSysObjectCtxBase& obj_ctx,
514 RGWObjVersionTracker *objv_tracker,
515 const rgw_raw_obj& obj,
516 optional_yield y)
517 {
518 RGWSI_RADOS::Obj rados_obj;
519 int r = get_rados_obj(dpp, zone_svc, obj, &rados_obj);
520 if (r < 0) {
521 ldpp_dout(dpp, 20) << "get_rados_obj() on obj=" << obj << " returned " << r << dendl;
522 return r;
523 }
524
525 librados::ObjectWriteOperation op;
526
527 if (objv_tracker) {
528 objv_tracker->prepare_op_for_write(&op);
529 }
530
531 op.remove();
532 r = rados_obj.operate(dpp, &op, y);
533 if (r < 0)
534 return r;
535
536 return 0;
537 }
538
539 int RGWSI_SysObj_Core::write(const DoutPrefixProvider *dpp,
540 const rgw_raw_obj& obj,
541 real_time *pmtime,
542 map<std::string, bufferlist>& attrs,
543 bool exclusive,
544 const bufferlist& data,
545 RGWObjVersionTracker *objv_tracker,
546 real_time set_mtime,
547 optional_yield y)
548 {
549 RGWSI_RADOS::Obj rados_obj;
550 int r = get_rados_obj(dpp, zone_svc, obj, &rados_obj);
551 if (r < 0) {
552 ldpp_dout(dpp, 20) << "get_rados_obj() on obj=" << obj << " returned " << r << dendl;
553 return r;
554 }
555
556 librados::ObjectWriteOperation op;
557
558 if (exclusive) {
559 op.create(true); // exclusive create
560 } else {
561 op.remove();
562 op.set_op_flags2(LIBRADOS_OP_FLAG_FAILOK);
563 op.create(false);
564 }
565
566 if (objv_tracker) {
567 objv_tracker->prepare_op_for_write(&op);
568 }
569
570 if (real_clock::is_zero(set_mtime)) {
571 set_mtime = real_clock::now();
572 }
573
574 struct timespec mtime_ts = real_clock::to_timespec(set_mtime);
575 op.mtime2(&mtime_ts);
576 op.write_full(data);
577
578 bufferlist acl_bl;
579
580 for (map<string, bufferlist>::iterator iter = attrs.begin(); iter != attrs.end(); ++iter) {
581 const string& name = iter->first;
582 bufferlist& bl = iter->second;
583
584 if (!bl.length())
585 continue;
586
587 op.setxattr(name.c_str(), bl);
588 }
589
590 r = rados_obj.operate(dpp, &op, y);
591 if (r < 0) {
592 return r;
593 }
594
595 if (objv_tracker) {
596 objv_tracker->apply_write();
597 }
598
599 if (pmtime) {
600 *pmtime = set_mtime;
601 }
602
603 return 0;
604 }
605
606
607 int RGWSI_SysObj_Core::write_data(const DoutPrefixProvider *dpp,
608 const rgw_raw_obj& obj,
609 const bufferlist& bl,
610 bool exclusive,
611 RGWObjVersionTracker *objv_tracker,
612 optional_yield y)
613 {
614 RGWSI_RADOS::Obj rados_obj;
615 int r = get_rados_obj(dpp, zone_svc, obj, &rados_obj);
616 if (r < 0) {
617 ldpp_dout(dpp, 20) << "get_rados_obj() on obj=" << obj << " returned " << r << dendl;
618 return r;
619 }
620
621 librados::ObjectWriteOperation op;
622
623 if (exclusive) {
624 op.create(true);
625 }
626
627 if (objv_tracker) {
628 objv_tracker->prepare_op_for_write(&op);
629 }
630 op.write_full(bl);
631 r = rados_obj.operate(dpp, &op, y);
632 if (r < 0)
633 return r;
634
635 if (objv_tracker) {
636 objv_tracker->apply_write();
637 }
638 return 0;
639 }
640
641 int RGWSI_SysObj_Core::pool_list_prefixed_objs(const DoutPrefixProvider *dpp,
642 const rgw_pool& pool, const string& prefix,
643 std::function<void(const string&)> cb)
644 {
645 bool is_truncated;
646
647 auto rados_pool = rados_svc->pool(pool);
648
649 auto op = rados_pool.op();
650
651 RGWAccessListFilterPrefix filter(prefix);
652
653 int r = op.init(dpp, string(), &filter);
654 if (r < 0) {
655 return r;
656 }
657
658 do {
659 vector<string> oids;
660 #define MAX_OBJS_DEFAULT 1000
661 int r = op.get_next(MAX_OBJS_DEFAULT, &oids, &is_truncated);
662 if (r < 0) {
663 return r;
664 }
665 for (auto& val : oids) {
666 if (val.size() > prefix.size()) {
667 cb(val.substr(prefix.size()));
668 }
669 }
670 } while (is_truncated);
671
672 return 0;
673 }
674
675 int RGWSI_SysObj_Core::pool_list_objects_init(const DoutPrefixProvider *dpp,
676 const rgw_pool& pool,
677 const string& marker,
678 const string& prefix,
679 RGWSI_SysObj::Pool::ListCtx *_ctx)
680 {
681 _ctx->impl.emplace<PoolListImplInfo>(prefix);
682
683 auto& ctx = static_cast<PoolListImplInfo&>(*_ctx->impl);
684
685 ctx.pool = rados_svc->pool(pool);
686 ctx.op = ctx.pool.op();
687
688 int r = ctx.op.init(dpp, marker, &ctx.filter);
689 if (r < 0) {
690 ldpp_dout(dpp, 10) << "failed to list objects pool_iterate_begin() returned r=" << r << dendl;
691 return r;
692 }
693 return 0;
694 }
695
696 int RGWSI_SysObj_Core::pool_list_objects_next(RGWSI_SysObj::Pool::ListCtx& _ctx,
697 int max,
698 vector<string> *oids,
699 bool *is_truncated)
700 {
701 if (!_ctx.impl) {
702 return -EINVAL;
703 }
704 auto& ctx = static_cast<PoolListImplInfo&>(*_ctx.impl);
705 int r = ctx.op.get_next(max, oids, is_truncated);
706 if (r < 0) {
707 if(r != -ENOENT)
708 ldout(cct, 10) << "failed to list objects pool_iterate returned r=" << r << dendl;
709 return r;
710 }
711
712 return oids->size();
713 }
714
715 int RGWSI_SysObj_Core::pool_list_objects_get_marker(RGWSI_SysObj::Pool::ListCtx& _ctx,
716 string *marker)
717 {
718 if (!_ctx.impl) {
719 return -EINVAL;
720 }
721
722 auto& ctx = static_cast<PoolListImplInfo&>(*_ctx.impl);
723 return ctx.op.get_marker(marker);
724 }