Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / messages / MClientRequest.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
2 // vim: ts=8 sw=2 smarttab
3 /*
4  * Ceph - scalable distributed file system
5  *
6  * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
7  *
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.
12  * 
13  */
14
15
16 #ifndef CEPH_MCLIENTREQUEST_H
17 #define CEPH_MCLIENTREQUEST_H
18
19 /**
20  *
21  * MClientRequest - container for a client METADATA request.  created/sent by clients.  
22  *    can be forwarded around between MDS's.
23  *
24  *   int client - the originating client
25  *   long tid   - transaction id, unique among requests for that client.  probably just a counter!
26  *                -> the MDS passes the Request to the Reply constructor, so this always matches.
27  *  
28  *   int op - the metadata op code.  MDS_OP_RENAME, etc.
29  *   int caller_uid, _gid - guess
30  * 
31  * fixed size arguments are in a union.
32  * there's also a string argument, for e.g. symlink().
33  *  
34  */
35
36 #include "msg/Message.h"
37 #include "include/filepath.h"
38 #include "mds/mdstypes.h"
39 #include "include/ceph_features.h"
40
41 #include <sys/types.h>
42 #include <utime.h>
43 #include <sys/stat.h>
44 #include <fcntl.h>
45
46
47 // metadata ops.
48
49 class MClientRequest : public Message {
50   static const int HEAD_VERSION = 4;
51   static const int COMPAT_VERSION = 1;
52
53 public:
54   struct ceph_mds_request_head head;
55   utime_t stamp;
56
57   struct Release {
58     mutable ceph_mds_request_release item;
59     string dname;
60
61     Release() : item(), dname() {}
62     Release(const ceph_mds_request_release& rel, string name) :
63       item(rel), dname(name) {}
64
65     void encode(bufferlist& bl) const {
66       item.dname_len = dname.length();
67       ::encode(item, bl);
68       ::encode_nohead(dname, bl);
69     }
70     void decode(bufferlist::iterator& bl) {
71       ::decode(item, bl);
72       ::decode_nohead(item.dname_len, dname, bl);
73     }
74   };
75   vector<Release> releases;
76
77   // path arguments
78   filepath path, path2;
79   vector<uint64_t> gid_list;
80
81   bool queued_for_replay = false;
82
83  public:
84   // cons
85   MClientRequest()
86     : Message(CEPH_MSG_CLIENT_REQUEST, HEAD_VERSION, COMPAT_VERSION) {}
87   MClientRequest(int op)
88     : Message(CEPH_MSG_CLIENT_REQUEST, HEAD_VERSION, COMPAT_VERSION) {
89     memset(&head, 0, sizeof(head));
90     head.op = op;
91   }
92 private:
93   ~MClientRequest() override {}
94
95 public:
96   void set_mdsmap_epoch(epoch_t e) { head.mdsmap_epoch = e; }
97   epoch_t get_mdsmap_epoch() { return head.mdsmap_epoch; }
98   epoch_t get_osdmap_epoch() const {
99     assert(head.op == CEPH_MDS_OP_SETXATTR);
100     if (header.version >= 3)
101       return head.args.setxattr.osdmap_epoch;
102     else
103       return 0;
104   }
105   void set_osdmap_epoch(epoch_t e) {
106     assert(head.op == CEPH_MDS_OP_SETXATTR);
107     head.args.setxattr.osdmap_epoch = e;
108   }
109
110   metareqid_t get_reqid() {
111     // FIXME: for now, assume clients always have 1 incarnation
112     return metareqid_t(get_orig_source(), header.tid); 
113   }
114
115   /*bool open_file_mode_is_readonly() {
116     return file_mode_is_readonly(ceph_flags_to_mode(head.args.open.flags));
117     }*/
118   bool may_write() {
119     return
120       (head.op & CEPH_MDS_OP_WRITE) || 
121       (head.op == CEPH_MDS_OP_OPEN && (head.args.open.flags & (O_CREAT|O_TRUNC)));
122   }
123
124   int get_flags() const {
125     return head.flags;
126   }
127   bool is_replay() {
128     return get_flags() & CEPH_MDS_FLAG_REPLAY;
129   }
130
131   // normal fields
132   void set_stamp(utime_t t) { stamp = t; }
133   void set_oldest_client_tid(ceph_tid_t t) { head.oldest_client_tid = t; }
134   void inc_num_fwd() { head.num_fwd = head.num_fwd + 1; }
135   void set_retry_attempt(int a) { head.num_retry = a; }
136   void set_filepath(const filepath& fp) { path = fp; }
137   void set_filepath2(const filepath& fp) { path2 = fp; }
138   void set_string2(const char *s) { path2.set_path(s, 0); }
139   void set_caller_uid(unsigned u) { head.caller_uid = u; }
140   void set_caller_gid(unsigned g) { head.caller_gid = g; }
141   void set_gid_list(int count, const gid_t *gids) {
142     gid_list.reserve(count);
143     for (int i = 0; i < count; ++i) {
144       gid_list.push_back(gids[i]);
145     }
146   }
147   void set_dentry_wanted() {
148     head.flags = head.flags | CEPH_MDS_FLAG_WANT_DENTRY;
149   }
150   void set_replayed_op() {
151     head.flags = head.flags | CEPH_MDS_FLAG_REPLAY;
152   }
153
154   utime_t get_stamp() const { return stamp; }
155   ceph_tid_t get_oldest_client_tid() const { return head.oldest_client_tid; }
156   int get_num_fwd() const { return head.num_fwd; }
157   int get_retry_attempt() const { return head.num_retry; }
158   int get_op() const { return head.op; }
159   unsigned get_caller_uid() const { return head.caller_uid; }
160   unsigned get_caller_gid() const { return head.caller_gid; }
161   const vector<uint64_t>& get_caller_gid_list() const { return gid_list; }
162
163   const string& get_path() const { return path.get_path(); }
164   const filepath& get_filepath() const { return path; }
165   const string& get_path2() const { return path2.get_path(); }
166   const filepath& get_filepath2() const { return path2; }
167
168   int get_dentry_wanted() { return get_flags() & CEPH_MDS_FLAG_WANT_DENTRY; }
169
170   void mark_queued_for_replay() { queued_for_replay = true; }
171   bool is_queued_for_replay() { return queued_for_replay; }
172
173   void decode_payload() override {
174     bufferlist::iterator p = payload.begin();
175
176     if (header.version >= 4) {
177       ::decode(head, p);
178     } else {
179       struct ceph_mds_request_head_legacy old_mds_head;
180
181       ::decode(old_mds_head, p);
182       copy_from_legacy_head(&head, &old_mds_head);
183       head.version = 0;
184
185       /* Can't set the btime from legacy struct */
186       if (head.op == CEPH_MDS_OP_SETATTR) {
187         int localmask = head.args.setattr.mask;
188
189         localmask &= ~CEPH_SETATTR_BTIME;
190
191         head.args.setattr.btime = { 0 };
192         head.args.setattr.mask = localmask;
193       }
194     }
195
196     ::decode(path, p);
197     ::decode(path2, p);
198     ::decode_nohead(head.num_releases, releases, p);
199     if (header.version >= 2)
200       ::decode(stamp, p);
201     if (header.version >= 4) // epoch 3 was for a ceph_mds_request_args change
202       ::decode(gid_list, p);
203   }
204
205   void encode_payload(uint64_t features) override {
206     head.num_releases = releases.size();
207     head.version = CEPH_MDS_REQUEST_HEAD_VERSION;
208
209     if (features & CEPH_FEATURE_FS_BTIME) {
210       ::encode(head, payload);
211     } else {
212       struct ceph_mds_request_head_legacy old_mds_head;
213
214       copy_to_legacy_head(&old_mds_head, &head);
215       ::encode(old_mds_head, payload);
216     }
217
218     ::encode(path, payload);
219     ::encode(path2, payload);
220     ::encode_nohead(releases, payload);
221     ::encode(stamp, payload);
222     ::encode(gid_list, payload);
223   }
224
225   const char *get_type_name() const override { return "creq"; }
226   void print(ostream& out) const override {
227     out << "client_request(" << get_orig_source() 
228         << ":" << get_tid() 
229         << " " << ceph_mds_op_name(get_op());
230     if (head.op == CEPH_MDS_OP_GETATTR)
231       out << " " << ccap_string(head.args.getattr.mask);
232     if (head.op == CEPH_MDS_OP_SETATTR) {
233       if (head.args.setattr.mask & CEPH_SETATTR_MODE)
234         out << " mode=0" << std::oct << head.args.setattr.mode << std::dec;
235       if (head.args.setattr.mask & CEPH_SETATTR_UID)
236         out << " uid=" << head.args.setattr.uid;
237       if (head.args.setattr.mask & CEPH_SETATTR_GID)
238         out << " gid=" << head.args.setattr.gid;
239       if (head.args.setattr.mask & CEPH_SETATTR_SIZE)
240         out << " size=" << head.args.setattr.size;
241       if (head.args.setattr.mask & CEPH_SETATTR_MTIME)
242         out << " mtime=" << utime_t(head.args.setattr.mtime);
243       if (head.args.setattr.mask & CEPH_SETATTR_ATIME)
244         out << " atime=" << utime_t(head.args.setattr.atime);
245     }
246     if (head.op == CEPH_MDS_OP_SETFILELOCK ||
247         head.op == CEPH_MDS_OP_GETFILELOCK) {
248       out << "rule " << (int)head.args.filelock_change.rule
249           << ", type " << (int)head.args.filelock_change.type
250           << ", owner " << head.args.filelock_change.owner
251           << ", pid " << head.args.filelock_change.pid
252           << ", start " << head.args.filelock_change.start
253           << ", length " << head.args.filelock_change.length
254           << ", wait " << (int)head.args.filelock_change.wait;
255     }
256     //if (!get_filepath().empty()) 
257     out << " " << get_filepath();
258     if (!get_filepath2().empty())
259       out << " " << get_filepath2();
260     if (stamp != utime_t())
261       out << " " << stamp;
262     if (head.num_retry)
263       out << " RETRY=" << (int)head.num_retry;
264     if (get_flags() & CEPH_MDS_FLAG_REPLAY)
265       out << " REPLAY";
266     if (queued_for_replay)
267       out << " QUEUED_FOR_REPLAY";
268     out << " caller_uid=" << head.caller_uid
269         << ", caller_gid=" << head.caller_gid
270         << '{';
271     for (auto i = gid_list.begin(); i != gid_list.end(); ++i)
272       out << *i << ',';
273     out << '}'
274         << ")";
275   }
276
277 };
278
279 WRITE_CLASS_ENCODER(MClientRequest::Release)
280
281 #endif