]>
Commit | Line | Data |
---|---|---|
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 | ||
16 | ||
17 | #include "CDentry.h" | |
18 | #include "CInode.h" | |
19 | #include "CDir.h" | |
1e59de90 | 20 | #include "SnapClient.h" |
7c673cae FG |
21 | |
22 | #include "MDSRank.h" | |
23 | #include "MDCache.h" | |
24 | #include "Locker.h" | |
25 | #include "LogSegment.h" | |
26 | ||
27 | #include "messages/MLock.h" | |
28 | ||
29 | #define dout_context g_ceph_context | |
30 | #define dout_subsys ceph_subsys_mds | |
31 | #undef dout_prefix | |
f67539c2 | 32 | #define dout_prefix *_dout << "mds." << dir->mdcache->mds->get_nodeid() << ".cache.den(" << dir->dirfrag() << " " << name << ") " |
7c673cae | 33 | |
20effc67 | 34 | using namespace std; |
7c673cae | 35 | |
aee94f69 | 36 | ostream& CDentry::print_db_line_prefix(ostream& out) const |
7c673cae | 37 | { |
f67539c2 | 38 | return out << ceph_clock_now() << " mds." << dir->mdcache->mds->get_nodeid() << ".cache.den(" << dir->ino() << " " << name << ") "; |
7c673cae FG |
39 | } |
40 | ||
41 | LockType CDentry::lock_type(CEPH_LOCK_DN); | |
42 | LockType CDentry::versionlock_type(CEPH_LOCK_DVERSION); | |
43 | ||
44 | ||
45 | // CDentry | |
46 | ||
47 | ostream& operator<<(ostream& out, const CDentry& dn) | |
48 | { | |
49 | filepath path; | |
50 | dn.make_path(path); | |
51 | ||
52 | out << "[dentry " << path; | |
53 | ||
54 | if (true || dn.first != 0 || dn.last != CEPH_NOSNAP) { | |
55 | out << " [" << dn.first << ","; | |
56 | if (dn.last == CEPH_NOSNAP) | |
57 | out << "head"; | |
58 | else | |
59 | out << dn.last; | |
60 | out << ']'; | |
61 | } | |
62 | ||
63 | if (dn.is_auth()) { | |
64 | out << " auth"; | |
65 | if (dn.is_replicated()) | |
66 | out << dn.get_replicas(); | |
67 | } else { | |
20effc67 TL |
68 | mds_authority_t a = dn.authority(); |
69 | out << " rep@" << a.first; | |
70 | if (a.second != CDIR_AUTH_UNKNOWN) | |
71 | out << "," << a.second; | |
7c673cae FG |
72 | out << "." << dn.get_replica_nonce(); |
73 | } | |
74 | ||
75 | if (dn.get_linkage()->is_null()) out << " NULL"; | |
76 | if (dn.get_linkage()->is_remote()) { | |
77 | out << " REMOTE("; | |
78 | out << dn.get_linkage()->get_remote_d_type_string(); | |
79 | out << ")"; | |
80 | } | |
81 | ||
82 | if (!dn.lock.is_sync_and_unlocked()) | |
83 | out << " " << dn.lock; | |
84 | if (!dn.versionlock.is_sync_and_unlocked()) | |
85 | out << " " << dn.versionlock; | |
86 | ||
87 | if (dn.get_projected_version() != dn.get_version()) | |
88 | out << " pv=" << dn.get_projected_version(); | |
89 | out << " v=" << dn.get_version(); | |
90 | ||
11fdf7f2 TL |
91 | if (dn.get_num_auth_pins()) { |
92 | out << " ap=" << dn.get_num_auth_pins(); | |
93 | #ifdef MDS_AUTHPIN_SET | |
94 | dn.print_authpin_set(out); | |
95 | #endif | |
96 | } | |
7c673cae | 97 | |
11fdf7f2 TL |
98 | { |
99 | const CInode *inode = dn.get_linkage()->get_inode(); | |
100 | out << " ino="; | |
101 | if (inode) { | |
102 | out << inode->ino(); | |
103 | } else { | |
104 | out << "(nil)"; | |
105 | } | |
106 | } | |
7c673cae | 107 | |
31f18b77 FG |
108 | out << " state=" << dn.get_state(); |
109 | if (dn.is_new()) out << "|new"; | |
110 | if (dn.state_test(CDentry::STATE_BOTTOMLRU)) out << "|bottomlru"; | |
7c673cae FG |
111 | |
112 | if (dn.get_num_ref()) { | |
113 | out << " |"; | |
114 | dn.print_pin_set(out); | |
115 | } | |
116 | ||
f67539c2 TL |
117 | if (dn.get_alternate_name().size()) { |
118 | out << " altname=" << binstrprint(dn.get_alternate_name(), 16); | |
119 | } | |
120 | ||
7c673cae FG |
121 | out << " " << &dn; |
122 | out << "]"; | |
123 | return out; | |
124 | } | |
125 | ||
126 | ||
127 | bool operator<(const CDentry& l, const CDentry& r) | |
128 | { | |
129 | if ((l.get_dir()->ino() < r.get_dir()->ino()) || | |
130 | (l.get_dir()->ino() == r.get_dir()->ino() && | |
131 | (l.get_name() < r.get_name() || | |
132 | (l.get_name() == r.get_name() && l.last < r.last)))) | |
133 | return true; | |
134 | return false; | |
135 | } | |
136 | ||
137 | ||
aee94f69 | 138 | void CDentry::print(ostream& out) const |
7c673cae FG |
139 | { |
140 | out << *this; | |
141 | } | |
142 | ||
143 | ||
144 | /* | |
145 | inodeno_t CDentry::get_ino() | |
146 | { | |
147 | if (get_inode()) | |
148 | return get_inode()->ino(); | |
149 | return inodeno_t(); | |
150 | } | |
151 | */ | |
152 | ||
153 | mds_authority_t CDentry::authority() const | |
154 | { | |
155 | return dir->authority(); | |
156 | } | |
157 | ||
158 | ||
11fdf7f2 | 159 | void CDentry::add_waiter(uint64_t tag, MDSContext *c) |
7c673cae FG |
160 | { |
161 | // wait on the directory? | |
162 | if (tag & (WAIT_UNFREEZE|WAIT_SINGLEAUTH)) { | |
163 | dir->add_waiter(tag, c); | |
164 | return; | |
165 | } | |
166 | MDSCacheObject::add_waiter(tag, c); | |
167 | } | |
168 | ||
169 | ||
170 | version_t CDentry::pre_dirty(version_t min) | |
171 | { | |
172 | projected_version = dir->pre_dirty(min); | |
11fdf7f2 | 173 | dout(10) << __func__ << " " << *this << dendl; |
7c673cae FG |
174 | return projected_version; |
175 | } | |
176 | ||
177 | ||
178 | void CDentry::_mark_dirty(LogSegment *ls) | |
179 | { | |
180 | // state+pin | |
181 | if (!state_test(STATE_DIRTY)) { | |
182 | state_set(STATE_DIRTY); | |
7c673cae | 183 | get(PIN_DIRTY); |
b32b8144 FG |
184 | dir->inc_num_dirty(); |
185 | dir->dirty_dentries.push_back(&item_dir_dirty); | |
11fdf7f2 | 186 | ceph_assert(ls); |
7c673cae FG |
187 | } |
188 | if (ls) | |
189 | ls->dirty_dentries.push_back(&item_dirty); | |
190 | } | |
191 | ||
192 | void CDentry::mark_dirty(version_t pv, LogSegment *ls) | |
193 | { | |
11fdf7f2 | 194 | dout(10) << __func__ << " " << *this << dendl; |
7c673cae FG |
195 | |
196 | // i now live in this new dir version | |
11fdf7f2 | 197 | ceph_assert(pv <= projected_version); |
7c673cae FG |
198 | version = pv; |
199 | _mark_dirty(ls); | |
200 | ||
201 | // mark dir too | |
f67539c2 | 202 | dir->mark_dirty(ls, pv); |
7c673cae FG |
203 | } |
204 | ||
205 | ||
206 | void CDentry::mark_clean() | |
207 | { | |
11fdf7f2 TL |
208 | dout(10) << __func__ << " " << *this << dendl; |
209 | ceph_assert(is_dirty()); | |
7c673cae FG |
210 | |
211 | // not always true for recalc_auth_bits during resolve finish | |
212 | //assert(dir->get_version() == 0 || version <= dir->get_version()); // hmm? | |
213 | ||
b32b8144 | 214 | state_clear(STATE_DIRTY|STATE_NEW); |
7c673cae | 215 | dir->dec_num_dirty(); |
b32b8144 FG |
216 | |
217 | item_dir_dirty.remove_myself(); | |
7c673cae FG |
218 | item_dirty.remove_myself(); |
219 | ||
b32b8144 FG |
220 | put(PIN_DIRTY); |
221 | } | |
7c673cae FG |
222 | |
223 | void CDentry::mark_new() | |
224 | { | |
11fdf7f2 | 225 | dout(10) << __func__ << " " << *this << dendl; |
7c673cae FG |
226 | state_set(STATE_NEW); |
227 | } | |
228 | ||
1e59de90 TL |
229 | void CDentry::mark_auth() |
230 | { | |
231 | if (!is_auth()) { | |
232 | state_set(STATE_AUTH); | |
233 | dir->adjust_dentry_lru(this); | |
234 | } | |
235 | } | |
236 | ||
237 | void CDentry::clear_auth() | |
238 | { | |
239 | if (is_auth()) { | |
240 | state_clear(STATE_AUTH); | |
241 | dir->adjust_dentry_lru(this); | |
242 | } | |
243 | } | |
244 | ||
7c673cae FG |
245 | void CDentry::make_path_string(string& s, bool projected) const |
246 | { | |
247 | if (dir) { | |
248 | dir->inode->make_path_string(s, projected); | |
249 | } else { | |
250 | s = "???"; | |
251 | } | |
252 | s += "/"; | |
253 | s.append(name.data(), name.length()); | |
254 | } | |
255 | ||
256 | void CDentry::make_path(filepath& fp, bool projected) const | |
257 | { | |
11fdf7f2 | 258 | ceph_assert(dir); |
7c673cae | 259 | dir->inode->make_path(fp, projected); |
94b18763 | 260 | fp.push_dentry(get_name()); |
7c673cae FG |
261 | } |
262 | ||
263 | /* | |
264 | * we only add ourselves to remote_parents when the linkage is | |
265 | * active (no longer projected). if the passed dnl is projected, | |
266 | * don't link in, and do that work later in pop_projected_linkage(). | |
267 | */ | |
268 | void CDentry::link_remote(CDentry::linkage_t *dnl, CInode *in) | |
269 | { | |
11fdf7f2 TL |
270 | ceph_assert(dnl->is_remote()); |
271 | ceph_assert(in->ino() == dnl->get_remote_ino()); | |
7c673cae FG |
272 | dnl->inode = in; |
273 | ||
274 | if (dnl == &linkage) | |
275 | in->add_remote_parent(this); | |
20effc67 TL |
276 | |
277 | // check for reintegration | |
278 | dir->mdcache->eval_remote(this); | |
7c673cae FG |
279 | } |
280 | ||
281 | void CDentry::unlink_remote(CDentry::linkage_t *dnl) | |
282 | { | |
11fdf7f2 TL |
283 | ceph_assert(dnl->is_remote()); |
284 | ceph_assert(dnl->inode); | |
7c673cae FG |
285 | |
286 | if (dnl == &linkage) | |
287 | dnl->inode->remove_remote_parent(this); | |
288 | ||
289 | dnl->inode = 0; | |
290 | } | |
291 | ||
292 | void CDentry::push_projected_linkage() | |
293 | { | |
294 | _project_linkage(); | |
295 | ||
296 | if (is_auth()) { | |
297 | CInode *diri = dir->inode; | |
298 | if (diri->is_stray()) | |
299 | diri->mdcache->notify_stray_removed(); | |
300 | } | |
301 | } | |
302 | ||
303 | ||
304 | void CDentry::push_projected_linkage(CInode *inode) | |
305 | { | |
306 | // dirty rstat tracking is in the projected plane | |
307 | bool dirty_rstat = inode->is_dirty_rstat(); | |
308 | if (dirty_rstat) | |
309 | inode->clear_dirty_rstat(); | |
310 | ||
311 | _project_linkage()->inode = inode; | |
312 | inode->push_projected_parent(this); | |
313 | ||
314 | if (dirty_rstat) | |
315 | inode->mark_dirty_rstat(); | |
316 | ||
317 | if (is_auth()) { | |
318 | CInode *diri = dir->inode; | |
319 | if (diri->is_stray()) | |
320 | diri->mdcache->notify_stray_created(); | |
321 | } | |
322 | } | |
323 | ||
324 | CDentry::linkage_t *CDentry::pop_projected_linkage() | |
325 | { | |
11fdf7f2 | 326 | ceph_assert(projected.size()); |
7c673cae FG |
327 | |
328 | linkage_t& n = projected.front(); | |
329 | ||
330 | /* | |
331 | * the idea here is that the link_remote_inode(), link_primary_inode(), | |
332 | * etc. calls should make linkage identical to &n (and we assert as | |
333 | * much). | |
334 | */ | |
335 | ||
336 | if (n.remote_ino) { | |
337 | dir->link_remote_inode(this, n.remote_ino, n.remote_d_type); | |
338 | if (n.inode) { | |
339 | linkage.inode = n.inode; | |
340 | linkage.inode->add_remote_parent(this); | |
341 | } | |
f67539c2 TL |
342 | } else { |
343 | if (n.inode) { | |
344 | dir->link_primary_inode(this, n.inode); | |
345 | n.inode->pop_projected_parent(); | |
346 | } | |
7c673cae FG |
347 | } |
348 | ||
11fdf7f2 TL |
349 | ceph_assert(n.inode == linkage.inode); |
350 | ceph_assert(n.remote_ino == linkage.remote_ino); | |
351 | ceph_assert(n.remote_d_type == linkage.remote_d_type); | |
7c673cae FG |
352 | |
353 | projected.pop_front(); | |
354 | ||
355 | return &linkage; | |
356 | } | |
357 | ||
358 | ||
359 | ||
360 | // ---------------------------- | |
361 | // auth pins | |
362 | ||
363 | int CDentry::get_num_dir_auth_pins() const | |
364 | { | |
11fdf7f2 | 365 | ceph_assert(!is_projected()); |
7c673cae FG |
366 | if (get_linkage()->is_primary()) |
367 | return auth_pins + get_linkage()->get_inode()->get_num_auth_pins(); | |
368 | return auth_pins; | |
369 | } | |
370 | ||
91327a77 | 371 | bool CDentry::can_auth_pin(int *err_ret) const |
7c673cae | 372 | { |
11fdf7f2 | 373 | ceph_assert(dir); |
91327a77 | 374 | return dir->can_auth_pin(err_ret); |
7c673cae FG |
375 | } |
376 | ||
377 | void CDentry::auth_pin(void *by) | |
378 | { | |
379 | if (auth_pins == 0) | |
380 | get(PIN_AUTHPIN); | |
381 | auth_pins++; | |
382 | ||
383 | #ifdef MDS_AUTHPIN_SET | |
384 | auth_pin_set.insert(by); | |
385 | #endif | |
386 | ||
11fdf7f2 | 387 | dout(10) << "auth_pin by " << by << " on " << *this << " now " << auth_pins << dendl; |
7c673cae | 388 | |
11fdf7f2 | 389 | dir->adjust_nested_auth_pins(1, by); |
7c673cae FG |
390 | } |
391 | ||
392 | void CDentry::auth_unpin(void *by) | |
393 | { | |
394 | auth_pins--; | |
395 | ||
396 | #ifdef MDS_AUTHPIN_SET | |
11fdf7f2 TL |
397 | { |
398 | auto it = auth_pin_set.find(by); | |
399 | ceph_assert(it != auth_pin_set.end()); | |
400 | auth_pin_set.erase(it); | |
401 | } | |
7c673cae FG |
402 | #endif |
403 | ||
404 | if (auth_pins == 0) | |
405 | put(PIN_AUTHPIN); | |
406 | ||
11fdf7f2 TL |
407 | dout(10) << "auth_unpin by " << by << " on " << *this << " now " << auth_pins << dendl; |
408 | ceph_assert(auth_pins >= 0); | |
7c673cae | 409 | |
11fdf7f2 | 410 | dir->adjust_nested_auth_pins(-1, by); |
7c673cae FG |
411 | } |
412 | ||
11fdf7f2 | 413 | void CDentry::adjust_nested_auth_pins(int diradj, void *by) |
7c673cae | 414 | { |
11fdf7f2 | 415 | dir->adjust_nested_auth_pins(diradj, by); |
7c673cae FG |
416 | } |
417 | ||
418 | bool CDentry::is_frozen() const | |
419 | { | |
420 | return dir->is_frozen(); | |
421 | } | |
422 | ||
423 | bool CDentry::is_freezing() const | |
424 | { | |
425 | return dir->is_freezing(); | |
426 | } | |
427 | ||
7c673cae FG |
428 | // ---------------------------- |
429 | // locking | |
430 | ||
11fdf7f2 | 431 | void CDentry::set_object_info(MDSCacheObjectInfo &info) |
7c673cae FG |
432 | { |
433 | info.dirfrag = dir->dirfrag(); | |
11fdf7f2 | 434 | info.dname = name; |
7c673cae FG |
435 | info.snapid = last; |
436 | } | |
437 | ||
438 | void CDentry::encode_lock_state(int type, bufferlist& bl) | |
439 | { | |
11fdf7f2 | 440 | encode(first, bl); |
7c673cae FG |
441 | |
442 | // null, ino, or remote_ino? | |
443 | char c; | |
444 | if (linkage.is_primary()) { | |
445 | c = 1; | |
11fdf7f2 | 446 | encode(c, bl); |
f67539c2 | 447 | encode(linkage.get_inode()->ino(), bl); |
7c673cae FG |
448 | } |
449 | else if (linkage.is_remote()) { | |
450 | c = 2; | |
11fdf7f2 TL |
451 | encode(c, bl); |
452 | encode(linkage.get_remote_ino(), bl); | |
7c673cae FG |
453 | } |
454 | else if (linkage.is_null()) { | |
455 | // encode nothing. | |
456 | } | |
457 | else ceph_abort(); | |
458 | } | |
459 | ||
11fdf7f2 | 460 | void CDentry::decode_lock_state(int type, const bufferlist& bl) |
7c673cae | 461 | { |
11fdf7f2 | 462 | auto p = bl.cbegin(); |
7c673cae FG |
463 | |
464 | snapid_t newfirst; | |
11fdf7f2 | 465 | decode(newfirst, p); |
7c673cae FG |
466 | |
467 | if (!is_auth() && newfirst != first) { | |
11fdf7f2 TL |
468 | dout(10) << __func__ << " first " << first << " -> " << newfirst << dendl; |
469 | ceph_assert(newfirst > first); | |
7c673cae FG |
470 | first = newfirst; |
471 | } | |
472 | ||
473 | if (p.end()) { | |
474 | // null | |
11fdf7f2 | 475 | ceph_assert(linkage.is_null()); |
7c673cae FG |
476 | return; |
477 | } | |
478 | ||
479 | char c; | |
480 | inodeno_t ino; | |
11fdf7f2 | 481 | decode(c, p); |
7c673cae FG |
482 | |
483 | switch (c) { | |
484 | case 1: | |
485 | case 2: | |
11fdf7f2 | 486 | decode(ino, p); |
7c673cae FG |
487 | // newly linked? |
488 | if (linkage.is_null() && !is_auth()) { | |
489 | // force trim from cache! | |
11fdf7f2 | 490 | dout(10) << __func__ << " replica dentry null -> non-null, must trim" << dendl; |
7c673cae FG |
491 | //assert(get_num_ref() == 0); |
492 | } else { | |
493 | // verify? | |
494 | ||
495 | } | |
496 | break; | |
497 | default: | |
498 | ceph_abort(); | |
499 | } | |
500 | } | |
501 | ||
502 | ||
503 | ClientLease *CDentry::add_client_lease(client_t c, Session *session) | |
504 | { | |
505 | ClientLease *l; | |
506 | if (client_lease_map.count(c)) | |
507 | l = client_lease_map[c]; | |
508 | else { | |
11fdf7f2 | 509 | dout(20) << __func__ << " client." << c << " on " << lock << dendl; |
b32b8144 | 510 | if (client_lease_map.empty()) { |
7c673cae | 511 | get(PIN_CLIENTLEASE); |
b32b8144 FG |
512 | lock.get_client_lease(); |
513 | } | |
7c673cae FG |
514 | l = client_lease_map[c] = new ClientLease(c, this); |
515 | l->seq = ++session->lease_seq; | |
516 | ||
7c673cae FG |
517 | } |
518 | ||
519 | return l; | |
520 | } | |
521 | ||
522 | void CDentry::remove_client_lease(ClientLease *l, Locker *locker) | |
523 | { | |
11fdf7f2 | 524 | ceph_assert(l->parent == this); |
7c673cae FG |
525 | |
526 | bool gather = false; | |
527 | ||
11fdf7f2 | 528 | dout(20) << __func__ << " client." << l->client << " on " << lock << dendl; |
7c673cae FG |
529 | |
530 | client_lease_map.erase(l->client); | |
531 | l->item_lease.remove_myself(); | |
532 | l->item_session_lease.remove_myself(); | |
533 | delete l; | |
534 | ||
b32b8144 FG |
535 | if (client_lease_map.empty()) { |
536 | gather = !lock.is_stable(); | |
537 | lock.put_client_lease(); | |
7c673cae | 538 | put(PIN_CLIENTLEASE); |
b32b8144 | 539 | } |
7c673cae FG |
540 | |
541 | if (gather) | |
542 | locker->eval_gather(&lock); | |
543 | } | |
544 | ||
545 | void CDentry::remove_client_leases(Locker *locker) | |
546 | { | |
547 | while (!client_lease_map.empty()) | |
548 | remove_client_lease(client_lease_map.begin()->second, locker); | |
549 | } | |
550 | ||
551 | void CDentry::_put() | |
552 | { | |
553 | if (get_num_ref() <= ((int)is_dirty() + 1)) { | |
554 | CDentry::linkage_t *dnl = get_projected_linkage(); | |
555 | if (dnl->is_primary()) { | |
556 | CInode *in = dnl->get_inode(); | |
557 | if (get_num_ref() == (int)is_dirty() + !!in->get_num_ref()) | |
558 | in->mdcache->maybe_eval_stray(in, true); | |
559 | } | |
560 | } | |
561 | } | |
562 | ||
f67539c2 TL |
563 | void CDentry::encode_remote(inodeno_t& ino, unsigned char d_type, |
564 | std::string_view alternate_name, | |
565 | bufferlist &bl) | |
566 | { | |
567 | bl.append('l'); // remote link | |
568 | ||
569 | // marker, name, ino | |
570 | ENCODE_START(2, 1, bl); | |
571 | encode(ino, bl); | |
572 | encode(d_type, bl); | |
573 | encode(alternate_name, bl); | |
574 | ENCODE_FINISH(bl); | |
575 | } | |
576 | ||
577 | void CDentry::decode_remote(char icode, inodeno_t& ino, unsigned char& d_type, | |
578 | mempool::mds_co::string& alternate_name, | |
579 | ceph::buffer::list::const_iterator& bl) | |
580 | { | |
581 | if (icode == 'l') { | |
582 | DECODE_START(2, bl); | |
583 | decode(ino, bl); | |
584 | decode(d_type, bl); | |
585 | if (struct_v >= 2) | |
586 | decode(alternate_name, bl); | |
587 | DECODE_FINISH(bl); | |
588 | } else if (icode == 'L') { | |
589 | decode(ino, bl); | |
590 | decode(d_type, bl); | |
591 | } else ceph_assert(0); | |
592 | } | |
593 | ||
7c673cae FG |
594 | void CDentry::dump(Formatter *f) const |
595 | { | |
11fdf7f2 | 596 | ceph_assert(f != NULL); |
7c673cae FG |
597 | |
598 | filepath path; | |
599 | make_path(path); | |
600 | ||
601 | f->dump_string("path", path.get_path()); | |
602 | f->dump_unsigned("path_ino", path.get_ino().val); | |
603 | f->dump_unsigned("snap_first", first); | |
604 | f->dump_unsigned("snap_last", last); | |
605 | ||
606 | f->dump_bool("is_primary", get_linkage()->is_primary()); | |
607 | f->dump_bool("is_remote", get_linkage()->is_remote()); | |
608 | f->dump_bool("is_null", get_linkage()->is_null()); | |
609 | f->dump_bool("is_new", is_new()); | |
610 | if (get_linkage()->get_inode()) { | |
611 | f->dump_unsigned("inode", get_linkage()->get_inode()->ino()); | |
612 | } else { | |
613 | f->dump_unsigned("inode", 0); | |
614 | } | |
615 | ||
616 | if (linkage.is_remote()) { | |
617 | f->dump_string("remote_type", linkage.get_remote_d_type_string()); | |
618 | } else { | |
619 | f->dump_string("remote_type", ""); | |
620 | } | |
621 | ||
622 | f->dump_unsigned("version", get_version()); | |
623 | f->dump_unsigned("projected_version", get_projected_version()); | |
624 | ||
625 | f->dump_int("auth_pins", auth_pins); | |
7c673cae FG |
626 | |
627 | MDSCacheObject::dump(f); | |
628 | ||
629 | f->open_object_section("lock"); | |
630 | lock.dump(f); | |
631 | f->close_section(); | |
632 | ||
633 | f->open_object_section("versionlock"); | |
634 | versionlock.dump(f); | |
635 | f->close_section(); | |
636 | ||
637 | f->open_array_section("states"); | |
638 | MDSCacheObject::dump_states(f); | |
639 | if (state_test(STATE_NEW)) | |
640 | f->dump_string("state", "new"); | |
641 | if (state_test(STATE_FRAGMENTING)) | |
642 | f->dump_string("state", "fragmenting"); | |
643 | if (state_test(STATE_PURGING)) | |
644 | f->dump_string("state", "purging"); | |
645 | if (state_test(STATE_BADREMOTEINO)) | |
646 | f->dump_string("state", "badremoteino"); | |
647 | if (state_test(STATE_STRAY)) | |
648 | f->dump_string("state", "stray"); | |
649 | f->close_section(); | |
650 | } | |
651 | ||
652 | std::string CDentry::linkage_t::get_remote_d_type_string() const | |
653 | { | |
654 | switch (DTTOIF(remote_d_type)) { | |
655 | case S_IFSOCK: return "sock"; | |
656 | case S_IFLNK: return "lnk"; | |
657 | case S_IFREG: return "reg"; | |
658 | case S_IFBLK: return "blk"; | |
659 | case S_IFDIR: return "dir"; | |
660 | case S_IFCHR: return "chr"; | |
661 | case S_IFIFO: return "fifo"; | |
662 | default: ceph_abort(); return ""; | |
663 | } | |
664 | } | |
181888fb | 665 | |
1e59de90 TL |
666 | bool CDentry::scrub(snapid_t next_seq) |
667 | { | |
668 | dout(20) << "scrubbing " << *this << " next_seq = " << next_seq << dendl; | |
669 | ||
670 | /* attempt to locate damage in first of CDentry, see: | |
671 | * https://tracker.ceph.com/issues/56140 | |
672 | */ | |
673 | /* skip projected dentries as first/last may have placeholder values */ | |
674 | if (!is_projected()) { | |
675 | CDir* dir = get_dir(); | |
676 | ||
677 | if (first > next_seq) { | |
678 | derr << __func__ << ": first > next_seq (" << next_seq << ") " << *this << dendl; | |
679 | dir->go_bad_dentry(last, get_name()); | |
680 | return true; | |
681 | } else if (first > last) { | |
682 | derr << __func__ << ": first > last " << *this << dendl; | |
683 | dir->go_bad_dentry(last, get_name()); | |
684 | return true; | |
685 | } | |
686 | ||
687 | auto&& realm = dir->get_inode()->find_snaprealm(); | |
688 | if (realm) { | |
689 | auto&& snaps = realm->get_snaps(); | |
690 | auto it = snaps.lower_bound(first); | |
691 | bool stale = last != CEPH_NOSNAP && (it == snaps.end() || *it > last); | |
692 | if (stale) { | |
693 | dout(20) << "is stale" << dendl; | |
694 | /* TODO: maybe trim? */ | |
695 | } | |
696 | } | |
697 | } | |
698 | return false; | |
699 | } | |
700 | ||
701 | bool CDentry::check_corruption(bool load) | |
702 | { | |
703 | auto&& snapclient = dir->mdcache->mds->snapclient; | |
704 | auto next_snap = snapclient->get_last_seq()+1; | |
705 | if (first > last || (snapclient->is_server_ready() && first > next_snap)) { | |
706 | if (load) { | |
707 | dout(1) << "loaded already corrupt dentry: " << *this << dendl; | |
708 | corrupt_first_loaded = true; | |
709 | } else { | |
710 | derr << "newly corrupt dentry to be committed: " << *this << dendl; | |
711 | } | |
712 | if (g_conf().get_val<bool>("mds_go_bad_corrupt_dentry")) { | |
713 | dir->go_bad_dentry(last, get_name()); | |
714 | } | |
715 | if (!load && g_conf().get_val<bool>("mds_abort_on_newly_corrupt_dentry")) { | |
716 | dir->mdcache->mds->clog->error() << "MDS abort because newly corrupt dentry to be committed: " << *this; | |
aee94f69 | 717 | dir->mdcache->mds->abort("detected newly corrupt dentry"); /* avoid writing out newly corrupted dn */ |
1e59de90 TL |
718 | } |
719 | return true; | |
720 | } | |
721 | return false; | |
722 | } | |
723 | ||
181888fb | 724 | MEMPOOL_DEFINE_OBJECT_FACTORY(CDentry, co_dentry, mds_co); |