]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #include "librbd/io/Utils.h" | |
f91f0fd5 | 5 | #include "common/dout.h" |
11fdf7f2 | 6 | #include "include/buffer.h" |
f91f0fd5 TL |
7 | #include "include/rados/librados.hpp" |
8 | #include "librbd/io/AioCompletion.h" | |
9 | #include "librbd/io/ImageRequest.h" | |
11fdf7f2 | 10 | #include "osd/osd_types.h" |
f91f0fd5 TL |
11 | #include "osdc/Striper.h" |
12 | ||
13 | #define dout_subsys ceph_subsys_rbd | |
14 | #undef dout_prefix | |
15 | #define dout_prefix *_dout << "librbd::io::util: " << __func__ << ": " | |
11fdf7f2 TL |
16 | |
17 | namespace librbd { | |
18 | namespace io { | |
19 | namespace util { | |
20 | ||
21 | bool assemble_write_same_extent( | |
9f95a23c | 22 | const LightweightObjectExtent &object_extent, const ceph::bufferlist& data, |
11fdf7f2 TL |
23 | ceph::bufferlist *ws_data, bool force_write) { |
24 | size_t data_len = data.length(); | |
25 | ||
26 | if (!force_write) { | |
27 | bool may_writesame = true; | |
28 | for (auto& q : object_extent.buffer_extents) { | |
29 | if (!(q.first % data_len == 0 && q.second % data_len == 0)) { | |
30 | may_writesame = false; | |
31 | break; | |
32 | } | |
33 | } | |
34 | ||
35 | if (may_writesame) { | |
36 | ws_data->append(data); | |
37 | return true; | |
38 | } | |
39 | } | |
40 | ||
41 | for (auto& q : object_extent.buffer_extents) { | |
42 | bufferlist sub_bl; | |
43 | uint64_t sub_off = q.first % data_len; | |
44 | uint64_t sub_len = data_len - sub_off; | |
45 | uint64_t extent_left = q.second; | |
46 | while (extent_left >= sub_len) { | |
47 | sub_bl.substr_of(data, sub_off, sub_len); | |
48 | ws_data->claim_append(sub_bl); | |
49 | extent_left -= sub_len; | |
50 | if (sub_off) { | |
51 | sub_off = 0; | |
52 | sub_len = data_len; | |
53 | } | |
54 | } | |
55 | if (extent_left) { | |
56 | sub_bl.substr_of(data, sub_off, extent_left); | |
57 | ws_data->claim_append(sub_bl); | |
58 | } | |
59 | } | |
60 | return false; | |
61 | } | |
62 | ||
f91f0fd5 TL |
63 | template <typename I> |
64 | void read_parent(I *image_ctx, uint64_t object_no, uint64_t off, | |
65 | uint64_t len, librados::snap_t snap_id, | |
66 | const ZTracer::Trace &trace, ceph::bufferlist* data, | |
67 | Context* on_finish) { | |
68 | ||
69 | auto cct = image_ctx->cct; | |
70 | ||
71 | std::shared_lock image_locker{image_ctx->image_lock}; | |
72 | ||
73 | // calculate reverse mapping onto the image | |
74 | Extents parent_extents; | |
75 | Striper::extent_to_file(cct, &image_ctx->layout, object_no, off, len, | |
76 | parent_extents); | |
77 | ||
78 | uint64_t parent_overlap = 0; | |
79 | uint64_t object_overlap = 0; | |
80 | int r = image_ctx->get_parent_overlap(snap_id, &parent_overlap); | |
81 | if (r == 0) { | |
82 | object_overlap = image_ctx->prune_parent_extents(parent_extents, | |
83 | parent_overlap); | |
84 | } | |
85 | ||
86 | if (object_overlap == 0) { | |
87 | image_locker.unlock(); | |
88 | ||
89 | on_finish->complete(-ENOENT); | |
90 | return; | |
91 | } | |
92 | ||
93 | ldout(cct, 20) << dendl; | |
94 | ||
95 | auto comp = AioCompletion::create_and_start(on_finish, image_ctx->parent, | |
96 | AIO_TYPE_READ); | |
97 | ldout(cct, 20) << "completion " << comp << ", extents " << parent_extents | |
98 | << dendl; | |
99 | ||
100 | ImageRequest<I>::aio_read(image_ctx->parent, comp, std::move(parent_extents), | |
101 | ReadResult{data}, 0, trace); | |
102 | } | |
103 | ||
11fdf7f2 TL |
104 | } // namespace util |
105 | } // namespace io | |
106 | } // namespace librbd | |
107 | ||
f91f0fd5 TL |
108 | template void librbd::io::util::read_parent( |
109 | librbd::ImageCtx *image_ctx, uint64_t object_no, uint64_t off, uint64_t len, | |
110 | librados::snap_t snap_id, const ZTracer::Trace &trace, | |
111 | ceph::bufferlist* data, Context* on_finish); |