]>
git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/cache/pwl/ImageCacheState.cc
2c6117d9e2ff3bd8ec73725e866555b09b264458
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/ceph_json.h"
11 #include "common/environment.h"
12 #include "common/hostname.h"
13 #include "librbd/plugin/Api.h"
16 #define dout_subsys ceph_subsys_rbd_pwl
18 #define dout_prefix *_dout << "librbd::cache::pwl::ImageCacheState: " \
26 bool get_json_format(const std::string
& s
, JSONFormattable
*f
) {
28 bool success
= p
.parse(s
.c_str(), s
.size());
30 decode_json_obj(*f
, &p
);
37 ImageCacheState
<I
>::ImageCacheState(I
*image_ctx
, plugin::Api
<I
>& plugin_api
) :
38 m_image_ctx(image_ctx
), m_plugin_api(plugin_api
) {
39 ldout(image_ctx
->cct
, 20) << "Initialize RWL cache state with config data. "
42 ConfigProxy
&config
= image_ctx
->config
;
43 log_periodic_stats
= config
.get_val
<bool>("rbd_persistent_cache_log_periodic_stats");
44 cache_type
= config
.get_val
<std::string
>("rbd_persistent_cache_mode");
48 ImageCacheState
<I
>::ImageCacheState(
49 I
*image_ctx
, JSONFormattable
&f
, plugin::Api
<I
>& plugin_api
) :
50 m_image_ctx(image_ctx
), m_plugin_api(plugin_api
) {
51 ldout(image_ctx
->cct
, 20) << "Initialize RWL cache state with data from "
52 << "server side"<< dendl
;
54 present
= (bool)f
["present"];
55 empty
= (bool)f
["empty"];
56 clean
= (bool)f
["clean"];
57 host
= (string
)f
["pwl_host"];
58 path
= (string
)f
["pwl_path"];
60 std::istringstream
iss(f
["pwl_size"]);
65 ConfigProxy
&config
= image_ctx
->config
;
66 log_periodic_stats
= config
.get_val
<bool>("rbd_persistent_cache_log_periodic_stats");
70 void ImageCacheState
<I
>::write_image_cache_state(Context
*on_finish
) {
71 std::shared_lock owner_lock
{m_image_ctx
->owner_lock
};
73 ::encode_json(IMAGE_CACHE_STATE
.c_str(), *this, &f
);
74 std::ostringstream oss
;
76 std::string image_state_json
= oss
.str();
78 ldout(m_image_ctx
->cct
, 20) << __func__
<< " Store state: "
79 << image_state_json
<< dendl
;
80 m_plugin_api
.execute_image_metadata_set(m_image_ctx
, IMAGE_CACHE_STATE
,
81 image_state_json
, on_finish
);
85 void ImageCacheState
<I
>::clear_image_cache_state(Context
*on_finish
) {
86 std::shared_lock owner_lock
{m_image_ctx
->owner_lock
};
87 ldout(m_image_ctx
->cct
, 20) << __func__
<< " Remove state: " << dendl
;
88 m_plugin_api
.execute_image_metadata_remove(
89 m_image_ctx
, IMAGE_CACHE_STATE
, on_finish
);
93 void ImageCacheState
<I
>::dump(ceph::Formatter
*f
) const {
94 ::encode_json("present", present
, f
);
95 ::encode_json("empty", empty
, f
);
96 ::encode_json("clean", clean
, f
);
97 ::encode_json("cache_type", cache_type
, f
);
98 ::encode_json("pwl_host", host
, f
);
99 ::encode_json("pwl_path", path
, f
);
100 ::encode_json("pwl_size", size
, f
);
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;
108 ldout(image_ctx
->cct
, 20) << "image_cache_state:" << cache_state_str
<< dendl
;
111 bool dirty_cache
= plugin_api
.test_image_features(image_ctx
, RBD_FEATURE_DIRTY_CACHE
);
113 cls_client::metadata_get(&image_ctx
->md_ctx
, image_ctx
->header_oid
,
114 IMAGE_CACHE_STATE
, &cache_state_str
);
117 bool pwl_enabled
= cache::util::is_pwl_enabled(*image_ctx
);
118 bool cache_desired
= pwl_enabled
;
119 cache_desired
&= !image_ctx
->read_only
;
120 cache_desired
&= !plugin_api
.test_image_features(image_ctx
, RBD_FEATURE_MIGRATING
);
121 cache_desired
&= !plugin_api
.test_image_features(image_ctx
, RBD_FEATURE_JOURNALING
);
122 cache_desired
&= !image_ctx
->old_format
;
124 if (!dirty_cache
&& !cache_desired
) {
125 ldout(image_ctx
->cct
, 20) << "Do not desire to use image cache." << dendl
;
126 } else if (dirty_cache
&& !cache_desired
) {
127 lderr(image_ctx
->cct
) << "There's a dirty cache, but RWL cache is disabled."
130 }else if ((!dirty_cache
|| cache_state_str
.empty()) && cache_desired
) {
131 cache_state
= new ImageCacheState
<I
>(image_ctx
, plugin_api
);
133 ceph_assert(!cache_state_str
.empty());
135 bool success
= get_json_format(cache_state_str
, &f
);
137 lderr(image_ctx
->cct
) << "Failed to parse cache state: "
138 << cache_state_str
<< dendl
;
143 bool cache_exists
= (bool)f
["present"];
144 int cache_type
= (int)f
["cache_type"];
146 switch (cache_type
) {
147 case IMAGE_CACHE_TYPE_SSD
:
148 case IMAGE_CACHE_TYPE_RWL
:
150 cache_state
= new ImageCacheState
<I
>(image_ctx
, plugin_api
);
152 cache_state
= new ImageCacheState
<I
>(image_ctx
, f
, plugin_api
);
162 template <typename I
>
163 ImageCacheState
<I
>* ImageCacheState
<I
>::get_image_cache_state(
164 I
* image_ctx
, plugin::Api
<I
>& plugin_api
) {
165 ImageCacheState
<I
>* cache_state
= nullptr;
166 string cache_state_str
;
167 cls_client::metadata_get(&image_ctx
->md_ctx
, image_ctx
->header_oid
,
168 IMAGE_CACHE_STATE
, &cache_state_str
);
169 if (!cache_state_str
.empty()) {
171 bool success
= get_json_format(cache_state_str
, &f
);
173 cache_state
= new ImageCacheState
<I
>(image_ctx
, plugin_api
);
175 cache_state
= new ImageCacheState
<I
>(image_ctx
, f
, plugin_api
);
181 template <typename I
>
182 bool ImageCacheState
<I
>::is_valid() {
184 (host
.compare(ceph_get_short_hostname()) != 0)) {
185 auto cleanstring
= "dirty";
187 cleanstring
= "clean";
189 lderr(m_image_ctx
->cct
) << "An image cache (RWL) remains on another host "
190 << host
<< " which is " << cleanstring
191 << ". Flush/close the image there to remove the "
192 << "image cache" << dendl
;
200 } // namespace librbd
202 template class librbd::cache::pwl::ImageCacheState
<librbd::ImageCtx
>;