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