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.
15 #ifndef CEPH_MDS_LOCKER_H
16 #define CEPH_MDS_LOCKER_H
18 #include "include/types.h"
43 #include "SimpleLock.h"
52 Locker(MDSRank
*m
, MDCache
*c
) : mds(m
), mdcache(c
) {}
54 SimpleLock
*get_lock(int lock_type
, MDSCacheObjectInfo
&info
);
56 void dispatch(Message
*m
);
57 void handle_lock(MLock
*m
);
61 void nudge_log(SimpleLock
*lock
);
64 void send_lock_message(SimpleLock
*lock
, int msg
);
65 void send_lock_message(SimpleLock
*lock
, int msg
, const bufferlist
&data
);
68 void _drop_rdlocks(MutationImpl
*mut
, set
<CInode
*> *pneed_issue
);
69 void _drop_non_rdlocks(MutationImpl
*mut
, set
<CInode
*> *pneed_issue
);
71 void include_snap_rdlocks(set
<SimpleLock
*>& rdlocks
, CInode
*in
);
72 void include_snap_rdlocks_wlayout(set
<SimpleLock
*>& rdlocks
, CInode
*in
,
73 file_layout_t
**layout
);
75 bool acquire_locks(MDRequestRef
& mdr
,
76 set
<SimpleLock
*> &rdlocks
,
77 set
<SimpleLock
*> &wrlocks
,
78 set
<SimpleLock
*> &xlocks
,
79 map
<SimpleLock
*,mds_rank_t
> *remote_wrlocks
=NULL
,
80 CInode
*auth_pin_freeze
=NULL
,
81 bool auth_pin_nonblock
=false);
83 void notify_freeze_waiter(MDSCacheObject
*o
);
84 void cancel_locking(MutationImpl
*mut
, set
<CInode
*> *pneed_issue
);
85 void drop_locks(MutationImpl
*mut
, set
<CInode
*> *pneed_issue
=0);
86 void set_xlocks_done(MutationImpl
*mut
, bool skip_dentry
=false);
87 void drop_non_rdlocks(MutationImpl
*mut
, set
<CInode
*> *pneed_issue
=0);
88 void drop_rdlocks_for_early_reply(MutationImpl
*mut
);
90 void eval_gather(SimpleLock
*lock
, bool first
=false, bool *need_issue
=0, list
<MDSInternalContextBase
*> *pfinishers
=0);
91 void eval(SimpleLock
*lock
, bool *need_issue
);
92 void eval_any(SimpleLock
*lock
, bool *need_issue
, list
<MDSInternalContextBase
*> *pfinishers
=0, bool first
=false) {
93 if (!lock
->is_stable())
94 eval_gather(lock
, first
, need_issue
, pfinishers
);
95 else if (lock
->get_parent()->is_auth())
96 eval(lock
, need_issue
);
99 void eval_scatter_gathers(CInode
*in
);
101 void eval_cap_gather(CInode
*in
, set
<CInode
*> *issue_set
=0);
103 bool eval(CInode
*in
, int mask
, bool caps_imported
=false);
104 void try_eval(MDSCacheObject
*p
, int mask
);
105 void try_eval(SimpleLock
*lock
, bool *pneed_issue
);
107 bool _rdlock_kick(SimpleLock
*lock
, bool as_anon
);
108 bool rdlock_try(SimpleLock
*lock
, client_t client
, MDSInternalContextBase
*c
);
109 bool rdlock_start(SimpleLock
*lock
, MDRequestRef
& mut
, bool as_anon
=false);
110 void rdlock_finish(SimpleLock
*lock
, MutationImpl
*mut
, bool *pneed_issue
);
111 bool can_rdlock_set(set
<SimpleLock
*>& locks
);
112 bool rdlock_try_set(set
<SimpleLock
*>& locks
);
113 void rdlock_take_set(set
<SimpleLock
*>& locks
, MutationRef
& mut
);
115 void wrlock_force(SimpleLock
*lock
, MutationRef
& mut
);
116 bool wrlock_start(SimpleLock
*lock
, MDRequestRef
& mut
, bool nowait
=false);
117 void wrlock_finish(SimpleLock
*lock
, MutationImpl
*mut
, bool *pneed_issue
);
119 void remote_wrlock_start(SimpleLock
*lock
, mds_rank_t target
, MDRequestRef
& mut
);
120 void remote_wrlock_finish(SimpleLock
*lock
, mds_rank_t target
, MutationImpl
*mut
);
122 bool xlock_start(SimpleLock
*lock
, MDRequestRef
& mut
);
123 void _finish_xlock(SimpleLock
*lock
, client_t xlocker
, bool *pneed_issue
);
124 void xlock_finish(SimpleLock
*lock
, MutationImpl
*mut
, bool *pneed_issue
);
126 void xlock_export(SimpleLock
*lock
, MutationImpl
*mut
);
127 void xlock_import(SimpleLock
*lock
);
132 void try_simple_eval(SimpleLock
*lock
);
133 bool simple_rdlock_try(SimpleLock
*lock
, MDSInternalContextBase
*con
);
135 void simple_eval(SimpleLock
*lock
, bool *need_issue
);
136 void handle_simple_lock(SimpleLock
*lock
, MLock
*m
);
139 bool simple_sync(SimpleLock
*lock
, bool *need_issue
=0);
141 void simple_lock(SimpleLock
*lock
, bool *need_issue
=0);
142 void simple_excl(SimpleLock
*lock
, bool *need_issue
=0);
143 void simple_xlock(SimpleLock
*lock
);
148 void scatter_eval(ScatterLock
*lock
, bool *need_issue
); // public for MDCache::adjust_subtree_auth()
151 void scatter_nudge(ScatterLock
*lock
, MDSInternalContextBase
*c
, bool forcelockchange
=false);
154 void handle_scatter_lock(ScatterLock
*lock
, MLock
*m
);
155 bool scatter_scatter_fastpath(ScatterLock
*lock
);
156 void scatter_scatter(ScatterLock
*lock
, bool nowait
=false);
157 void scatter_tempsync(ScatterLock
*lock
, bool *need_issue
=0);
159 void scatter_writebehind(ScatterLock
*lock
);
161 void scatter_writebehind_finish(ScatterLock
*lock
, MutationRef
& mut
);
163 xlist
<ScatterLock
*> updated_scatterlocks
;
165 void mark_updated_scatterlock(ScatterLock
*lock
);
168 void handle_reqrdlock(SimpleLock
*lock
, MLock
*m
);
174 // when to defer processing client cap release or writeback due to being
175 // frozen. the condition must be consistent across handle_client_caps and
176 // process_request_cap_release to preserve ordering.
177 bool should_defer_client_cap_frozen(CInode
*in
);
179 void process_request_cap_release(MDRequestRef
& mdr
, client_t client
, const ceph_mds_request_release
& r
,
180 const string
&dname
);
182 void kick_cap_releases(MDRequestRef
& mdr
);
183 void kick_issue_caps(CInode
*in
, client_t client
, ceph_seq_t seq
);
185 void remove_client_cap(CInode
*in
, client_t client
);
187 void get_late_revoking_clients(std::list
<client_t
> *result
) const;
188 bool any_late_revoking_caps(xlist
<Capability
*> const &revoking
) const;
191 bool _need_flush_mdlog(CInode
*in
, int wanted_caps
);
192 void adjust_cap_wanted(Capability
*cap
, int wanted
, int issue_seq
);
193 void handle_client_caps(class MClientCaps
*m
);
194 void _update_cap_fields(CInode
*in
, int dirty
, MClientCaps
*m
, inode_t
*pi
);
195 void _do_snap_update(CInode
*in
, snapid_t snap
, int dirty
, snapid_t follows
, client_t client
, MClientCaps
*m
, MClientCaps
*ack
);
196 void _do_null_snapflush(CInode
*head_in
, client_t client
, snapid_t last
=CEPH_NOSNAP
);
197 bool _do_cap_update(CInode
*in
, Capability
*cap
, int dirty
, snapid_t follows
, MClientCaps
*m
,
198 MClientCaps
*ack
=0, bool *need_flush
=NULL
);
199 void handle_client_cap_release(class MClientCapRelease
*m
);
200 void _do_cap_release(client_t client
, inodeno_t ino
, uint64_t cap_id
, ceph_seq_t mseq
, ceph_seq_t seq
);
203 // Maintain a global list to quickly find if any caps are late revoking
204 xlist
<Capability
*> revoking_caps
;
205 // Maintain a per-client list to find clients responsible for late ones quickly
206 std::map
<client_t
, xlist
<Capability
*> > revoking_caps_by_client
;
210 void local_wrlock_grab(LocalLock
*lock
, MutationRef
& mut
);
212 bool local_wrlock_start(LocalLock
*lock
, MDRequestRef
& mut
);
213 void local_wrlock_finish(LocalLock
*lock
, MutationImpl
*mut
);
214 bool local_xlock_start(LocalLock
*lock
, MDRequestRef
& mut
);
215 void local_xlock_finish(LocalLock
*lock
, MutationImpl
*mut
);
220 void file_eval(ScatterLock
*lock
, bool *need_issue
);
222 void handle_file_lock(ScatterLock
*lock
, MLock
*m
);
223 void scatter_mix(ScatterLock
*lock
, bool *need_issue
=0);
224 void file_excl(ScatterLock
*lock
, bool *need_issue
=0);
225 void file_xsyn(SimpleLock
*lock
, bool *need_issue
=0);
228 void file_recover(ScatterLock
*lock
);
231 xlist
<ScatterLock
*> updated_filelocks
;
233 void mark_updated_Filelock(ScatterLock
*lock
);
237 version_t
issue_file_data_version(CInode
*in
);
238 Capability
* issue_new_caps(CInode
*in
, int mode
, Session
*session
, SnapRealm
*conrealm
, bool is_replay
);
239 bool issue_caps(CInode
*in
, Capability
*only_cap
=0);
240 void issue_caps_set(set
<CInode
*>& inset
);
241 void issue_truncate(CInode
*in
);
242 void revoke_stale_caps(Session
*session
);
243 void revoke_stale_caps(Capability
*cap
);
244 void resume_stale_caps(Session
*session
);
245 void remove_stale_leases(Session
*session
);
248 void request_inode_file_caps(CInode
*in
);
250 void handle_inode_file_caps(class MInodeFileCaps
*m
);
252 void file_update_finish(CInode
*in
, MutationRef
& mut
, bool share_max
, bool issue_client_cap
,
253 client_t client
, MClientCaps
*ack
);
255 uint64_t calc_new_max_size(inode_t
*pi
, uint64_t size
);
257 void calc_new_client_ranges(CInode
*in
, uint64_t size
,
258 map
<client_t
, client_writeable_range_t
>* new_ranges
,
259 bool *max_increased
);
260 bool check_inode_max_size(CInode
*in
, bool force_wrlock
=false,
261 uint64_t newmax
=0, uint64_t newsize
=0,
262 utime_t mtime
=utime_t());
263 void share_inode_max_size(CInode
*in
, Capability
*only_cap
=0);
266 friend class C_MDL_CheckMaxSize
;
267 friend class C_MDL_RequestInodeFileCaps
;
268 friend class C_Locker_FileUpdate_finish
;
269 friend class C_Locker_RetryCapRelease
;
270 friend class C_Locker_Eval
;
271 friend class C_Locker_ScatterWB
;
272 friend class LockerContext
;
273 friend class LockerLogContext
;
276 // -- client leases --
278 void handle_client_lease(struct MClientLease
*m
);
280 void issue_client_lease(CDentry
*dn
, client_t client
, bufferlist
&bl
, utime_t now
, Session
*session
);
281 void revoke_client_leases(SimpleLock
*lock
);