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