]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/Features.cc
import 15.2.0 Octopus source
[ceph.git] / ceph / src / librbd / Features.cc
CommitLineData
11fdf7f2
TL
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#include <boost/lexical_cast.hpp>
5#include <boost/algorithm/string.hpp>
6
7#include "librbd/Features.h"
8#include "include/rbd/features.h"
9
10#include <map>
11#include <vector>
12
13static const std::map<std::string, uint64_t> RBD_FEATURE_MAP = {
14 {RBD_FEATURE_NAME_LAYERING, RBD_FEATURE_LAYERING},
15 {RBD_FEATURE_NAME_STRIPINGV2, RBD_FEATURE_STRIPINGV2},
16 {RBD_FEATURE_NAME_EXCLUSIVE_LOCK, RBD_FEATURE_EXCLUSIVE_LOCK},
17 {RBD_FEATURE_NAME_OBJECT_MAP, RBD_FEATURE_OBJECT_MAP},
18 {RBD_FEATURE_NAME_FAST_DIFF, RBD_FEATURE_FAST_DIFF},
19 {RBD_FEATURE_NAME_DEEP_FLATTEN, RBD_FEATURE_DEEP_FLATTEN},
20 {RBD_FEATURE_NAME_JOURNALING, RBD_FEATURE_JOURNALING},
21 {RBD_FEATURE_NAME_DATA_POOL, RBD_FEATURE_DATA_POOL},
22 {RBD_FEATURE_NAME_OPERATIONS, RBD_FEATURE_OPERATIONS},
23 {RBD_FEATURE_NAME_MIGRATING, RBD_FEATURE_MIGRATING},
9f95a23c 24 {RBD_FEATURE_NAME_NON_PRIMARY, RBD_FEATURE_NON_PRIMARY},
11fdf7f2 25};
9f95a23c 26static_assert((RBD_FEATURE_NON_PRIMARY << 1) > RBD_FEATURES_ALL,
11fdf7f2
TL
27 "new RBD feature added");
28
29
30namespace librbd {
31
32std::string rbd_features_to_string(uint64_t features,
33 std::ostream *err)
34{
35 std::string r;
36 for (auto& i : RBD_FEATURE_MAP) {
37 if (features & i.second) {
9f95a23c
TL
38 if (!r.empty()) {
39 r += ",";
11fdf7f2
TL
40 }
41 r += i.first;
42 features &= ~i.second;
43 }
44 }
45 if (err && features) {
46 *err << "ignoring unknown feature mask 0x"
47 << std::hex << features << std::dec;
48 }
49 return r;
50}
51
52uint64_t rbd_features_from_string(const std::string& orig_value,
53 std::ostream *err)
54{
55 uint64_t features = 0;
56 std::string value = orig_value;
57 boost::trim(value);
58
59 // empty string means default features
60 if (!value.size()) {
61 return RBD_FEATURES_DEFAULT;
62 }
63
64 try {
65 // numeric?
66 features = boost::lexical_cast<uint64_t>(value);
67
68 // drop unrecognized bits
69 uint64_t unsupported_features = (features & ~RBD_FEATURES_ALL);
70 if (unsupported_features != 0ull) {
71 features &= RBD_FEATURES_ALL;
72 if (err) {
73 *err << "ignoring unknown feature mask 0x"
74 << std::hex << unsupported_features << std::dec;
75 }
76 }
9f95a23c
TL
77
78 uint64_t ignore_features_mask = (
79 RBD_FEATURES_INTERNAL | RBD_FEATURES_MUTABLE_INTERNAL);
80 uint64_t ignored_features = (features & ignore_features_mask);
81 if (ignored_features != 0ULL) {
82 features &= ~ignore_features_mask;
11fdf7f2 83 if (err) {
9f95a23c 84 *err << "ignoring feature mask 0x" << std::hex << ignored_features;
11fdf7f2
TL
85 }
86 }
87 } catch (boost::bad_lexical_cast&) {
88 // feature name list?
89 bool errors = false;
90 std::vector<std::string> feature_names;
91 boost::split(feature_names, value, boost::is_any_of(","));
92 for (auto feature_name: feature_names) {
93 boost::trim(feature_name);
94 auto feature_it = RBD_FEATURE_MAP.find(feature_name);
95 if (feature_it != RBD_FEATURE_MAP.end()) {
96 features += feature_it->second;
97 } else if (err) {
98 if (errors) {
99 *err << ", ";
100 } else {
101 errors = true;
102 }
103 *err << "ignoring unknown feature " << feature_name;
104 }
105 }
106 }
107 return features;
108}
109
110} // namespace librbd