]> git.proxmox.com Git - ceph.git/blob - ceph/src/mds/Capability.cc
b6258e466df38b6013edb1950b01ffcb4a95dff2
[ceph.git] / ceph / src / mds / Capability.cc
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"
16 #include "CInode.h"
17 #include "SessionMap.h"
18
19 #include "common/Formatter.h"
20
21
22 /*
23 * Capability::Export
24 */
25
26 void Capability::Export::encode(ceph::buffer::list &bl) const
27 {
28 ENCODE_START(3, 2, bl);
29 encode(cap_id, bl);
30 encode(wanted, bl);
31 encode(issued, bl);
32 encode(pending, bl);
33 encode(client_follows, bl);
34 encode(seq, bl);
35 encode(mseq, bl);
36 encode(last_issue_stamp, bl);
37 encode(state, bl);
38 ENCODE_FINISH(bl);
39 }
40
41 void Capability::Export::decode(ceph::buffer::list::const_iterator &p)
42 {
43 DECODE_START_LEGACY_COMPAT_LEN(3, 2, 2, p);
44 decode(cap_id, p);
45 decode(wanted, p);
46 decode(issued, p);
47 decode(pending, p);
48 decode(client_follows, p);
49 decode(seq, p);
50 decode(mseq, p);
51 decode(last_issue_stamp, p);
52 if (struct_v >= 3)
53 decode(state, p);
54 DECODE_FINISH(p);
55 }
56
57 void Capability::Export::dump(ceph::Formatter *f) const
58 {
59 f->dump_unsigned("cap_id", cap_id);
60 f->dump_stream("wanted") << ccap_string(wanted);
61 f->dump_stream("issued") << ccap_string(issued);
62 f->dump_stream("pending") << ccap_string(pending);
63 f->dump_unsigned("client_follows", client_follows);
64 f->dump_unsigned("seq", seq);
65 f->dump_unsigned("migrate_seq", mseq);
66 f->dump_stream("last_issue_stamp") << last_issue_stamp;
67 }
68
69 void Capability::Export::generate_test_instances(std::list<Capability::Export*>& ls)
70 {
71 ls.push_back(new Export);
72 ls.push_back(new Export);
73 ls.back()->wanted = 1;
74 ls.back()->issued = 2;
75 ls.back()->pending = 3;
76 ls.back()->client_follows = 4;
77 ls.back()->mseq = 5;
78 ls.back()->last_issue_stamp = utime_t(6, 7);
79 }
80
81 void Capability::Import::encode(ceph::buffer::list &bl) const
82 {
83 ENCODE_START(1, 1, bl);
84 encode(cap_id, bl);
85 encode(issue_seq, bl);
86 encode(mseq, bl);
87 ENCODE_FINISH(bl);
88 }
89
90 void Capability::Import::decode(ceph::buffer::list::const_iterator &bl)
91 {
92 DECODE_START(1, bl);
93 decode(cap_id, bl);
94 decode(issue_seq, bl);
95 decode(mseq, bl);
96 DECODE_FINISH(bl);
97 }
98
99 void Capability::Import::dump(ceph::Formatter *f) const
100 {
101 f->dump_unsigned("cap_id", cap_id);
102 f->dump_unsigned("issue_seq", issue_seq);
103 f->dump_unsigned("migrate_seq", mseq);
104 }
105
106 /*
107 * Capability::revoke_info
108 */
109
110 void Capability::revoke_info::encode(ceph::buffer::list& bl) const
111 {
112 ENCODE_START(2, 2, bl)
113 encode(before, bl);
114 encode(seq, bl);
115 encode(last_issue, bl);
116 ENCODE_FINISH(bl);
117 }
118
119 void Capability::revoke_info::decode(ceph::buffer::list::const_iterator& bl)
120 {
121 DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, bl);
122 decode(before, bl);
123 decode(seq, bl);
124 decode(last_issue, bl);
125 DECODE_FINISH(bl);
126 }
127
128 void Capability::revoke_info::dump(ceph::Formatter *f) const
129 {
130 f->dump_unsigned("before", before);
131 f->dump_unsigned("seq", seq);
132 f->dump_unsigned("last_issue", last_issue);
133 }
134
135 void Capability::revoke_info::generate_test_instances(std::list<Capability::revoke_info*>& ls)
136 {
137 ls.push_back(new revoke_info);
138 ls.push_back(new revoke_info);
139 ls.back()->before = 1;
140 ls.back()->seq = 2;
141 ls.back()->last_issue = 3;
142 }
143
144
145 /*
146 * Capability
147 */
148 Capability::Capability(CInode *i, Session *s, uint64_t id) :
149 item_session_caps(this), item_snaprealm_caps(this),
150 item_revoking_caps(this), item_client_revoking_caps(this),
151 lock_caches(member_offset(MDLockCache, item_cap_lock_cache)),
152 inode(i), session(s), cap_id(id)
153 {
154 if (session) {
155 session->touch_cap_bottom(this);
156 cap_gen = session->get_cap_gen();
157 if (session->is_stale())
158 --cap_gen; // not valid
159
160 auto& conn = session->get_connection();
161 if (conn) {
162 if (!conn->has_feature(CEPH_FEATURE_MDS_INLINE_DATA))
163 state |= STATE_NOINLINE;
164 if (!conn->has_feature(CEPH_FEATURE_FS_FILE_LAYOUT_V2))
165 state |= STATE_NOPOOLNS;
166 if (!conn->has_feature(CEPH_FEATURE_MDS_QUOTA))
167 state |= STATE_NOQUOTA;
168 }
169 } else {
170 cap_gen = 0;
171 }
172 }
173
174 client_t Capability::get_client() const
175 {
176 return session ? session->get_client() : client_t(-1);
177 }
178
179 bool Capability::is_stale() const
180 {
181 return session ? session->is_stale() : false;
182 }
183
184 bool Capability::is_valid() const
185 {
186 return !session || session->get_cap_gen() == cap_gen;
187 }
188
189 void Capability::revalidate()
190 {
191 if (!is_valid())
192 cap_gen = session->get_cap_gen();
193 }
194
195 void Capability::mark_notable()
196 {
197 state |= STATE_NOTABLE;
198 session->touch_cap(this);
199 }
200
201 void Capability::maybe_clear_notable()
202 {
203 if ((_issued == _pending) &&
204 !is_clientwriteable() &&
205 !is_wanted_notable(_wanted)) {
206 ceph_assert(is_notable());
207 state &= ~STATE_NOTABLE;
208 session->touch_cap_bottom(this);
209 }
210 }
211
212 void Capability::set_wanted(int w) {
213 CInode *in = get_inode();
214 if (in) {
215 if (!is_wanted_notable(_wanted) && is_wanted_notable(w)) {
216 in->adjust_num_caps_notable(1);
217 if (!is_notable())
218 mark_notable();
219 } else if (is_wanted_notable(_wanted) && !is_wanted_notable(w)) {
220 in->adjust_num_caps_notable(-1);
221 maybe_clear_notable();
222 }
223 }
224 _wanted = w;
225 }
226
227 void Capability::encode(ceph::buffer::list& bl) const
228 {
229 ENCODE_START(2, 2, bl)
230 encode(last_sent, bl);
231 encode(last_issue_stamp, bl);
232
233 encode(_wanted, bl);
234 encode(_pending, bl);
235 encode(_revokes, bl);
236 ENCODE_FINISH(bl);
237 }
238
239 void Capability::decode(ceph::buffer::list::const_iterator &bl)
240 {
241 DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, bl)
242 decode(last_sent, bl);
243 decode(last_issue_stamp, bl);
244
245 __u32 tmp_wanted;
246 decode(tmp_wanted, bl);
247 set_wanted(tmp_wanted);
248 decode(_pending, bl);
249 decode(_revokes, bl);
250 DECODE_FINISH(bl);
251
252 calc_issued();
253 }
254
255 void Capability::dump(ceph::Formatter *f) const
256 {
257 if (inode)
258 f->dump_stream("ino") << inode->ino();
259 f->dump_unsigned("last_sent", last_sent);
260 f->dump_stream("last_issue_stamp") << last_issue_stamp;
261 f->dump_stream("wanted") << ccap_string(_wanted);
262 f->dump_stream("pending") << ccap_string(_pending);
263
264 f->open_array_section("revokes");
265 for (const auto &r : _revokes) {
266 f->open_object_section("revoke");
267 r.dump(f);
268 f->close_section();
269 }
270 f->close_section();
271 }
272
273 void Capability::generate_test_instances(std::list<Capability*>& ls)
274 {
275 ls.push_back(new Capability);
276 ls.push_back(new Capability);
277 ls.back()->last_sent = 11;
278 ls.back()->last_issue_stamp = utime_t(12, 13);
279 ls.back()->set_wanted(14);
280 ls.back()->_pending = 15;
281 {
282 auto &r = ls.back()->_revokes.emplace_back();
283 r.before = 16;
284 r.seq = 17;
285 r.last_issue = 18;
286 }
287 {
288 auto &r = ls.back()->_revokes.emplace_back();
289 r.before = 19;
290 r.seq = 20;
291 r.last_issue = 21;
292 }
293 }
294
295 MEMPOOL_DEFINE_OBJECT_FACTORY(Capability, co_cap, mds_co);