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