]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net> | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License version 2.1, as published by the Free Software | |
11 | * Foundation. See file COPYING. | |
12 | * | |
13 | */ | |
14 | ||
15 | #include "Capability.h" | |
11fdf7f2 | 16 | #include "CInode.h" |
a8e16298 | 17 | #include "SessionMap.h" |
7c673cae FG |
18 | |
19 | #include "common/Formatter.h" | |
20 | ||
aee94f69 TL |
21 | #define dout_context g_ceph_context |
22 | #define dout_subsys ceph_subsys_mds | |
23 | #undef dout_prefix | |
24 | #define dout_prefix *_dout << "Capability " | |
25 | ||
7c673cae FG |
26 | |
27 | /* | |
28 | * Capability::Export | |
29 | */ | |
30 | ||
f67539c2 | 31 | void Capability::Export::encode(ceph::buffer::list &bl) const |
7c673cae | 32 | { |
11fdf7f2 TL |
33 | ENCODE_START(3, 2, bl); |
34 | encode(cap_id, bl); | |
35 | encode(wanted, bl); | |
36 | encode(issued, bl); | |
37 | encode(pending, bl); | |
38 | encode(client_follows, bl); | |
39 | encode(seq, bl); | |
40 | encode(mseq, bl); | |
41 | encode(last_issue_stamp, bl); | |
42 | encode(state, bl); | |
7c673cae FG |
43 | ENCODE_FINISH(bl); |
44 | } | |
45 | ||
f67539c2 | 46 | void Capability::Export::decode(ceph::buffer::list::const_iterator &p) |
7c673cae | 47 | { |
11fdf7f2 TL |
48 | DECODE_START_LEGACY_COMPAT_LEN(3, 2, 2, p); |
49 | decode(cap_id, p); | |
50 | decode(wanted, p); | |
51 | decode(issued, p); | |
52 | decode(pending, p); | |
53 | decode(client_follows, p); | |
54 | decode(seq, p); | |
55 | decode(mseq, p); | |
56 | decode(last_issue_stamp, p); | |
57 | if (struct_v >= 3) | |
58 | decode(state, p); | |
7c673cae FG |
59 | DECODE_FINISH(p); |
60 | } | |
61 | ||
f67539c2 | 62 | void Capability::Export::dump(ceph::Formatter *f) const |
7c673cae FG |
63 | { |
64 | f->dump_unsigned("cap_id", cap_id); | |
f67539c2 TL |
65 | f->dump_stream("wanted") << ccap_string(wanted); |
66 | f->dump_stream("issued") << ccap_string(issued); | |
67 | f->dump_stream("pending") << ccap_string(pending); | |
7c673cae FG |
68 | f->dump_unsigned("client_follows", client_follows); |
69 | f->dump_unsigned("seq", seq); | |
70 | f->dump_unsigned("migrate_seq", mseq); | |
71 | f->dump_stream("last_issue_stamp") << last_issue_stamp; | |
72 | } | |
73 | ||
9f95a23c | 74 | void Capability::Export::generate_test_instances(std::list<Capability::Export*>& ls) |
7c673cae FG |
75 | { |
76 | ls.push_back(new Export); | |
77 | ls.push_back(new Export); | |
78 | ls.back()->wanted = 1; | |
79 | ls.back()->issued = 2; | |
80 | ls.back()->pending = 3; | |
81 | ls.back()->client_follows = 4; | |
82 | ls.back()->mseq = 5; | |
83 | ls.back()->last_issue_stamp = utime_t(6, 7); | |
84 | } | |
85 | ||
f67539c2 | 86 | void Capability::Import::encode(ceph::buffer::list &bl) const |
7c673cae FG |
87 | { |
88 | ENCODE_START(1, 1, bl); | |
11fdf7f2 TL |
89 | encode(cap_id, bl); |
90 | encode(issue_seq, bl); | |
91 | encode(mseq, bl); | |
7c673cae FG |
92 | ENCODE_FINISH(bl); |
93 | } | |
94 | ||
f67539c2 | 95 | void Capability::Import::decode(ceph::buffer::list::const_iterator &bl) |
7c673cae FG |
96 | { |
97 | DECODE_START(1, bl); | |
11fdf7f2 TL |
98 | decode(cap_id, bl); |
99 | decode(issue_seq, bl); | |
100 | decode(mseq, bl); | |
7c673cae FG |
101 | DECODE_FINISH(bl); |
102 | } | |
103 | ||
f67539c2 | 104 | void Capability::Import::dump(ceph::Formatter *f) const |
7c673cae FG |
105 | { |
106 | f->dump_unsigned("cap_id", cap_id); | |
107 | f->dump_unsigned("issue_seq", issue_seq); | |
108 | f->dump_unsigned("migrate_seq", mseq); | |
109 | } | |
110 | ||
111 | /* | |
112 | * Capability::revoke_info | |
113 | */ | |
114 | ||
f67539c2 | 115 | void Capability::revoke_info::encode(ceph::buffer::list& bl) const |
7c673cae FG |
116 | { |
117 | ENCODE_START(2, 2, bl) | |
11fdf7f2 TL |
118 | encode(before, bl); |
119 | encode(seq, bl); | |
120 | encode(last_issue, bl); | |
7c673cae FG |
121 | ENCODE_FINISH(bl); |
122 | } | |
123 | ||
f67539c2 | 124 | void Capability::revoke_info::decode(ceph::buffer::list::const_iterator& bl) |
7c673cae FG |
125 | { |
126 | DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, bl); | |
11fdf7f2 TL |
127 | decode(before, bl); |
128 | decode(seq, bl); | |
129 | decode(last_issue, bl); | |
7c673cae FG |
130 | DECODE_FINISH(bl); |
131 | } | |
132 | ||
f67539c2 | 133 | void Capability::revoke_info::dump(ceph::Formatter *f) const |
7c673cae FG |
134 | { |
135 | f->dump_unsigned("before", before); | |
136 | f->dump_unsigned("seq", seq); | |
137 | f->dump_unsigned("last_issue", last_issue); | |
138 | } | |
139 | ||
9f95a23c | 140 | void Capability::revoke_info::generate_test_instances(std::list<Capability::revoke_info*>& ls) |
7c673cae FG |
141 | { |
142 | ls.push_back(new revoke_info); | |
143 | ls.push_back(new revoke_info); | |
144 | ls.back()->before = 1; | |
145 | ls.back()->seq = 2; | |
146 | ls.back()->last_issue = 3; | |
147 | } | |
148 | ||
149 | ||
150 | /* | |
151 | * Capability | |
152 | */ | |
a8e16298 | 153 | Capability::Capability(CInode *i, Session *s, uint64_t id) : |
a8e16298 TL |
154 | item_session_caps(this), item_snaprealm_caps(this), |
155 | item_revoking_caps(this), item_client_revoking_caps(this), | |
9f95a23c TL |
156 | lock_caches(member_offset(MDLockCache, item_cap_lock_cache)), |
157 | inode(i), session(s), cap_id(id) | |
a8e16298 TL |
158 | { |
159 | if (session) { | |
160 | session->touch_cap_bottom(this); | |
161 | cap_gen = session->get_cap_gen(); | |
494da23a TL |
162 | if (session->is_stale()) |
163 | --cap_gen; // not valid | |
11fdf7f2 TL |
164 | |
165 | auto& conn = session->get_connection(); | |
166 | if (conn) { | |
167 | if (!conn->has_feature(CEPH_FEATURE_MDS_INLINE_DATA)) | |
168 | state |= STATE_NOINLINE; | |
169 | if (!conn->has_feature(CEPH_FEATURE_FS_FILE_LAYOUT_V2)) | |
170 | state |= STATE_NOPOOLNS; | |
171 | if (!conn->has_feature(CEPH_FEATURE_MDS_QUOTA)) | |
172 | state |= STATE_NOQUOTA; | |
173 | } | |
9f95a23c TL |
174 | } else { |
175 | cap_gen = 0; | |
a8e16298 TL |
176 | } |
177 | } | |
178 | ||
179 | client_t Capability::get_client() const | |
180 | { | |
181 | return session ? session->get_client() : client_t(-1); | |
182 | } | |
183 | ||
aee94f69 TL |
184 | int Capability::confirm_receipt(ceph_seq_t seq, unsigned caps) { |
185 | int was_revoking = (_issued & ~_pending); | |
186 | if (seq == last_sent) { | |
187 | _revokes.clear(); | |
188 | _issued = caps; | |
189 | // don't add bits | |
190 | _pending &= caps; | |
191 | ||
192 | // if the revoking is not totally finished just add the | |
193 | // new revoking caps back. | |
194 | if (was_revoking && revoking()) { | |
195 | CInode *in = get_inode(); | |
196 | dout(10) << "revocation is not totally finished yet on " << *in | |
197 | << ", the session " << *session << dendl; | |
198 | _revokes.emplace_back(_pending, last_sent, last_issue); | |
199 | if (!is_notable()) | |
200 | mark_notable(); | |
201 | } | |
202 | } else { | |
203 | // can i forget any revocations? | |
204 | while (!_revokes.empty() && _revokes.front().seq < seq) | |
205 | _revokes.pop_front(); | |
206 | if (!_revokes.empty()) { | |
207 | if (_revokes.front().seq == seq) | |
208 | _revokes.begin()->before = caps; | |
209 | calc_issued(); | |
210 | } else { | |
211 | // seq < last_sent | |
212 | _issued = caps | _pending; | |
213 | } | |
214 | } | |
215 | ||
216 | if (was_revoking && _issued == _pending) { | |
217 | item_revoking_caps.remove_myself(); | |
218 | item_client_revoking_caps.remove_myself(); | |
219 | maybe_clear_notable(); | |
220 | } | |
221 | return was_revoking & ~_issued; // return revoked | |
222 | } | |
223 | ||
a8e16298 TL |
224 | bool Capability::is_stale() const |
225 | { | |
226 | return session ? session->is_stale() : false; | |
227 | } | |
228 | ||
229 | bool Capability::is_valid() const | |
230 | { | |
231 | return !session || session->get_cap_gen() == cap_gen; | |
232 | } | |
233 | ||
234 | void Capability::revalidate() | |
235 | { | |
494da23a TL |
236 | if (!is_valid()) |
237 | cap_gen = session->get_cap_gen(); | |
a8e16298 TL |
238 | } |
239 | ||
240 | void Capability::mark_notable() | |
241 | { | |
242 | state |= STATE_NOTABLE; | |
243 | session->touch_cap(this); | |
244 | } | |
245 | ||
246 | void Capability::maybe_clear_notable() | |
247 | { | |
248 | if ((_issued == _pending) && | |
249 | !is_clientwriteable() && | |
250 | !is_wanted_notable(_wanted)) { | |
251 | ceph_assert(is_notable()); | |
252 | state &= ~STATE_NOTABLE; | |
253 | session->touch_cap_bottom(this); | |
254 | } | |
255 | } | |
256 | ||
257 | void Capability::set_wanted(int w) { | |
258 | CInode *in = get_inode(); | |
259 | if (in) { | |
260 | if (!is_wanted_notable(_wanted) && is_wanted_notable(w)) { | |
f91f0fd5 | 261 | in->adjust_num_caps_notable(1); |
a8e16298 TL |
262 | if (!is_notable()) |
263 | mark_notable(); | |
264 | } else if (is_wanted_notable(_wanted) && !is_wanted_notable(w)) { | |
f91f0fd5 | 265 | in->adjust_num_caps_notable(-1); |
a8e16298 TL |
266 | maybe_clear_notable(); |
267 | } | |
268 | } | |
269 | _wanted = w; | |
270 | } | |
7c673cae | 271 | |
f67539c2 | 272 | void Capability::encode(ceph::buffer::list& bl) const |
7c673cae FG |
273 | { |
274 | ENCODE_START(2, 2, bl) | |
11fdf7f2 TL |
275 | encode(last_sent, bl); |
276 | encode(last_issue_stamp, bl); | |
7c673cae | 277 | |
11fdf7f2 TL |
278 | encode(_wanted, bl); |
279 | encode(_pending, bl); | |
280 | encode(_revokes, bl); | |
7c673cae FG |
281 | ENCODE_FINISH(bl); |
282 | } | |
283 | ||
f67539c2 | 284 | void Capability::decode(ceph::buffer::list::const_iterator &bl) |
7c673cae FG |
285 | { |
286 | DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, bl) | |
11fdf7f2 TL |
287 | decode(last_sent, bl); |
288 | decode(last_issue_stamp, bl); | |
289 | ||
290 | __u32 tmp_wanted; | |
291 | decode(tmp_wanted, bl); | |
292 | set_wanted(tmp_wanted); | |
293 | decode(_pending, bl); | |
294 | decode(_revokes, bl); | |
7c673cae FG |
295 | DECODE_FINISH(bl); |
296 | ||
a8e16298 | 297 | calc_issued(); |
7c673cae FG |
298 | } |
299 | ||
f67539c2 | 300 | void Capability::dump(ceph::Formatter *f) const |
7c673cae | 301 | { |
f67539c2 TL |
302 | if (inode) |
303 | f->dump_stream("ino") << inode->ino(); | |
7c673cae | 304 | f->dump_unsigned("last_sent", last_sent); |
f67539c2 TL |
305 | f->dump_stream("last_issue_stamp") << last_issue_stamp; |
306 | f->dump_stream("wanted") << ccap_string(_wanted); | |
307 | f->dump_stream("pending") << ccap_string(_pending); | |
7c673cae FG |
308 | |
309 | f->open_array_section("revokes"); | |
94b18763 | 310 | for (const auto &r : _revokes) { |
7c673cae | 311 | f->open_object_section("revoke"); |
94b18763 | 312 | r.dump(f); |
7c673cae FG |
313 | f->close_section(); |
314 | } | |
315 | f->close_section(); | |
316 | } | |
317 | ||
9f95a23c | 318 | void Capability::generate_test_instances(std::list<Capability*>& ls) |
7c673cae FG |
319 | { |
320 | ls.push_back(new Capability); | |
321 | ls.push_back(new Capability); | |
322 | ls.back()->last_sent = 11; | |
323 | ls.back()->last_issue_stamp = utime_t(12, 13); | |
11fdf7f2 | 324 | ls.back()->set_wanted(14); |
7c673cae | 325 | ls.back()->_pending = 15; |
94b18763 | 326 | { |
11fdf7f2 | 327 | auto &r = ls.back()->_revokes.emplace_back(); |
94b18763 FG |
328 | r.before = 16; |
329 | r.seq = 17; | |
330 | r.last_issue = 18; | |
331 | } | |
332 | { | |
11fdf7f2 | 333 | auto &r = ls.back()->_revokes.emplace_back(); |
94b18763 FG |
334 | r.before = 19; |
335 | r.seq = 20; | |
336 | r.last_issue = 21; | |
337 | } | |
7c673cae | 338 | } |
94b18763 FG |
339 | |
340 | MEMPOOL_DEFINE_OBJECT_FACTORY(Capability, co_cap, mds_co); |