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