1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #ifndef CEPH_CLIENT_METAREQUEST_H
5 #define CEPH_CLIENT_METAREQUEST_H
8 #include "include/types.h"
9 #include "include/xlist.h"
10 #include "include/filepath.h"
11 #include "mds/mdstypes.h"
15 #include "messages/MClientRequest.h"
16 #include "messages/MClientReply.h"
23 InodeRef _inode
, _old_inode
, _other_inode
;
24 Dentry
*_dentry
= NULL
; //associated with path
25 Dentry
*_old_dentry
= NULL
; //associated with path2
28 ceph::coarse_mono_time created
= ceph::coarse_mono_clock::zero();
31 ceph_mds_request_head head
;
33 std::string alternate_name
;
34 std::vector
<uint8_t> fscrypt_auth
;
35 std::vector
<uint8_t> fscrypt_file
;
37 int inode_drop
= 0; //the inode caps this operation will drop
38 int inode_unless
= 0; //unless we have these caps already
39 int old_inode_drop
= 0, old_inode_unless
= 0;
40 int dentry_drop
= 0, dentry_unless
= 0;
41 int old_dentry_drop
= 0, old_dentry_unless
= 0;
42 int other_inode_drop
= 0, other_inode_unless
= 0;
43 std::vector
<MClientRequest::Release
> cap_releases
;
45 int regetattr_mask
= 0; // getattr mask if i need to re-stat after a traceless reply
48 mds_rank_t mds
= -1; // who i am asking
49 mds_rank_t resend_mds
= -1; // someone wants you to (re)send the request here
50 bool send_to_auth
= false; // must send to auth mds
51 __u32 sent_on_mseq
= 0; // mseq at last submission of this request
52 int num_fwd
= 0; // # of times i've been forwarded
53 int retry_attempt
= 0;
54 std::atomic
<uint64_t> ref
= { 1 };
56 ceph::cref_t
<MClientReply
> reply
= NULL
; // the reply
61 dir_result_t
*dirp
= NULL
;
64 bool got_unsafe
= false;
66 xlist
<MetaRequest
*>::item item
;
67 xlist
<MetaRequest
*>::item unsafe_item
;
68 xlist
<MetaRequest
*>::item unsafe_dir_item
;
69 xlist
<MetaRequest
*>::item unsafe_target_item
;
71 ceph::condition_variable
*caller_cond
= NULL
; // who to take up
72 ceph::condition_variable
*dispatch_cond
= NULL
; // who to kick back
73 std::list
<ceph::condition_variable
*> waitfor_safe
;
78 explicit MetaRequest(int op
) :
79 item(this), unsafe_item(this), unsafe_dir_item(this),
80 unsafe_target_item(this) {
81 memset(&head
, 0, sizeof(head
));
89 * Prematurely terminate the request, such that callers
90 * to make_request will receive `rc` as their result.
99 * Whether abort() has been called for this request
101 inline bool aborted() const
103 return abort_rc
!= 0;
107 * Given that abort() has been called for this request, what `rc` was
110 int get_abort_code() const
115 void set_inode(Inode
*in
) {
121 void take_inode(InodeRef
*out
) {
124 void set_old_inode(Inode
*in
) {
128 return _old_inode
.get();
130 void take_old_inode(InodeRef
*out
) {
131 out
->swap(_old_inode
);
133 void set_other_inode(Inode
*in
) {
136 Inode
*other_inode() {
137 return _other_inode
.get();
139 void take_other_inode(InodeRef
*out
) {
140 out
->swap(_other_inode
);
142 void set_dentry(Dentry
*d
);
144 void set_old_dentry(Dentry
*d
);
145 Dentry
*old_dentry();
152 /// psuedo-private put method; use Client::put_request()
158 void set_inode_owner_uid_gid(unsigned u
, unsigned g
) {
159 /* it makes sense to set owner_{u,g}id only for OPs which create inodes */
160 ceph_assert(IS_CEPH_MDS_OP_NEWINODE(head
.op
));
166 void set_tid(ceph_tid_t t
) { tid
= t
; }
167 void set_oldest_client_tid(ceph_tid_t t
) { head
.oldest_client_tid
= t
; }
168 void inc_num_fwd() { head
.ext_num_fwd
= head
.ext_num_fwd
+ 1; }
169 void set_retry_attempt(int a
) { head
.ext_num_retry
= a
; }
170 void set_filepath(const filepath
& fp
) { path
= fp
; }
171 void set_filepath2(const filepath
& fp
) { path2
= fp
; }
172 void set_alternate_name(std::string an
) { alternate_name
= an
; }
173 void set_string2(const char *s
) { path2
.set_path(std::string_view(s
), 0); }
174 void set_caller_perms(const UserPerm
& _perms
) {
176 head
.caller_uid
= perms
.uid();
177 head
.caller_gid
= perms
.gid();
179 uid_t
get_uid() { return perms
.uid(); }
180 uid_t
get_gid() { return perms
.gid(); }
181 void set_data(const bufferlist
&d
) { data
= d
; }
182 void set_dentry_wanted() {
183 head
.flags
= head
.flags
| CEPH_MDS_FLAG_WANT_DENTRY
;
185 int get_op() { return head
.op
; }
186 ceph_tid_t
get_tid() { return tid
; }
187 filepath
& get_filepath() { return path
; }
188 filepath
& get_filepath2() { return path2
; }
192 (head
.op
& CEPH_MDS_OP_WRITE
) ||
193 (head
.op
== CEPH_MDS_OP_OPEN
&& (head
.args
.open
.flags
& (O_CREAT
|O_TRUNC
)));
196 if ((head
.op
& CEPH_MDS_OP_WRITE
) ||
197 head
.op
== CEPH_MDS_OP_OPEN
) // do not forward _any_ open request.
201 bool auth_is_best(int issued
) {
206 if (head
.op
& CEPH_MDS_OP_WRITE
)
210 case CEPH_MDS_OP_OPEN
:
211 case CEPH_MDS_OP_READDIR
:
213 case CEPH_MDS_OP_GETATTR
:
215 * If any 'x' caps is issued we can just choose the auth MDS
216 * instead of the random replica MDSes. Because only when the
217 * Locker is in LOCK_EXEC state will the loner client could
218 * get the 'x' caps. And if we send the getattr requests to
219 * any replica MDS it must auth pin and tries to rdlock from
220 * the auth MDS, and then the auth MDS need to do the Locker
221 * state transition to LOCK_SYNC. And after that the lock state
224 * This cost much when doing the Locker state transition and
225 * usually will need to revoke caps from clients.
227 * And for the 'Xs' caps for getxattr we will also choose the
228 * auth MDS, because the MDS side code is buggy due to setxattr
229 * won't notify the replica MDSes when the values changed and
230 * the replica MDS will return the old values. Though we will
231 * fix it in MDS code, but this still makes sense for old ceph.
233 if (((head
.args
.getattr
.mask
& CEPH_CAP_ANY_SHARED
) &&
234 (issued
& CEPH_CAP_ANY_EXCL
)) ||
235 (head
.args
.getattr
.mask
& (CEPH_STAT_RSTAT
| CEPH_STAT_CAP_XATTR
)))
242 void dump(Formatter
*f
) const;