]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/ObjectMap.h
import 15.2.5
[ceph.git] / ceph / src / librbd / ObjectMap.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_OBJECT_MAP_H
5 #define CEPH_LIBRBD_OBJECT_MAP_H
6
7 #include "include/int_types.h"
8 #include "include/fs_types.h"
9 #include "include/rados/librados_fwd.hpp"
10 #include "include/rbd/object_map_types.h"
11 #include "common/AsyncOpTracker.h"
12 #include "common/bit_vector.hpp"
13 #include "common/RWLock.h"
14 #include "common/RefCountedObj.h"
15 #include "librbd/Utils.h"
16 #include <boost/optional.hpp>
17
18 class Context;
19 namespace ZTracer { struct Trace; }
20
21 namespace librbd {
22
23 template <typename Op> class BlockGuard;
24 struct BlockGuardCell;
25 class ImageCtx;
26
27 template <typename ImageCtxT = ImageCtx>
28 class ObjectMap : public RefCountedObject {
29 public:
30 static ObjectMap *create(ImageCtxT &image_ctx, uint64_t snap_id) {
31 return new ObjectMap(image_ctx, snap_id);
32 }
33
34 ObjectMap(ImageCtxT &image_ctx, uint64_t snap_id);
35 ~ObjectMap();
36
37 static int aio_remove(librados::IoCtx &io_ctx, const std::string &image_id, librados::AioCompletion *c);
38 static std::string object_map_name(const std::string &image_id,
39 uint64_t snap_id);
40
41 static bool is_compatible(const file_layout_t& layout, uint64_t size);
42
43 uint8_t operator[](uint64_t object_no) const;
44 inline uint64_t size() const {
45 std::shared_lock locker{m_lock};
46 return m_object_map.size();
47 }
48
49 inline void set_state(uint64_t object_no, uint8_t new_state,
50 const boost::optional<uint8_t> &current_state) {
51 std::unique_lock locker{m_lock};
52 ceph_assert(object_no < m_object_map.size());
53 if (current_state && m_object_map[object_no] != *current_state) {
54 return;
55 }
56 m_object_map[object_no] = new_state;
57 }
58
59 void open(Context *on_finish);
60 void close(Context *on_finish);
61 bool set_object_map(ceph::BitVector<2> &target_object_map);
62 bool object_may_exist(uint64_t object_no) const;
63 bool object_may_not_exist(uint64_t object_no) const;
64
65 void aio_save(Context *on_finish);
66 void aio_resize(uint64_t new_size, uint8_t default_object_state,
67 Context *on_finish);
68
69 template <typename T, void(T::*MF)(int) = &T::complete>
70 bool aio_update(uint64_t snap_id, uint64_t start_object_no, uint8_t new_state,
71 const boost::optional<uint8_t> &current_state,
72 const ZTracer::Trace &parent_trace, bool ignore_enoent,
73 T *callback_object) {
74 return aio_update<T, MF>(snap_id, start_object_no, start_object_no + 1,
75 new_state, current_state, parent_trace,
76 ignore_enoent, callback_object);
77 }
78
79 template <typename T, void(T::*MF)(int) = &T::complete>
80 bool aio_update(uint64_t snap_id, uint64_t start_object_no,
81 uint64_t end_object_no, uint8_t new_state,
82 const boost::optional<uint8_t> &current_state,
83 const ZTracer::Trace &parent_trace, bool ignore_enoent,
84 T *callback_object) {
85 ceph_assert(start_object_no < end_object_no);
86 std::unique_lock locker{m_lock};
87
88 if (snap_id == CEPH_NOSNAP) {
89 end_object_no = std::min(end_object_no, m_object_map.size());
90 if (start_object_no >= end_object_no) {
91 return false;
92 }
93
94 auto it = m_object_map.begin() + start_object_no;
95 auto end_it = m_object_map.begin() + end_object_no;
96 for (; it != end_it; ++it) {
97 if (update_required(it, new_state)) {
98 break;
99 }
100 }
101
102 if (it == end_it) {
103 return false;
104 }
105
106 m_async_op_tracker.start_op();
107 UpdateOperation update_operation(start_object_no, end_object_no,
108 new_state, current_state, parent_trace,
109 ignore_enoent,
110 util::create_context_callback<T, MF>(
111 callback_object));
112 detained_aio_update(std::move(update_operation));
113 } else {
114 aio_update(snap_id, start_object_no, end_object_no, new_state,
115 current_state, parent_trace, ignore_enoent,
116 util::create_context_callback<T, MF>(callback_object));
117 }
118 return true;
119 }
120
121 void rollback(uint64_t snap_id, Context *on_finish);
122 void snapshot_add(uint64_t snap_id, Context *on_finish);
123 void snapshot_remove(uint64_t snap_id, Context *on_finish);
124
125 private:
126 struct UpdateOperation {
127 uint64_t start_object_no;
128 uint64_t end_object_no;
129 uint8_t new_state;
130 boost::optional<uint8_t> current_state;
131 ZTracer::Trace parent_trace;
132 bool ignore_enoent;
133 Context *on_finish;
134
135 UpdateOperation(uint64_t start_object_no, uint64_t end_object_no,
136 uint8_t new_state,
137 const boost::optional<uint8_t> &current_state,
138 const ZTracer::Trace &parent_trace,
139 bool ignore_enoent, Context *on_finish)
140 : start_object_no(start_object_no), end_object_no(end_object_no),
141 new_state(new_state), current_state(current_state),
142 parent_trace(parent_trace), ignore_enoent(ignore_enoent),
143 on_finish(on_finish) {
144 }
145 };
146
147 typedef BlockGuard<UpdateOperation> UpdateGuard;
148
149 ImageCtxT &m_image_ctx;
150 uint64_t m_snap_id;
151
152 mutable ceph::shared_mutex m_lock;
153 ceph::BitVector<2> m_object_map;
154
155 AsyncOpTracker m_async_op_tracker;
156 UpdateGuard *m_update_guard = nullptr;
157
158 void detained_aio_update(UpdateOperation &&update_operation);
159 void handle_detained_aio_update(BlockGuardCell *cell, int r,
160 Context *on_finish);
161
162 void aio_update(uint64_t snap_id, uint64_t start_object_no,
163 uint64_t end_object_no, uint8_t new_state,
164 const boost::optional<uint8_t> &current_state,
165 const ZTracer::Trace &parent_trace, bool ignore_enoent,
166 Context *on_finish);
167 bool update_required(const ceph::BitVector<2>::Iterator &it,
168 uint8_t new_state);
169
170 };
171
172 } // namespace librbd
173
174 extern template class librbd::ObjectMap<librbd::ImageCtx>;
175
176 #endif // CEPH_LIBRBD_OBJECT_MAP_H