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.
17 #ifndef CEPH_CDENTRY_H
18 #define CEPH_CDENTRY_H
23 #include "include/counter.h"
24 #include "include/types.h"
25 #include "include/buffer_fwd.h"
26 #include "include/lru.h"
27 #include "include/elist.h"
28 #include "include/filepath.h"
30 #include "MDSCacheObject.h"
31 #include "SimpleLock.h"
32 #include "LocalLock.h"
33 #include "ScrubHeader.h"
47 bool operator<(const CDentry
& l
, const CDentry
& r
);
50 class CDentry
: public MDSCacheObject
, public LRUObject
, public Counter
<CDentry
> {
57 unsigned char remote_d_type
;
59 linkage_t() : inode(0), remote_ino(0), remote_d_type(0) {}
61 // dentry type is primary || remote || null
62 // inode ptr is required for primary, optional for remote, undefined for null
63 bool is_primary() const { return remote_ino
== 0 && inode
!= 0; }
64 bool is_remote() const { return remote_ino
> 0; }
65 bool is_null() const { return remote_ino
== 0 && inode
== 0; }
67 CInode
*get_inode() { return inode
; }
68 const CInode
*get_inode() const { return inode
; }
69 inodeno_t
get_remote_ino() const { return remote_ino
; }
70 unsigned char get_remote_d_type() const { return remote_d_type
; }
71 std::string
get_remote_d_type_string() const;
73 void set_remote(inodeno_t ino
, unsigned char d_type
) {
75 remote_d_type
= d_type
;
78 void link_remote(CInode
*in
);
83 static const int STATE_NEW
= (1<<0);
84 static const int STATE_FRAGMENTING
= (1<<1);
85 static const int STATE_PURGING
= (1<<2);
86 static const int STATE_BADREMOTEINO
= (1<<3);
87 static const int STATE_EVALUATINGSTRAY
= (1<<4);
88 static const int STATE_PURGINGPINNED
= (1<<5);
89 // stray dentry needs notification of releasing reference
90 static const int STATE_STRAY
= STATE_NOTIFYREF
;
93 static const int PIN_INODEPIN
= 1; // linked inode is pinned
94 static const int PIN_FRAGMENTING
= -2; // containing dir is refragmenting
95 static const int PIN_PURGING
= 3;
96 static const int PIN_SCRUBPARENT
= 4;
98 static const unsigned EXPORT_NONCE
= 1;
101 CDentry(const std::string
& n
, __u32 h
,
102 snapid_t f
, snapid_t l
) :
106 lock(this, &lock_type
),
107 versionlock(this, &versionlock_type
),
109 version(0), projected_version(0) {
111 CDentry(const std::string
& n
, __u32 h
, inodeno_t ino
, unsigned char dt
,
112 snapid_t f
, snapid_t l
) :
116 lock(this, &lock_type
),
117 versionlock(this, &versionlock_type
),
119 version(0), projected_version(0) {
120 linkage
.remote_ino
= ino
;
121 linkage
.remote_d_type
= dt
;
124 const char *pin_name(int p
) const override
{
126 case PIN_INODEPIN
: return "inodepin";
127 case PIN_FRAGMENTING
: return "fragmenting";
128 case PIN_PURGING
: return "purging";
129 case PIN_SCRUBPARENT
: return "scrubparent";
130 default: return generic_pin_name(p
);
135 //static const int WAIT_LOCK_OFFSET = 8;
137 void add_waiter(uint64_t tag
, MDSInternalContextBase
*c
) override
;
139 bool is_lt(const MDSCacheObject
*r
) const override
{
140 return *this < *static_cast<const CDentry
*>(r
);
144 return dentry_key_t(last
, name
.c_str(), hash
);
147 const CDir
*get_dir() const { return dir
; }
148 CDir
*get_dir() { return dir
; }
149 const std::string
& get_name() const { return name
; }
151 __u32
get_hash() const { return hash
; }
154 const linkage_t
*get_linkage() const { return &linkage
; }
155 linkage_t
*get_linkage() { return &linkage
; }
157 linkage_t
*_project_linkage() {
158 projected
.push_back(linkage_t());
159 return &projected
.back();
161 void push_projected_linkage();
162 void push_projected_linkage(inodeno_t ino
, char d_type
) {
163 linkage_t
*p
= _project_linkage();
165 p
->remote_d_type
= d_type
;
167 void push_projected_linkage(CInode
*inode
);
168 linkage_t
*pop_projected_linkage();
170 bool is_projected() const { return !projected
.empty(); }
172 linkage_t
*get_projected_linkage() {
173 if (!projected
.empty())
174 return &projected
.back();
178 const linkage_t
*get_projected_linkage() const {
179 if (!projected
.empty())
180 return &projected
.back();
184 CInode
*get_projected_inode() {
185 return get_projected_linkage()->inode
;
188 bool use_projected(client_t client
, const MutationRef
& mut
) const {
189 return lock
.can_read_projected(client
) ||
190 lock
.get_xlock_by() == mut
;
192 linkage_t
*get_linkage(client_t client
, const MutationRef
& mut
) {
193 return use_projected(client
, mut
) ? get_projected_linkage() : get_linkage();
196 // ref counts: pin ourselves in the LRU when we're pinned.
197 void first_get() override
{
200 void last_put() override
{
203 void _put() override
;
206 bool can_auth_pin() const override
;
207 void auth_pin(void *by
) override
;
208 void auth_unpin(void *by
) override
;
209 void adjust_nested_auth_pins(int adjustment
, int diradj
, void *by
);
210 bool is_frozen() const override
;
211 bool is_freezing() const override
;
212 int get_num_dir_auth_pins() const;
215 void link_remote(linkage_t
*dnl
, CInode
*in
);
216 void unlink_remote(linkage_t
*dnl
);
219 CDentry(const CDentry
& m
);
220 const CDentry
& operator= (const CDentry
& right
);
223 void make_path_string(std::string
& s
, bool projected
=false) const;
224 void make_path(filepath
& fp
, bool projected
=false) const;
227 version_t
get_version() const { return version
; }
228 void set_version(version_t v
) { projected_version
= version
= v
; }
229 version_t
get_projected_version() const { return projected_version
; }
230 void set_projected_version(version_t v
) { projected_version
= v
; }
232 mds_authority_t
authority() const override
;
234 version_t
pre_dirty(version_t min
=0);
235 void _mark_dirty(LogSegment
*ls
);
236 void mark_dirty(version_t projected_dirv
, LogSegment
*ls
);
240 bool is_new() const { return state_test(STATE_NEW
); }
241 void clear_new() { state_clear(STATE_NEW
); }
244 void encode_replica(mds_rank_t mds
, bufferlist
& bl
) {
245 if (!is_replicated())
246 lock
.replicate_relax();
248 __u32 nonce
= add_replica(mds
);
251 ::encode(linkage
.remote_ino
, bl
);
252 ::encode(linkage
.remote_d_type
, bl
);
253 __s32 ls
= lock
.get_replica_state();
256 void decode_replica(bufferlist::iterator
& p
, bool is_new
);
259 // note: this assumes the dentry already exists.
260 // i.e., the name is already extracted... so we just need the other state.
261 void encode_export(bufferlist
& bl
) {
264 ::encode(version
, bl
);
265 ::encode(projected_version
, bl
);
267 ::encode(replica_map
, bl
);
268 get(PIN_TEMPEXPORTING
);
270 void finish_export() {
273 replica_nonce
= EXPORT_NONCE
;
274 state_clear(CDentry::STATE_AUTH
);
277 put(PIN_TEMPEXPORTING
);
279 void abort_export() {
280 put(PIN_TEMPEXPORTING
);
282 void decode_import(bufferlist::iterator
& blp
, LogSegment
*ls
) {
283 ::decode(first
, blp
);
285 ::decode(nstate
, blp
);
286 ::decode(version
, blp
);
287 ::decode(projected_version
, blp
);
289 ::decode(replica_map
, blp
);
293 state_set(CDentry::STATE_AUTH
);
294 if (nstate
& STATE_DIRTY
)
296 if (!replica_map
.empty())
302 SimpleLock
* get_lock(int type
) override
{
303 assert(type
== CEPH_LOCK_DN
);
306 void set_object_info(MDSCacheObjectInfo
&info
) override
;
307 void encode_lock_state(int type
, bufferlist
& bl
) override
;
308 void decode_lock_state(int type
, bufferlist
& bl
) override
;
310 // ---------------------------------------------
311 // replicas (on clients)
313 bool is_any_leases() const {
314 return !client_lease_map
.empty();
316 const ClientLease
*get_client_lease(client_t c
) const {
317 if (client_lease_map
.count(c
))
318 return client_lease_map
.find(c
)->second
;
321 ClientLease
*get_client_lease(client_t c
) {
322 if (client_lease_map
.count(c
))
323 return client_lease_map
.find(c
)->second
;
326 bool have_client_lease(client_t c
) const {
327 const ClientLease
*l
= get_client_lease(c
);
334 ClientLease
*add_client_lease(client_t c
, Session
*session
);
335 void remove_client_lease(ClientLease
*r
, Locker
*locker
); // returns remaining mask (if any), and kicks locker eval_gathers
336 void remove_client_leases(Locker
*locker
);
338 ostream
& print_db_line_prefix(ostream
& out
) override
;
339 void print(ostream
& out
) override
;
340 void dump(Formatter
*f
) const;
345 snapid_t first
, last
;
347 elist
<CDentry
*>::item item_dirty
;
348 elist
<CDentry
*>::item item_stray
;
351 static LockType lock_type
;
352 static LockType versionlock_type
;
355 LocalLock versionlock
;
357 map
<client_t
,ClientLease
*> client_lease_map
;
361 friend class Migrator
;
363 friend class MDCache
;
364 friend class StrayManager
;
366 friend class C_MDC_XlockRequest
;
368 CDir
*dir
; // containing dirfrag
370 list
<linkage_t
> projected
;
372 version_t version
; // dir version when last touched.
373 version_t projected_version
; // what it will be when i unlock/commit.
376 ostream
& operator<<(ostream
& out
, const CDentry
& dn
);