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