1171802Sdelphij/*	$NetBSD: tmpfs.h,v 1.26 2007/02/22 06:37:00 thorpej Exp $	*/
2170808Sdelphij
3182739Sdelphij/*-
4171802Sdelphij * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc.
5170808Sdelphij * All rights reserved.
6170808Sdelphij *
7170808Sdelphij * This code is derived from software contributed to The NetBSD Foundation
8170808Sdelphij * by Julio M. Merino Vidal, developed as part of Google's Summer of Code
9170808Sdelphij * 2005 program.
10170808Sdelphij *
11170808Sdelphij * Redistribution and use in source and binary forms, with or without
12170808Sdelphij * modification, are permitted provided that the following conditions
13170808Sdelphij * are met:
14170808Sdelphij * 1. Redistributions of source code must retain the above copyright
15170808Sdelphij *    notice, this list of conditions and the following disclaimer.
16170808Sdelphij * 2. Redistributions in binary form must reproduce the above copyright
17170808Sdelphij *    notice, this list of conditions and the following disclaimer in the
18170808Sdelphij *    documentation and/or other materials provided with the distribution.
19170808Sdelphij *
20170808Sdelphij * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21170808Sdelphij * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22170808Sdelphij * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23170808Sdelphij * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24170808Sdelphij * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25170808Sdelphij * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26170808Sdelphij * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27170808Sdelphij * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28170808Sdelphij * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29170808Sdelphij * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30170808Sdelphij * POSSIBILITY OF SUCH DAMAGE.
31170808Sdelphij *
32170808Sdelphij * $FreeBSD: releng/10.2/sys/fs/tmpfs/tmpfs.h 278571 2015-02-11 09:02:21Z kib $
33170808Sdelphij */
34170808Sdelphij
35170808Sdelphij#ifndef _FS_TMPFS_TMPFS_H_
36170808Sdelphij#define _FS_TMPFS_TMPFS_H_
37170808Sdelphij
38170808Sdelphij#include <sys/dirent.h>
39170808Sdelphij#include <sys/mount.h>
40170808Sdelphij#include <sys/queue.h>
41170808Sdelphij#include <sys/vnode.h>
42170808Sdelphij#include <sys/file.h>
43170808Sdelphij#include <sys/lock.h>
44170808Sdelphij#include <sys/mutex.h>
45170808Sdelphij
46170808Sdelphij#include <sys/malloc.h>
47170808Sdelphij#include <sys/systm.h>
48245115Sgleb#include <sys/tree.h>
49170808Sdelphij#include <sys/vmmeter.h>
50170808Sdelphij#include <vm/swap_pager.h>
51170808Sdelphij
52170808SdelphijMALLOC_DECLARE(M_TMPFSMNT);
53171087SdelphijMALLOC_DECLARE(M_TMPFSNAME);
54170808Sdelphij
55170808Sdelphij/*
56170808Sdelphij * Internal representation of a tmpfs directory entry.
57170808Sdelphij */
58245115Sgleb
59245115SglebLIST_HEAD(tmpfs_dir_duphead, tmpfs_dirent);
60245115Sgleb
61170808Sdelphijstruct tmpfs_dirent {
62245115Sgleb	/*
63245115Sgleb	 * Depending on td_cookie flag entry can be of 3 types:
64245115Sgleb	 * - regular -- no hash collisions, stored in RB-Tree
65245115Sgleb	 * - duphead -- synthetic linked list head for dup entries
66245115Sgleb	 * - dup -- stored in linked list instead of RB-Tree
67245115Sgleb	 */
68245115Sgleb	union {
69245115Sgleb		/* regular and duphead entry types */
70245115Sgleb		RB_ENTRY(tmpfs_dirent)		td_entries;
71170808Sdelphij
72245115Sgleb		/* dup entry type */
73245115Sgleb		struct {
74245115Sgleb			LIST_ENTRY(tmpfs_dirent) entries;
75245115Sgleb			LIST_ENTRY(tmpfs_dirent) index_entries;
76245115Sgleb		} td_dup;
77245115Sgleb	} uh;
78170808Sdelphij
79245115Sgleb	uint32_t			td_cookie;
80245115Sgleb	uint32_t			td_hash;
81245115Sgleb	u_int				td_namelen;
82170808Sdelphij
83211598Sed	/* Pointer to the node this entry refers to.  In case this field
84211598Sed	 * is NULL, the node is a whiteout. */
85170808Sdelphij	struct tmpfs_node *		td_node;
86245115Sgleb
87245115Sgleb	union {
88245115Sgleb		/*
89245115Sgleb		 * The name of the entry, allocated from a string pool.  This
90245115Sgleb		 * string is not required to be zero-terminated.
91245115Sgleb		 */
92245115Sgleb		char *			td_name;	/* regular, dup */
93245115Sgleb		struct tmpfs_dir_duphead td_duphead;	/* duphead */
94245115Sgleb	} ud;
95170808Sdelphij};
96170808Sdelphij
97245115Sgleb/* A directory in tmpfs holds a list of directory entries, which in
98170808Sdelphij * turn point to other files (which can be directories themselves).
99170808Sdelphij *
100245115Sgleb * In tmpfs, this list is managed by a RB-Tree, whose head is defined by
101170808Sdelphij * the struct tmpfs_dir type.
102170808Sdelphij *
103245115Sgleb * It is important to notice that directories do not have entries for . and
104170808Sdelphij * .. as other file systems do.  These can be generated when requested
105170808Sdelphij * based on information available by other means, such as the pointer to
106170808Sdelphij * the node itself in the former case or the pointer to the parent directory
107170808Sdelphij * in the latter case.  This is done to simplify tmpfs's code and, more
108170808Sdelphij * importantly, to remove redundancy. */
109245115SglebRB_HEAD(tmpfs_dir, tmpfs_dirent);
110170808Sdelphij
111171802Sdelphij/* Each entry in a directory has a cookie that identifies it.  Cookies
112171802Sdelphij * supersede offsets within directories because, given how tmpfs stores
113245115Sgleb * directories in memory, there is no such thing as an offset.
114245115Sgleb *
115171802Sdelphij * The '.', '..' and the end of directory markers have fixed cookies which
116171802Sdelphij * cannot collide with the cookies generated by other entries.  The cookies
117245115Sgleb * for the other entries are generated based on the file name hash value or
118245115Sgleb * unique number in case of name hash collision.
119171802Sdelphij *
120245115Sgleb * To preserve compatibility cookies are limited to 31 bits.
121245115Sgleb */
122170808Sdelphij
123245115Sgleb#define	TMPFS_DIRCOOKIE_DOT		0
124245115Sgleb#define	TMPFS_DIRCOOKIE_DOTDOT		1
125245115Sgleb#define	TMPFS_DIRCOOKIE_EOF		2
126245115Sgleb#define	TMPFS_DIRCOOKIE_MASK		((off_t)0x3fffffffU)
127245115Sgleb#define	TMPFS_DIRCOOKIE_MIN		((off_t)0x00000004U)
128245115Sgleb#define	TMPFS_DIRCOOKIE_DUP		((off_t)0x40000000U)
129245115Sgleb#define	TMPFS_DIRCOOKIE_DUPHEAD		((off_t)0x80000000U)
130245115Sgleb#define	TMPFS_DIRCOOKIE_DUP_MIN		TMPFS_DIRCOOKIE_DUP
131245115Sgleb#define	TMPFS_DIRCOOKIE_DUP_MAX		\
132245115Sgleb	(TMPFS_DIRCOOKIE_DUP | TMPFS_DIRCOOKIE_MASK)
133171802Sdelphij
134170808Sdelphij/*
135170808Sdelphij * Internal representation of a tmpfs file system node.
136170808Sdelphij *
137170808Sdelphij * This structure is splitted in two parts: one holds attributes common
138170808Sdelphij * to all file types and the other holds data that is only applicable to
139170808Sdelphij * a particular type.  The code must be careful to only access those
140170808Sdelphij * attributes that are actually allowed by the node's type.
141170808Sdelphij *
142170808Sdelphij *
143170808Sdelphij * Below is the key of locks used to protected the fields in the following
144170808Sdelphij * structures.
145170808Sdelphij *
146170808Sdelphij */
147170808Sdelphijstruct tmpfs_node {
148170808Sdelphij	/* Doubly-linked list entry which links all existing nodes for a
149170808Sdelphij	 * single file system.  This is provided to ease the removal of
150170808Sdelphij	 * all nodes during the unmount operation. */
151170808Sdelphij	LIST_ENTRY(tmpfs_node)	tn_entries;
152170808Sdelphij
153170808Sdelphij	/* The node's type.  Any of 'VBLK', 'VCHR', 'VDIR', 'VFIFO',
154170808Sdelphij	 * 'VLNK', 'VREG' and 'VSOCK' is allowed.  The usage of vnode
155170808Sdelphij	 * types instead of a custom enumeration is to make things simpler
156170808Sdelphij	 * and faster, as we do not need to convert between two types. */
157170808Sdelphij	enum vtype		tn_type;
158170808Sdelphij
159170808Sdelphij	/* Node identifier. */
160170808Sdelphij	ino_t			tn_id;
161170808Sdelphij
162170808Sdelphij	/* Node's internal status.  This is used by several file system
163170808Sdelphij	 * operations to do modifications to the node in a delayed
164170808Sdelphij	 * fashion. */
165170808Sdelphij	int			tn_status;
166170808Sdelphij#define	TMPFS_NODE_ACCESSED	(1 << 1)
167170808Sdelphij#define	TMPFS_NODE_MODIFIED	(1 << 2)
168170808Sdelphij#define	TMPFS_NODE_CHANGED	(1 << 3)
169170808Sdelphij
170170808Sdelphij	/* The node size.  It does not necessarily match the real amount
171170808Sdelphij	 * of memory consumed by it. */
172170808Sdelphij	off_t			tn_size;
173170808Sdelphij
174170808Sdelphij	/* Generic node attributes. */
175170808Sdelphij	uid_t			tn_uid;
176170808Sdelphij	gid_t			tn_gid;
177170808Sdelphij	mode_t			tn_mode;
178248597Spjd	u_long			tn_flags;
179170808Sdelphij	nlink_t			tn_links;
180170808Sdelphij	struct timespec		tn_atime;
181170808Sdelphij	struct timespec		tn_mtime;
182170808Sdelphij	struct timespec		tn_ctime;
183170808Sdelphij	struct timespec		tn_birthtime;
184170808Sdelphij	unsigned long		tn_gen;
185170808Sdelphij
186170808Sdelphij	/* As there is a single vnode for each active file within the
187170808Sdelphij	 * system, care has to be taken to avoid allocating more than one
188170808Sdelphij	 * vnode per file.  In order to do this, a bidirectional association
189170808Sdelphij	 * is kept between vnodes and nodes.
190170808Sdelphij	 *
191170808Sdelphij	 * Whenever a vnode is allocated, its v_data field is updated to
192170808Sdelphij	 * point to the node it references.  At the same time, the node's
193170808Sdelphij	 * tn_vnode field is modified to point to the new vnode representing
194170808Sdelphij	 * it.  Further attempts to allocate a vnode for this same node will
195170808Sdelphij	 * result in returning a new reference to the value stored in
196170808Sdelphij	 * tn_vnode.
197170808Sdelphij	 *
198170808Sdelphij	 * May be NULL when the node is unused (that is, no vnode has been
199170808Sdelphij	 * allocated for it or it has been reclaimed). */
200170808Sdelphij	struct vnode *		tn_vnode;
201170808Sdelphij
202170808Sdelphij	/* interlock to protect tn_vpstate */
203170808Sdelphij	struct mtx	tn_interlock;
204170808Sdelphij
205170808Sdelphij	/* Identify if current node has vnode assiocate with
206170808Sdelphij	 * or allocating vnode.
207170808Sdelphij	 */
208170808Sdelphij	int		tn_vpstate;
209170808Sdelphij
210170808Sdelphij	/* misc data field for different tn_type node */
211170808Sdelphij	union {
212170808Sdelphij		/* Valid when tn_type == VBLK || tn_type == VCHR. */
213170808Sdelphij		dev_t			tn_rdev;
214170808Sdelphij
215170808Sdelphij		/* Valid when tn_type == VDIR. */
216245115Sgleb		struct tn_dir {
217170808Sdelphij			/* Pointer to the parent directory.  The root
218170808Sdelphij			 * directory has a pointer to itself in this field;
219170808Sdelphij			 * this property identifies the root node. */
220170808Sdelphij			struct tmpfs_node *	tn_parent;
221170808Sdelphij
222245115Sgleb			/* Head of a tree that links the contents of
223245115Sgleb			 * the directory together. */
224170808Sdelphij			struct tmpfs_dir	tn_dirhead;
225170808Sdelphij
226245115Sgleb			/* Head of a list the contains fake directory entries
227245115Sgleb			 * heads, i.e. entries with TMPFS_DIRCOOKIE_DUPHEAD
228245115Sgleb			 * flag. */
229245115Sgleb			struct tmpfs_dir_duphead tn_dupindex;
230245115Sgleb
231170808Sdelphij			/* Number and pointer of the first directory entry
232170808Sdelphij			 * returned by the readdir operation if it were
233170808Sdelphij			 * called again to continue reading data from the
234170808Sdelphij			 * same directory as before.  This is used to speed
235170808Sdelphij			 * up reads of long directories, assuming that no
236170808Sdelphij			 * more than one read is in progress at a given time.
237245115Sgleb			 * Otherwise, these values are discarded. */
238170808Sdelphij			off_t			tn_readdir_lastn;
239170808Sdelphij			struct tmpfs_dirent *	tn_readdir_lastp;
240245115Sgleb		} tn_dir;
241170808Sdelphij
242170808Sdelphij		/* Valid when tn_type == VLNK. */
243170808Sdelphij		/* The link's target, allocated from a string pool. */
244170808Sdelphij		char *			tn_link;
245170808Sdelphij
246170808Sdelphij		/* Valid when tn_type == VREG. */
247170808Sdelphij		struct tn_reg {
248170808Sdelphij			/* The contents of regular files stored in a tmpfs
249170808Sdelphij			 * file system are represented by a single anonymous
250170808Sdelphij			 * memory object (aobj, for short).  The aobj provides
251170808Sdelphij			 * direct access to any position within the file,
252170808Sdelphij			 * because its contents are always mapped in a
253170808Sdelphij			 * contiguous region of virtual memory.  It is a task
254170808Sdelphij			 * of the memory management subsystem (see uvm(9)) to
255170808Sdelphij			 * issue the required page ins or page outs whenever
256170808Sdelphij			 * a position within the file is accessed. */
257170808Sdelphij			vm_object_t		tn_aobj;
258170808Sdelphij
259170808Sdelphij		}tn_reg;
260170808Sdelphij
261170808Sdelphij		/* Valid when tn_type = VFIFO */
262170808Sdelphij		struct tn_fifo {
263170808Sdelphij			fo_rdwr_t		*tn_fo_read;
264170808Sdelphij			fo_rdwr_t		*tn_fo_write;
265170808Sdelphij		}tn_fifo;
266170808Sdelphij	}tn_spec;
267170808Sdelphij};
268170808SdelphijLIST_HEAD(tmpfs_node_list, tmpfs_node);
269170808Sdelphij
270170808Sdelphij#define tn_rdev tn_spec.tn_rdev
271170808Sdelphij#define tn_dir tn_spec.tn_dir
272170808Sdelphij#define tn_link tn_spec.tn_link
273170808Sdelphij#define tn_reg tn_spec.tn_reg
274170808Sdelphij#define tn_fifo tn_spec.tn_fifo
275170808Sdelphij
276170808Sdelphij#define TMPFS_NODE_LOCK(node) mtx_lock(&(node)->tn_interlock)
277170808Sdelphij#define TMPFS_NODE_UNLOCK(node) mtx_unlock(&(node)->tn_interlock)
278197953Sdelphij#define TMPFS_NODE_MTX(node) (&(node)->tn_interlock)
279269169Skib#define	TMPFS_NODE_ASSERT_LOCKED(node) mtx_assert(TMPFS_NODE_MTX(node), \
280269169Skib    MA_OWNED)
281170808Sdelphij
282197953Sdelphij#ifdef INVARIANTS
283197953Sdelphij#define TMPFS_ASSERT_LOCKED(node) do {					\
284197953Sdelphij		MPASS(node != NULL);					\
285197953Sdelphij		MPASS(node->tn_vnode != NULL);				\
286197953Sdelphij		if (!VOP_ISLOCKED(node->tn_vnode) &&			\
287197953Sdelphij		    !mtx_owned(TMPFS_NODE_MTX(node)))			\
288197953Sdelphij			panic("tmpfs: node is not locked: %p", node);	\
289197953Sdelphij	} while (0)
290197953Sdelphij#define TMPFS_ASSERT_ELOCKED(node) do {					\
291197953Sdelphij		MPASS((node) != NULL);					\
292197953Sdelphij		MPASS((node)->tn_vnode != NULL);			\
293197953Sdelphij		mtx_assert(TMPFS_NODE_MTX(node), MA_OWNED);		\
294197953Sdelphij		ASSERT_VOP_LOCKED((node)->tn_vnode, "tmpfs");		\
295197953Sdelphij	} while (0)
296197953Sdelphij#else
297197953Sdelphij#define TMPFS_ASSERT_LOCKED(node) (void)0
298197953Sdelphij#define TMPFS_ASSERT_ELOCKED(node) (void)0
299197953Sdelphij#endif
300197953Sdelphij
301170808Sdelphij#define TMPFS_VNODE_ALLOCATING	1
302170808Sdelphij#define TMPFS_VNODE_WANT	2
303197953Sdelphij#define TMPFS_VNODE_DOOMED	4
304253967Skib#define	TMPFS_VNODE_WRECLAIM	8
305170808Sdelphij
306170808Sdelphij/*
307170808Sdelphij * Internal representation of a tmpfs mount point.
308170808Sdelphij */
309170808Sdelphijstruct tmpfs_mount {
310170808Sdelphij	/* Maximum number of memory pages available for use by the file
311170808Sdelphij	 * system, set during mount time.  This variable must never be
312171038Sdelphij	 * used directly as it may be bigger than the current amount of
313170808Sdelphij	 * free memory; in the extreme case, it will hold the SIZE_MAX
314233998Sgleb	 * value. */
315170808Sdelphij	size_t			tm_pages_max;
316170808Sdelphij
317233998Sgleb	/* Number of pages in use by the file system. */
318170808Sdelphij	size_t			tm_pages_used;
319170808Sdelphij
320170808Sdelphij	/* Pointer to the node representing the root directory of this
321170808Sdelphij	 * file system. */
322170808Sdelphij	struct tmpfs_node *	tm_root;
323170808Sdelphij
324170808Sdelphij	/* Maximum number of possible nodes for this file system; set
325170808Sdelphij	 * during mount time.  We need a hard limit on the maximum number
326170808Sdelphij	 * of nodes to avoid allocating too much of them; their objects
327170808Sdelphij	 * cannot be released until the file system is unmounted.
328170808Sdelphij	 * Otherwise, we could easily run out of memory by creating lots
329170808Sdelphij	 * of empty files and then simply removing them. */
330170808Sdelphij	ino_t			tm_nodes_max;
331170808Sdelphij
332171362Sdelphij	/* unrhdr used to allocate inode numbers */
333171362Sdelphij	struct unrhdr *		tm_ino_unr;
334170808Sdelphij
335170808Sdelphij	/* Number of nodes currently that are in use. */
336170808Sdelphij	ino_t			tm_nodes_inuse;
337170808Sdelphij
338170808Sdelphij	/* maximum representable file size */
339170808Sdelphij	u_int64_t		tm_maxfilesize;
340171070Sdelphij
341170808Sdelphij	/* Nodes are organized in two different lists.  The used list
342170808Sdelphij	 * contains all nodes that are currently used by the file system;
343170808Sdelphij	 * i.e., they refer to existing files.  The available list contains
344170808Sdelphij	 * all nodes that are currently available for use by new files.
345170808Sdelphij	 * Nodes must be kept in this list (instead of deleting them)
346170808Sdelphij	 * because we need to keep track of their generation number (tn_gen
347170808Sdelphij	 * field).
348170808Sdelphij	 *
349170808Sdelphij	 * Note that nodes are lazily allocated: if the available list is
350170808Sdelphij	 * empty and we have enough space to create more nodes, they will be
351170808Sdelphij	 * created and inserted in the used list.  Once these are released,
352170808Sdelphij	 * they will go into the available list, remaining alive until the
353170808Sdelphij	 * file system is unmounted. */
354170808Sdelphij	struct tmpfs_node_list	tm_nodes_used;
355170808Sdelphij
356170808Sdelphij	/* All node lock to protect the node list and tmp_pages_used */
357170808Sdelphij	struct mtx allnode_lock;
358170808Sdelphij
359170808Sdelphij	/* Pools used to store file system meta data.  These are not shared
360170808Sdelphij	 * across several instances of tmpfs for the reasons described in
361170808Sdelphij	 * tmpfs_pool.c. */
362170808Sdelphij	uma_zone_t		tm_dirent_pool;
363170808Sdelphij	uma_zone_t		tm_node_pool;
364234346Sjh
365234346Sjh	/* Read-only status. */
366234346Sjh	int			tm_ronly;
367170808Sdelphij};
368170808Sdelphij#define TMPFS_LOCK(tm) mtx_lock(&(tm)->allnode_lock)
369170808Sdelphij#define TMPFS_UNLOCK(tm) mtx_unlock(&(tm)->allnode_lock)
370170808Sdelphij
371170808Sdelphij/*
372170808Sdelphij * This structure maps a file identifier to a tmpfs node.  Used by the
373170808Sdelphij * NFS code.
374170808Sdelphij */
375170808Sdelphijstruct tmpfs_fid {
376170808Sdelphij	uint16_t		tf_len;
377170808Sdelphij	uint16_t		tf_pad;
378171067Sdelphij	ino_t			tf_id;
379170808Sdelphij	unsigned long		tf_gen;
380170808Sdelphij};
381170808Sdelphij
382170808Sdelphij#ifdef _KERNEL
383170808Sdelphij/*
384170808Sdelphij * Prototypes for tmpfs_subr.c.
385170808Sdelphij */
386170808Sdelphij
387269175Skibint	tmpfs_alloc_node(struct mount *mp, struct tmpfs_mount *, enum vtype,
388170808Sdelphij	    uid_t uid, gid_t gid, mode_t mode, struct tmpfs_node *,
389191990Sattilio	    char *, dev_t, struct tmpfs_node **);
390170808Sdelphijvoid	tmpfs_free_node(struct tmpfs_mount *, struct tmpfs_node *);
391170808Sdelphijint	tmpfs_alloc_dirent(struct tmpfs_mount *, struct tmpfs_node *,
392245115Sgleb	    const char *, u_int, struct tmpfs_dirent **);
393245115Sglebvoid	tmpfs_free_dirent(struct tmpfs_mount *, struct tmpfs_dirent *);
394245115Sglebvoid	tmpfs_dirent_init(struct tmpfs_dirent *, const char *, u_int);
395250189Skibvoid	tmpfs_destroy_vobject(struct vnode *vp, vm_object_t obj);
396171799Sdelphijint	tmpfs_alloc_vp(struct mount *, struct tmpfs_node *, int,
397191990Sattilio	    struct vnode **);
398170808Sdelphijvoid	tmpfs_free_vp(struct vnode *);
399170808Sdelphijint	tmpfs_alloc_file(struct vnode *, struct vnode **, struct vattr *,
400170808Sdelphij	    struct componentname *, char *);
401278571Skibvoid	tmpfs_check_mtime(struct vnode *);
402170808Sdelphijvoid	tmpfs_dir_attach(struct vnode *, struct tmpfs_dirent *);
403170808Sdelphijvoid	tmpfs_dir_detach(struct vnode *, struct tmpfs_dirent *);
404245115Sglebvoid	tmpfs_dir_destroy(struct tmpfs_mount *, struct tmpfs_node *);
405170808Sdelphijstruct tmpfs_dirent *	tmpfs_dir_lookup(struct tmpfs_node *node,
406188318Skib			    struct tmpfs_node *f,
407170808Sdelphij			    struct componentname *cnp);
408245115Sglebint	tmpfs_dir_getdents(struct tmpfs_node *, struct uio *, int,
409245115Sgleb	    u_long *, int *);
410211598Sedint	tmpfs_dir_whiteout_add(struct vnode *, struct componentname *);
411211598Sedvoid	tmpfs_dir_whiteout_remove(struct vnode *, struct componentname *);
412230180Salcint	tmpfs_reg_resize(struct vnode *, off_t, boolean_t);
413248597Spjdint	tmpfs_chflags(struct vnode *, u_long, struct ucred *, struct thread *);
414170808Sdelphijint	tmpfs_chmod(struct vnode *, mode_t, struct ucred *, struct thread *);
415170808Sdelphijint	tmpfs_chown(struct vnode *, uid_t, gid_t, struct ucred *,
416170808Sdelphij	    struct thread *);
417170808Sdelphijint	tmpfs_chsize(struct vnode *, u_quad_t, struct ucred *, struct thread *);
418267816Skibint	tmpfs_chtimes(struct vnode *, struct vattr *, struct ucred *cred,
419267816Skib	    struct thread *);
420170808Sdelphijvoid	tmpfs_itimes(struct vnode *, const struct timespec *,
421170808Sdelphij	    const struct timespec *);
422170808Sdelphij
423170808Sdelphijvoid	tmpfs_update(struct vnode *);
424170808Sdelphijint	tmpfs_truncate(struct vnode *, off_t);
425170808Sdelphij
426170808Sdelphij/*
427170808Sdelphij * Convenience macros to simplify some logical expressions.
428170808Sdelphij */
429170808Sdelphij#define IMPLIES(a, b) (!(a) || (b))
430170808Sdelphij#define IFF(a, b) (IMPLIES(a, b) && IMPLIES(b, a))
431170808Sdelphij
432170808Sdelphij/*
433170808Sdelphij * Checks that the directory entry pointed by 'de' matches the name 'name'
434170808Sdelphij * with a length of 'len'.
435170808Sdelphij */
436170808Sdelphij#define TMPFS_DIRENT_MATCHES(de, name, len) \
437245115Sgleb    (de->td_namelen == len && \
438245115Sgleb    bcmp((de)->ud.td_name, (name), (de)->td_namelen) == 0)
439170808Sdelphij
440170808Sdelphij/*
441170808Sdelphij * Ensures that the node pointed by 'node' is a directory and that its
442170808Sdelphij * contents are consistent with respect to directories.
443170808Sdelphij */
444245115Sgleb#define TMPFS_VALIDATE_DIR(node) do { \
445245115Sgleb	MPASS((node)->tn_type == VDIR); \
446245115Sgleb	MPASS((node)->tn_size % sizeof(struct tmpfs_dirent) == 0); \
447245115Sgleb} while (0)
448170808Sdelphij
449170808Sdelphij/*
450170808Sdelphij * Memory management stuff.
451170808Sdelphij */
452170808Sdelphij
453233998Sgleb/*
454233998Sgleb * Amount of memory pages to reserve for the system (e.g., to not use by
455170808Sdelphij * tmpfs).
456170808Sdelphij */
457233998Sgleb#define TMPFS_PAGES_MINRESERVED		(4 * 1024 * 1024 / PAGE_SIZE)
458170808Sdelphij
459233998Sglebsize_t tmpfs_mem_avail(void);
460170808Sdelphij
461233998Sglebsize_t tmpfs_pages_used(struct tmpfs_mount *tmp);
462170808Sdelphij
463170808Sdelphij#endif
464170808Sdelphij
465170808Sdelphij/*
466170808Sdelphij * Macros/functions to convert from generic data structures to tmpfs
467170808Sdelphij * specific ones.
468170808Sdelphij */
469170808Sdelphij
470170808Sdelphijstatic inline
471170808Sdelphijstruct tmpfs_mount *
472170808SdelphijVFS_TO_TMPFS(struct mount *mp)
473170808Sdelphij{
474170808Sdelphij	struct tmpfs_mount *tmp;
475170808Sdelphij
476170808Sdelphij	MPASS((mp) != NULL && (mp)->mnt_data != NULL);
477170808Sdelphij	tmp = (struct tmpfs_mount *)(mp)->mnt_data;
478170808Sdelphij	return tmp;
479170808Sdelphij}
480170808Sdelphij
481170808Sdelphijstatic inline
482170808Sdelphijstruct tmpfs_node *
483170808SdelphijVP_TO_TMPFS_NODE(struct vnode *vp)
484170808Sdelphij{
485170808Sdelphij	struct tmpfs_node *node;
486170808Sdelphij
487170808Sdelphij	MPASS((vp) != NULL && (vp)->v_data != NULL);
488170808Sdelphij	node = (struct tmpfs_node *)vp->v_data;
489170808Sdelphij	return node;
490170808Sdelphij}
491170808Sdelphij
492170808Sdelphijstatic inline
493170808Sdelphijstruct tmpfs_node *
494170808SdelphijVP_TO_TMPFS_DIR(struct vnode *vp)
495170808Sdelphij{
496170808Sdelphij	struct tmpfs_node *node;
497170808Sdelphij
498170808Sdelphij	node = VP_TO_TMPFS_NODE(vp);
499170808Sdelphij	TMPFS_VALIDATE_DIR(node);
500170808Sdelphij	return node;
501170808Sdelphij}
502170808Sdelphij
503170808Sdelphij#endif /* _FS_TMPFS_TMPFS_H_ */
504