Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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
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