Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/fs/tmpfs/tmpfs.h
39507 views
1
/* $NetBSD: tmpfs.h,v 1.26 2007/02/22 06:37:00 thorpej Exp $ */
2
3
/*-
4
* SPDX-License-Identifier: BSD-2-Clause
5
*
6
* Copyright (c) 2005, 2006 The NetBSD Foundation, Inc.
7
* All rights reserved.
8
*
9
* This code is derived from software contributed to The NetBSD Foundation
10
* by Julio M. Merino Vidal, developed as part of Google's Summer of Code
11
* 2005 program.
12
*
13
* Redistribution and use in source and binary forms, with or without
14
* modification, are permitted provided that the following conditions
15
* are met:
16
* 1. Redistributions of source code must retain the above copyright
17
* notice, this list of conditions and the following disclaimer.
18
* 2. Redistributions in binary form must reproduce the above copyright
19
* notice, this list of conditions and the following disclaimer in the
20
* documentation and/or other materials provided with the distribution.
21
*
22
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
* POSSIBILITY OF SUCH DAMAGE.
33
*/
34
35
#ifndef _FS_TMPFS_TMPFS_H_
36
#define _FS_TMPFS_TMPFS_H_
37
38
#include <sys/cdefs.h>
39
#include <sys/queue.h>
40
#include <sys/tree.h>
41
42
#ifdef _SYS_MALLOC_H_
43
MALLOC_DECLARE(M_TMPFSNAME);
44
#endif
45
46
#define OBJ_TMPFS OBJ_PAGERPRIV1 /* has tmpfs vnode allocated */
47
#define OBJ_TMPFS_VREF OBJ_PAGERPRIV2 /* vnode is referenced */
48
49
/*
50
* Internal representation of a tmpfs directory entry.
51
*/
52
53
LIST_HEAD(tmpfs_dir_duphead, tmpfs_dirent);
54
55
struct tmpfs_dirent {
56
/*
57
* Depending on td_cookie flag entry can be of 3 types:
58
* - regular -- no hash collisions, stored in RB-Tree
59
* - duphead -- synthetic linked list head for dup entries
60
* - dup -- stored in linked list instead of RB-Tree
61
*/
62
union {
63
/* regular and duphead entry types */
64
RB_ENTRY(tmpfs_dirent) td_entries;
65
66
/* dup entry type */
67
struct {
68
LIST_ENTRY(tmpfs_dirent) entries;
69
LIST_ENTRY(tmpfs_dirent) index_entries;
70
} td_dup;
71
} uh;
72
73
uint32_t td_cookie;
74
uint32_t td_hash;
75
u_int td_namelen;
76
77
/*
78
* Pointer to the node this entry refers to. In case this field
79
* is NULL, the node is a whiteout.
80
*/
81
struct tmpfs_node * td_node;
82
83
union {
84
/*
85
* The name of the entry, allocated from a string pool. This
86
* string is not required to be zero-terminated.
87
*/
88
char * td_name; /* regular, dup */
89
struct tmpfs_dir_duphead td_duphead; /* duphead */
90
} ud;
91
};
92
93
/*
94
* A directory in tmpfs holds a collection of directory entries, which
95
* in turn point to other files (which can be directories themselves).
96
*
97
* In tmpfs, this collection is managed by a RB-Tree, whose head is
98
* defined by the struct tmpfs_dir type.
99
*
100
* It is important to notice that directories do not have entries for . and
101
* .. as other file systems do. These can be generated when requested
102
* based on information available by other means, such as the pointer to
103
* the node itself in the former case or the pointer to the parent directory
104
* in the latter case. This is done to simplify tmpfs's code and, more
105
* importantly, to remove redundancy.
106
*/
107
RB_HEAD(tmpfs_dir, tmpfs_dirent);
108
109
/*
110
* Each entry in a directory has a cookie that identifies it. Cookies
111
* supersede offsets within directories because, given how tmpfs stores
112
* directories in memory, there is no such thing as an offset.
113
*
114
* The '.', '..' and the end of directory markers have fixed cookies which
115
* cannot collide with the cookies generated by other entries. The cookies
116
* for the other entries are generated based on the file name hash value or
117
* unique number in case of name hash collision.
118
*
119
* To preserve compatibility cookies are limited to 31 bits.
120
*/
121
122
#define TMPFS_DIRCOOKIE_DOT 0
123
#define TMPFS_DIRCOOKIE_DOTDOT 1
124
#define TMPFS_DIRCOOKIE_EOF 2
125
#define TMPFS_DIRCOOKIE_MASK ((off_t)0x3fffffffU)
126
#define TMPFS_DIRCOOKIE_MIN ((off_t)0x00000004U)
127
#define TMPFS_DIRCOOKIE_DUP ((off_t)0x40000000U)
128
#define TMPFS_DIRCOOKIE_DUPHEAD ((off_t)0x80000000U)
129
#define TMPFS_DIRCOOKIE_DUP_MIN TMPFS_DIRCOOKIE_DUP
130
#define TMPFS_DIRCOOKIE_DUP_MAX \
131
(TMPFS_DIRCOOKIE_DUP | TMPFS_DIRCOOKIE_MASK)
132
133
/*
134
* Internal representation of a tmpfs extended attribute entry.
135
*/
136
LIST_HEAD(tmpfs_extattr_list, tmpfs_extattr);
137
138
struct tmpfs_extattr {
139
LIST_ENTRY(tmpfs_extattr) ea_extattrs;
140
int ea_namespace; /* attr namespace */
141
char *ea_name; /* attr name */
142
unsigned char ea_namelen; /* attr name length */
143
char *ea_value; /* attr value buffer */
144
ssize_t ea_size; /* attr value size */
145
};
146
147
/*
148
* Internal representation of a tmpfs file system node.
149
*
150
* This structure is splitted in two parts: one holds attributes common
151
* to all file types and the other holds data that is only applicable to
152
* a particular type. The code must be careful to only access those
153
* attributes that are actually allowed by the node's type.
154
*
155
* Below is the key of locks used to protected the fields in the following
156
* structures.
157
* (v) vnode lock in exclusive mode
158
* (vi) vnode lock in exclusive mode, or vnode lock in shared vnode and
159
* tn_interlock
160
* (i) tn_interlock
161
* (m) tmpfs_mount tm_allnode_lock
162
* (c) stable after creation
163
* (v) tn_reg.tn_aobj vm_object lock
164
*/
165
struct tmpfs_node {
166
/*
167
* Doubly-linked list entry which links all existing nodes for
168
* a single file system. This is provided to ease the removal
169
* of all nodes during the unmount operation, and to support
170
* the implementation of VOP_VNTOCNP(). tn_attached is false
171
* when the node is removed from list and unlocked.
172
*/
173
LIST_ENTRY(tmpfs_node) tn_entries; /* (m) */
174
175
/* Node identifier. */
176
ino_t tn_id; /* (c) */
177
178
/*
179
* The node's type. Any of 'VBLK', 'VCHR', 'VDIR', 'VFIFO',
180
* 'VLNK', 'VREG' and 'VSOCK' is allowed. The usage of vnode
181
* types instead of a custom enumeration is to make things simpler
182
* and faster, as we do not need to convert between two types.
183
*/
184
__enum_uint8(vtype) tn_type; /* (c) */
185
186
/*
187
* See the top comment. Reordered here to fill LP64 hole.
188
*/
189
bool tn_attached; /* (m) */
190
191
/*
192
* Node's internal status. This is used by several file system
193
* operations to do modifications to the node in a delayed
194
* fashion.
195
*
196
* tn_accessed has a dedicated byte to allow update by store without
197
* using atomics. This provides a micro-optimization to e.g.
198
* tmpfs_read_pgcache().
199
*/
200
uint8_t tn_status; /* (vi) */
201
uint8_t tn_accessed; /* unlocked */
202
203
/*
204
* The node size. It does not necessarily match the real amount
205
* of memory consumed by it.
206
*/
207
off_t tn_size; /* (v) */
208
209
/* Generic node attributes. */
210
uid_t tn_uid; /* (v) */
211
gid_t tn_gid; /* (v) */
212
mode_t tn_mode; /* (v) */
213
int tn_links; /* (v) */
214
u_long tn_flags; /* (v) */
215
struct timespec tn_atime; /* (vi) */
216
struct timespec tn_mtime; /* (vi) */
217
struct timespec tn_ctime; /* (vi) */
218
struct timespec tn_birthtime; /* (v) */
219
unsigned long tn_gen; /* (c) */
220
221
/*
222
* As there is a single vnode for each active file within the
223
* system, care has to be taken to avoid allocating more than one
224
* vnode per file. In order to do this, a bidirectional association
225
* is kept between vnodes and nodes.
226
*
227
* Whenever a vnode is allocated, its v_data field is updated to
228
* point to the node it references. At the same time, the node's
229
* tn_vnode field is modified to point to the new vnode representing
230
* it. Further attempts to allocate a vnode for this same node will
231
* result in returning a new reference to the value stored in
232
* tn_vnode.
233
*
234
* May be NULL when the node is unused (that is, no vnode has been
235
* allocated for it or it has been reclaimed).
236
*/
237
struct vnode * tn_vnode; /* (i) */
238
239
/*
240
* Interlock to protect tn_vpstate, and tn_status under shared
241
* vnode lock.
242
*/
243
struct mtx tn_interlock;
244
245
/*
246
* Identify if current node has vnode assiocate with
247
* or allocating vnode.
248
*/
249
int tn_vpstate; /* (i) */
250
251
/* Transient refcounter on this node. */
252
u_int tn_refcount; /* 0<->1 (m) + (i) */
253
254
/* Extended attributes of this node. */
255
struct tmpfs_extattr_list tn_extattrs; /* (v) */
256
257
/* misc data field for different tn_type node */
258
union {
259
/* Valid when tn_type == VBLK || tn_type == VCHR. */
260
dev_t tn_rdev; /* (c) */
261
262
/* Valid when tn_type == VDIR. */
263
struct tn_dir {
264
/*
265
* Pointer to the parent directory. The root
266
* directory has a pointer to itself in this field;
267
* this property identifies the root node.
268
*/
269
struct tmpfs_node * tn_parent;
270
271
/*
272
* Head of a tree that links the contents of
273
* the directory together.
274
*/
275
struct tmpfs_dir tn_dirhead;
276
277
/*
278
* Head of a list the contains fake directory entries
279
* heads, i.e. entries with TMPFS_DIRCOOKIE_DUPHEAD
280
* flag.
281
*/
282
struct tmpfs_dir_duphead tn_dupindex;
283
284
/*
285
* Number and pointer of the first directory entry
286
* returned by the readdir operation if it were
287
* called again to continue reading data from the
288
* same directory as before. This is used to speed
289
* up reads of long directories, assuming that no
290
* more than one read is in progress at a given time.
291
* Otherwise, these values are discarded.
292
*/
293
off_t tn_readdir_lastn;
294
struct tmpfs_dirent * tn_readdir_lastp;
295
296
/*
297
* Total size of whiteout directory entries. This
298
* must be a multiple of sizeof(struct tmpfs_dirent)
299
* and is used to determine whether a directory is
300
* empty (excluding whiteout entries) during rename/
301
* rmdir operations.
302
*/
303
off_t tn_wht_size; /* (v) */
304
} tn_dir;
305
306
/* Valid when tn_type == VLNK. */
307
/* The link's target, allocated from a string pool. */
308
struct tn_link {
309
char * tn_link_target; /* (c) */
310
char tn_link_smr; /* (c) */
311
} tn_link;
312
313
/* Valid when tn_type == VREG. */
314
struct tn_reg {
315
/*
316
* The contents of regular files stored in a
317
* tmpfs file system are represented by a
318
* single anonymous memory object (aobj, for
319
* short). The aobj provides direct access to
320
* any position within the file. It is a task
321
* of the memory management subsystem to issue
322
* the required page ins or page outs whenever
323
* a position within the file is accessed.
324
*/
325
vm_object_t tn_aobj; /* (c) */
326
struct tmpfs_mount *tn_tmp; /* (c) */
327
vm_pindex_t tn_pages; /* (v) */
328
} tn_reg;
329
} tn_spec; /* (v) */
330
};
331
LIST_HEAD(tmpfs_node_list, tmpfs_node);
332
333
#define tn_rdev tn_spec.tn_rdev
334
#define tn_dir tn_spec.tn_dir
335
#define tn_link_target tn_spec.tn_link.tn_link_target
336
#define tn_link_smr tn_spec.tn_link.tn_link_smr
337
#define tn_reg tn_spec.tn_reg
338
#define tn_fifo tn_spec.tn_fifo
339
340
#define TMPFS_LINK_MAX INT_MAX
341
342
#define TMPFS_NODE_LOCK(node) mtx_lock(&(node)->tn_interlock)
343
#define TMPFS_NODE_UNLOCK(node) mtx_unlock(&(node)->tn_interlock)
344
#define TMPFS_NODE_MTX(node) (&(node)->tn_interlock)
345
#define TMPFS_NODE_ASSERT_LOCKED(node) mtx_assert(TMPFS_NODE_MTX(node), \
346
MA_OWNED)
347
348
#ifdef INVARIANTS
349
#define TMPFS_ASSERT_LOCKED(node) do { \
350
MPASS((node) != NULL); \
351
MPASS((node)->tn_vnode != NULL); \
352
ASSERT_VOP_LOCKED((node)->tn_vnode, "tmpfs assert"); \
353
} while (0)
354
#else
355
#define TMPFS_ASSERT_LOCKED(node) (void)0
356
#endif
357
358
/* tn_vpstate */
359
#define TMPFS_VNODE_ALLOCATING 1
360
#define TMPFS_VNODE_WANT 2
361
#define TMPFS_VNODE_DOOMED 4
362
#define TMPFS_VNODE_WRECLAIM 8
363
364
/* tn_status */
365
#define TMPFS_NODE_MODIFIED 0x01
366
#define TMPFS_NODE_CHANGED 0x02
367
368
/*
369
* Internal representation of a tmpfs mount point.
370
*/
371
struct tmpfs_mount {
372
/*
373
* Original value of the "size" parameter, for reference purposes,
374
* mostly.
375
*/
376
off_t tm_size_max;
377
/*
378
* Maximum number of memory pages available for use by the file
379
* system, set during mount time. This variable must never be
380
* used directly as it may be bigger than the current amount of
381
* free memory; in the extreme case, it will hold the ULONG_MAX
382
* value.
383
*/
384
u_long tm_pages_max;
385
386
/* Number of pages in use by the file system. */
387
u_long tm_pages_used;
388
389
/*
390
* Pointer to the node representing the root directory of this
391
* file system.
392
*/
393
struct tmpfs_node * tm_root;
394
395
/*
396
* Maximum number of possible nodes for this file system; set
397
* during mount time. We need a hard limit on the maximum number
398
* of nodes to avoid allocating too much of them; their objects
399
* cannot be released until the file system is unmounted.
400
* Otherwise, we could easily run out of memory by creating lots
401
* of empty files and then simply removing them.
402
*/
403
ino_t tm_nodes_max;
404
405
/* unrhdr used to allocate inode numbers */
406
struct unrhdr64 tm_ino_unr;
407
408
/* Number of nodes currently that are in use. */
409
ino_t tm_nodes_inuse;
410
411
/* Memory used by extended attributes */
412
uint64_t tm_ea_memory_inuse;
413
414
/* Maximum memory available for extended attributes */
415
uint64_t tm_ea_memory_max;
416
417
/* Refcounter on this struct tmpfs_mount. */
418
uint64_t tm_refcount;
419
420
/* maximum representable file size */
421
u_int64_t tm_maxfilesize;
422
423
/*
424
* The used list contains all nodes that are currently used by
425
* the file system; i.e., they refer to existing files.
426
*/
427
struct tmpfs_node_list tm_nodes_used;
428
429
/* All node lock to protect the node list and tmp_pages_used. */
430
struct mtx tm_allnode_lock;
431
432
/* Read-only status. */
433
bool tm_ronly;
434
/* Do not use namecache. */
435
bool tm_nonc;
436
/* Do not update mtime on writes through mmaped areas. */
437
bool tm_nomtime;
438
439
/* Read from page cache directly. */
440
bool tm_pgread;
441
};
442
#define TMPFS_LOCK(tm) mtx_lock(&(tm)->tm_allnode_lock)
443
#define TMPFS_UNLOCK(tm) mtx_unlock(&(tm)->tm_allnode_lock)
444
#define TMPFS_MP_ASSERT_LOCKED(tm) mtx_assert(&(tm)->tm_allnode_lock, MA_OWNED)
445
446
/*
447
* This structure maps a file identifier to a tmpfs node. Used by the
448
* NFS code.
449
*/
450
struct tmpfs_fid_data {
451
unsigned short tfd_len;
452
ino_t tfd_id;
453
unsigned long tfd_gen;
454
} __packed;
455
456
struct tmpfs_dir_cursor {
457
struct tmpfs_dirent *tdc_current;
458
struct tmpfs_dirent *tdc_tree;
459
};
460
461
#ifdef _KERNEL
462
/*
463
* Prototypes for tmpfs_subr.c.
464
*/
465
466
void tmpfs_ref_node(struct tmpfs_node *node);
467
int tmpfs_alloc_node(struct mount *mp, struct tmpfs_mount *, __enum_uint8(vtype),
468
uid_t uid, gid_t gid, mode_t mode, struct tmpfs_node *,
469
const char *, dev_t, struct tmpfs_node **);
470
int tmpfs_fo_close(struct file *fp, struct thread *td);
471
void tmpfs_free_node(struct tmpfs_mount *, struct tmpfs_node *);
472
bool tmpfs_free_node_locked(struct tmpfs_mount *, struct tmpfs_node *, bool);
473
void tmpfs_free_tmp(struct tmpfs_mount *);
474
int tmpfs_alloc_dirent(struct tmpfs_mount *, struct tmpfs_node *,
475
const char *, u_int, struct tmpfs_dirent **);
476
void tmpfs_free_dirent(struct tmpfs_mount *, struct tmpfs_dirent *);
477
void tmpfs_dirent_init(struct tmpfs_dirent *, const char *, u_int);
478
void tmpfs_destroy_vobject(struct vnode *vp, vm_object_t obj);
479
int tmpfs_alloc_vp(struct mount *, struct tmpfs_node *, int,
480
struct vnode **);
481
void tmpfs_free_vp(struct vnode *);
482
int tmpfs_alloc_file(struct vnode *, struct vnode **, struct vattr *,
483
struct componentname *, const char *);
484
void tmpfs_check_mtime(struct vnode *);
485
void tmpfs_dir_attach(struct vnode *, struct tmpfs_dirent *);
486
void tmpfs_dir_detach(struct vnode *, struct tmpfs_dirent *);
487
void tmpfs_dir_destroy(struct tmpfs_mount *, struct tmpfs_node *);
488
struct tmpfs_dirent * tmpfs_dir_lookup(struct tmpfs_node *node,
489
struct tmpfs_node *f,
490
struct componentname *cnp);
491
int tmpfs_dir_getdents(struct tmpfs_mount *, struct tmpfs_node *,
492
struct uio *, int, uint64_t *, int *);
493
int tmpfs_dir_whiteout_add(struct vnode *, struct componentname *);
494
void tmpfs_dir_whiteout_remove(struct vnode *, struct componentname *);
495
void tmpfs_dir_clear_whiteouts(struct vnode *);
496
int tmpfs_reg_resize(struct vnode *, off_t, boolean_t);
497
int tmpfs_reg_punch_hole(struct vnode *vp, off_t *, off_t *);
498
int tmpfs_chflags(struct vnode *, u_long, struct ucred *, struct thread *);
499
int tmpfs_chmod(struct vnode *, mode_t, struct ucred *, struct thread *);
500
int tmpfs_chown(struct vnode *, uid_t, gid_t, struct ucred *,
501
struct thread *);
502
int tmpfs_chsize(struct vnode *, u_quad_t, struct ucred *, struct thread *);
503
int tmpfs_chtimes(struct vnode *, struct vattr *, struct ucred *cred,
504
struct thread *);
505
void tmpfs_itimes(struct vnode *, const struct timespec *,
506
const struct timespec *);
507
508
void tmpfs_set_accessed(struct tmpfs_mount *tm, struct tmpfs_node *node);
509
void tmpfs_set_status(struct tmpfs_mount *tm, struct tmpfs_node *node,
510
int status);
511
int tmpfs_truncate(struct vnode *, off_t);
512
struct tmpfs_dirent *tmpfs_dir_first(struct tmpfs_node *dnode,
513
struct tmpfs_dir_cursor *dc);
514
struct tmpfs_dirent *tmpfs_dir_next(struct tmpfs_node *dnode,
515
struct tmpfs_dir_cursor *dc);
516
bool tmpfs_pages_check_avail(struct tmpfs_mount *tmp, size_t req_pages);
517
void tmpfs_extattr_free(struct tmpfs_extattr* ea);
518
static __inline void
519
tmpfs_update(struct vnode *vp)
520
{
521
522
tmpfs_itimes(vp, NULL, NULL);
523
}
524
525
/*
526
* Convenience macros to simplify some logical expressions.
527
*/
528
#define IMPLIES(a, b) (!(a) || (b))
529
530
/*
531
* Checks that the directory entry pointed by 'de' matches the name 'name'
532
* with a length of 'len'.
533
*/
534
#define TMPFS_DIRENT_MATCHES(de, name, len) \
535
(de->td_namelen == len && \
536
bcmp((de)->ud.td_name, (name), (de)->td_namelen) == 0)
537
538
/*
539
* Ensures that the node pointed by 'node' is a directory and that its
540
* contents are consistent with respect to directories.
541
*/
542
#define TMPFS_VALIDATE_DIR(node) do { \
543
MPASS((node)->tn_type == VDIR); \
544
MPASS((node)->tn_size % sizeof(struct tmpfs_dirent) == 0); \
545
MPASS((node)->tn_dir.tn_wht_size % sizeof(struct tmpfs_dirent) == 0); \
546
MPASS((node)->tn_dir.tn_wht_size <= (node)->tn_size); \
547
} while (0)
548
549
/*
550
* Amount of memory pages to reserve for the system (e.g., to not use by
551
* tmpfs).
552
*/
553
#if !defined(TMPFS_PAGES_MINRESERVED)
554
#define TMPFS_PAGES_MINRESERVED (4 * 1024 * 1024 / PAGE_SIZE)
555
#endif
556
557
/*
558
* Percent of available memory + swap available to use by tmpfs file systems
559
* without a size limit.
560
*/
561
#if !defined(TMPFS_MEM_PERCENT)
562
#define TMPFS_MEM_PERCENT 100
563
#endif
564
565
/*
566
* Amount of memory to reserve for extended attributes.
567
*/
568
#if !defined(TMPFS_EA_MEMORY_RESERVED)
569
#define TMPFS_EA_MEMORY_RESERVED (16 * 1024 * 1024)
570
#endif
571
572
size_t tmpfs_mem_avail(void);
573
size_t tmpfs_pages_used(struct tmpfs_mount *tmp);
574
int tmpfs_subr_init(void);
575
void tmpfs_subr_uninit(void);
576
577
extern int tmpfs_pager_type;
578
579
/*
580
* Macros/functions to convert from generic data structures to tmpfs
581
* specific ones.
582
*/
583
584
static inline struct vnode *
585
VM_TO_TMPFS_VP(vm_object_t obj)
586
{
587
struct tmpfs_node *node;
588
589
if ((obj->flags & OBJ_TMPFS) == 0)
590
return (NULL);
591
592
/*
593
* swp_priv is the back-pointer to the tmpfs node, if any,
594
* which uses the vm object as backing store. The object
595
* handle is not used to avoid locking sw_alloc_sx on tmpfs
596
* node instantiation/destroy.
597
*/
598
node = obj->un_pager.swp.swp_priv;
599
return (node->tn_vnode);
600
}
601
602
static inline struct tmpfs_mount *
603
VM_TO_TMPFS_MP(vm_object_t obj)
604
{
605
struct tmpfs_node *node;
606
607
if ((obj->flags & OBJ_TMPFS) == 0)
608
return (NULL);
609
610
node = obj->un_pager.swp.swp_priv;
611
MPASS(node->tn_type == VREG);
612
return (node->tn_reg.tn_tmp);
613
}
614
615
static inline struct tmpfs_mount *
616
VFS_TO_TMPFS(struct mount *mp)
617
{
618
struct tmpfs_mount *tmp;
619
620
MPASS(mp != NULL && mp->mnt_data != NULL);
621
tmp = (struct tmpfs_mount *)mp->mnt_data;
622
return (tmp);
623
}
624
625
static inline struct tmpfs_node *
626
VP_TO_TMPFS_NODE(struct vnode *vp)
627
{
628
struct tmpfs_node *node;
629
630
MPASS(vp != NULL && vp->v_data != NULL);
631
node = (struct tmpfs_node *)vp->v_data;
632
return (node);
633
}
634
635
#define VP_TO_TMPFS_NODE_SMR(vp) \
636
((struct tmpfs_node *)vn_load_v_data_smr(vp))
637
638
static inline struct tmpfs_node *
639
VP_TO_TMPFS_DIR(struct vnode *vp)
640
{
641
struct tmpfs_node *node;
642
643
node = VP_TO_TMPFS_NODE(vp);
644
TMPFS_VALIDATE_DIR(node);
645
return (node);
646
}
647
648
static inline bool
649
tmpfs_use_nc(struct vnode *vp)
650
{
651
652
return (!(VFS_TO_TMPFS(vp->v_mount)->tm_nonc));
653
}
654
655
static inline void
656
tmpfs_update_getattr(struct vnode *vp)
657
{
658
struct tmpfs_node *node;
659
660
node = VP_TO_TMPFS_NODE(vp);
661
if (__predict_false((node->tn_status & (TMPFS_NODE_MODIFIED |
662
TMPFS_NODE_CHANGED)) != 0 || node->tn_accessed))
663
tmpfs_update(vp);
664
}
665
666
extern struct fileops tmpfs_fnops;
667
668
#endif /* _KERNEL */
669
670
#endif /* _FS_TMPFS_TMPFS_H_ */
671
672