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