]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame_incremental - include/xfs_inode.h
xfsprogs: Release v6.15.0
[thirdparty/xfsprogs-dev.git] / include / xfs_inode.h
... / ...
CommitLineData
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
5 */
6
7#ifndef __XFS_INODE_H__
8#define __XFS_INODE_H__
9
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
15typedef struct {
16 uid_t val;
17} kuid_t;
18
19typedef struct {
20 gid_t val;
21} kgid_t;
22
23static inline kuid_t make_kuid(uid_t uid)
24{
25 kuid_t v = { .val = uid };
26 return v;
27}
28
29static 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
40/* These match kernel side includes */
41#include "xfs_inode_buf.h"
42#include "xfs_inode_fork.h"
43#include "xfs_inode_util.h"
44
45struct xfs_trans;
46struct xfs_mount;
47struct xfs_inode_log_item;
48struct inode;
49
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
57static inline bool IS_I_VERSION(const struct inode *inode) { return false; }
58#define inode_maybe_inc_iversion(inode,flags) (0)
59
60/*
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.
64 */
65struct inode {
66 mode_t i_mode;
67 kuid_t i_uid;
68 kgid_t i_gid;
69 uint32_t i_nlink;
70 xfs_dev_t i_rdev; /* This actually holds xfs_dev_t */
71 unsigned int i_count;
72 unsigned long i_state; /* Not actually used in userspace */
73 uint32_t i_generation;
74 uint64_t i_version;
75 struct timespec64 __i_atime;
76 struct timespec64 __i_mtime;
77 struct timespec64 __i_ctime; /* use inode_*_ctime accessors! */
78 spinlock_t i_lock;
79};
80
81static inline void
82inode_set_iversion(struct inode *inode, uint64_t version)
83{
84 inode->i_version = version;
85}
86
87static inline uint32_t i_uid_read(struct inode *inode)
88{
89 return inode->i_uid.val;
90}
91static inline uint32_t i_gid_read(struct inode *inode)
92{
93 return inode->i_gid.val;
94}
95static inline void i_uid_write(struct inode *inode, uid_t uid)
96{
97 inode->i_uid.val = uid;
98}
99static inline void i_gid_write(struct inode *inode, gid_t gid)
100{
101 inode->i_gid.val = gid;
102}
103
104static inline void inode_fsuid_set(struct inode *inode,
105 struct mnt_idmap *idmap)
106{
107 inode->i_uid = make_kuid(0);
108}
109
110static inline void inode_fsgid_set(struct inode *inode,
111 struct mnt_idmap *idmap)
112{
113 inode->i_gid = make_kgid(0);
114}
115
116static inline void ihold(struct inode *inode)
117{
118 inode->i_count++;
119}
120
121static inline time64_t inode_get_atime_sec(const struct inode *inode)
122{
123 return inode->__i_atime.tv_sec;
124}
125
126static inline long inode_get_atime_nsec(const struct inode *inode)
127{
128 return inode->__i_atime.tv_nsec;
129}
130
131static inline struct timespec64 inode_get_atime(const struct inode *inode)
132{
133 return inode->__i_atime;
134}
135
136static 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
143static 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
151static inline time64_t inode_get_mtime_sec(const struct inode *inode)
152{
153 return inode->__i_mtime.tv_sec;
154}
155
156static inline long inode_get_mtime_nsec(const struct inode *inode)
157{
158 return inode->__i_mtime.tv_nsec;
159}
160
161static inline struct timespec64 inode_get_mtime(const struct inode *inode)
162{
163 return inode->__i_mtime;
164}
165
166static 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
173static 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
181static inline time64_t inode_get_ctime_sec(const struct inode *inode)
182{
183 return inode->__i_ctime.tv_sec;
184}
185
186static inline long inode_get_ctime_nsec(const struct inode *inode)
187{
188 return inode->__i_ctime.tv_nsec;
189}
190
191static inline struct timespec64 inode_get_ctime(const struct inode *inode)
192{
193 return inode->__i_ctime;
194}
195
196static 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
203extern struct timespec64 current_time(struct inode *inode);
204
205static 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
213static inline bool inode_wrong_type(const struct inode *inode, umode_t mode)
214{
215 return (inode->i_mode ^ mode) & S_IFMT;
216}
217
218typedef 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() */
223 struct xfs_ifork *i_cowfp; /* copy on write extents */
224 struct xfs_ifork i_df; /* data fork */
225 struct xfs_ifork i_af; /* attribute fork */
226 struct xfs_inode_log_item *i_itemp; /* logging information */
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
231 xfs_fsize_t i_disk_size; /* number of bytes in file */
232 xfs_rfsblock_t i_nblocks; /* # of direct & btree blocks */
233 prid_t i_projid; /* owner's project id */
234 xfs_extlen_t i_extsize; /* basic/minimum extent size */
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 */
240 union {
241 uint32_t i_used_blocks; /* used blocks in RTG */
242 xfs_extlen_t i_cowextsize; /* basic cow extent size */
243 uint16_t i_flushiter; /* incremented on flush */
244 };
245 uint8_t i_forkoff; /* attr fork offset >> 3 */
246 enum xfs_metafile_type i_metatype; /* XFS_METAFILE_* */
247 uint16_t i_diflags; /* XFS_DIFLAG_... */
248 uint64_t i_diflags2; /* XFS_DIFLAG2_... */
249 struct timespec64 i_crtime; /* time created */
250
251 /* unlinked list pointers */
252 xfs_agino_t i_next_unlinked;
253 xfs_agino_t i_prev_unlinked;
254
255 xfs_fsize_t i_size; /* in-memory size */
256 struct inode i_vnode;
257} xfs_inode_t;
258
259static inline bool xfs_inode_has_attr_fork(const struct xfs_inode *ip)
260{
261 return ip->i_forkoff > 0;
262}
263
264static inline struct xfs_ifork *
265xfs_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:
273 if (!xfs_inode_has_attr_fork(ip))
274 return NULL;
275 return &ip->i_af;
276 case XFS_COW_FORK:
277 return ip->i_cowfp;
278 default:
279 ASSERT(0);
280 return NULL;
281 }
282}
283
284static inline unsigned int xfs_inode_fork_boff(struct xfs_inode *ip)
285{
286 return ip->i_forkoff << 3;
287}
288
289static 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
297static 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
304static inline unsigned int
305xfs_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
319/* Convert from vfs inode to xfs inode */
320static 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 */
326static inline struct inode *VFS_I(struct xfs_inode *ip)
327{
328 return &ip->i_vnode;
329}
330
331/* convert from const xfs inode to const vfs inode */
332static inline const struct inode *VFS_IC(const struct xfs_inode *ip)
333{
334 return &ip->i_vnode;
335}
336
337/* We only have i_size in the xfs inode in userspace */
338static inline loff_t i_size_read(struct inode *inode)
339{
340 return XFS_I(inode)->i_size;
341}
342
343/*
344 * wrappers around the mode checks to simplify code
345 */
346static inline bool XFS_ISREG(struct xfs_inode *ip)
347{
348 return S_ISREG(VFS_I(ip)->i_mode);
349}
350
351static inline bool XFS_ISDIR(struct xfs_inode *ip)
352{
353 return S_ISDIR(VFS_I(ip)->i_mode);
354}
355
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 */
361static inline xfs_fsize_t XFS_ISIZE(struct xfs_inode *ip)
362{
363 if (XFS_ISREG(ip))
364 return ip->i_size;
365 return ip->i_disk_size;
366}
367#define XFS_IS_REALTIME_INODE(ip) ((ip)->i_diflags & XFS_DIFLAG_REALTIME)
368
369static 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
374/* inode link counts */
375static inline void set_nlink(struct inode *inode, uint32_t nlink)
376{
377 inode->i_nlink = nlink;
378}
379static inline void inc_nlink(struct inode *inode)
380{
381 inode->i_nlink++;
382}
383static inline void drop_nlink(struct inode *inode)
384{
385 inode->i_nlink--;
386}
387
388static inline bool xfs_is_reflink_inode(const struct xfs_inode *ip)
389{
390 return ip->i_diflags2 & XFS_DIFLAG2_REFLINK;
391}
392
393static inline bool xfs_inode_has_bigtime(const struct xfs_inode *ip)
394{
395 return ip->i_diflags2 & XFS_DIFLAG2_BIGTIME;
396}
397
398static inline bool xfs_inode_has_large_extent_counts(const struct xfs_inode *ip)
399{
400 return ip->i_diflags2 & XFS_DIFLAG2_NREXT64;
401}
402
403
404/*
405 * Decide if this file is a realtime file whose data allocation unit is larger
406 * than a single filesystem block.
407 */
408static inline bool xfs_inode_has_bigrtalloc(const struct xfs_inode *ip)
409{
410 return XFS_IS_REALTIME_INODE(ip) && ip->i_mount->m_sb.sb_rextsize > 1;
411}
412
413static inline bool xfs_is_always_cow_inode(const struct xfs_inode *ip)
414{
415 return false;
416}
417
418static inline bool xfs_is_metadir_inode(const struct xfs_inode *ip)
419{
420 return ip->i_diflags2 & XFS_DIFLAG2_METADATA;
421}
422
423extern void libxfs_trans_inode_alloc_buf (struct xfs_trans *,
424 struct xfs_buf *);
425
426extern void libxfs_trans_ichgtime(struct xfs_trans *,
427 struct xfs_inode *, int);
428extern int libxfs_iflush_int (struct xfs_inode *, struct xfs_buf *);
429
430int libxfs_icreate(struct xfs_trans *tp, xfs_ino_t ino,
431 const struct xfs_icreate_args *args, struct xfs_inode **ipp);
432
433/* Inode Cache Interfaces */
434extern int libxfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
435 uint, struct xfs_inode **);
436extern void libxfs_irele(struct xfs_inode *ip);
437
438#define XFS_DEFAULT_COWEXTSZ_HINT 32
439
440#define XFS_INHERIT_GID(pip) (VFS_I(pip)->i_mode & S_ISGID)
441
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
448#endif /* __XFS_INODE_H__ */