]> git.proxmox.com Git - ceph.git/blame - ceph/src/mds/CDentry.cc
update ceph source to reef 18.2.1
[ceph.git] / ceph / src / mds / CDentry.cc
CommitLineData
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 34using namespace std;
7c673cae 35
aee94f69 36ostream& 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
41LockType CDentry::lock_type(CEPH_LOCK_DN);
42LockType CDentry::versionlock_type(CEPH_LOCK_DVERSION);
43
44
45// CDentry
46
47ostream& 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
127bool 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 138void CDentry::print(ostream& out) const
7c673cae
FG
139{
140 out << *this;
141}
142
143
144/*
145inodeno_t CDentry::get_ino()
146{
147 if (get_inode())
148 return get_inode()->ino();
149 return inodeno_t();
150}
151*/
152
153mds_authority_t CDentry::authority() const
154{
155 return dir->authority();
156}
157
158
11fdf7f2 159void 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
170version_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
178void 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
192void 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
206void 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
223void CDentry::mark_new()
224{
11fdf7f2 225 dout(10) << __func__ << " " << *this << dendl;
7c673cae
FG
226 state_set(STATE_NEW);
227}
228
1e59de90
TL
229void CDentry::mark_auth()
230{
231 if (!is_auth()) {
232 state_set(STATE_AUTH);
233 dir->adjust_dentry_lru(this);
234 }
235}
236
237void CDentry::clear_auth()
238{
239 if (is_auth()) {
240 state_clear(STATE_AUTH);
241 dir->adjust_dentry_lru(this);
242 }
243}
244
7c673cae
FG
245void 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
256void 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 */
268void 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
281void 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
292void 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
304void 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
324CDentry::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
363int 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 371bool 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
377void 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
392void 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 413void CDentry::adjust_nested_auth_pins(int diradj, void *by)
7c673cae 414{
11fdf7f2 415 dir->adjust_nested_auth_pins(diradj, by);
7c673cae
FG
416}
417
418bool CDentry::is_frozen() const
419{
420 return dir->is_frozen();
421}
422
423bool CDentry::is_freezing() const
424{
425 return dir->is_freezing();
426}
427
7c673cae
FG
428// ----------------------------
429// locking
430
11fdf7f2 431void 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
438void 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 460void 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
503ClientLease *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
522void 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
545void 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
551void 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
563void 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
577void 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
594void 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
652std::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
666bool 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
701bool 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 724MEMPOOL_DEFINE_OBJECT_FACTORY(CDentry, co_dentry, mds_co);