]>
git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/cache/pwl/ImageCacheState.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "librbd/cache/Types.h"
5 #include "librbd/cache/Utils.h"
6 #include "librbd/cache/pwl/ImageCacheState.h"
7 #include "librbd/ImageCtx.h"
8 #include "librbd/Operations.h"
9 #include "common/config_proxy.h"
10 #include "common/environment.h"
11 #include "common/hostname.h"
12 #include "librbd/plugin/Api.h"
15 #define dout_subsys ceph_subsys_rbd_pwl
17 #define dout_prefix *_dout << "librbd::cache::pwl::ImageCacheState: " \
27 void ImageCacheState
<I
>::init_from_config() {
28 ldout(m_image_ctx
->cct
, 20) << dendl
;
35 ConfigProxy
&config
= m_image_ctx
->config
;
36 mode
= config
.get_val
<std::string
>("rbd_persistent_cache_mode");
41 bool ImageCacheState
<I
>::init_from_metadata(json_spirit::mValue
& json_root
) {
42 ldout(m_image_ctx
->cct
, 20) << dendl
;
45 auto& o
= json_root
.get_obj();
46 present
= o
["present"].get_bool();
47 empty
= o
["empty"].get_bool();
48 clean
= o
["clean"].get_bool();
49 host
= o
["host"].get_str();
50 path
= o
["path"].get_str();
51 mode
= o
["mode"].get_str();
52 size
= o
["size"].get_uint64();
53 } catch (std::runtime_error
& e
) {
54 lderr(m_image_ctx
->cct
) << "failed to parse cache state: " << e
.what()
63 void ImageCacheState
<I
>::write_image_cache_state(std::unique_lock
<ceph::mutex
>& locker
,
65 ceph_assert(ceph_mutex_is_locked_by_me(*locker
.mutex()));
66 stats_timestamp
= ceph_clock_now();
67 json_spirit::mObject o
;
68 o
["present"] = present
;
75 o
["stats_timestamp"] = stats_timestamp
.sec();
76 o
["allocated_bytes"] = allocated_bytes
;
77 o
["cached_bytes"] = cached_bytes
;
78 o
["dirty_bytes"] = dirty_bytes
;
79 o
["free_bytes"] = free_bytes
;
80 o
["hits_full"] = hits_full
;
81 o
["hits_partial"] = hits_partial
;
83 o
["hit_bytes"] = hit_bytes
;
84 o
["miss_bytes"] = miss_bytes
;
85 std::string image_state_json
= json_spirit::write(o
);
88 std::shared_lock owner_lock
{m_image_ctx
->owner_lock
};
89 ldout(m_image_ctx
->cct
, 20) << __func__
<< " Store state: "
90 << image_state_json
<< dendl
;
91 m_plugin_api
.execute_image_metadata_set(m_image_ctx
, PERSISTENT_CACHE_STATE
,
92 image_state_json
, on_finish
);
96 void ImageCacheState
<I
>::clear_image_cache_state(Context
*on_finish
) {
97 std::shared_lock owner_lock
{m_image_ctx
->owner_lock
};
98 ldout(m_image_ctx
->cct
, 20) << __func__
<< " Remove state: " << dendl
;
99 m_plugin_api
.execute_image_metadata_remove(
100 m_image_ctx
, PERSISTENT_CACHE_STATE
, on_finish
);
103 template <typename I
>
104 ImageCacheState
<I
>* ImageCacheState
<I
>::create_image_cache_state(
105 I
* image_ctx
, plugin::Api
<I
>& plugin_api
, int &r
) {
106 std::string cache_state_str
;
107 ImageCacheState
<I
>* cache_state
= nullptr;
110 bool dirty_cache
= plugin_api
.test_image_features(image_ctx
, RBD_FEATURE_DIRTY_CACHE
);
112 cls_client::metadata_get(&image_ctx
->md_ctx
, image_ctx
->header_oid
,
113 PERSISTENT_CACHE_STATE
, &cache_state_str
);
116 ldout(image_ctx
->cct
, 20) << "image_cache_state: " << cache_state_str
<< dendl
;
118 bool pwl_enabled
= cache::util::is_pwl_enabled(*image_ctx
);
119 bool cache_desired
= pwl_enabled
;
120 cache_desired
&= !image_ctx
->read_only
;
121 cache_desired
&= !plugin_api
.test_image_features(image_ctx
, RBD_FEATURE_MIGRATING
);
122 cache_desired
&= !plugin_api
.test_image_features(image_ctx
, RBD_FEATURE_JOURNALING
);
123 cache_desired
&= !image_ctx
->old_format
;
125 if (!dirty_cache
&& !cache_desired
) {
126 ldout(image_ctx
->cct
, 20) << "Do not desire to use image cache." << dendl
;
127 } else if (dirty_cache
&& !cache_desired
) {
128 lderr(image_ctx
->cct
) << "There's a dirty cache, but RWL cache is disabled."
131 }else if ((!dirty_cache
|| cache_state_str
.empty()) && cache_desired
) {
132 cache_state
= new ImageCacheState
<I
>(image_ctx
, plugin_api
);
133 cache_state
->init_from_config();
135 ceph_assert(!cache_state_str
.empty());
136 json_spirit::mValue json_root
;
137 if (!json_spirit::read(cache_state_str
.c_str(), json_root
)) {
138 lderr(image_ctx
->cct
) << "failed to parse cache state" << dendl
;
142 cache_state
= new ImageCacheState
<I
>(image_ctx
, plugin_api
);
143 if (!cache_state
->init_from_metadata(json_root
)) {
148 if (!cache_state
->present
) {
149 cache_state
->init_from_config();
155 template <typename I
>
156 ImageCacheState
<I
>* ImageCacheState
<I
>::get_image_cache_state(
157 I
* image_ctx
, plugin::Api
<I
>& plugin_api
) {
158 ImageCacheState
<I
>* cache_state
= nullptr;
159 string cache_state_str
;
160 cls_client::metadata_get(&image_ctx
->md_ctx
, image_ctx
->header_oid
,
161 PERSISTENT_CACHE_STATE
, &cache_state_str
);
162 if (!cache_state_str
.empty()) {
163 // ignore errors, best effort
164 cache_state
= new ImageCacheState
<I
>(image_ctx
, plugin_api
);
165 json_spirit::mValue json_root
;
166 if (!json_spirit::read(cache_state_str
.c_str(), json_root
)) {
167 lderr(image_ctx
->cct
) << "failed to parse cache state" << dendl
;
169 cache_state
->init_from_metadata(json_root
);
175 template <typename I
>
176 bool ImageCacheState
<I
>::is_valid() {
178 (host
.compare(ceph_get_short_hostname()) != 0)) {
179 auto cleanstring
= "dirty";
181 cleanstring
= "clean";
183 lderr(m_image_ctx
->cct
) << "An image cache (RWL) remains on another host "
184 << host
<< " which is " << cleanstring
185 << ". Flush/close the image there to remove the "
186 << "image cache" << dendl
;
194 } // namespace librbd
196 template class librbd::cache::pwl::ImageCacheState
<librbd::ImageCtx
>;