1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #ifndef CEPH_LIBRBD_OBJECT_MAP_H
5 #define CEPH_LIBRBD_OBJECT_MAP_H
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>
19 namespace ZTracer
{ struct Trace
; }
23 template <typename Op
> class BlockGuard
;
24 struct BlockGuardCell
;
27 template <typename ImageCtxT
= ImageCtx
>
28 class ObjectMap
: public RefCountedObject
{
30 static ObjectMap
*create(ImageCtxT
&image_ctx
, uint64_t snap_id
) {
31 return new ObjectMap(image_ctx
, snap_id
);
34 ObjectMap(ImageCtxT
&image_ctx
, uint64_t snap_id
);
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
,
41 static bool is_compatible(const file_layout_t
& layout
, uint64_t size
);
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();
49 inline void set_state(uint64_t object_no
, uint8_t new_state
,
50 const boost::optional
<uint8_t> ¤t_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
) {
56 m_object_map
[object_no
] = new_state
;
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;
65 void aio_save(Context
*on_finish
);
66 void aio_resize(uint64_t new_size
, uint8_t default_object_state
,
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> ¤t_state
,
72 const ZTracer::Trace
&parent_trace
, bool ignore_enoent
,
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
);
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> ¤t_state
,
83 const ZTracer::Trace
&parent_trace
, bool ignore_enoent
,
85 ceph_assert(start_object_no
< end_object_no
);
86 std::unique_lock locker
{m_lock
};
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
) {
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
)) {
106 m_async_op_tracker
.start_op();
107 UpdateOperation
update_operation(start_object_no
, end_object_no
,
108 new_state
, current_state
, parent_trace
,
110 util::create_context_callback
<T
, MF
>(
112 detained_aio_update(std::move(update_operation
));
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
));
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
);
126 struct UpdateOperation
{
127 uint64_t start_object_no
;
128 uint64_t end_object_no
;
130 boost::optional
<uint8_t> current_state
;
131 ZTracer::Trace parent_trace
;
135 UpdateOperation(uint64_t start_object_no
, uint64_t end_object_no
,
137 const boost::optional
<uint8_t> ¤t_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
) {
147 typedef BlockGuard
<UpdateOperation
> UpdateGuard
;
149 ImageCtxT
&m_image_ctx
;
152 mutable ceph::shared_mutex m_lock
;
153 ceph::BitVector
<2> m_object_map
;
155 AsyncOpTracker m_async_op_tracker
;
156 UpdateGuard
*m_update_guard
= nullptr;
158 void detained_aio_update(UpdateOperation
&&update_operation
);
159 void handle_detained_aio_update(BlockGuardCell
*cell
, int r
,
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> ¤t_state
,
165 const ZTracer::Trace
&parent_trace
, bool ignore_enoent
,
167 bool update_required(const ceph::BitVector
<2>::Iterator
&it
,
172 } // namespace librbd
174 extern template class librbd::ObjectMap
<librbd::ImageCtx
>;
176 #endif // CEPH_LIBRBD_OBJECT_MAP_H