1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
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.
15 #include "Capability.h"
17 #include "SessionMap.h"
19 #include "common/Formatter.h"
26 void Capability::Export::encode(ceph::buffer::list
&bl
) const
28 ENCODE_START(3, 2, bl
);
33 encode(client_follows
, bl
);
36 encode(last_issue_stamp
, bl
);
41 void Capability::Export::decode(ceph::buffer::list::const_iterator
&p
)
43 DECODE_START_LEGACY_COMPAT_LEN(3, 2, 2, p
);
48 decode(client_follows
, p
);
51 decode(last_issue_stamp
, p
);
57 void Capability::Export::dump(ceph::Formatter
*f
) const
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
;
69 void Capability::Export::generate_test_instances(std::list
<Capability::Export
*>& ls
)
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;
78 ls
.back()->last_issue_stamp
= utime_t(6, 7);
81 void Capability::Import::encode(ceph::buffer::list
&bl
) const
83 ENCODE_START(1, 1, bl
);
85 encode(issue_seq
, bl
);
90 void Capability::Import::decode(ceph::buffer::list::const_iterator
&bl
)
94 decode(issue_seq
, bl
);
99 void Capability::Import::dump(ceph::Formatter
*f
) const
101 f
->dump_unsigned("cap_id", cap_id
);
102 f
->dump_unsigned("issue_seq", issue_seq
);
103 f
->dump_unsigned("migrate_seq", mseq
);
107 * Capability::revoke_info
110 void Capability::revoke_info::encode(ceph::buffer::list
& bl
) const
112 ENCODE_START(2, 2, bl
)
115 encode(last_issue
, bl
);
119 void Capability::revoke_info::decode(ceph::buffer::list::const_iterator
& bl
)
121 DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, bl
);
124 decode(last_issue
, bl
);
128 void Capability::revoke_info::dump(ceph::Formatter
*f
) const
130 f
->dump_unsigned("before", before
);
131 f
->dump_unsigned("seq", seq
);
132 f
->dump_unsigned("last_issue", last_issue
);
135 void Capability::revoke_info::generate_test_instances(std::list
<Capability::revoke_info
*>& ls
)
137 ls
.push_back(new revoke_info
);
138 ls
.push_back(new revoke_info
);
139 ls
.back()->before
= 1;
141 ls
.back()->last_issue
= 3;
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
)
155 session
->touch_cap_bottom(this);
156 cap_gen
= session
->get_cap_gen();
157 if (session
->is_stale())
158 --cap_gen
; // not valid
160 auto& conn
= session
->get_connection();
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
;
174 client_t
Capability::get_client() const
176 return session
? session
->get_client() : client_t(-1);
179 bool Capability::is_stale() const
181 return session
? session
->is_stale() : false;
184 bool Capability::is_valid() const
186 return !session
|| session
->get_cap_gen() == cap_gen
;
189 void Capability::revalidate()
192 cap_gen
= session
->get_cap_gen();
195 void Capability::mark_notable()
197 state
|= STATE_NOTABLE
;
198 session
->touch_cap(this);
201 void Capability::maybe_clear_notable()
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);
212 void Capability::set_wanted(int w
) {
213 CInode
*in
= get_inode();
215 if (!is_wanted_notable(_wanted
) && is_wanted_notable(w
)) {
216 in
->adjust_num_caps_notable(1);
219 } else if (is_wanted_notable(_wanted
) && !is_wanted_notable(w
)) {
220 in
->adjust_num_caps_notable(-1);
221 maybe_clear_notable();
227 void Capability::encode(ceph::buffer::list
& bl
) const
229 ENCODE_START(2, 2, bl
)
230 encode(last_sent
, bl
);
231 encode(last_issue_stamp
, bl
);
234 encode(_pending
, bl
);
235 encode(_revokes
, bl
);
239 void Capability::decode(ceph::buffer::list::const_iterator
&bl
)
241 DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, bl
)
242 decode(last_sent
, bl
);
243 decode(last_issue_stamp
, bl
);
246 decode(tmp_wanted
, bl
);
247 set_wanted(tmp_wanted
);
248 decode(_pending
, bl
);
249 decode(_revokes
, bl
);
255 void Capability::dump(ceph::Formatter
*f
) const
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
);
264 f
->open_array_section("revokes");
265 for (const auto &r
: _revokes
) {
266 f
->open_object_section("revoke");
273 void Capability::generate_test_instances(std::list
<Capability
*>& ls
)
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;
282 auto &r
= ls
.back()->_revokes
.emplace_back();
288 auto &r
= ls
.back()->_revokes
.emplace_back();
295 MEMPOOL_DEFINE_OBJECT_FACTORY(Capability
, co_cap
, mds_co
);