]>
git.proxmox.com Git - ceph.git/blob - ceph/src/mds/CDentry.cc
6ab0de1593824fa949795fc8676fd3de45bccb01
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
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.
24 #include "LogSegment.h"
26 #include "messages/MLock.h"
28 #define dout_context g_ceph_context
29 #define dout_subsys ceph_subsys_mds
31 #define dout_prefix *_dout << "mds." << dir->cache->mds->get_nodeid() << ".cache.den(" << dir->dirfrag() << " " << name << ") "
34 ostream
& CDentry::print_db_line_prefix(ostream
& out
)
36 return out
<< ceph_clock_now() << " mds." << dir
->cache
->mds
->get_nodeid() << ".cache.den(" << dir
->ino() << " " << name
<< ") ";
39 LockType
CDentry::lock_type(CEPH_LOCK_DN
);
40 LockType
CDentry::versionlock_type(CEPH_LOCK_DVERSION
);
45 ostream
& operator<<(ostream
& out
, const CDentry
& dn
)
50 out
<< "[dentry " << path
;
52 if (true || dn
.first
!= 0 || dn
.last
!= CEPH_NOSNAP
) {
53 out
<< " [" << dn
.first
<< ",";
54 if (dn
.last
== CEPH_NOSNAP
)
63 if (dn
.is_replicated())
64 out
<< dn
.get_replicas();
66 out
<< " rep@" << dn
.authority();
67 out
<< "." << dn
.get_replica_nonce();
70 if (dn
.get_linkage()->is_null()) out
<< " NULL";
71 if (dn
.get_linkage()->is_remote()) {
73 out
<< dn
.get_linkage()->get_remote_d_type_string();
77 if (!dn
.lock
.is_sync_and_unlocked())
78 out
<< " " << dn
.lock
;
79 if (!dn
.versionlock
.is_sync_and_unlocked())
80 out
<< " " << dn
.versionlock
;
82 if (dn
.get_projected_version() != dn
.get_version())
83 out
<< " pv=" << dn
.get_projected_version();
84 out
<< " v=" << dn
.get_version();
86 if (dn
.is_auth_pinned())
87 out
<< " ap=" << dn
.get_num_auth_pins() << "+" << dn
.get_num_nested_auth_pins();
89 out
<< " inode=" << dn
.get_linkage()->get_inode();
91 out
<< " state=" << dn
.get_state();
92 if (dn
.is_new()) out
<< "|new";
93 if (dn
.state_test(CDentry::STATE_BOTTOMLRU
)) out
<< "|bottomlru";
95 if (dn
.get_num_ref()) {
97 dn
.print_pin_set(out
);
106 bool operator<(const CDentry
& l
, const CDentry
& r
)
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
))))
117 void CDentry::print(ostream
& out
)
124 inodeno_t CDentry::get_ino()
127 return get_inode()->ino();
132 mds_authority_t
CDentry::authority() const
134 return dir
->authority();
138 void CDentry::add_waiter(uint64_t tag
, MDSInternalContextBase
*c
)
140 // wait on the directory?
141 if (tag
& (WAIT_UNFREEZE
|WAIT_SINGLEAUTH
)) {
142 dir
->add_waiter(tag
, c
);
145 MDSCacheObject::add_waiter(tag
, c
);
149 version_t
CDentry::pre_dirty(version_t min
)
151 projected_version
= dir
->pre_dirty(min
);
152 dout(10) << " pre_dirty " << *this << dendl
;
153 return projected_version
;
157 void CDentry::_mark_dirty(LogSegment
*ls
)
160 if (!state_test(STATE_DIRTY
)) {
161 state_set(STATE_DIRTY
);
163 dir
->inc_num_dirty();
164 dir
->dirty_dentries
.push_back(&item_dir_dirty
);
168 ls
->dirty_dentries
.push_back(&item_dirty
);
171 void CDentry::mark_dirty(version_t pv
, LogSegment
*ls
)
173 dout(10) << " mark_dirty " << *this << dendl
;
175 // i now live in this new dir version
176 assert(pv
<= projected_version
);
181 dir
->mark_dirty(pv
, ls
);
185 void CDentry::mark_clean()
187 dout(10) << " mark_clean " << *this << dendl
;
190 // not always true for recalc_auth_bits during resolve finish
191 //assert(dir->get_version() == 0 || version <= dir->get_version()); // hmm?
193 state_clear(STATE_DIRTY
|STATE_NEW
);
194 dir
->dec_num_dirty();
196 item_dir_dirty
.remove_myself();
197 item_dirty
.remove_myself();
202 void CDentry::mark_new()
204 dout(10) << " mark_new " << *this << dendl
;
205 state_set(STATE_NEW
);
208 void CDentry::make_path_string(string
& s
, bool projected
) const
211 dir
->inode
->make_path_string(s
, projected
);
216 s
.append(name
.data(), name
.length());
219 void CDentry::make_path(filepath
& fp
, bool projected
) const
222 dir
->inode
->make_path(fp
, projected
);
223 fp
.push_dentry(name
);
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().
231 void CDentry::link_remote(CDentry::linkage_t
*dnl
, CInode
*in
)
233 assert(dnl
->is_remote());
234 assert(in
->ino() == dnl
->get_remote_ino());
238 in
->add_remote_parent(this);
241 void CDentry::unlink_remote(CDentry::linkage_t
*dnl
)
243 assert(dnl
->is_remote());
247 dnl
->inode
->remove_remote_parent(this);
252 void CDentry::push_projected_linkage()
257 CInode
*diri
= dir
->inode
;
258 if (diri
->is_stray())
259 diri
->mdcache
->notify_stray_removed();
264 void CDentry::push_projected_linkage(CInode
*inode
)
266 // dirty rstat tracking is in the projected plane
267 bool dirty_rstat
= inode
->is_dirty_rstat();
269 inode
->clear_dirty_rstat();
271 _project_linkage()->inode
= inode
;
272 inode
->push_projected_parent(this);
275 inode
->mark_dirty_rstat();
278 CInode
*diri
= dir
->inode
;
279 if (diri
->is_stray())
280 diri
->mdcache
->notify_stray_created();
284 CDentry::linkage_t
*CDentry::pop_projected_linkage()
286 assert(projected
.size());
288 linkage_t
& n
= projected
.front();
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
297 dir
->link_remote_inode(this, n
.remote_ino
, n
.remote_d_type
);
299 linkage
.inode
= n
.inode
;
300 linkage
.inode
->add_remote_parent(this);
302 } else if (n
.inode
) {
303 dir
->link_primary_inode(this, n
.inode
);
304 n
.inode
->pop_projected_parent();
307 assert(n
.inode
== linkage
.inode
);
308 assert(n
.remote_ino
== linkage
.remote_ino
);
309 assert(n
.remote_d_type
== linkage
.remote_d_type
);
311 projected
.pop_front();
318 // ----------------------------
321 int CDentry::get_num_dir_auth_pins() const
323 assert(!is_projected());
324 if (get_linkage()->is_primary())
325 return auth_pins
+ get_linkage()->get_inode()->get_num_auth_pins();
329 bool CDentry::can_auth_pin() const
332 return dir
->can_auth_pin();
335 void CDentry::auth_pin(void *by
)
341 #ifdef MDS_AUTHPIN_SET
342 auth_pin_set
.insert(by
);
345 dout(10) << "auth_pin by " << by
<< " on " << *this
346 << " now " << auth_pins
<< "+" << nested_auth_pins
349 dir
->adjust_nested_auth_pins(1, 1, by
);
352 void CDentry::auth_unpin(void *by
)
356 #ifdef MDS_AUTHPIN_SET
357 assert(auth_pin_set
.count(by
));
358 auth_pin_set
.erase(auth_pin_set
.find(by
));
364 dout(10) << "auth_unpin by " << by
<< " on " << *this
365 << " now " << auth_pins
<< "+" << nested_auth_pins
367 assert(auth_pins
>= 0);
369 dir
->adjust_nested_auth_pins(-1, -1, by
);
372 void CDentry::adjust_nested_auth_pins(int adjustment
, int diradj
, void *by
)
374 nested_auth_pins
+= adjustment
;
376 dout(35) << "adjust_nested_auth_pins by " << by
377 << ", change " << adjustment
<< " yields "
378 << auth_pins
<< "+" << nested_auth_pins
380 assert(nested_auth_pins
>= 0);
382 dir
->adjust_nested_auth_pins(adjustment
, diradj
, by
);
385 bool CDentry::is_frozen() const
387 return dir
->is_frozen();
390 bool CDentry::is_freezing() const
392 return dir
->is_freezing();
395 void CDentry::decode_replica(bufferlist::iterator
& p
, bool is_new
)
399 replica_nonce
= nonce
;
404 unsigned char rdtype
;
407 lock
.decode_state(p
, is_new
);
410 ::decode(need_recover
, p
);
414 dir
->link_remote_inode(this, rino
, rdtype
);
416 lock
.mark_need_recover();
420 // ----------------------------
423 void CDentry::set_object_info(MDSCacheObjectInfo
&info
)
425 info
.dirfrag
= dir
->dirfrag();
430 void CDentry::encode_lock_state(int type
, bufferlist
& bl
)
434 // null, ino, or remote_ino?
436 if (linkage
.is_primary()) {
439 ::encode(linkage
.get_inode()->inode
.ino
, bl
);
441 else if (linkage
.is_remote()) {
444 ::encode(linkage
.get_remote_ino(), bl
);
446 else if (linkage
.is_null()) {
452 void CDentry::decode_lock_state(int type
, bufferlist
& bl
)
454 bufferlist::iterator p
= bl
.begin();
457 ::decode(newfirst
, p
);
459 if (!is_auth() && newfirst
!= first
) {
460 dout(10) << "decode_lock_state first " << first
<< " -> " << newfirst
<< dendl
;
461 assert(newfirst
> first
);
467 assert(linkage
.is_null());
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);
495 ClientLease
*CDentry::add_client_lease(client_t c
, Session
*session
)
498 if (client_lease_map
.count(c
))
499 l
= client_lease_map
[c
];
501 dout(20) << "add_client_lease client." << c
<< " on " << lock
<< dendl
;
502 if (client_lease_map
.empty()) {
503 get(PIN_CLIENTLEASE
);
504 lock
.get_client_lease();
506 l
= client_lease_map
[c
] = new ClientLease(c
, this);
507 l
->seq
= ++session
->lease_seq
;
514 void CDentry::remove_client_lease(ClientLease
*l
, Locker
*locker
)
516 assert(l
->parent
== this);
520 dout(20) << "remove_client_lease client." << l
->client
<< " on " << lock
<< dendl
;
522 client_lease_map
.erase(l
->client
);
523 l
->item_lease
.remove_myself();
524 l
->item_session_lease
.remove_myself();
527 if (client_lease_map
.empty()) {
528 gather
= !lock
.is_stable();
529 lock
.put_client_lease();
530 put(PIN_CLIENTLEASE
);
534 locker
->eval_gather(&lock
);
537 void CDentry::remove_client_leases(Locker
*locker
)
539 while (!client_lease_map
.empty())
540 remove_client_lease(client_lease_map
.begin()->second
, locker
);
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);
555 void CDentry::dump(Formatter
*f
) const
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
);
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());
574 f
->dump_unsigned("inode", 0);
577 if (linkage
.is_remote()) {
578 f
->dump_string("remote_type", linkage
.get_remote_d_type_string());
580 f
->dump_string("remote_type", "");
583 f
->dump_unsigned("version", get_version());
584 f
->dump_unsigned("projected_version", get_projected_version());
586 f
->dump_int("auth_pins", auth_pins
);
587 f
->dump_int("nested_auth_pins", nested_auth_pins
);
589 MDSCacheObject::dump(f
);
591 f
->open_object_section("lock");
595 f
->open_object_section("versionlock");
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");
614 std::string
CDentry::linkage_t::get_remote_d_type_string() const
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 "";
628 MEMPOOL_DEFINE_OBJECT_FACTORY(CDentry
, co_dentry
, mds_co
);