]> git.proxmox.com Git - ceph.git/blob - ceph/src/client/Inode.h
update sources to 12.2.7
[ceph.git] / ceph / src / client / Inode.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_INODE_H
5 #define CEPH_CLIENT_INODE_H
6
7 #include <numeric>
8
9 #include "include/types.h"
10 #include "include/xlist.h"
11
12 #include "mds/mdstypes.h" // hrm
13
14 #include "osdc/ObjectCacher.h"
15 #include "include/assert.h"
16
17 #include "InodeRef.h"
18 #include "UserPerm.h"
19 #include "Delegation.h"
20
21 class Client;
22 struct MetaSession;
23 class Dentry;
24 class Dir;
25 struct SnapRealm;
26 struct Inode;
27 class ceph_lock_state_t;
28 class MetaRequest;
29 class filepath;
30 class Fh;
31
32 struct Cap {
33 MetaSession *session;
34 Inode *inode;
35 xlist<Cap*>::item cap_item;
36
37 uint64_t cap_id;
38 unsigned issued;
39 unsigned implemented;
40 unsigned wanted; // as known to mds.
41 uint64_t seq, issue_seq;
42 __u32 mseq; // migration seq
43 __u32 gen;
44 UserPerm latest_perms;
45
46 Cap() : session(NULL), inode(NULL), cap_item(this), cap_id(0), issued(0),
47 implemented(0), wanted(0), seq(0), issue_seq(0), mseq(0), gen(0),
48 latest_perms() {}
49
50 void dump(Formatter *f) const;
51 };
52
53 struct CapSnap {
54 //snapid_t follows; // map key
55 InodeRef in;
56 SnapContext context;
57 int issued, dirty;
58
59 uint64_t size;
60 utime_t ctime, btime, mtime, atime;
61 version_t time_warp_seq;
62 uint64_t change_attr;
63 uint32_t mode;
64 uid_t uid;
65 gid_t gid;
66 map<string,bufferptr> xattrs;
67 version_t xattr_version;
68
69 bufferlist inline_data;
70 version_t inline_version;
71
72 bool writing, dirty_data;
73 uint64_t flush_tid;
74
75 explicit CapSnap(Inode *i)
76 : in(i), issued(0), dirty(0), size(0), time_warp_seq(0), change_attr(0),
77 mode(0), uid(0), gid(0), xattr_version(0), inline_version(0),
78 writing(false), dirty_data(false), flush_tid(0)
79 {}
80
81 void dump(Formatter *f) const;
82 };
83
84 // inode flags
85 #define I_COMPLETE 1
86 #define I_DIR_ORDERED 2
87 #define I_CAP_DROPPED 4
88 #define I_SNAPDIR_OPEN 8
89
90 struct Inode {
91 Client *client;
92
93 // -- the actual inode --
94 inodeno_t ino; // ORDER DEPENDENCY: oset
95 snapid_t snapid;
96 ino_t faked_ino;
97
98 uint32_t rdev; // if special file
99
100 // affected by any inode change...
101 utime_t ctime; // inode change time
102 utime_t btime; // birth time
103
104 // perm (namespace permissions)
105 uint32_t mode;
106 uid_t uid;
107 gid_t gid;
108
109 // nlink
110 int32_t nlink;
111
112 // file (data access)
113 ceph_dir_layout dir_layout;
114 file_layout_t layout;
115 uint64_t size; // on directory, # dentries
116 uint32_t truncate_seq;
117 uint64_t truncate_size;
118 utime_t mtime; // file data modify time.
119 utime_t atime; // file data access time.
120 uint32_t time_warp_seq; // count of (potential) mtime/atime timewarps (i.e., utimes())
121 uint64_t change_attr;
122
123 uint64_t max_size; // max size we can write to
124
125 // dirfrag, recursive accountin
126 frag_info_t dirstat;
127 nest_info_t rstat;
128
129 // special stuff
130 version_t version; // auth only
131 version_t xattr_version;
132
133 // inline data
134 version_t inline_version;
135 bufferlist inline_data;
136
137 bool is_root() const { return ino == MDS_INO_ROOT; }
138 bool is_symlink() const { return (mode & S_IFMT) == S_IFLNK; }
139 bool is_dir() const { return (mode & S_IFMT) == S_IFDIR; }
140 bool is_file() const { return (mode & S_IFMT) == S_IFREG; }
141
142 bool has_dir_layout() const {
143 return layout != file_layout_t();
144 }
145
146 __u32 hash_dentry_name(const string &dn) {
147 int which = dir_layout.dl_dir_hash;
148 if (!which)
149 which = CEPH_STR_HASH_LINUX;
150 assert(ceph_str_hash_valid(which));
151 return ceph_str_hash(which, dn.data(), dn.length());
152 }
153
154 unsigned flags;
155
156 quota_info_t quota;
157
158 bool is_complete_and_ordered() {
159 static const unsigned wants = I_COMPLETE | I_DIR_ORDERED;
160 return (flags & wants) == wants;
161 }
162
163 // about the dir (if this is one!)
164 Dir *dir; // if i'm a dir.
165 fragtree_t dirfragtree;
166 set<int> dir_contacts;
167 uint64_t dir_release_count, dir_ordered_count;
168 bool dir_hashed, dir_replicated;
169
170 // per-mds caps
171 map<mds_rank_t, Cap*> caps; // mds -> Cap
172 Cap *auth_cap;
173 int64_t cap_dirtier_uid;
174 int64_t cap_dirtier_gid;
175 unsigned dirty_caps, flushing_caps;
176 std::map<ceph_tid_t, int> flushing_cap_tids;
177 int shared_gen, cache_gen;
178 int snap_caps, snap_cap_refs;
179 utime_t hold_caps_until;
180 xlist<Inode*>::item delay_cap_item, dirty_cap_item, flushing_cap_item;
181
182 SnapRealm *snaprealm;
183 xlist<Inode*>::item snaprealm_item;
184 InodeRef snapdir_parent; // only if we are a snapdir inode
185 map<snapid_t,CapSnap> cap_snaps; // pending flush to mds
186
187 //int open_by_mode[CEPH_FILE_MODE_NUM];
188 map<int,int> open_by_mode;
189 map<int,int> cap_refs;
190
191 ObjectCacher::ObjectSet oset; // ORDER DEPENDENCY: ino
192
193 uint64_t reported_size, wanted_max_size, requested_max_size;
194
195 int _ref; // ref count. 1 for each dentry, fh that links to me.
196 int ll_ref; // separate ref count for ll client
197 set<Dentry*> dn_set; // if i'm linked to a dentry.
198 string symlink; // symlink content, if it's a symlink
199 map<string,bufferptr> xattrs;
200 map<frag_t,int> fragmap; // known frag -> mds mappings
201
202 list<Cond*> waitfor_caps;
203 list<Cond*> waitfor_commit;
204 list<Cond*> waitfor_deleg;
205
206 Dentry *get_first_parent() {
207 assert(!dn_set.empty());
208 return *dn_set.begin();
209 }
210
211 void make_long_path(filepath& p);
212 void make_nosnap_relative_path(filepath& p);
213
214 void get();
215 int _put(int n=1);
216
217 int get_num_ref() {
218 return _ref;
219 }
220
221 void ll_get() {
222 ll_ref++;
223 }
224 void ll_put(int n=1) {
225 assert(ll_ref >= n);
226 ll_ref -= n;
227 }
228
229 // file locks
230 ceph_lock_state_t *fcntl_locks;
231 ceph_lock_state_t *flock_locks;
232
233 list<Delegation> delegations;
234
235 xlist<MetaRequest*> unsafe_ops;
236
237 std::set<Fh*> fhs;
238
239 Inode(Client *c, vinodeno_t vino, file_layout_t *newlayout)
240 : client(c), ino(vino.ino), snapid(vino.snapid), faked_ino(0),
241 rdev(0), mode(0), uid(0), gid(0), nlink(0),
242 size(0), truncate_seq(1), truncate_size(-1),
243 time_warp_seq(0), change_attr(0), max_size(0), version(0),
244 xattr_version(0), inline_version(0), flags(0),
245 dir(0), dir_release_count(1), dir_ordered_count(1),
246 dir_hashed(false), dir_replicated(false), auth_cap(NULL),
247 cap_dirtier_uid(-1), cap_dirtier_gid(-1),
248 dirty_caps(0), flushing_caps(0), shared_gen(0), cache_gen(0),
249 snap_caps(0), snap_cap_refs(0),
250 delay_cap_item(this), dirty_cap_item(this), flushing_cap_item(this),
251 snaprealm(0), snaprealm_item(this),
252 oset((void *)this, newlayout->pool_id, this->ino),
253 reported_size(0), wanted_max_size(0), requested_max_size(0),
254 _ref(0), ll_ref(0), dn_set(),
255 fcntl_locks(NULL), flock_locks(NULL)
256 {
257 memset(&dir_layout, 0, sizeof(dir_layout));
258 memset(&quota, 0, sizeof(quota));
259 }
260 ~Inode();
261
262 vinodeno_t vino() const { return vinodeno_t(ino, snapid); }
263
264 struct Compare {
265 bool operator() (Inode* const & left, Inode* const & right) {
266 if (left->ino.val < right->ino.val) {
267 return (left->snapid.val < right->snapid.val);
268 }
269 return false;
270 }
271 };
272
273 bool check_mode(const UserPerm& perms, unsigned want);
274
275 // CAPS --------
276 void get_open_ref(int mode);
277 bool put_open_ref(int mode);
278
279 void get_cap_ref(int cap);
280 int put_cap_ref(int cap);
281 bool is_any_caps();
282 bool cap_is_valid(Cap* cap) const;
283 int caps_issued(int *implemented = 0) const;
284 void touch_cap(Cap *cap);
285 void try_touch_cap(mds_rank_t mds);
286 bool caps_issued_mask(unsigned mask, bool allow_impl=false);
287 int caps_used();
288 int caps_file_wanted();
289 int caps_wanted();
290 int caps_mds_wanted();
291 int caps_dirty();
292 const UserPerm *get_best_perms();
293
294 bool have_valid_size();
295 Dir *open_dir();
296
297 void add_fh(Fh *f) {fhs.insert(f);}
298 void rm_fh(Fh *f) {fhs.erase(f);}
299 void set_async_err(int r);
300 void dump(Formatter *f) const;
301
302 void break_all_delegs() { break_deleg(false); };
303
304 void recall_deleg(bool skip_read);
305 bool has_recalled_deleg();
306 int set_deleg(Fh *fh, unsigned type, ceph_deleg_cb_t cb, void *priv);
307 void unset_deleg(Fh *fh);
308
309 void mark_caps_dirty(int caps);
310 void mark_caps_clean();
311 private:
312 // how many opens for write on this Inode?
313 long open_count_for_write()
314 {
315 return (long)(open_by_mode[CEPH_FILE_MODE_RDWR] +
316 open_by_mode[CEPH_FILE_MODE_WR]);
317 };
318
319 // how many opens of any sort on this inode?
320 long open_count()
321 {
322 return (long) std::accumulate(open_by_mode.begin(), open_by_mode.end(), 0,
323 [] (int value, const std::map<int, int>::value_type& p)
324 { return value + p.second; });
325 };
326
327 void break_deleg(bool skip_read);
328 bool delegations_broken(bool skip_read);
329
330 };
331
332 ostream& operator<<(ostream &out, const Inode &in);
333
334 #endif