Added
Link Here
|
1 |
diff --git src/librbd/api/Trash.cc src/librbd/api/Trash.cc |
2 |
index 52f79632d5..3d539ab1e2 100644 |
3 |
--- src/librbd/api/Trash.cc |
4 |
+++ src/librbd/api/Trash.cc |
5 |
@@ -24,7 +24,6 @@ |
6 |
#include <json_spirit/json_spirit.h> |
7 |
#include "librbd/journal/DisabledPolicy.h" |
8 |
#include "librbd/image/ListWatchersRequest.h" |
9 |
-#include <experimental/map> |
10 |
|
11 |
#define dout_subsys ceph_subsys_rbd |
12 |
#undef dout_prefix |
13 |
@@ -124,48 +123,6 @@ int enable_mirroring(IoCtx &io_ctx, const std::string &image_id) { |
14 |
return 0; |
15 |
} |
16 |
|
17 |
-int list_trash_image_specs( |
18 |
- librados::IoCtx &io_ctx, |
19 |
- std::map<std::string, cls::rbd::TrashImageSpec>* trash_image_specs, |
20 |
- bool exclude_user_remove_source) { |
21 |
- CephContext *cct((CephContext *)io_ctx.cct()); |
22 |
- ldout(cct, 20) << "list_trash_image_specs " << &io_ctx << dendl; |
23 |
- |
24 |
- bool more_entries; |
25 |
- uint32_t max_read = 1024; |
26 |
- std::string last_read; |
27 |
- do { |
28 |
- std::map<string, cls::rbd::TrashImageSpec> trash_entries; |
29 |
- int r = cls_client::trash_list(&io_ctx, last_read, max_read, |
30 |
- &trash_entries); |
31 |
- if (r < 0 && r != -ENOENT) { |
32 |
- lderr(cct) << "error listing rbd trash entries: " << cpp_strerror(r) |
33 |
- << dendl; |
34 |
- return r; |
35 |
- } else if (r == -ENOENT) { |
36 |
- break; |
37 |
- } |
38 |
- |
39 |
- if (trash_entries.empty()) { |
40 |
- break; |
41 |
- } |
42 |
- |
43 |
- for (const auto &entry : trash_entries) { |
44 |
- if (exclude_user_remove_source && |
45 |
- entry.second.source == cls::rbd::TRASH_IMAGE_SOURCE_REMOVING) { |
46 |
- continue; |
47 |
- } |
48 |
- |
49 |
- trash_image_specs->insert({entry.first, entry.second}); |
50 |
- } |
51 |
- |
52 |
- last_read = trash_entries.rbegin()->first; |
53 |
- more_entries = (trash_entries.size() >= max_read); |
54 |
- } while (more_entries); |
55 |
- |
56 |
- return 0; |
57 |
-} |
58 |
- |
59 |
} // anonymous namespace |
60 |
|
61 |
template <typename I> |
62 |
@@ -281,37 +238,15 @@ int Trash<I>::move(librados::IoCtx &io_ctx, rbd_trash_image_source_t source, |
63 |
return -EOPNOTSUPP; |
64 |
} |
65 |
|
66 |
- // search for an interrupted trash move request |
67 |
- std::map<std::string, cls::rbd::TrashImageSpec> trash_image_specs; |
68 |
- int r = list_trash_image_specs(io_ctx, &trash_image_specs, true); |
69 |
- if (r < 0) { |
70 |
- return r; |
71 |
- } |
72 |
- |
73 |
- std::experimental::erase_if( |
74 |
- trash_image_specs, [image_name](const auto& pair) { |
75 |
- const auto& spec = pair.second; |
76 |
- return (spec.source != cls::rbd::TRASH_IMAGE_SOURCE_USER || |
77 |
- spec.state != cls::rbd::TRASH_IMAGE_STATE_MOVING || |
78 |
- spec.name != image_name); |
79 |
- }); |
80 |
- if (trash_image_specs.empty()) { |
81 |
- return -ENOENT; |
82 |
- } |
83 |
- |
84 |
- image_id = trash_image_specs.begin()->first; |
85 |
- ldout(cct, 15) << "derived image id " << image_id << " from existing " |
86 |
- << "trash entry" << dendl; |
87 |
+ // image doesn't exist -- perhaps already in the trash since removing |
88 |
+ // from the directory is the last step |
89 |
+ return -ENOENT; |
90 |
} else if (r < 0) { |
91 |
lderr(cct) << "failed to retrieve image id: " << cpp_strerror(r) << dendl; |
92 |
return r; |
93 |
} |
94 |
|
95 |
- if (image_name.empty() || image_id.empty()) { |
96 |
- lderr(cct) << "invalid image name/id" << dendl; |
97 |
- return -EINVAL; |
98 |
- } |
99 |
- |
100 |
+ ceph_assert(!image_name.empty() && !image_id.empty()); |
101 |
return Trash<I>::move(io_ctx, source, image_name, image_id, delay); |
102 |
} |
103 |
|
104 |
@@ -342,23 +277,41 @@ template <typename I> |
105 |
int Trash<I>::list(IoCtx &io_ctx, vector<trash_image_info_t> &entries, |
106 |
bool exclude_user_remove_source) { |
107 |
CephContext *cct((CephContext *)io_ctx.cct()); |
108 |
- ldout(cct, 20) << __func__ << " " << &io_ctx << dendl; |
109 |
+ ldout(cct, 20) << "trash_list " << &io_ctx << dendl; |
110 |
|
111 |
- std::map<std::string, cls::rbd::TrashImageSpec> trash_image_specs; |
112 |
- int r = list_trash_image_specs(io_ctx, &trash_image_specs, |
113 |
- exclude_user_remove_source); |
114 |
- if (r < 0) { |
115 |
- return r; |
116 |
- } |
117 |
+ bool more_entries; |
118 |
+ uint32_t max_read = 1024; |
119 |
+ std::string last_read = ""; |
120 |
+ do { |
121 |
+ map<string, cls::rbd::TrashImageSpec> trash_entries; |
122 |
+ int r = cls_client::trash_list(&io_ctx, last_read, max_read, |
123 |
+ &trash_entries); |
124 |
+ if (r < 0 && r != -ENOENT) { |
125 |
+ lderr(cct) << "error listing rbd trash entries: " << cpp_strerror(r) |
126 |
+ << dendl; |
127 |
+ return r; |
128 |
+ } else if (r == -ENOENT) { |
129 |
+ break; |
130 |
+ } |
131 |
|
132 |
- entries.reserve(trash_image_specs.size()); |
133 |
- for (const auto& [image_id, spec] : trash_image_specs) { |
134 |
- rbd_trash_image_source_t source = |
135 |
- static_cast<rbd_trash_image_source_t>(spec.source); |
136 |
- entries.push_back({image_id, spec.name, source, |
137 |
- spec.deletion_time.sec(), |
138 |
- spec.deferment_end_time.sec()}); |
139 |
- } |
140 |
+ if (trash_entries.empty()) { |
141 |
+ break; |
142 |
+ } |
143 |
+ |
144 |
+ for (const auto &entry : trash_entries) { |
145 |
+ rbd_trash_image_source_t source = |
146 |
+ static_cast<rbd_trash_image_source_t>(entry.second.source); |
147 |
+ if (exclude_user_remove_source && |
148 |
+ source == RBD_TRASH_IMAGE_SOURCE_REMOVING) { |
149 |
+ continue; |
150 |
+ } |
151 |
+ entries.push_back({entry.first, entry.second.name, source, |
152 |
+ entry.second.deletion_time.sec(), |
153 |
+ entry.second.deferment_end_time.sec()}); |
154 |
+ } |
155 |
+ last_read = trash_entries.rbegin()->first; |
156 |
+ more_entries = (trash_entries.size() >= max_read); |
157 |
+ } while (more_entries); |
158 |
|
159 |
return 0; |
160 |
} |
161 |
@@ -587,12 +540,8 @@ int Trash<I>::remove(IoCtx &io_ctx, const std::string &image_id, bool force, |
162 |
lderr(cct) << "error: deferment time has not expired." << dendl; |
163 |
return -EPERM; |
164 |
} |
165 |
- if (trash_spec.state == cls::rbd::TRASH_IMAGE_STATE_MOVING) { |
166 |
- lderr(cct) << "error: image is pending moving to the trash." |
167 |
- << dendl; |
168 |
- return -EUCLEAN; |
169 |
- } else if (trash_spec.state != cls::rbd::TRASH_IMAGE_STATE_NORMAL && |
170 |
- trash_spec.state != cls::rbd::TRASH_IMAGE_STATE_REMOVING) { |
171 |
+ if (trash_spec.state != cls::rbd::TRASH_IMAGE_STATE_NORMAL && |
172 |
+ trash_spec.state != cls::rbd::TRASH_IMAGE_STATE_REMOVING) { |
173 |
lderr(cct) << "error: image is pending restoration." << dendl; |
174 |
return -EBUSY; |
175 |
} |
176 |
@@ -750,3 +699,4 @@ int Trash<I>::restore(librados::IoCtx &io_ctx, |
177 |
} // namespace librbd |
178 |
|
179 |
template class librbd::api::Trash<librbd::ImageCtx>; |
180 |
+ |