]>
Commit | Line | Data |
---|---|---|
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- | |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #ifndef CEPH_CLIENT_METAREQUEST_H | |
5 | #define CEPH_CLIENT_METAREQUEST_H | |
6 | ||
7 | ||
8 | #include "include/types.h" | |
9 | #include "include/xlist.h" | |
10 | #include "include/filepath.h" | |
11 | #include "mds/mdstypes.h" | |
12 | #include "InodeRef.h" | |
13 | #include "UserPerm.h" | |
14 | ||
15 | #include "messages/MClientRequest.h" | |
16 | ||
17 | class MClientReply; | |
18 | class Dentry; | |
19 | class dir_result_t; | |
20 | ||
21 | struct MetaRequest { | |
22 | private: | |
23 | InodeRef _inode, _old_inode, _other_inode; | |
24 | Dentry *_dentry; //associated with path | |
25 | Dentry *_old_dentry; //associated with path2 | |
26 | int abort_rc; | |
27 | public: | |
28 | uint64_t tid; | |
29 | utime_t op_stamp; | |
30 | ceph_mds_request_head head; | |
31 | filepath path, path2; | |
32 | bufferlist data; | |
33 | int inode_drop; //the inode caps this operation will drop | |
34 | int inode_unless; //unless we have these caps already | |
35 | int old_inode_drop, old_inode_unless; | |
36 | int dentry_drop, dentry_unless; | |
37 | int old_dentry_drop, old_dentry_unless; | |
38 | int other_inode_drop, other_inode_unless; | |
39 | vector<MClientRequest::Release> cap_releases; | |
40 | ||
41 | int regetattr_mask; // getattr mask if i need to re-stat after a traceless reply | |
42 | ||
43 | utime_t sent_stamp; | |
44 | mds_rank_t mds; // who i am asking | |
45 | mds_rank_t resend_mds; // someone wants you to (re)send the request here | |
46 | bool send_to_auth; // must send to auth mds | |
47 | __u32 sent_on_mseq; // mseq at last submission of this request | |
48 | int num_fwd; // # of times i've been forwarded | |
49 | int retry_attempt; | |
50 | std::atomic<uint64_t> ref = { 1 }; | |
51 | ||
52 | MClientReply *reply; // the reply | |
53 | bool kick; | |
54 | bool success; | |
55 | ||
56 | // readdir result | |
57 | dir_result_t *dirp; | |
58 | ||
59 | //possible responses | |
60 | bool got_unsafe; | |
61 | ||
62 | xlist<MetaRequest*>::item item; | |
63 | xlist<MetaRequest*>::item unsafe_item; | |
64 | xlist<MetaRequest*>::item unsafe_dir_item; | |
65 | xlist<MetaRequest*>::item unsafe_target_item; | |
66 | ||
67 | Cond *caller_cond; // who to take up | |
68 | Cond *dispatch_cond; // who to kick back | |
69 | list<Cond*> waitfor_safe; | |
70 | ||
71 | InodeRef target; | |
72 | UserPerm perms; | |
73 | ||
74 | explicit MetaRequest(int op) : | |
75 | _dentry(NULL), _old_dentry(NULL), abort_rc(0), | |
76 | tid(0), | |
77 | inode_drop(0), inode_unless(0), | |
78 | old_inode_drop(0), old_inode_unless(0), | |
79 | dentry_drop(0), dentry_unless(0), | |
80 | old_dentry_drop(0), old_dentry_unless(0), | |
81 | other_inode_drop(0), other_inode_unless(0), | |
82 | regetattr_mask(0), | |
83 | mds(-1), resend_mds(-1), send_to_auth(false), sent_on_mseq(0), | |
84 | num_fwd(0), retry_attempt(0), | |
85 | reply(0), | |
86 | kick(false), success(false), | |
87 | got_unsafe(false), item(this), unsafe_item(this), | |
88 | unsafe_dir_item(this), unsafe_target_item(this), | |
89 | caller_cond(0), dispatch_cond(0) { | |
90 | memset(&head, 0, sizeof(head)); | |
91 | head.op = op; | |
92 | } | |
93 | ~MetaRequest(); | |
94 | ||
95 | /** | |
96 | * Prematurely terminate the request, such that callers | |
97 | * to make_request will receive `rc` as their result. | |
98 | */ | |
99 | void abort(int rc) | |
100 | { | |
101 | assert(rc != 0); | |
102 | abort_rc = rc; | |
103 | } | |
104 | ||
105 | /** | |
106 | * Whether abort() has been called for this request | |
107 | */ | |
108 | inline bool aborted() const | |
109 | { | |
110 | return abort_rc != 0; | |
111 | } | |
112 | ||
113 | /** | |
114 | * Given that abort() has been called for this request, what `rc` was | |
115 | * passed into it? | |
116 | */ | |
117 | int get_abort_code() const | |
118 | { | |
119 | return abort_rc; | |
120 | } | |
121 | ||
122 | void set_inode(Inode *in) { | |
123 | _inode = in; | |
124 | } | |
125 | Inode *inode() { | |
126 | return _inode.get(); | |
127 | } | |
128 | void take_inode(InodeRef *out) { | |
129 | out->swap(_inode); | |
130 | } | |
131 | void set_old_inode(Inode *in) { | |
132 | _old_inode = in; | |
133 | } | |
134 | Inode *old_inode() { | |
135 | return _old_inode.get(); | |
136 | } | |
137 | void take_old_inode(InodeRef *out) { | |
138 | out->swap(_old_inode); | |
139 | } | |
140 | void set_other_inode(Inode *in) { | |
141 | _other_inode = in; | |
142 | } | |
143 | Inode *other_inode() { | |
144 | return _other_inode.get(); | |
145 | } | |
146 | void take_other_inode(InodeRef *out) { | |
147 | out->swap(_other_inode); | |
148 | } | |
149 | void set_dentry(Dentry *d); | |
150 | Dentry *dentry(); | |
151 | void set_old_dentry(Dentry *d); | |
152 | Dentry *old_dentry(); | |
153 | ||
154 | MetaRequest* get() { | |
155 | ref++; | |
156 | return this; | |
157 | } | |
158 | ||
159 | /// psuedo-private put method; use Client::put_request() | |
160 | bool _put() { | |
161 | int v = --ref; | |
162 | return v == 0; | |
163 | } | |
164 | ||
165 | // normal fields | |
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.num_fwd = head.num_fwd + 1; } | |
169 | void set_retry_attempt(int a) { head.num_retry = a; } | |
170 | void set_filepath(const filepath& fp) { path = fp; } | |
171 | void set_filepath2(const filepath& fp) { path2 = fp; } | |
172 | void set_string2(const char *s) { path2.set_path(s, 0); } | |
173 | void set_caller_perms(const UserPerm& _perms) { | |
174 | perms.shallow_copy(_perms); | |
175 | head.caller_uid = perms.uid(); | |
176 | head.caller_gid = perms.gid(); | |
177 | } | |
178 | uid_t get_uid() { return perms.uid(); } | |
179 | uid_t get_gid() { return perms.gid(); } | |
180 | void set_data(const bufferlist &d) { data = d; } | |
181 | void set_dentry_wanted() { | |
182 | head.flags = head.flags | CEPH_MDS_FLAG_WANT_DENTRY; | |
183 | } | |
184 | int get_op() { return head.op; } | |
185 | ceph_tid_t get_tid() { return tid; } | |
186 | filepath& get_filepath() { return path; } | |
187 | filepath& get_filepath2() { return path2; } | |
188 | ||
189 | bool is_write() { | |
190 | return | |
191 | (head.op & CEPH_MDS_OP_WRITE) || | |
192 | (head.op == CEPH_MDS_OP_OPEN && (head.args.open.flags & (O_CREAT|O_TRUNC))); | |
193 | } | |
194 | bool can_forward() { | |
195 | if ((head.op & CEPH_MDS_OP_WRITE) || | |
196 | head.op == CEPH_MDS_OP_OPEN) // do not forward _any_ open request. | |
197 | return false; | |
198 | return true; | |
199 | } | |
200 | bool auth_is_best() { | |
201 | if ((head.op & CEPH_MDS_OP_WRITE) || head.op == CEPH_MDS_OP_OPEN || | |
202 | head.op == CEPH_MDS_OP_READDIR) | |
203 | return true; | |
204 | return false; | |
205 | } | |
206 | ||
207 | void dump(Formatter *f) const; | |
208 | ||
209 | }; | |
210 | ||
211 | #endif |