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