]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/deep_copy/ObjectCopyRequest.h
5d57a8b32c222c7ef8018a875f6b782f0d13328c
[ceph.git] / ceph / src / librbd / deep_copy / ObjectCopyRequest.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #ifndef CEPH_LIBRBD_DEEP_COPY_OBJECT_COPY_REQUEST_H
5 #define CEPH_LIBRBD_DEEP_COPY_OBJECT_COPY_REQUEST_H
6
7 #include "include/int_types.h"
8 #include "include/interval_set.h"
9 #include "include/rados/librados.hpp"
10 #include "common/snap_types.h"
11 #include "librbd/ImageCtx.h"
12 #include "librbd/deep_copy/Types.h"
13 #include "librbd/io/Types.h"
14 #include <list>
15 #include <map>
16 #include <string>
17
18 class Context;
19 class RWLock;
20
21 namespace librbd {
22
23 namespace io { class AsyncOperation; }
24
25 namespace deep_copy {
26
27 struct Handler;
28
29 template <typename ImageCtxT = librbd::ImageCtx>
30 class ObjectCopyRequest {
31 public:
32 static ObjectCopyRequest* create(ImageCtxT *src_image_ctx,
33 ImageCtxT *dst_image_ctx,
34 librados::snap_t src_snap_id_start,
35 librados::snap_t dst_snap_id_start,
36 const SnapMap &snap_map,
37 uint64_t object_number, bool flatten,
38 Handler* handler, Context *on_finish) {
39 return new ObjectCopyRequest(src_image_ctx, dst_image_ctx,
40 src_snap_id_start, dst_snap_id_start, snap_map,
41 object_number, flatten, handler, on_finish);
42 }
43
44 ObjectCopyRequest(ImageCtxT *src_image_ctx, ImageCtxT *dst_image_ctx,
45 librados::snap_t src_snap_id_start,
46 librados::snap_t dst_snap_id_start, const SnapMap &snap_map,
47 uint64_t object_number, bool flatten, Handler* handler,
48 Context *on_finish);
49
50 void send();
51
52 // testing support
53 inline librados::IoCtx &get_src_io_ctx() {
54 return m_src_io_ctx;
55 }
56 inline librados::IoCtx &get_dst_io_ctx() {
57 return m_dst_io_ctx;
58 }
59
60 private:
61 /**
62 * @verbatim
63 *
64 * <start>
65 * | /----------------------\
66 * | | |
67 * v v | (repeat for each src object)
68 * LIST_SNAPS < * * * |
69 * | * (-ENOENT and snap set stale)
70 * | * * * * * * |
71 * | * /-----------\ |
72 * | * | | (repeat for each snapshot)
73 * v * v | |
74 * READ_OBJECT ---------/ |
75 * | | |
76 * | \----------------------/
77 * v
78 * READ_FROM_PARENT (skip if not needed)
79 * |
80 * | /-----------\
81 * | | | (repeat for each snapshot)
82 * v v |
83 * WRITE_OBJECT --------/
84 * |
85 * | /-----------\
86 * | | | (repeat for each snapshot)
87 * v v |
88 * UPDATE_OBJECT_MAP ---/ (skip if object
89 * | map disabled)
90 * v
91 * <finish>
92 *
93 * @endverbatim
94 */
95
96 struct SrcObjectExtent {
97 uint64_t object_no = 0;
98 uint64_t offset = 0;
99 uint64_t length = 0;
100 bool noent = false;
101
102 SrcObjectExtent() {
103 }
104 SrcObjectExtent(uint64_t object_no, uint64_t offset, uint64_t length)
105 : object_no(object_no), offset(offset), length(length) {
106 }
107 };
108
109 typedef std::map<uint64_t, SrcObjectExtent> SrcObjectExtents;
110
111 enum CopyOpType {
112 COPY_OP_TYPE_WRITE,
113 COPY_OP_TYPE_ZERO,
114 COPY_OP_TYPE_TRUNC,
115 COPY_OP_TYPE_REMOVE,
116 COPY_OP_TYPE_REMOVE_TRUNC,
117 };
118
119 typedef std::map<uint64_t, uint64_t> ExtentMap;
120
121 struct CopyOp {
122 CopyOp(CopyOpType type, uint64_t src_offset, uint64_t dst_offset,
123 uint64_t length)
124 : type(type), src_offset(src_offset), dst_offset(dst_offset),
125 length(length) {
126 }
127
128 CopyOpType type;
129 uint64_t src_offset;
130 uint64_t dst_offset;
131 uint64_t length;
132
133 ExtentMap src_extent_map;
134 ExtentMap dst_extent_map;
135 bufferlist out_bl;
136 };
137
138 typedef std::list<CopyOp> CopyOps;
139 typedef std::pair<librados::snap_t, librados::snap_t> WriteReadSnapIds;
140 typedef std::map<librados::snap_t, uint8_t> SnapObjectStates;
141 typedef std::map<librados::snap_t, std::map<uint64_t, uint64_t>> SnapObjectSizes;
142
143 ImageCtxT *m_src_image_ctx;
144 ImageCtxT *m_dst_image_ctx;
145 CephContext *m_cct;
146 librados::snap_t m_src_snap_id_start;
147 librados::snap_t m_dst_snap_id_start;
148 SnapMap m_snap_map;
149 uint64_t m_dst_object_number;
150 bool m_flatten;
151 Handler* m_handler;
152 Context *m_on_finish;
153
154 decltype(m_src_image_ctx->data_ctx) m_src_io_ctx;
155 decltype(m_dst_image_ctx->data_ctx) m_dst_io_ctx;
156 std::string m_dst_oid;
157
158 std::set<uint64_t> m_src_objects;
159 uint64_t m_src_ono;
160 std::string m_src_oid;
161 SrcObjectExtents m_src_object_extents;
162 librados::snap_set_t m_snap_set;
163 int m_snap_ret = 0;
164 bool m_retry_missing_read = false;
165 librados::snap_set_t m_retry_snap_set;
166 bool m_read_whole_object = false;
167
168 std::map<WriteReadSnapIds, CopyOps> m_read_ops;
169 std::list<WriteReadSnapIds> m_read_snaps;
170 std::map<librados::snap_t, CopyOps> m_write_ops;
171 std::map<librados::snap_t, interval_set<uint64_t>> m_zero_interval;
172 std::map<librados::snap_t, interval_set<uint64_t>> m_dst_zero_interval;
173 std::map<librados::snap_t, uint8_t> m_dst_object_state;
174 std::map<librados::snap_t, bool> m_dst_object_may_exist;
175 bufferlist m_read_from_parent_data;
176
177 io::AsyncOperation* m_src_async_op = nullptr;
178
179 void send_list_snaps();
180 void handle_list_snaps(int r);
181
182 void send_read_object();
183 void handle_read_object(int r);
184
185 void send_read_from_parent();
186 void handle_read_from_parent(int r);
187
188 void send_write_object();
189 void handle_write_object(int r);
190
191 void send_update_object_map();
192 void handle_update_object_map(int r);
193
194 Context *start_lock_op(ceph::shared_mutex &owner_lock, int* r);
195
196 uint64_t src_to_dst_object_offset(uint64_t objectno, uint64_t offset);
197
198 void compute_src_object_extents();
199 void compute_read_ops();
200 void compute_read_from_parent_ops(io::Extents *image_extents);
201 void merge_write_ops();
202 void compute_zero_ops();
203
204 void compute_dst_object_may_exist();
205
206 void finish(int r);
207 };
208
209 } // namespace deep_copy
210 } // namespace librbd
211
212 extern template class librbd::deep_copy::ObjectCopyRequest<librbd::ImageCtx>;
213
214 #endif // CEPH_LIBRBD_DEEP_COPY_OBJECT_COPY_REQUEST_H