]>
Commit | Line | Data |
---|---|---|
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 "Mutation.h" | |
16 | #include "ScatterLock.h" | |
17 | #include "CDir.h" | |
18 | ||
19 | #include "messages/MClientRequest.h" | |
20 | #include "messages/MMDSSlaveRequest.h" | |
21 | ||
22 | ||
23 | // MutationImpl | |
24 | ||
25 | void MutationImpl::pin(MDSCacheObject *o) | |
26 | { | |
27 | if (pins.count(o) == 0) { | |
28 | o->get(MDSCacheObject::PIN_REQUEST); | |
29 | pins.insert(o); | |
30 | } | |
31 | } | |
32 | ||
33 | void MutationImpl::unpin(MDSCacheObject *o) | |
34 | { | |
35 | assert(pins.count(o)); | |
36 | o->put(MDSCacheObject::PIN_REQUEST); | |
37 | pins.erase(o); | |
38 | } | |
39 | ||
40 | void MutationImpl::set_stickydirs(CInode *in) | |
41 | { | |
42 | if (stickydirs.count(in) == 0) { | |
43 | in->get_stickydirs(); | |
44 | stickydirs.insert(in); | |
45 | } | |
46 | } | |
47 | ||
48 | void MutationImpl::drop_pins() | |
49 | { | |
50 | for (set<MDSCacheObject*>::iterator it = pins.begin(); | |
51 | it != pins.end(); | |
52 | ++it) | |
53 | (*it)->put(MDSCacheObject::PIN_REQUEST); | |
54 | pins.clear(); | |
55 | } | |
56 | ||
57 | void MutationImpl::start_locking(SimpleLock *lock, int target) | |
58 | { | |
59 | assert(locking == NULL); | |
60 | pin(lock->get_parent()); | |
61 | locking = lock; | |
62 | locking_target_mds = target; | |
63 | } | |
64 | ||
65 | void MutationImpl::finish_locking(SimpleLock *lock) | |
66 | { | |
67 | assert(locking == lock); | |
68 | locking = NULL; | |
69 | locking_target_mds = -1; | |
70 | } | |
71 | ||
72 | ||
73 | // auth pins | |
74 | bool MutationImpl::is_auth_pinned(MDSCacheObject *object) const | |
75 | { | |
76 | return auth_pins.count(object) || remote_auth_pins.count(object); | |
77 | } | |
78 | ||
79 | void MutationImpl::auth_pin(MDSCacheObject *object) | |
80 | { | |
81 | if (!is_auth_pinned(object)) { | |
82 | object->auth_pin(this); | |
83 | auth_pins.insert(object); | |
84 | } | |
85 | } | |
86 | ||
87 | void MutationImpl::auth_unpin(MDSCacheObject *object) | |
88 | { | |
89 | assert(auth_pins.count(object)); | |
90 | object->auth_unpin(this); | |
91 | auth_pins.erase(object); | |
92 | } | |
93 | ||
94 | void MutationImpl::drop_local_auth_pins() | |
95 | { | |
96 | for (set<MDSCacheObject*>::iterator it = auth_pins.begin(); | |
97 | it != auth_pins.end(); | |
98 | ++it) { | |
99 | assert((*it)->is_auth()); | |
100 | (*it)->auth_unpin(this); | |
101 | } | |
102 | auth_pins.clear(); | |
103 | } | |
104 | ||
105 | void MutationImpl::add_projected_inode(CInode *in) | |
106 | { | |
107 | projected_inodes.push_back(in); | |
108 | } | |
109 | ||
110 | void MutationImpl::pop_and_dirty_projected_inodes() | |
111 | { | |
112 | while (!projected_inodes.empty()) { | |
113 | CInode *in = projected_inodes.front(); | |
114 | projected_inodes.pop_front(); | |
115 | in->pop_and_dirty_projected_inode(ls); | |
116 | } | |
117 | } | |
118 | ||
119 | void MutationImpl::add_projected_fnode(CDir *dir) | |
120 | { | |
121 | projected_fnodes.push_back(dir); | |
122 | } | |
123 | ||
124 | void MutationImpl::pop_and_dirty_projected_fnodes() | |
125 | { | |
126 | while (!projected_fnodes.empty()) { | |
127 | CDir *dir = projected_fnodes.front(); | |
128 | projected_fnodes.pop_front(); | |
129 | dir->pop_and_dirty_projected_fnode(ls); | |
130 | } | |
131 | } | |
132 | ||
133 | void MutationImpl::add_updated_lock(ScatterLock *lock) | |
134 | { | |
135 | updated_locks.push_back(lock); | |
136 | } | |
137 | ||
138 | void MutationImpl::add_cow_inode(CInode *in) | |
139 | { | |
140 | pin(in); | |
141 | dirty_cow_inodes.push_back(in); | |
142 | } | |
143 | ||
144 | void MutationImpl::add_cow_dentry(CDentry *dn) | |
145 | { | |
146 | pin(dn); | |
147 | dirty_cow_dentries.push_back(pair<CDentry*,version_t>(dn, dn->get_projected_version())); | |
148 | } | |
149 | ||
150 | void MutationImpl::apply() | |
151 | { | |
152 | pop_and_dirty_projected_inodes(); | |
153 | pop_and_dirty_projected_fnodes(); | |
154 | ||
155 | for (list<CInode*>::iterator p = dirty_cow_inodes.begin(); | |
156 | p != dirty_cow_inodes.end(); | |
157 | ++p) | |
158 | (*p)->_mark_dirty(ls); | |
159 | for (list<pair<CDentry*,version_t> >::iterator p = dirty_cow_dentries.begin(); | |
160 | p != dirty_cow_dentries.end(); | |
161 | ++p) | |
162 | p->first->mark_dirty(p->second, ls); | |
163 | ||
164 | for (list<ScatterLock*>::iterator p = updated_locks.begin(); | |
165 | p != updated_locks.end(); | |
166 | ++p) | |
167 | (*p)->mark_dirty(); | |
168 | } | |
169 | ||
170 | void MutationImpl::cleanup() | |
171 | { | |
172 | drop_local_auth_pins(); | |
173 | drop_pins(); | |
174 | } | |
175 | ||
176 | void MutationImpl::_dump_op_descriptor_unlocked(ostream& stream) const | |
177 | { | |
178 | stream << "Mutation"; | |
179 | } | |
180 | ||
181 | // MDRequestImpl | |
182 | ||
183 | MDRequestImpl::~MDRequestImpl() | |
184 | { | |
185 | if (client_request) | |
186 | client_request->put(); | |
187 | if (slave_request) | |
188 | slave_request->put(); | |
189 | delete _more; | |
190 | } | |
191 | ||
192 | MDRequestImpl::More* MDRequestImpl::more() | |
193 | { | |
194 | if (!_more) | |
195 | _more = new More(); | |
196 | return _more; | |
197 | } | |
198 | ||
199 | bool MDRequestImpl::has_more() const | |
200 | { | |
201 | return _more != nullptr; | |
202 | } | |
203 | ||
204 | bool MDRequestImpl::has_witnesses() | |
205 | { | |
206 | return (_more != nullptr) && (!_more->witnessed.empty()); | |
207 | } | |
208 | ||
209 | bool MDRequestImpl::slave_did_prepare() | |
210 | { | |
211 | return has_more() && more()->slave_commit; | |
212 | } | |
213 | ||
214 | bool MDRequestImpl::slave_rolling_back() | |
215 | { | |
216 | return has_more() && more()->slave_rolling_back; | |
217 | } | |
218 | ||
219 | bool MDRequestImpl::did_ino_allocation() const | |
220 | { | |
221 | return alloc_ino || used_prealloc_ino || prealloc_inos.size(); | |
222 | } | |
223 | ||
224 | bool MDRequestImpl::freeze_auth_pin(CInode *inode) | |
225 | { | |
226 | assert(!more()->rename_inode || more()->rename_inode == inode); | |
227 | more()->rename_inode = inode; | |
228 | more()->is_freeze_authpin = true; | |
229 | auth_pin(inode); | |
230 | if (!inode->freeze_inode(1)) { | |
231 | return false; | |
232 | } | |
233 | inode->freeze_auth_pin(); | |
234 | inode->unfreeze_inode(); | |
235 | return true; | |
236 | } | |
237 | ||
238 | void MDRequestImpl::unfreeze_auth_pin(bool clear_inode) | |
239 | { | |
240 | assert(more()->is_freeze_authpin); | |
241 | CInode *inode = more()->rename_inode; | |
242 | if (inode->is_frozen_auth_pin()) | |
243 | inode->unfreeze_auth_pin(); | |
244 | else | |
245 | inode->unfreeze_inode(); | |
246 | more()->is_freeze_authpin = false; | |
247 | if (clear_inode) | |
248 | more()->rename_inode = NULL; | |
249 | } | |
250 | ||
251 | void MDRequestImpl::set_remote_frozen_auth_pin(CInode *inode) | |
252 | { | |
253 | more()->rename_inode = inode; | |
254 | more()->is_remote_frozen_authpin = true; | |
255 | } | |
256 | ||
257 | void MDRequestImpl::set_ambiguous_auth(CInode *inode) | |
258 | { | |
259 | assert(!more()->rename_inode || more()->rename_inode == inode); | |
260 | assert(!more()->is_ambiguous_auth); | |
261 | ||
262 | inode->set_ambiguous_auth(); | |
263 | more()->rename_inode = inode; | |
264 | more()->is_ambiguous_auth = true; | |
265 | } | |
266 | ||
267 | void MDRequestImpl::clear_ambiguous_auth() | |
268 | { | |
269 | CInode *inode = more()->rename_inode; | |
270 | assert(inode && more()->is_ambiguous_auth); | |
271 | inode->clear_ambiguous_auth(); | |
272 | more()->is_ambiguous_auth = false; | |
273 | } | |
274 | ||
275 | bool MDRequestImpl::can_auth_pin(MDSCacheObject *object) | |
276 | { | |
277 | return object->can_auth_pin() || | |
278 | (is_auth_pinned(object) && has_more() && | |
279 | more()->is_freeze_authpin && | |
280 | more()->rename_inode == object); | |
281 | } | |
282 | ||
283 | void MDRequestImpl::drop_local_auth_pins() | |
284 | { | |
285 | if (has_more() && more()->is_freeze_authpin) | |
286 | unfreeze_auth_pin(true); | |
287 | MutationImpl::drop_local_auth_pins(); | |
288 | } | |
289 | ||
290 | const filepath& MDRequestImpl::get_filepath() | |
291 | { | |
292 | if (client_request) | |
293 | return client_request->get_filepath(); | |
294 | return more()->filepath1; | |
295 | } | |
296 | ||
297 | const filepath& MDRequestImpl::get_filepath2() | |
298 | { | |
299 | if (client_request) | |
300 | return client_request->get_filepath2(); | |
301 | return more()->filepath2; | |
302 | } | |
303 | ||
304 | void MDRequestImpl::set_filepath(const filepath& fp) | |
305 | { | |
306 | assert(!client_request); | |
307 | more()->filepath1 = fp; | |
308 | } | |
309 | ||
310 | void MDRequestImpl::set_filepath2(const filepath& fp) | |
311 | { | |
312 | assert(!client_request); | |
313 | more()->filepath2 = fp; | |
314 | } | |
315 | ||
316 | bool MDRequestImpl::is_queued_for_replay() const | |
317 | { | |
318 | return client_request ? client_request->is_queued_for_replay() : false; | |
319 | } | |
320 | ||
321 | MClientRequest* MDRequestImpl::release_client_request() | |
322 | { | |
323 | msg_lock.lock(); | |
324 | auto req = client_request; | |
325 | client_request = nullptr; | |
326 | msg_lock.unlock(); | |
327 | return req; | |
328 | } | |
329 | ||
330 | void MDRequestImpl::reset_slave_request(MMDSSlaveRequest *req) | |
331 | { | |
332 | msg_lock.lock(); | |
333 | auto old = slave_request; | |
334 | slave_request = req; | |
335 | msg_lock.unlock(); | |
336 | if (old) | |
337 | old->put(); | |
338 | } | |
339 | ||
340 | void MDRequestImpl::print(ostream &out) const | |
341 | { | |
342 | out << "request(" << reqid; | |
343 | //if (request) out << " " << *request; | |
344 | if (is_slave()) out << " slave_to mds." << slave_to_mds; | |
345 | if (client_request) out << " cr=" << client_request; | |
346 | if (slave_request) out << " sr=" << slave_request; | |
347 | out << ")"; | |
348 | } | |
349 | ||
350 | void MDRequestImpl::dump(Formatter *f) const | |
351 | { | |
352 | _dump(f); | |
353 | } | |
354 | ||
355 | void MDRequestImpl::_dump(Formatter *f) const | |
356 | { | |
357 | f->dump_string("flag_point", state_string()); | |
358 | f->dump_stream("reqid") << reqid; | |
359 | { | |
360 | msg_lock.lock(); | |
361 | boost::intrusive_ptr<MClientRequest> _client_request(client_request); | |
362 | boost::intrusive_ptr<MMDSSlaveRequest> _slave_request(slave_request); | |
363 | msg_lock.unlock(); | |
364 | ||
365 | if (_client_request) { | |
366 | f->dump_string("op_type", "client_request"); | |
367 | f->open_object_section("client_info"); | |
368 | f->dump_stream("client") << _client_request->get_orig_source(); | |
369 | f->dump_int("tid", _client_request->get_tid()); | |
370 | f->close_section(); // client_info | |
371 | } else if (is_slave() && _slave_request) { // replies go to an existing mdr | |
372 | f->dump_string("op_type", "slave_request"); | |
373 | f->open_object_section("master_info"); | |
374 | f->dump_stream("master") << _slave_request->get_orig_source(); | |
375 | f->close_section(); // master_info | |
376 | ||
377 | f->open_object_section("request_info"); | |
378 | f->dump_int("attempt", _slave_request->get_attempt()); | |
379 | f->dump_string("op_type", | |
380 | MMDSSlaveRequest::get_opname(_slave_request->get_op())); | |
381 | f->dump_int("lock_type", _slave_request->get_lock_type()); | |
382 | f->dump_stream("object_info") << _slave_request->get_object_info(); | |
383 | f->dump_stream("srcdnpath") << _slave_request->srcdnpath; | |
384 | f->dump_stream("destdnpath") << _slave_request->destdnpath; | |
385 | f->dump_stream("witnesses") << _slave_request->witnesses; | |
386 | f->dump_bool("has_inode_export", | |
387 | _slave_request->inode_export_v != 0); | |
388 | f->dump_int("inode_export_v", _slave_request->inode_export_v); | |
389 | f->dump_stream("op_stamp") << _slave_request->op_stamp; | |
390 | f->close_section(); // request_info | |
391 | } | |
392 | else if (internal_op != -1) { // internal request | |
393 | f->dump_string("op_type", "internal_op"); | |
394 | f->dump_int("internal_op", internal_op); | |
395 | f->dump_string("op_name", ceph_mds_op_name(internal_op)); | |
396 | } | |
397 | else { | |
398 | f->dump_string("op_type", "no_available_op_found"); | |
399 | } | |
400 | } | |
401 | { | |
402 | f->open_array_section("events"); | |
403 | Mutex::Locker l(lock); | |
404 | for (auto& i : events) { | |
405 | f->dump_object("event", i); | |
406 | } | |
407 | f->close_section(); // events | |
408 | } | |
409 | } | |
410 | ||
411 | void MDRequestImpl::_dump_op_descriptor_unlocked(ostream& stream) const | |
412 | { | |
413 | msg_lock.lock(); | |
414 | boost::intrusive_ptr<MClientRequest> _client_request(client_request); | |
415 | boost::intrusive_ptr<MMDSSlaveRequest> _slave_request(slave_request); | |
416 | msg_lock.unlock(); | |
417 | ||
418 | if (_client_request) { | |
419 | _client_request->print(stream); | |
420 | } else if (_slave_request) { | |
421 | _slave_request->print(stream); | |
422 | } else if (internal_op >= 0) { | |
423 | stream << "internal op " << ceph_mds_op_name(internal_op) << ":" << reqid; | |
424 | } else { | |
425 | // drat, it's triggered by a slave request, but we don't have a message | |
426 | // FIXME | |
427 | stream << "rejoin:" << reqid; | |
428 | } | |
429 | } |