]> git.proxmox.com Git - ceph.git/blame - ceph/src/mds/Capability.cc
update ceph source to reef 18.2.1
[ceph.git] / ceph / src / mds / Capability.cc
CommitLineData
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 31void 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 46void 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 62void 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 74void 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 86void 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 95void 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 104void 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 115void 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 124void 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 133void 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 140void 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 153Capability::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
179client_t Capability::get_client() const
180{
181 return session ? session->get_client() : client_t(-1);
182}
183
aee94f69
TL
184int 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
224bool Capability::is_stale() const
225{
226 return session ? session->is_stale() : false;
227}
228
229bool Capability::is_valid() const
230{
231 return !session || session->get_cap_gen() == cap_gen;
232}
233
234void Capability::revalidate()
235{
494da23a
TL
236 if (!is_valid())
237 cap_gen = session->get_cap_gen();
a8e16298
TL
238}
239
240void Capability::mark_notable()
241{
242 state |= STATE_NOTABLE;
243 session->touch_cap(this);
244}
245
246void 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
257void 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 272void 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 284void 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 300void 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 318void 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
340MEMPOOL_DEFINE_OBJECT_FACTORY(Capability, co_cap, mds_co);