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$
33170808Sdelphij */
34170808Sdelphij
35170808Sdelphij#ifndef _FS_TMPFS_TMPFS_H_
36170808Sdelphij#define _FS_TMPFS_TMPFS_H_
37170808Sdelphij
38170808Sdelphij/* ---------------------------------------------------------------------
39170808Sdelphij * KERNEL-SPECIFIC DEFINITIONS
40170808Sdelphij * --------------------------------------------------------------------- */
41170808Sdelphij#include <sys/dirent.h>
42170808Sdelphij#include <sys/mount.h>
43170808Sdelphij#include <sys/queue.h>
44170808Sdelphij#include <sys/vnode.h>
45170808Sdelphij#include <sys/file.h>
46170808Sdelphij#include <sys/lock.h>
47170808Sdelphij#include <sys/mutex.h>
48170808Sdelphij
49170808Sdelphij/* --------------------------------------------------------------------- */
50170808Sdelphij#include <sys/malloc.h>
51170808Sdelphij#include <sys/systm.h>
52245115Sgleb#include <sys/tree.h>
53170808Sdelphij#include <sys/vmmeter.h>
54170808Sdelphij#include <vm/swap_pager.h>
55170808Sdelphij
56170808SdelphijMALLOC_DECLARE(M_TMPFSMNT);
57171087SdelphijMALLOC_DECLARE(M_TMPFSNAME);
58170808Sdelphij
59170808Sdelphij/* --------------------------------------------------------------------- */
60170808Sdelphij
61170808Sdelphij/*
62170808Sdelphij * Internal representation of a tmpfs directory entry.
63170808Sdelphij */
64245115Sgleb
65245115SglebLIST_HEAD(tmpfs_dir_duphead, tmpfs_dirent);
66245115Sgleb
67170808Sdelphijstruct tmpfs_dirent {
68245115Sgleb	/*
69245115Sgleb	 * Depending on td_cookie flag entry can be of 3 types:
70245115Sgleb	 * - regular -- no hash collisions, stored in RB-Tree
71245115Sgleb	 * - duphead -- synthetic linked list head for dup entries
72245115Sgleb	 * - dup -- stored in linked list instead of RB-Tree
73245115Sgleb	 */
74245115Sgleb	union {
75245115Sgleb		/* regular and duphead entry types */
76245115Sgleb		RB_ENTRY(tmpfs_dirent)		td_entries;
77170808Sdelphij
78245115Sgleb		/* dup entry type */
79245115Sgleb		struct {
80245115Sgleb			LIST_ENTRY(tmpfs_dirent) entries;
81245115Sgleb			LIST_ENTRY(tmpfs_dirent) index_entries;
82245115Sgleb		} td_dup;
83245115Sgleb	} uh;
84170808Sdelphij
85245115Sgleb	uint32_t			td_cookie;
86245115Sgleb	uint32_t			td_hash;
87245115Sgleb	u_int				td_namelen;
88170808Sdelphij
89211598Sed	/* Pointer to the node this entry refers to.  In case this field
90211598Sed	 * is NULL, the node is a whiteout. */
91170808Sdelphij	struct tmpfs_node *		td_node;
92245115Sgleb
93245115Sgleb	union {
94245115Sgleb		/*
95245115Sgleb		 * The name of the entry, allocated from a string pool.  This
96245115Sgleb		 * string is not required to be zero-terminated.
97245115Sgleb		 */
98245115Sgleb		char *			td_name;	/* regular, dup */
99245115Sgleb		struct tmpfs_dir_duphead td_duphead;	/* duphead */
100245115Sgleb	} ud;
101170808Sdelphij};
102170808Sdelphij
103245115Sgleb/* A directory in tmpfs holds a list of directory entries, which in
104170808Sdelphij * turn point to other files (which can be directories themselves).
105170808Sdelphij *
106245115Sgleb * In tmpfs, this list is managed by a RB-Tree, whose head is defined by
107170808Sdelphij * the struct tmpfs_dir type.
108170808Sdelphij *
109245115Sgleb * It is important to notice that directories do not have entries for . and
110170808Sdelphij * .. as other file systems do.  These can be generated when requested
111170808Sdelphij * based on information available by other means, such as the pointer to
112170808Sdelphij * the node itself in the former case or the pointer to the parent directory
113170808Sdelphij * in the latter case.  This is done to simplify tmpfs's code and, more
114170808Sdelphij * importantly, to remove redundancy. */
115245115SglebRB_HEAD(tmpfs_dir, tmpfs_dirent);
116170808Sdelphij
117171802Sdelphij/* Each entry in a directory has a cookie that identifies it.  Cookies
118171802Sdelphij * supersede offsets within directories because, given how tmpfs stores
119245115Sgleb * directories in memory, there is no such thing as an offset.
120245115Sgleb *
121171802Sdelphij * The '.', '..' and the end of directory markers have fixed cookies which
122171802Sdelphij * cannot collide with the cookies generated by other entries.  The cookies
123245115Sgleb * for the other entries are generated based on the file name hash value or
124245115Sgleb * unique number in case of name hash collision.
125171802Sdelphij *
126245115Sgleb * To preserve compatibility cookies are limited to 31 bits.
127245115Sgleb */
128170808Sdelphij
129245115Sgleb#define	TMPFS_DIRCOOKIE_DOT		0
130245115Sgleb#define	TMPFS_DIRCOOKIE_DOTDOT		1
131245115Sgleb#define	TMPFS_DIRCOOKIE_EOF		2
132245115Sgleb#define	TMPFS_DIRCOOKIE_MASK		((off_t)0x3fffffffU)
133245115Sgleb#define	TMPFS_DIRCOOKIE_MIN		((off_t)0x00000004U)
134245115Sgleb#define	TMPFS_DIRCOOKIE_DUP		((off_t)0x40000000U)
135245115Sgleb#define	TMPFS_DIRCOOKIE_DUPHEAD		((off_t)0x80000000U)
136245115Sgleb#define	TMPFS_DIRCOOKIE_DUP_MIN		TMPFS_DIRCOOKIE_DUP
137245115Sgleb#define	TMPFS_DIRCOOKIE_DUP_MAX		\
138245115Sgleb	(TMPFS_DIRCOOKIE_DUP | TMPFS_DIRCOOKIE_MASK)
139171802Sdelphij
140170808Sdelphij/* --------------------------------------------------------------------- */
141170808Sdelphij
142170808Sdelphij/*
143170808Sdelphij * Internal representation of a tmpfs file system node.
144170808Sdelphij *
145170808Sdelphij * This structure is splitted in two parts: one holds attributes common
146170808Sdelphij * to all file types and the other holds data that is only applicable to
147170808Sdelphij * a particular type.  The code must be careful to only access those
148170808Sdelphij * attributes that are actually allowed by the node's type.
149170808Sdelphij *
150170808Sdelphij *
151170808Sdelphij * Below is the key of locks used to protected the fields in the following
152170808Sdelphij * structures.
153170808Sdelphij *
154170808Sdelphij */
155170808Sdelphijstruct tmpfs_node {
156170808Sdelphij	/* Doubly-linked list entry which links all existing nodes for a
157170808Sdelphij	 * single file system.  This is provided to ease the removal of
158170808Sdelphij	 * all nodes during the unmount operation. */
159170808Sdelphij	LIST_ENTRY(tmpfs_node)	tn_entries;
160170808Sdelphij
161170808Sdelphij	/* The node's type.  Any of 'VBLK', 'VCHR', 'VDIR', 'VFIFO',
162170808Sdelphij	 * 'VLNK', 'VREG' and 'VSOCK' is allowed.  The usage of vnode
163170808Sdelphij	 * types instead of a custom enumeration is to make things simpler
164170808Sdelphij	 * and faster, as we do not need to convert between two types. */
165170808Sdelphij	enum vtype		tn_type;
166170808Sdelphij
167170808Sdelphij	/* Node identifier. */
168170808Sdelphij	ino_t			tn_id;
169170808Sdelphij
170170808Sdelphij	/* Node's internal status.  This is used by several file system
171170808Sdelphij	 * operations to do modifications to the node in a delayed
172170808Sdelphij	 * fashion. */
173170808Sdelphij	int			tn_status;
174170808Sdelphij#define	TMPFS_NODE_ACCESSED	(1 << 1)
175170808Sdelphij#define	TMPFS_NODE_MODIFIED	(1 << 2)
176170808Sdelphij#define	TMPFS_NODE_CHANGED	(1 << 3)
177170808Sdelphij
178170808Sdelphij	/* The node size.  It does not necessarily match the real amount
179170808Sdelphij	 * of memory consumed by it. */
180170808Sdelphij	off_t			tn_size;
181170808Sdelphij
182170808Sdelphij	/* Generic node attributes. */
183170808Sdelphij	uid_t			tn_uid;
184170808Sdelphij	gid_t			tn_gid;
185170808Sdelphij	mode_t			tn_mode;
186248597Spjd	u_long			tn_flags;
187170808Sdelphij	nlink_t			tn_links;
188170808Sdelphij	struct timespec		tn_atime;
189170808Sdelphij	struct timespec		tn_mtime;
190170808Sdelphij	struct timespec		tn_ctime;
191170808Sdelphij	struct timespec		tn_birthtime;
192170808Sdelphij	unsigned long		tn_gen;
193170808Sdelphij
194170808Sdelphij	/* As there is a single vnode for each active file within the
195170808Sdelphij	 * system, care has to be taken to avoid allocating more than one
196170808Sdelphij	 * vnode per file.  In order to do this, a bidirectional association
197170808Sdelphij	 * is kept between vnodes and nodes.
198170808Sdelphij	 *
199170808Sdelphij	 * Whenever a vnode is allocated, its v_data field is updated to
200170808Sdelphij	 * point to the node it references.  At the same time, the node's
201170808Sdelphij	 * tn_vnode field is modified to point to the new vnode representing
202170808Sdelphij	 * it.  Further attempts to allocate a vnode for this same node will
203170808Sdelphij	 * result in returning a new reference to the value stored in
204170808Sdelphij	 * tn_vnode.
205170808Sdelphij	 *
206170808Sdelphij	 * May be NULL when the node is unused (that is, no vnode has been
207170808Sdelphij	 * allocated for it or it has been reclaimed). */
208170808Sdelphij	struct vnode *		tn_vnode;
209170808Sdelphij
210170808Sdelphij	/* interlock to protect tn_vpstate */
211170808Sdelphij	struct mtx	tn_interlock;
212170808Sdelphij
213170808Sdelphij	/* Identify if current node has vnode assiocate with
214170808Sdelphij	 * or allocating vnode.
215170808Sdelphij	 */
216170808Sdelphij	int		tn_vpstate;
217170808Sdelphij
218170808Sdelphij	/* misc data field for different tn_type node */
219170808Sdelphij	union {
220170808Sdelphij		/* Valid when tn_type == VBLK || tn_type == VCHR. */
221170808Sdelphij		dev_t			tn_rdev;
222170808Sdelphij
223170808Sdelphij		/* Valid when tn_type == VDIR. */
224245115Sgleb		struct tn_dir {
225170808Sdelphij			/* Pointer to the parent directory.  The root
226170808Sdelphij			 * directory has a pointer to itself in this field;
227170808Sdelphij			 * this property identifies the root node. */
228170808Sdelphij			struct tmpfs_node *	tn_parent;
229170808Sdelphij
230245115Sgleb			/* Head of a tree that links the contents of
231245115Sgleb			 * the directory together. */
232170808Sdelphij			struct tmpfs_dir	tn_dirhead;
233170808Sdelphij
234245115Sgleb			/* Head of a list the contains fake directory entries
235245115Sgleb			 * heads, i.e. entries with TMPFS_DIRCOOKIE_DUPHEAD
236245115Sgleb			 * flag. */
237245115Sgleb			struct tmpfs_dir_duphead tn_dupindex;
238245115Sgleb
239170808Sdelphij			/* Number and pointer of the first directory entry
240170808Sdelphij			 * returned by the readdir operation if it were
241170808Sdelphij			 * called again to continue reading data from the
242170808Sdelphij			 * same directory as before.  This is used to speed
243170808Sdelphij			 * up reads of long directories, assuming that no
244170808Sdelphij			 * more than one read is in progress at a given time.
245245115Sgleb			 * Otherwise, these values are discarded. */
246170808Sdelphij			off_t			tn_readdir_lastn;
247170808Sdelphij			struct tmpfs_dirent *	tn_readdir_lastp;
248245115Sgleb		} tn_dir;
249170808Sdelphij
250170808Sdelphij		/* Valid when tn_type == VLNK. */
251170808Sdelphij		/* The link's target, allocated from a string pool. */
252170808Sdelphij		char *			tn_link;
253170808Sdelphij
254170808Sdelphij		/* Valid when tn_type == VREG. */
255170808Sdelphij		struct tn_reg {
256170808Sdelphij			/* The contents of regular files stored in a tmpfs
257170808Sdelphij			 * file system are represented by a single anonymous
258170808Sdelphij			 * memory object (aobj, for short).  The aobj provides
259170808Sdelphij			 * direct access to any position within the file,
260170808Sdelphij			 * because its contents are always mapped in a
261170808Sdelphij			 * contiguous region of virtual memory.  It is a task
262170808Sdelphij			 * of the memory management subsystem (see uvm(9)) to
263170808Sdelphij			 * issue the required page ins or page outs whenever
264170808Sdelphij			 * a position within the file is accessed. */
265170808Sdelphij			vm_object_t		tn_aobj;
266170808Sdelphij
267170808Sdelphij		}tn_reg;
268170808Sdelphij
269170808Sdelphij		/* Valid when tn_type = VFIFO */
270170808Sdelphij		struct tn_fifo {
271170808Sdelphij			fo_rdwr_t		*tn_fo_read;
272170808Sdelphij			fo_rdwr_t		*tn_fo_write;
273170808Sdelphij		}tn_fifo;
274170808Sdelphij	}tn_spec;
275170808Sdelphij};
276170808SdelphijLIST_HEAD(tmpfs_node_list, tmpfs_node);
277170808Sdelphij
278170808Sdelphij#define tn_rdev tn_spec.tn_rdev
279170808Sdelphij#define tn_dir tn_spec.tn_dir
280170808Sdelphij#define tn_link tn_spec.tn_link
281170808Sdelphij#define tn_reg tn_spec.tn_reg
282170808Sdelphij#define tn_fifo tn_spec.tn_fifo
283170808Sdelphij
284170808Sdelphij#define TMPFS_NODE_LOCK(node) mtx_lock(&(node)->tn_interlock)
285170808Sdelphij#define TMPFS_NODE_UNLOCK(node) mtx_unlock(&(node)->tn_interlock)
286197953Sdelphij#define TMPFS_NODE_MTX(node) (&(node)->tn_interlock)
287170808Sdelphij
288197953Sdelphij#ifdef INVARIANTS
289197953Sdelphij#define TMPFS_ASSERT_LOCKED(node) do {					\
290197953Sdelphij		MPASS(node != NULL);					\
291197953Sdelphij		MPASS(node->tn_vnode != NULL);				\
292197953Sdelphij		if (!VOP_ISLOCKED(node->tn_vnode) &&			\
293197953Sdelphij		    !mtx_owned(TMPFS_NODE_MTX(node)))			\
294197953Sdelphij			panic("tmpfs: node is not locked: %p", node);	\
295197953Sdelphij	} while (0)
296197953Sdelphij#define TMPFS_ASSERT_ELOCKED(node) do {					\
297197953Sdelphij		MPASS((node) != NULL);					\
298197953Sdelphij		MPASS((node)->tn_vnode != NULL);			\
299197953Sdelphij		mtx_assert(TMPFS_NODE_MTX(node), MA_OWNED);		\
300197953Sdelphij		ASSERT_VOP_LOCKED((node)->tn_vnode, "tmpfs");		\
301197953Sdelphij	} while (0)
302197953Sdelphij#else
303197953Sdelphij#define TMPFS_ASSERT_LOCKED(node) (void)0
304197953Sdelphij#define TMPFS_ASSERT_ELOCKED(node) (void)0
305197953Sdelphij#endif
306197953Sdelphij
307170808Sdelphij#define TMPFS_VNODE_ALLOCATING	1
308170808Sdelphij#define TMPFS_VNODE_WANT	2
309197953Sdelphij#define TMPFS_VNODE_DOOMED	4
310253967Skib#define	TMPFS_VNODE_WRECLAIM	8
311170808Sdelphij/* --------------------------------------------------------------------- */
312170808Sdelphij
313170808Sdelphij/*
314170808Sdelphij * Internal representation of a tmpfs mount point.
315170808Sdelphij */
316170808Sdelphijstruct tmpfs_mount {
317170808Sdelphij	/* Maximum number of memory pages available for use by the file
318170808Sdelphij	 * system, set during mount time.  This variable must never be
319171038Sdelphij	 * used directly as it may be bigger than the current amount of
320170808Sdelphij	 * free memory; in the extreme case, it will hold the SIZE_MAX
321233998Sgleb	 * value. */
322170808Sdelphij	size_t			tm_pages_max;
323170808Sdelphij
324233998Sgleb	/* Number of pages in use by the file system. */
325170808Sdelphij	size_t			tm_pages_used;
326170808Sdelphij
327170808Sdelphij	/* Pointer to the node representing the root directory of this
328170808Sdelphij	 * file system. */
329170808Sdelphij	struct tmpfs_node *	tm_root;
330170808Sdelphij
331170808Sdelphij	/* Maximum number of possible nodes for this file system; set
332170808Sdelphij	 * during mount time.  We need a hard limit on the maximum number
333170808Sdelphij	 * of nodes to avoid allocating too much of them; their objects
334170808Sdelphij	 * cannot be released until the file system is unmounted.
335170808Sdelphij	 * Otherwise, we could easily run out of memory by creating lots
336170808Sdelphij	 * of empty files and then simply removing them. */
337170808Sdelphij	ino_t			tm_nodes_max;
338170808Sdelphij
339171362Sdelphij	/* unrhdr used to allocate inode numbers */
340171362Sdelphij	struct unrhdr *		tm_ino_unr;
341170808Sdelphij
342170808Sdelphij	/* Number of nodes currently that are in use. */
343170808Sdelphij	ino_t			tm_nodes_inuse;
344170808Sdelphij
345170808Sdelphij	/* maximum representable file size */
346170808Sdelphij	u_int64_t		tm_maxfilesize;
347171070Sdelphij
348170808Sdelphij	/* Nodes are organized in two different lists.  The used list
349170808Sdelphij	 * contains all nodes that are currently used by the file system;
350170808Sdelphij	 * i.e., they refer to existing files.  The available list contains
351170808Sdelphij	 * all nodes that are currently available for use by new files.
352170808Sdelphij	 * Nodes must be kept in this list (instead of deleting them)
353170808Sdelphij	 * because we need to keep track of their generation number (tn_gen
354170808Sdelphij	 * field).
355170808Sdelphij	 *
356170808Sdelphij	 * Note that nodes are lazily allocated: if the available list is
357170808Sdelphij	 * empty and we have enough space to create more nodes, they will be
358170808Sdelphij	 * created and inserted in the used list.  Once these are released,
359170808Sdelphij	 * they will go into the available list, remaining alive until the
360170808Sdelphij	 * file system is unmounted. */
361170808Sdelphij	struct tmpfs_node_list	tm_nodes_used;
362170808Sdelphij
363170808Sdelphij	/* All node lock to protect the node list and tmp_pages_used */
364170808Sdelphij	struct mtx allnode_lock;
365170808Sdelphij
366170808Sdelphij	/* Pools used to store file system meta data.  These are not shared
367170808Sdelphij	 * across several instances of tmpfs for the reasons described in
368170808Sdelphij	 * tmpfs_pool.c. */
369170808Sdelphij	uma_zone_t		tm_dirent_pool;
370170808Sdelphij	uma_zone_t		tm_node_pool;
371234346Sjh
372234346Sjh	/* Read-only status. */
373234346Sjh	int			tm_ronly;
374170808Sdelphij};
375170808Sdelphij#define TMPFS_LOCK(tm) mtx_lock(&(tm)->allnode_lock)
376170808Sdelphij#define TMPFS_UNLOCK(tm) mtx_unlock(&(tm)->allnode_lock)
377170808Sdelphij
378170808Sdelphij/* --------------------------------------------------------------------- */
379170808Sdelphij
380170808Sdelphij/*
381170808Sdelphij * This structure maps a file identifier to a tmpfs node.  Used by the
382170808Sdelphij * NFS code.
383170808Sdelphij */
384170808Sdelphijstruct tmpfs_fid {
385170808Sdelphij	uint16_t		tf_len;
386170808Sdelphij	uint16_t		tf_pad;
387171067Sdelphij	ino_t			tf_id;
388170808Sdelphij	unsigned long		tf_gen;
389170808Sdelphij};
390170808Sdelphij
391170808Sdelphij/* --------------------------------------------------------------------- */
392170808Sdelphij
393170808Sdelphij#ifdef _KERNEL
394170808Sdelphij/*
395170808Sdelphij * Prototypes for tmpfs_subr.c.
396170808Sdelphij */
397170808Sdelphij
398170808Sdelphijint	tmpfs_alloc_node(struct tmpfs_mount *, enum vtype,
399170808Sdelphij	    uid_t uid, gid_t gid, mode_t mode, struct tmpfs_node *,
400191990Sattilio	    char *, dev_t, struct tmpfs_node **);
401170808Sdelphijvoid	tmpfs_free_node(struct tmpfs_mount *, struct tmpfs_node *);
402170808Sdelphijint	tmpfs_alloc_dirent(struct tmpfs_mount *, struct tmpfs_node *,
403245115Sgleb	    const char *, u_int, struct tmpfs_dirent **);
404245115Sglebvoid	tmpfs_free_dirent(struct tmpfs_mount *, struct tmpfs_dirent *);
405245115Sglebvoid	tmpfs_dirent_init(struct tmpfs_dirent *, const char *, u_int);
406250189Skibvoid	tmpfs_destroy_vobject(struct vnode *vp, vm_object_t obj);
407171799Sdelphijint	tmpfs_alloc_vp(struct mount *, struct tmpfs_node *, int,
408191990Sattilio	    struct vnode **);
409170808Sdelphijvoid	tmpfs_free_vp(struct vnode *);
410170808Sdelphijint	tmpfs_alloc_file(struct vnode *, struct vnode **, struct vattr *,
411170808Sdelphij	    struct componentname *, char *);
412170808Sdelphijvoid	tmpfs_dir_attach(struct vnode *, struct tmpfs_dirent *);
413170808Sdelphijvoid	tmpfs_dir_detach(struct vnode *, struct tmpfs_dirent *);
414245115Sglebvoid	tmpfs_dir_destroy(struct tmpfs_mount *, struct tmpfs_node *);
415170808Sdelphijstruct tmpfs_dirent *	tmpfs_dir_lookup(struct tmpfs_node *node,
416188318Skib			    struct tmpfs_node *f,
417170808Sdelphij			    struct componentname *cnp);
418245115Sglebint	tmpfs_dir_getdents(struct tmpfs_node *, struct uio *, int,
419245115Sgleb	    u_long *, int *);
420211598Sedint	tmpfs_dir_whiteout_add(struct vnode *, struct componentname *);
421211598Sedvoid	tmpfs_dir_whiteout_remove(struct vnode *, struct componentname *);
422230180Salcint	tmpfs_reg_resize(struct vnode *, off_t, boolean_t);
423248597Spjdint	tmpfs_chflags(struct vnode *, u_long, struct ucred *, struct thread *);
424170808Sdelphijint	tmpfs_chmod(struct vnode *, mode_t, struct ucred *, struct thread *);
425170808Sdelphijint	tmpfs_chown(struct vnode *, uid_t, gid_t, struct ucred *,
426170808Sdelphij	    struct thread *);
427170808Sdelphijint	tmpfs_chsize(struct vnode *, u_quad_t, struct ucred *, struct thread *);
428171070Sdelphijint	tmpfs_chtimes(struct vnode *, struct timespec *, struct timespec *,
429170808Sdelphij	    struct timespec *, int, struct ucred *, struct thread *);
430170808Sdelphijvoid	tmpfs_itimes(struct vnode *, const struct timespec *,
431170808Sdelphij	    const struct timespec *);
432170808Sdelphij
433170808Sdelphijvoid	tmpfs_update(struct vnode *);
434170808Sdelphijint	tmpfs_truncate(struct vnode *, off_t);
435170808Sdelphij
436170808Sdelphij/* --------------------------------------------------------------------- */
437170808Sdelphij
438170808Sdelphij/*
439170808Sdelphij * Convenience macros to simplify some logical expressions.
440170808Sdelphij */
441170808Sdelphij#define IMPLIES(a, b) (!(a) || (b))
442170808Sdelphij#define IFF(a, b) (IMPLIES(a, b) && IMPLIES(b, a))
443170808Sdelphij
444170808Sdelphij/* --------------------------------------------------------------------- */
445170808Sdelphij
446170808Sdelphij/*
447170808Sdelphij * Checks that the directory entry pointed by 'de' matches the name 'name'
448170808Sdelphij * with a length of 'len'.
449170808Sdelphij */
450170808Sdelphij#define TMPFS_DIRENT_MATCHES(de, name, len) \
451245115Sgleb    (de->td_namelen == len && \
452245115Sgleb    bcmp((de)->ud.td_name, (name), (de)->td_namelen) == 0)
453170808Sdelphij
454170808Sdelphij/* --------------------------------------------------------------------- */
455170808Sdelphij
456170808Sdelphij/*
457170808Sdelphij * Ensures that the node pointed by 'node' is a directory and that its
458170808Sdelphij * contents are consistent with respect to directories.
459170808Sdelphij */
460245115Sgleb#define TMPFS_VALIDATE_DIR(node) do { \
461245115Sgleb	MPASS((node)->tn_type == VDIR); \
462245115Sgleb	MPASS((node)->tn_size % sizeof(struct tmpfs_dirent) == 0); \
463245115Sgleb} while (0)
464170808Sdelphij
465170808Sdelphij/* --------------------------------------------------------------------- */
466170808Sdelphij
467170808Sdelphij/*
468170808Sdelphij * Memory management stuff.
469170808Sdelphij */
470170808Sdelphij
471233998Sgleb/*
472233998Sgleb * Amount of memory pages to reserve for the system (e.g., to not use by
473170808Sdelphij * tmpfs).
474170808Sdelphij */
475233998Sgleb#define TMPFS_PAGES_MINRESERVED		(4 * 1024 * 1024 / PAGE_SIZE)
476170808Sdelphij
477233998Sglebsize_t tmpfs_mem_avail(void);
478170808Sdelphij
479233998Sglebsize_t tmpfs_pages_used(struct tmpfs_mount *tmp);
480170808Sdelphij
481170808Sdelphij#endif
482170808Sdelphij
483170808Sdelphij/* --------------------------------------------------------------------- */
484170808Sdelphij
485170808Sdelphij/*
486170808Sdelphij * Macros/functions to convert from generic data structures to tmpfs
487170808Sdelphij * specific ones.
488170808Sdelphij */
489170808Sdelphij
490170808Sdelphijstatic inline
491170808Sdelphijstruct tmpfs_mount *
492170808SdelphijVFS_TO_TMPFS(struct mount *mp)
493170808Sdelphij{
494170808Sdelphij	struct tmpfs_mount *tmp;
495170808Sdelphij
496170808Sdelphij	MPASS((mp) != NULL && (mp)->mnt_data != NULL);
497170808Sdelphij	tmp = (struct tmpfs_mount *)(mp)->mnt_data;
498170808Sdelphij	return tmp;
499170808Sdelphij}
500170808Sdelphij
501170808Sdelphijstatic inline
502170808Sdelphijstruct tmpfs_node *
503170808SdelphijVP_TO_TMPFS_NODE(struct vnode *vp)
504170808Sdelphij{
505170808Sdelphij	struct tmpfs_node *node;
506170808Sdelphij
507170808Sdelphij	MPASS((vp) != NULL && (vp)->v_data != NULL);
508170808Sdelphij	node = (struct tmpfs_node *)vp->v_data;
509170808Sdelphij	return node;
510170808Sdelphij}
511170808Sdelphij
512170808Sdelphijstatic inline
513170808Sdelphijstruct tmpfs_node *
514170808SdelphijVP_TO_TMPFS_DIR(struct vnode *vp)
515170808Sdelphij{
516170808Sdelphij	struct tmpfs_node *node;
517170808Sdelphij
518170808Sdelphij	node = VP_TO_TMPFS_NODE(vp);
519170808Sdelphij	TMPFS_VALIDATE_DIR(node);
520170808Sdelphij	return node;
521170808Sdelphij}
522170808Sdelphij
523170808Sdelphij#endif /* _FS_TMPFS_TMPFS_H_ */
524