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