// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab #ifndef CEPH_LIBRBD_OBJECT_MAP_H #define CEPH_LIBRBD_OBJECT_MAP_H #include "include/int_types.h" #include "include/fs_types.h" #include "include/rbd/object_map_types.h" #include "common/bit_vector.hpp" #include "librbd/Utils.h" #include class Context; class RWLock; namespace librados { class IoCtx; } namespace ZTracer { struct Trace; } namespace librbd { template class BlockGuard; struct BlockGuardCell; class ImageCtx; template class ObjectMap { public: static ObjectMap *create(ImageCtxT &image_ctx, uint64_t snap_id) { return new ObjectMap(image_ctx, snap_id); } ObjectMap(ImageCtxT &image_ctx, uint64_t snap_id); ~ObjectMap(); static int aio_remove(librados::IoCtx &io_ctx, const std::string &image_id, librados::AioCompletion *c); static std::string object_map_name(const std::string &image_id, uint64_t snap_id); static bool is_compatible(const file_layout_t& layout, uint64_t size); ceph::BitVector<2u>::Reference operator[](uint64_t object_no); uint8_t operator[](uint64_t object_no) const; inline uint64_t size() const { return m_object_map.size(); } void open(Context *on_finish); void close(Context *on_finish); bool object_may_exist(uint64_t object_no) const; void aio_save(Context *on_finish); void aio_resize(uint64_t new_size, uint8_t default_object_state, Context *on_finish); template bool aio_update(uint64_t snap_id, uint64_t start_object_no, uint8_t new_state, const boost::optional ¤t_state, const ZTracer::Trace &parent_trace, T *callback_object) { return aio_update(snap_id, start_object_no, start_object_no + 1, new_state, current_state, parent_trace, callback_object); } template bool aio_update(uint64_t snap_id, uint64_t start_object_no, uint64_t end_object_no, uint8_t new_state, const boost::optional ¤t_state, const ZTracer::Trace &parent_trace, T *callback_object) { assert(start_object_no < end_object_no); if (snap_id == CEPH_NOSNAP) { auto it = m_object_map.begin() + start_object_no; auto end_it = m_object_map.begin() + end_object_no; for (; it != end_it; ++it) { if (update_required(it, new_state)) { break; } } if (it == end_it) { return false; } UpdateOperation update_operation(start_object_no, end_object_no, new_state, current_state, parent_trace, util::create_context_callback( callback_object)); detained_aio_update(std::move(update_operation)); } else { aio_update(snap_id, start_object_no, end_object_no, new_state, current_state, parent_trace, util::create_context_callback(callback_object)); } return true; } void rollback(uint64_t snap_id, Context *on_finish); void snapshot_add(uint64_t snap_id, Context *on_finish); void snapshot_remove(uint64_t snap_id, Context *on_finish); private: struct UpdateOperation { uint64_t start_object_no; uint64_t end_object_no; uint8_t new_state; boost::optional current_state; ZTracer::Trace parent_trace; Context *on_finish; UpdateOperation(uint64_t start_object_no, uint64_t end_object_no, uint8_t new_state, const boost::optional ¤t_state, const ZTracer::Trace &parent_trace, Context *on_finish) : start_object_no(start_object_no), end_object_no(end_object_no), new_state(new_state), current_state(current_state), parent_trace(parent_trace), on_finish(on_finish) { } }; typedef BlockGuard UpdateGuard; ImageCtxT &m_image_ctx; ceph::BitVector<2> m_object_map; uint64_t m_snap_id; UpdateGuard *m_update_guard = nullptr; void detained_aio_update(UpdateOperation &&update_operation); void handle_detained_aio_update(BlockGuardCell *cell, int r, Context *on_finish); void aio_update(uint64_t snap_id, uint64_t start_object_no, uint64_t end_object_no, uint8_t new_state, const boost::optional ¤t_state, const ZTracer::Trace &parent_trace, Context *on_finish); bool update_required(const ceph::BitVector<2>::Iterator &it, uint8_t new_state); }; } // namespace librbd extern template class librbd::ObjectMap; #endif // CEPH_LIBRBD_OBJECT_MAP_H