]>
Commit | Line | Data |
---|---|---|
959ef981 | 1 | // SPDX-License-Identifier: GPL-2.0 |
b626fb59 DC |
2 | /* |
3 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. | |
4 | * All Rights Reserved. | |
b626fb59 DC |
5 | */ |
6 | ||
7 | #ifndef __XFS_INODE_H__ | |
8 | #define __XFS_INODE_H__ | |
9 | ||
04fd1569 DW |
10 | /* |
11 | * Borrow the kernel's uid/gid types. These are used by xfs_inode_util.h, so | |
12 | * they must come first in the header file. | |
13 | */ | |
14 | ||
15 | typedef struct { | |
16 | uid_t val; | |
17 | } kuid_t; | |
18 | ||
19 | typedef struct { | |
20 | gid_t val; | |
21 | } kgid_t; | |
22 | ||
23 | static inline kuid_t make_kuid(uid_t uid) | |
24 | { | |
25 | kuid_t v = { .val = uid }; | |
26 | return v; | |
27 | } | |
28 | ||
29 | static inline kgid_t make_kgid(gid_t gid) | |
30 | { | |
31 | kgid_t v = { .val = gid }; | |
32 | return v; | |
33 | } | |
34 | ||
35 | #define KUIDT_INIT(value) (kuid_t){ value } | |
36 | #define KGIDT_INIT(value) (kgid_t){ value } | |
37 | #define GLOBAL_ROOT_UID KUIDT_INIT(0) | |
38 | #define GLOBAL_ROOT_GID KGIDT_INIT(0) | |
39 | ||
b626fb59 | 40 | /* These match kernel side includes */ |
6b803e5a CH |
41 | #include "xfs_inode_buf.h" |
42 | #include "xfs_inode_fork.h" | |
fadb819b | 43 | #include "xfs_inode_util.h" |
b626fb59 DC |
44 | |
45 | struct xfs_trans; | |
46 | struct xfs_mount; | |
47 | struct xfs_inode_log_item; | |
a565e345 | 48 | struct inode; |
b626fb59 | 49 | |
b192e77c ES |
50 | /* |
51 | * These are not actually used, they are only for userspace build | |
52 | * compatibility in code that looks at i_state | |
53 | */ | |
54 | #define I_DIRTY_TIME 0 | |
55 | #define I_DIRTY_TIME_EXPIRED 0 | |
56 | ||
a565e345 | 57 | static inline bool IS_I_VERSION(const struct inode *inode) { return false; } |
b192e77c ES |
58 | #define inode_maybe_inc_iversion(inode,flags) (0) |
59 | ||
b626fb59 | 60 | /* |
1bc6cbe3 DC |
61 | * Inode interface. This fakes up a "VFS inode" to make the xfs_inode appear |
62 | * similar to the kernel which now is used tohold certain parts of the on-disk | |
63 | * metadata. | |
b626fb59 | 64 | */ |
1bc6cbe3 | 65 | struct inode { |
ec24f6fa | 66 | mode_t i_mode; |
04fd1569 DW |
67 | kuid_t i_uid; |
68 | kgid_t i_gid; | |
ec24f6fa DW |
69 | uint32_t i_nlink; |
70 | xfs_dev_t i_rdev; /* This actually holds xfs_dev_t */ | |
50edfee5 | 71 | unsigned int i_count; |
ec24f6fa DW |
72 | unsigned long i_state; /* Not actually used in userspace */ |
73 | uint32_t i_generation; | |
74 | uint64_t i_version; | |
bb16db6a JL |
75 | struct timespec64 __i_atime; |
76 | struct timespec64 __i_mtime; | |
6cfd0b48 | 77 | struct timespec64 __i_ctime; /* use inode_*_ctime accessors! */ |
686bddf9 | 78 | spinlock_t i_lock; |
1bc6cbe3 DC |
79 | }; |
80 | ||
fdf7f987 DW |
81 | static inline void |
82 | inode_set_iversion(struct inode *inode, uint64_t version) | |
83 | { | |
84 | inode->i_version = version; | |
85 | } | |
86 | ||
100eb9e9 CH |
87 | static inline uint32_t i_uid_read(struct inode *inode) |
88 | { | |
04fd1569 | 89 | return inode->i_uid.val; |
100eb9e9 CH |
90 | } |
91 | static inline uint32_t i_gid_read(struct inode *inode) | |
92 | { | |
04fd1569 | 93 | return inode->i_gid.val; |
100eb9e9 | 94 | } |
04fd1569 | 95 | static inline void i_uid_write(struct inode *inode, uid_t uid) |
100eb9e9 | 96 | { |
04fd1569 | 97 | inode->i_uid.val = uid; |
100eb9e9 | 98 | } |
04fd1569 | 99 | static inline void i_gid_write(struct inode *inode, gid_t gid) |
100eb9e9 | 100 | { |
04fd1569 | 101 | inode->i_gid.val = gid; |
100eb9e9 CH |
102 | } |
103 | ||
fdf7f987 DW |
104 | static inline void inode_fsuid_set(struct inode *inode, |
105 | struct mnt_idmap *idmap) | |
106 | { | |
107 | inode->i_uid = make_kuid(0); | |
108 | } | |
109 | ||
110 | static inline void inode_fsgid_set(struct inode *inode, | |
111 | struct mnt_idmap *idmap) | |
112 | { | |
113 | inode->i_gid = make_kgid(0); | |
114 | } | |
115 | ||
50edfee5 DW |
116 | static inline void ihold(struct inode *inode) |
117 | { | |
118 | inode->i_count++; | |
119 | } | |
120 | ||
bb16db6a JL |
121 | static inline time64_t inode_get_atime_sec(const struct inode *inode) |
122 | { | |
123 | return inode->__i_atime.tv_sec; | |
124 | } | |
125 | ||
126 | static inline long inode_get_atime_nsec(const struct inode *inode) | |
127 | { | |
128 | return inode->__i_atime.tv_nsec; | |
129 | } | |
130 | ||
131 | static inline struct timespec64 inode_get_atime(const struct inode *inode) | |
132 | { | |
133 | return inode->__i_atime; | |
134 | } | |
135 | ||
136 | static inline struct timespec64 inode_set_atime_to_ts(struct inode *inode, | |
137 | struct timespec64 ts) | |
138 | { | |
139 | inode->__i_atime = ts; | |
140 | return ts; | |
141 | } | |
142 | ||
143 | static inline struct timespec64 inode_set_atime(struct inode *inode, | |
144 | time64_t sec, long nsec) | |
145 | { | |
146 | struct timespec64 ts = { .tv_sec = sec, | |
147 | .tv_nsec = nsec }; | |
148 | return inode_set_atime_to_ts(inode, ts); | |
149 | } | |
150 | ||
151 | static inline time64_t inode_get_mtime_sec(const struct inode *inode) | |
152 | { | |
153 | return inode->__i_mtime.tv_sec; | |
154 | } | |
155 | ||
156 | static inline long inode_get_mtime_nsec(const struct inode *inode) | |
157 | { | |
158 | return inode->__i_mtime.tv_nsec; | |
159 | } | |
160 | ||
161 | static inline struct timespec64 inode_get_mtime(const struct inode *inode) | |
162 | { | |
163 | return inode->__i_mtime; | |
164 | } | |
165 | ||
166 | static inline struct timespec64 inode_set_mtime_to_ts(struct inode *inode, | |
167 | struct timespec64 ts) | |
168 | { | |
169 | inode->__i_mtime = ts; | |
170 | return ts; | |
171 | } | |
172 | ||
173 | static inline struct timespec64 inode_set_mtime(struct inode *inode, | |
174 | time64_t sec, long nsec) | |
175 | { | |
176 | struct timespec64 ts = { .tv_sec = sec, | |
177 | .tv_nsec = nsec }; | |
178 | return inode_set_mtime_to_ts(inode, ts); | |
179 | } | |
180 | ||
181 | static inline time64_t inode_get_ctime_sec(const struct inode *inode) | |
182 | { | |
183 | return inode->__i_ctime.tv_sec; | |
184 | } | |
185 | ||
186 | static inline long inode_get_ctime_nsec(const struct inode *inode) | |
187 | { | |
188 | return inode->__i_ctime.tv_nsec; | |
189 | } | |
190 | ||
6cfd0b48 JL |
191 | static inline struct timespec64 inode_get_ctime(const struct inode *inode) |
192 | { | |
faea09b8 | 193 | return inode->__i_ctime; |
6cfd0b48 JL |
194 | } |
195 | ||
196 | static inline struct timespec64 inode_set_ctime_to_ts(struct inode *inode, | |
197 | struct timespec64 ts) | |
198 | { | |
199 | inode->__i_ctime = ts; | |
200 | return ts; | |
201 | } | |
202 | ||
f99988c2 JL |
203 | extern struct timespec64 current_time(struct inode *inode); |
204 | ||
205 | static inline struct timespec64 inode_set_ctime_current(struct inode *inode) | |
206 | { | |
207 | struct timespec64 now = current_time(inode); | |
208 | ||
209 | inode_set_ctime_to_ts(inode, now); | |
210 | return now; | |
211 | } | |
212 | ||
3c2daed2 DW |
213 | static inline bool inode_wrong_type(const struct inode *inode, umode_t mode) |
214 | { | |
215 | return (inode->i_mode ^ mode) & S_IFMT; | |
216 | } | |
217 | ||
b626fb59 DC |
218 | typedef struct xfs_inode { |
219 | struct cache_node i_node; | |
220 | struct xfs_mount *i_mount; /* fs mount struct ptr */ | |
221 | xfs_ino_t i_ino; /* inode number (agno/agino) */ | |
222 | struct xfs_imap i_imap; /* location for xfs_imap() */ | |
cb8a004a | 223 | struct xfs_ifork *i_cowfp; /* copy on write extents */ |
b626fb59 | 224 | struct xfs_ifork i_df; /* data fork */ |
7ff5f1ed | 225 | struct xfs_ifork i_af; /* attribute fork */ |
b626fb59 | 226 | struct xfs_inode_log_item *i_itemp; /* logging information */ |
2711590c DW |
227 | uint64_t i_delayed_blks; /* count of delay alloc blks */ |
228 | /* Space that has been set aside to root a btree in this file. */ | |
229 | uint64_t i_meta_resv_asked; | |
230 | ||
509dcb4b | 231 | xfs_fsize_t i_disk_size; /* number of bytes in file */ |
aa00f286 | 232 | xfs_rfsblock_t i_nblocks; /* # of direct & btree blocks */ |
0ca7fa97 | 233 | prid_t i_projid; /* owner's project id */ |
fd2f92c8 | 234 | xfs_extlen_t i_extsize; /* basic/minimum extent size */ |
611ad47e CH |
235 | /* |
236 | * i_used_blocks is used for zoned rtrmap inodes, | |
237 | * i_cowextsize is used for other v3 inodes, | |
238 | * i_flushiter for v1/2 inodes | |
239 | */ | |
dc1d7a09 | 240 | union { |
611ad47e | 241 | uint32_t i_used_blocks; /* used blocks in RTG */ |
dc1d7a09 CH |
242 | xfs_extlen_t i_cowextsize; /* basic cow extent size */ |
243 | uint16_t i_flushiter; /* incremented on flush */ | |
244 | }; | |
073f2424 | 245 | uint8_t i_forkoff; /* attr fork offset >> 3 */ |
65713c2c | 246 | enum xfs_metafile_type i_metatype; /* XFS_METAFILE_* */ |
4350eee7 | 247 | uint16_t i_diflags; /* XFS_DIFLAG_... */ |
defd6446 | 248 | uint64_t i_diflags2; /* XFS_DIFLAG2_... */ |
a1f6b388 | 249 | struct timespec64 i_crtime; /* time created */ |
cb8a004a | 250 | |
69535dad DC |
251 | /* unlinked list pointers */ |
252 | xfs_agino_t i_next_unlinked; | |
0f1f6742 | 253 | xfs_agino_t i_prev_unlinked; |
69535dad | 254 | |
b626fb59 | 255 | xfs_fsize_t i_size; /* in-memory size */ |
1bc6cbe3 | 256 | struct inode i_vnode; |
b626fb59 DC |
257 | } xfs_inode_t; |
258 | ||
b99309ee | 259 | static inline bool xfs_inode_has_attr_fork(const struct xfs_inode *ip) |
4f841585 DW |
260 | { |
261 | return ip->i_forkoff > 0; | |
262 | } | |
263 | ||
722e81c1 DW |
264 | static inline struct xfs_ifork * |
265 | xfs_ifork_ptr( | |
266 | struct xfs_inode *ip, | |
267 | int whichfork) | |
268 | { | |
269 | switch (whichfork) { | |
270 | case XFS_DATA_FORK: | |
271 | return &ip->i_df; | |
272 | case XFS_ATTR_FORK: | |
4f841585 | 273 | if (!xfs_inode_has_attr_fork(ip)) |
7ff5f1ed DW |
274 | return NULL; |
275 | return &ip->i_af; | |
722e81c1 DW |
276 | case XFS_COW_FORK: |
277 | return ip->i_cowfp; | |
278 | default: | |
279 | ASSERT(0); | |
280 | return NULL; | |
281 | } | |
282 | } | |
283 | ||
eae3e30d DW |
284 | static inline unsigned int xfs_inode_fork_boff(struct xfs_inode *ip) |
285 | { | |
286 | return ip->i_forkoff << 3; | |
287 | } | |
288 | ||
289 | static inline unsigned int xfs_inode_data_fork_size(struct xfs_inode *ip) | |
290 | { | |
291 | if (xfs_inode_has_attr_fork(ip)) | |
292 | return xfs_inode_fork_boff(ip); | |
293 | ||
294 | return XFS_LITINO(ip->i_mount); | |
295 | } | |
296 | ||
297 | static inline unsigned int xfs_inode_attr_fork_size(struct xfs_inode *ip) | |
298 | { | |
299 | if (xfs_inode_has_attr_fork(ip)) | |
300 | return XFS_LITINO(ip->i_mount) - xfs_inode_fork_boff(ip); | |
301 | return 0; | |
302 | } | |
303 | ||
304 | static inline unsigned int | |
305 | xfs_inode_fork_size( | |
306 | struct xfs_inode *ip, | |
307 | int whichfork) | |
308 | { | |
309 | switch (whichfork) { | |
310 | case XFS_DATA_FORK: | |
311 | return xfs_inode_data_fork_size(ip); | |
312 | case XFS_ATTR_FORK: | |
313 | return xfs_inode_attr_fork_size(ip); | |
314 | default: | |
315 | return 0; | |
316 | } | |
317 | } | |
318 | ||
ca75eb20 BF |
319 | /* Convert from vfs inode to xfs inode */ |
320 | static inline struct xfs_inode *XFS_I(struct inode *inode) | |
321 | { | |
322 | return container_of(inode, struct xfs_inode, i_vnode); | |
323 | } | |
324 | ||
325 | /* convert from xfs inode to vfs inode */ | |
1bc6cbe3 DC |
326 | static inline struct inode *VFS_I(struct xfs_inode *ip) |
327 | { | |
328 | return &ip->i_vnode; | |
329 | } | |
330 | ||
4bba3a07 AH |
331 | /* convert from const xfs inode to const vfs inode */ |
332 | static inline const struct inode *VFS_IC(const struct xfs_inode *ip) | |
333 | { | |
334 | return &ip->i_vnode; | |
335 | } | |
336 | ||
ca75eb20 BF |
337 | /* We only have i_size in the xfs inode in userspace */ |
338 | static inline loff_t i_size_read(struct inode *inode) | |
339 | { | |
340 | return XFS_I(inode)->i_size; | |
341 | } | |
342 | ||
e37bf53c DC |
343 | /* |
344 | * wrappers around the mode checks to simplify code | |
345 | */ | |
346 | static inline bool XFS_ISREG(struct xfs_inode *ip) | |
347 | { | |
348 | return S_ISREG(VFS_I(ip)->i_mode); | |
349 | } | |
350 | ||
351 | static inline bool XFS_ISDIR(struct xfs_inode *ip) | |
352 | { | |
353 | return S_ISDIR(VFS_I(ip)->i_mode); | |
354 | } | |
355 | ||
b626fb59 DC |
356 | /* |
357 | * For regular files we only update the on-disk filesize when actually | |
358 | * writing data back to disk. Until then only the copy in the VFS inode | |
359 | * is uptodate. | |
360 | */ | |
361 | static inline xfs_fsize_t XFS_ISIZE(struct xfs_inode *ip) | |
362 | { | |
e37bf53c | 363 | if (XFS_ISREG(ip)) |
b626fb59 | 364 | return ip->i_size; |
509dcb4b | 365 | return ip->i_disk_size; |
b626fb59 | 366 | } |
4350eee7 | 367 | #define XFS_IS_REALTIME_INODE(ip) ((ip)->i_diflags & XFS_DIFLAG_REALTIME) |
b626fb59 | 368 | |
611ad47e CH |
369 | static inline bool xfs_is_zoned_inode(struct xfs_inode *ip) |
370 | { | |
371 | return xfs_has_zoned(ip->i_mount) && XFS_IS_REALTIME_INODE(ip); | |
372 | } | |
373 | ||
bcbe04c1 DC |
374 | /* inode link counts */ |
375 | static inline void set_nlink(struct inode *inode, uint32_t nlink) | |
376 | { | |
377 | inode->i_nlink = nlink; | |
378 | } | |
379 | static inline void inc_nlink(struct inode *inode) | |
380 | { | |
381 | inode->i_nlink++; | |
382 | } | |
7b3f2025 DW |
383 | static inline void drop_nlink(struct inode *inode) |
384 | { | |
385 | inode->i_nlink--; | |
386 | } | |
bcbe04c1 | 387 | |
b99309ee | 388 | static inline bool xfs_is_reflink_inode(const struct xfs_inode *ip) |
cfe32f0d | 389 | { |
defd6446 | 390 | return ip->i_diflags2 & XFS_DIFLAG2_REFLINK; |
cfe32f0d DW |
391 | } |
392 | ||
b99309ee | 393 | static inline bool xfs_inode_has_bigtime(const struct xfs_inode *ip) |
e7e3beb9 | 394 | { |
defd6446 | 395 | return ip->i_diflags2 & XFS_DIFLAG2_BIGTIME; |
e7e3beb9 DW |
396 | } |
397 | ||
b99309ee | 398 | static inline bool xfs_inode_has_large_extent_counts(const struct xfs_inode *ip) |
5a8b4d6a CB |
399 | { |
400 | return ip->i_diflags2 & XFS_DIFLAG2_NREXT64; | |
401 | } | |
402 | ||
378e94fc DW |
403 | |
404 | /* | |
405 | * Decide if this file is a realtime file whose data allocation unit is larger | |
406 | * than a single filesystem block. | |
407 | */ | |
b99309ee | 408 | static inline bool xfs_inode_has_bigrtalloc(const struct xfs_inode *ip) |
378e94fc DW |
409 | { |
410 | return XFS_IS_REALTIME_INODE(ip) && ip->i_mount->m_sb.sb_rextsize > 1; | |
411 | } | |
412 | ||
b99309ee | 413 | static inline bool xfs_is_always_cow_inode(const struct xfs_inode *ip) |
8a8799bb DW |
414 | { |
415 | return false; | |
416 | } | |
417 | ||
65713c2c DW |
418 | static inline bool xfs_is_metadir_inode(const struct xfs_inode *ip) |
419 | { | |
420 | return ip->i_diflags2 & XFS_DIFLAG2_METADATA; | |
421 | } | |
422 | ||
b626fb59 DC |
423 | extern void libxfs_trans_inode_alloc_buf (struct xfs_trans *, |
424 | struct xfs_buf *); | |
425 | ||
426 | extern void libxfs_trans_ichgtime(struct xfs_trans *, | |
427 | struct xfs_inode *, int); | |
428 | extern int libxfs_iflush_int (struct xfs_inode *, struct xfs_buf *); | |
429 | ||
b47055a4 DW |
430 | int libxfs_icreate(struct xfs_trans *tp, xfs_ino_t ino, |
431 | const struct xfs_icreate_args *args, struct xfs_inode **ipp); | |
432 | ||
b626fb59 DC |
433 | /* Inode Cache Interfaces */ |
434 | extern int libxfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t, | |
1fecabf9 | 435 | uint, struct xfs_inode **); |
31845e4c | 436 | extern void libxfs_irele(struct xfs_inode *ip); |
b626fb59 | 437 | |
8a8799bb DW |
438 | #define XFS_DEFAULT_COWEXTSZ_HINT 32 |
439 | ||
fdf7f987 DW |
440 | #define XFS_INHERIT_GID(pip) (VFS_I(pip)->i_mode & S_ISGID) |
441 | ||
fa2f7708 DW |
442 | #define xfs_inherit_noatime (false) |
443 | #define xfs_inherit_nodump (false) | |
444 | #define xfs_inherit_sync (false) | |
445 | #define xfs_inherit_nosymlinks (false) | |
446 | #define xfs_inherit_nodefrag (false) | |
447 | ||
b626fb59 | 448 | #endif /* __XFS_INODE_H__ */ |