17a2de9a4SMatthew Dillon /* $NetBSD: tmpfs.h,v 1.26 2007/02/22 06:37:00 thorpej Exp $ */
27a2de9a4SMatthew Dillon
37a2de9a4SMatthew Dillon /*-
47a2de9a4SMatthew Dillon * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc.
57a2de9a4SMatthew Dillon * All rights reserved.
67a2de9a4SMatthew Dillon *
77a2de9a4SMatthew Dillon * This code is derived from software contributed to The NetBSD Foundation
87a2de9a4SMatthew Dillon * by Julio M. Merino Vidal, developed as part of Google's Summer of Code
97a2de9a4SMatthew Dillon * 2005 program.
107a2de9a4SMatthew Dillon *
117a2de9a4SMatthew Dillon * Redistribution and use in source and binary forms, with or without
127a2de9a4SMatthew Dillon * modification, are permitted provided that the following conditions
137a2de9a4SMatthew Dillon * are met:
147a2de9a4SMatthew Dillon * 1. Redistributions of source code must retain the above copyright
157a2de9a4SMatthew Dillon * notice, this list of conditions and the following disclaimer.
167a2de9a4SMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright
177a2de9a4SMatthew Dillon * notice, this list of conditions and the following disclaimer in the
187a2de9a4SMatthew Dillon * documentation and/or other materials provided with the distribution.
197a2de9a4SMatthew Dillon *
207a2de9a4SMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
217a2de9a4SMatthew Dillon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
227a2de9a4SMatthew Dillon * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
237a2de9a4SMatthew Dillon * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
247a2de9a4SMatthew Dillon * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
257a2de9a4SMatthew Dillon * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
267a2de9a4SMatthew Dillon * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
277a2de9a4SMatthew Dillon * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
287a2de9a4SMatthew Dillon * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
297a2de9a4SMatthew Dillon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
307a2de9a4SMatthew Dillon * POSSIBILITY OF SUCH DAMAGE.
317a2de9a4SMatthew Dillon *
327a2de9a4SMatthew Dillon * $FreeBSD: src/sys/fs/tmpfs/tmpfs.h,v 1.18 2009/10/11 07:03:56 delphij Exp $
337a2de9a4SMatthew Dillon */
347a2de9a4SMatthew Dillon
357a2de9a4SMatthew Dillon #ifndef _VFS_TMPFS_TMPFS_H_
367a2de9a4SMatthew Dillon #define _VFS_TMPFS_TMPFS_H_
377a2de9a4SMatthew Dillon
387a2de9a4SMatthew Dillon /* ---------------------------------------------------------------------
397a2de9a4SMatthew Dillon * KERNEL-SPECIFIC DEFINITIONS
407a2de9a4SMatthew Dillon * --------------------------------------------------------------------- */
417a2de9a4SMatthew Dillon #include <sys/dirent.h>
427a2de9a4SMatthew Dillon #include <sys/mount.h>
4329ca4fd6SJohannes Hofmann #include <sys/tree.h>
447a2de9a4SMatthew Dillon #include <sys/vnode.h>
457a2de9a4SMatthew Dillon #include <sys/file.h>
467a2de9a4SMatthew Dillon #include <sys/lock.h>
477a2de9a4SMatthew Dillon #include <sys/lockf.h>
487a2de9a4SMatthew Dillon #include <sys/mutex.h>
497a2de9a4SMatthew Dillon
507a2de9a4SMatthew Dillon /* --------------------------------------------------------------------- */
517a2de9a4SMatthew Dillon #include <sys/malloc.h>
522d18109fSSascha Wildner #ifdef _KERNEL
537a2de9a4SMatthew Dillon #include <sys/systm.h>
542d18109fSSascha Wildner #endif
557a2de9a4SMatthew Dillon #include <sys/vmmeter.h>
567a2de9a4SMatthew Dillon #include <vm/swap_pager.h>
577a2de9a4SMatthew Dillon
587ea34faaSzrj #ifdef MALLOC_DECLARE
597a2de9a4SMatthew Dillon MALLOC_DECLARE(M_TMPFSMNT);
607ea34faaSzrj #endif
617a2de9a4SMatthew Dillon
627a2de9a4SMatthew Dillon /* --------------------------------------------------------------------- */
637a2de9a4SMatthew Dillon
647a2de9a4SMatthew Dillon /*
657a2de9a4SMatthew Dillon * Internal representation of a tmpfs directory entry.
667a2de9a4SMatthew Dillon */
677a2de9a4SMatthew Dillon struct tmpfs_dirent {
6829ca4fd6SJohannes Hofmann RB_ENTRY(tmpfs_dirent) rb_node;
69f5f22af6SMatthew Dillon RB_ENTRY(tmpfs_dirent) rb_cookienode;
707a2de9a4SMatthew Dillon
717a2de9a4SMatthew Dillon /* Length of the name stored in this directory entry. This avoids
727a2de9a4SMatthew Dillon * the need to recalculate it every time the name is used. */
737a2de9a4SMatthew Dillon uint16_t td_namelen;
747a2de9a4SMatthew Dillon
757a2de9a4SMatthew Dillon /* The name of the entry, allocated from a string pool. This
767a2de9a4SMatthew Dillon * string is not required to be zero-terminated; therefore, the
777a2de9a4SMatthew Dillon * td_namelen field must always be used when accessing its value. */
787a2de9a4SMatthew Dillon char *td_name;
797a2de9a4SMatthew Dillon
807a2de9a4SMatthew Dillon /* Pointer to the node this entry refers to. */
817a2de9a4SMatthew Dillon struct tmpfs_node *td_node;
827a2de9a4SMatthew Dillon };
837a2de9a4SMatthew Dillon
8429ca4fd6SJohannes Hofmann struct tmpfs_dirtree;
8529ca4fd6SJohannes Hofmann RB_HEAD(tmpfs_dirtree, tmpfs_dirent);
8629ca4fd6SJohannes Hofmann RB_PROTOTYPE(tmpfs_dirtree, tmpfs_dirent, rb_node,
8729ca4fd6SJohannes Hofmann tmpfs_dirtree_compare);
8829ca4fd6SJohannes Hofmann
89f5f22af6SMatthew Dillon RB_HEAD(tmpfs_dirtree_cookie, tmpfs_dirent);
90f5f22af6SMatthew Dillon RB_PROTOTYPE(tmpfs_dirtree_cookie, tmpfs_dirent, rb_cookienode,
91f5f22af6SMatthew Dillon tmpfs_dirtree_cookie_compare);
9229ca4fd6SJohannes Hofmann
93f5f22af6SMatthew Dillon
94f5f22af6SMatthew Dillon /*
95f5f22af6SMatthew Dillon * A directory in tmpfs holds a set of directory entries, which in
967a2de9a4SMatthew Dillon * turn point to other files (which can be directories themselves).
977a2de9a4SMatthew Dillon *
9829ca4fd6SJohannes Hofmann * In tmpfs, this set is managed by a red-black tree, whose root is defined
9929ca4fd6SJohannes Hofmann * by the struct tmpfs_dirtree type.
1007a2de9a4SMatthew Dillon *
10129ca4fd6SJohannes Hofmann * It is important to notice that directories do not have entries for . and
1027a2de9a4SMatthew Dillon * .. as other file systems do. These can be generated when requested
1037a2de9a4SMatthew Dillon * based on information available by other means, such as the pointer to
1047a2de9a4SMatthew Dillon * the node itself in the former case or the pointer to the parent directory
1057a2de9a4SMatthew Dillon * in the latter case. This is done to simplify tmpfs's code and, more
106f5f22af6SMatthew Dillon * importantly, to remove redundancy.
107f5f22af6SMatthew Dillon *
108f5f22af6SMatthew Dillon * Each entry in a directory has a cookie that identifies it. Cookies
1097a2de9a4SMatthew Dillon * supersede offsets within directories because, given how tmpfs stores
1107a2de9a4SMatthew Dillon * directories in memory, there is no such thing as an offset. (Emulating
1117a2de9a4SMatthew Dillon * a real offset could be very difficult.)
1127a2de9a4SMatthew Dillon *
1137a2de9a4SMatthew Dillon * The '.', '..' and the end of directory markers have fixed cookies which
1147a2de9a4SMatthew Dillon * cannot collide with the cookies generated by other entries. The cookies
1157a2de9a4SMatthew Dillon * for the other entries are generated based on the memory address on which
1167a2de9a4SMatthew Dillon * stores their information is stored.
1177a2de9a4SMatthew Dillon *
118f5f22af6SMatthew Dillon * DragonFly binaries use 64-bit cookies. We mask-off the signed bit to
119f5f22af6SMatthew Dillon * ensure that cookie 'offsets' are positive.
120f5f22af6SMatthew Dillon */
1217a2de9a4SMatthew Dillon #ifdef _KERNEL
122f5f22af6SMatthew Dillon
1235b09d16cSTomohiro Kusumi #define TMPFS_ROOTINO ((ino_t)2)
124de8da6a3STomohiro Kusumi
1257a2de9a4SMatthew Dillon #define TMPFS_DIRCOOKIE_DOT 0
1267a2de9a4SMatthew Dillon #define TMPFS_DIRCOOKIE_DOTDOT 1
127*e91c5b26SMatthew Dillon #define TMPFS_DIRCOOKIE_EOF ((off_t)0x7FFFFFFFFFFFFFFFLLU)
128f5f22af6SMatthew Dillon
1297a2de9a4SMatthew Dillon static __inline
1307a2de9a4SMatthew Dillon off_t
tmpfs_dircookie(struct tmpfs_dirent * de)1317a2de9a4SMatthew Dillon tmpfs_dircookie(struct tmpfs_dirent *de)
1327a2de9a4SMatthew Dillon {
133*e91c5b26SMatthew Dillon return ((off_t)((uintptr_t)de >> 1) & 0x7FFFFFFFFFFFFFFFLLU);
134*e91c5b26SMatthew Dillon }
135*e91c5b26SMatthew Dillon
136*e91c5b26SMatthew Dillon /*
137*e91c5b26SMatthew Dillon * WARNING! Caller should never try to actually access a tmpfs dirent
138*e91c5b26SMatthew Dillon * structure from a cookiedir() conversion. It is used strictly
139*e91c5b26SMatthew Dillon * for RBTREE operations.
140*e91c5b26SMatthew Dillon */
141*e91c5b26SMatthew Dillon static __inline
142*e91c5b26SMatthew Dillon void *
tmpfs_cookiedir(off_t off)143*e91c5b26SMatthew Dillon tmpfs_cookiedir(off_t off)
144*e91c5b26SMatthew Dillon {
145*e91c5b26SMatthew Dillon return ((void *)((uintptr_t)off << 1));
1467a2de9a4SMatthew Dillon }
147f5f22af6SMatthew Dillon
148525d1416STomohiro Kusumi #endif /* _KERNEL */
1497a2de9a4SMatthew Dillon
1507a2de9a4SMatthew Dillon /* --------------------------------------------------------------------- */
1517a2de9a4SMatthew Dillon
1527a2de9a4SMatthew Dillon /*
1537a2de9a4SMatthew Dillon * Internal representation of a tmpfs file system node.
1547a2de9a4SMatthew Dillon *
1557a2de9a4SMatthew Dillon * This structure is splitted in two parts: one holds attributes common
1567a2de9a4SMatthew Dillon * to all file types and the other holds data that is only applicable to
1577a2de9a4SMatthew Dillon * a particular type. The code must be careful to only access those
1587a2de9a4SMatthew Dillon * attributes that are actually allowed by the node's type.
1597a2de9a4SMatthew Dillon */
1607a2de9a4SMatthew Dillon struct tmpfs_node {
1617a2de9a4SMatthew Dillon /* Doubly-linked list entry which links all existing nodes for a
1627a2de9a4SMatthew Dillon * single file system. This is provided to ease the removal of
1637a2de9a4SMatthew Dillon * all nodes during the unmount operation. */
1647a2de9a4SMatthew Dillon LIST_ENTRY(tmpfs_node) tn_entries;
1657a2de9a4SMatthew Dillon
1667a2de9a4SMatthew Dillon /* The node's type. Any of 'VBLK', 'VCHR', 'VDIR', 'VFIFO',
1677a2de9a4SMatthew Dillon * 'VLNK', 'VREG' and 'VSOCK' is allowed. The usage of vnode
1687a2de9a4SMatthew Dillon * types instead of a custom enumeration is to make things simpler
1697a2de9a4SMatthew Dillon * and faster, as we do not need to convert between two types. */
1707a2de9a4SMatthew Dillon enum vtype tn_type;
1717a2de9a4SMatthew Dillon
1727a2de9a4SMatthew Dillon /* Node identifier. */
1737a2de9a4SMatthew Dillon ino_t tn_id;
1747a2de9a4SMatthew Dillon
1757a2de9a4SMatthew Dillon /* Node's internal status. This is used by several file system
1767a2de9a4SMatthew Dillon * operations to do modifications to the node in a delayed
1777a2de9a4SMatthew Dillon * fashion. */
1789cd86db5SMatthew Dillon int tn_blksize; /* small file optimization */
1797a2de9a4SMatthew Dillon int tn_status;
1807a2de9a4SMatthew Dillon #define TMPFS_NODE_ACCESSED (1 << 1)
1817a2de9a4SMatthew Dillon #define TMPFS_NODE_MODIFIED (1 << 2)
1827a2de9a4SMatthew Dillon #define TMPFS_NODE_CHANGED (1 << 3)
1837a2de9a4SMatthew Dillon
1847a2de9a4SMatthew Dillon /* The node size. It does not necessarily match the real amount
1857a2de9a4SMatthew Dillon * of memory consumed by it. */
1867a2de9a4SMatthew Dillon off_t tn_size;
1877a2de9a4SMatthew Dillon
1887a2de9a4SMatthew Dillon /* Generic node attributes. */
1897a2de9a4SMatthew Dillon uid_t tn_uid;
1907a2de9a4SMatthew Dillon gid_t tn_gid;
1917a2de9a4SMatthew Dillon mode_t tn_mode;
192513a5bc4Szrj u_int tn_flags;
1934d22d8eeSMatthew Dillon nlink_t tn_links; /* atomic ops req */
194fa4a12c4SMatthew Dillon long tn_atime;
195fa4a12c4SMatthew Dillon long tn_atimensec;
196fa4a12c4SMatthew Dillon long tn_mtime;
197fa4a12c4SMatthew Dillon long tn_mtimensec;
198fa4a12c4SMatthew Dillon long tn_ctime;
199fa4a12c4SMatthew Dillon long tn_ctimensec;
2007a2de9a4SMatthew Dillon unsigned long tn_gen;
2017a2de9a4SMatthew Dillon struct lockf tn_advlock;
2027a2de9a4SMatthew Dillon
2037a2de9a4SMatthew Dillon /* As there is a single vnode for each active file within the
2047a2de9a4SMatthew Dillon * system, care has to be taken to avoid allocating more than one
2057a2de9a4SMatthew Dillon * vnode per file. In order to do this, a bidirectional association
2067a2de9a4SMatthew Dillon * is kept between vnodes and nodes.
2077a2de9a4SMatthew Dillon *
2087a2de9a4SMatthew Dillon * Whenever a vnode is allocated, its v_data field is updated to
2097a2de9a4SMatthew Dillon * point to the node it references. At the same time, the node's
2107a2de9a4SMatthew Dillon * tn_vnode field is modified to point to the new vnode representing
2117a2de9a4SMatthew Dillon * it. Further attempts to allocate a vnode for this same node will
2127a2de9a4SMatthew Dillon * result in returning a new reference to the value stored in
2137a2de9a4SMatthew Dillon * tn_vnode.
2147a2de9a4SMatthew Dillon *
2157a2de9a4SMatthew Dillon * May be NULL when the node is unused (that is, no vnode has been
2167a2de9a4SMatthew Dillon * allocated for it or it has been reclaimed). */
2177a2de9a4SMatthew Dillon struct vnode * tn_vnode;
2187a2de9a4SMatthew Dillon
219a44ecf5cSMatthew Dillon /* interlock to protect structure */
2207a2de9a4SMatthew Dillon struct lock tn_interlock;
2217a2de9a4SMatthew Dillon
222a44ecf5cSMatthew Dillon /*
223a44ecf5cSMatthew Dillon * tmpfs vnode state, may specify an allocation in-progress.
2247a2de9a4SMatthew Dillon */
2257a2de9a4SMatthew Dillon int tn_vpstate;
2267a2de9a4SMatthew Dillon
2277a2de9a4SMatthew Dillon /* misc data field for different tn_type node */
2287a2de9a4SMatthew Dillon union {
2297a2de9a4SMatthew Dillon /* Valid when tn_type == VBLK || tn_type == VCHR. */
2307a2de9a4SMatthew Dillon dev_t tn_rdev; /*int32_t ?*/
2317a2de9a4SMatthew Dillon
2327a2de9a4SMatthew Dillon /* Valid when tn_type == VDIR. */
2337a2de9a4SMatthew Dillon struct tn_dir {
234f5f22af6SMatthew Dillon /*
235f5f22af6SMatthew Dillon * Pointer to the parent directory. The root
2367a2de9a4SMatthew Dillon * directory has a pointer to itself in this field;
237f5f22af6SMatthew Dillon * this property identifies the root node.
238f5f22af6SMatthew Dillon */
2397a2de9a4SMatthew Dillon struct tmpfs_node * tn_parent;
2407a2de9a4SMatthew Dillon
241f5f22af6SMatthew Dillon /*
242f5f22af6SMatthew Dillon * Directory entries are indexed by name and also
243f5f22af6SMatthew Dillon * indexed by cookie.
244f5f22af6SMatthew Dillon */
24529ca4fd6SJohannes Hofmann struct tmpfs_dirtree tn_dirtree;
246f5f22af6SMatthew Dillon struct tmpfs_dirtree_cookie tn_cookietree;
2477a2de9a4SMatthew Dillon } tn_dir;
2487a2de9a4SMatthew Dillon
2497a2de9a4SMatthew Dillon /* Valid when tn_type == VLNK. */
2507a2de9a4SMatthew Dillon /* The link's target, allocated from a string pool. */
2517a2de9a4SMatthew Dillon char * tn_link;
2527a2de9a4SMatthew Dillon
253a1b829f2SMatthew Dillon /*
254a1b829f2SMatthew Dillon * Valid when tn_type == VREG.
255a1b829f2SMatthew Dillon *
256a1b829f2SMatthew Dillon * aobj is used as backing store for the vnode object. It
257a1b829f2SMatthew Dillon * typically only contains swap assignments, but we also use
258a1b829f2SMatthew Dillon * it to save the vnode object's vm_page's when the vnode
259a1b829f2SMatthew Dillon * becomes inactive.
260a1b829f2SMatthew Dillon */
2617a2de9a4SMatthew Dillon struct tn_reg {
2627a2de9a4SMatthew Dillon vm_object_t tn_aobj;
2637a2de9a4SMatthew Dillon size_t tn_aobj_pages;
264a1b829f2SMatthew Dillon int tn_pages_in_aobj;
2657a2de9a4SMatthew Dillon } tn_reg;
2667a2de9a4SMatthew Dillon
2677a2de9a4SMatthew Dillon /* Valid when tn_type = VFIFO */
2687a2de9a4SMatthew Dillon struct tn_fifo {
2697a2de9a4SMatthew Dillon int (*tn_fo_read) (struct file *fp, struct uio *uio,
2707a2de9a4SMatthew Dillon struct ucred *cred, int flags);
2717a2de9a4SMatthew Dillon int (*tn_fo_write) (struct file *fp, struct uio *uio,
2727a2de9a4SMatthew Dillon struct ucred *cred, int flags);
2737a2de9a4SMatthew Dillon } tn_fifo;
2747a2de9a4SMatthew Dillon } tn_spec;
2757a2de9a4SMatthew Dillon };
2762d18109fSSascha Wildner
277d743c0f3STomohiro Kusumi /* Only userspace needs this */
2782d18109fSSascha Wildner #define VTOI(vp) ((struct tmpfs_node *)(vp)->v_data)
2792d18109fSSascha Wildner
2802d18109fSSascha Wildner #ifdef _KERNEL
2817a2de9a4SMatthew Dillon LIST_HEAD(tmpfs_node_list, tmpfs_node);
2827a2de9a4SMatthew Dillon
2837a2de9a4SMatthew Dillon #define tn_rdev tn_spec.tn_rdev
2847a2de9a4SMatthew Dillon #define tn_dir tn_spec.tn_dir
2857a2de9a4SMatthew Dillon #define tn_link tn_spec.tn_link
2867a2de9a4SMatthew Dillon #define tn_reg tn_spec.tn_reg
2877a2de9a4SMatthew Dillon #define tn_fifo tn_spec.tn_fifo
2887a2de9a4SMatthew Dillon
2897a2de9a4SMatthew Dillon #define TMPFS_NODE_LOCK(node) lockmgr(&(node)->tn_interlock, LK_EXCLUSIVE|LK_RETRY)
290ff837cd5SMatthew Dillon #define TMPFS_NODE_LOCK_SH(node) lockmgr(&(node)->tn_interlock, LK_SHARED|LK_RETRY)
2917a2de9a4SMatthew Dillon #define TMPFS_NODE_UNLOCK(node) lockmgr(&(node)->tn_interlock, LK_RELEASE)
2927a2de9a4SMatthew Dillon #define TMPFS_NODE_MTX(node) (&(node)->tn_interlock)
2937a2de9a4SMatthew Dillon
2947a2de9a4SMatthew Dillon #ifdef INVARIANTS
2957a2de9a4SMatthew Dillon #define TMPFS_ASSERT_LOCKED(node) do { \
2967a2de9a4SMatthew Dillon KKASSERT(node != NULL); \
2977a2de9a4SMatthew Dillon KKASSERT(node->tn_vnode != NULL); \
2987a2de9a4SMatthew Dillon if (!vn_islocked(node->tn_vnode) && \
2997a2de9a4SMatthew Dillon (lockstatus(TMPFS_NODE_MTX(node), curthread) == LK_EXCLUSIVE )) \
3007a2de9a4SMatthew Dillon panic("tmpfs: node is not locked: %p", node); \
3017a2de9a4SMatthew Dillon } while (0)
3027a2de9a4SMatthew Dillon #define TMPFS_ASSERT_ELOCKED(node) do { \
3037a2de9a4SMatthew Dillon KKASSERT((node) != NULL); \
3047a2de9a4SMatthew Dillon KKASSERT(lockstatus(TMPFS_NODE_MTX(node), curthread) == LK_EXCLUSIVE); \
3057a2de9a4SMatthew Dillon } while (0)
3067a2de9a4SMatthew Dillon #else
3077a2de9a4SMatthew Dillon #define TMPFS_ASSERT_LOCKED(node) (void)0
3087a2de9a4SMatthew Dillon #define TMPFS_ASSERT_ELOCKED(node) (void)0
309525d1416STomohiro Kusumi #endif /* INVARIANTS */
3107a2de9a4SMatthew Dillon
311a44ecf5cSMatthew Dillon #define TMPFS_VNODE_DOOMED 0x0001
3127a2de9a4SMatthew Dillon /* --------------------------------------------------------------------- */
3137a2de9a4SMatthew Dillon
3147a2de9a4SMatthew Dillon /*
3157a2de9a4SMatthew Dillon * Internal representation of a tmpfs mount point.
3167a2de9a4SMatthew Dillon */
3177a2de9a4SMatthew Dillon struct tmpfs_mount {
318aa1adbf0SMatthew Dillon struct mount *tm_mount;
319aa1adbf0SMatthew Dillon
3207a2de9a4SMatthew Dillon /* Maximum number of memory pages available for use by the file
3217a2de9a4SMatthew Dillon * system, set during mount time. This variable must never be
3227a2de9a4SMatthew Dillon * used directly as it may be bigger than the current amount of
3237a2de9a4SMatthew Dillon * free memory; in the extreme case, it will hold the SIZE_MAX
3247a2de9a4SMatthew Dillon * value. Instead, use the TMPFS_PAGES_MAX macro. */
325b37a7c00SMatthew Dillon long tm_pages_max;
3267a2de9a4SMatthew Dillon
3277a2de9a4SMatthew Dillon /* Number of pages in use by the file system. Cannot be bigger
3287a2de9a4SMatthew Dillon * than the value returned by TMPFS_PAGES_MAX in any case. */
329b37a7c00SMatthew Dillon long tm_pages_used;
3307a2de9a4SMatthew Dillon
3317a2de9a4SMatthew Dillon /* Pointer to the node representing the root directory of this
3327a2de9a4SMatthew Dillon * file system. */
3337a2de9a4SMatthew Dillon struct tmpfs_node * tm_root;
3347a2de9a4SMatthew Dillon
3357a2de9a4SMatthew Dillon /* Maximum number of possible nodes for this file system; set
3367a2de9a4SMatthew Dillon * during mount time. We need a hard limit on the maximum number
3377a2de9a4SMatthew Dillon * of nodes to avoid allocating too much of them; their objects
3387a2de9a4SMatthew Dillon * cannot be released until the file system is unmounted.
3397a2de9a4SMatthew Dillon * Otherwise, we could easily run out of memory by creating lots
3407a2de9a4SMatthew Dillon * of empty files and then simply removing them. */
3417a2de9a4SMatthew Dillon ino_t tm_nodes_max;
3427a2de9a4SMatthew Dillon
3437a2de9a4SMatthew Dillon /* Number of nodes currently that are in use. */
3447a2de9a4SMatthew Dillon ino_t tm_nodes_inuse;
3457a2de9a4SMatthew Dillon
3467a2de9a4SMatthew Dillon /* maximum representable file size */
3477a2de9a4SMatthew Dillon u_int64_t tm_maxfilesize;
3487a2de9a4SMatthew Dillon
3497a2de9a4SMatthew Dillon /* Nodes are organized in two different lists. The used list
3507a2de9a4SMatthew Dillon * contains all nodes that are currently used by the file system;
3517a2de9a4SMatthew Dillon * i.e., they refer to existing files. The available list contains
3527a2de9a4SMatthew Dillon * all nodes that are currently available for use by new files.
3537a2de9a4SMatthew Dillon * Nodes must be kept in this list (instead of deleting them)
3547a2de9a4SMatthew Dillon * because we need to keep track of their generation number (tn_gen
3557a2de9a4SMatthew Dillon * field).
3567a2de9a4SMatthew Dillon *
3577a2de9a4SMatthew Dillon * Note that nodes are lazily allocated: if the available list is
3587a2de9a4SMatthew Dillon * empty and we have enough space to create more nodes, they will be
3597a2de9a4SMatthew Dillon * created and inserted in the used list. Once these are released,
3607a2de9a4SMatthew Dillon * they will go into the available list, remaining alive until the
3617a2de9a4SMatthew Dillon * file system is unmounted. */
3627a2de9a4SMatthew Dillon struct tmpfs_node_list tm_nodes_used;
3637a2de9a4SMatthew Dillon
364d00cd01cSVenkatesh Srinivas /* Per-mount malloc zones for tmpfs nodes, names, and dirents */
365e9dbfea1SMatthew Dillon struct malloc_type *tm_node_zone_obj;
366e9dbfea1SMatthew Dillon struct malloc_type *tm_dirent_zone_obj;
367d00cd01cSVenkatesh Srinivas struct malloc_type *tm_name_zone;
3688e771504SVenkatesh Srinivas
369d6d9df16STomohiro Kusumi ino_t tm_ino;
3709fc94b5fSMatthew Dillon int tm_flags;
37166fa44e7SVenkatesh Srinivas
37266fa44e7SVenkatesh Srinivas struct netexport tm_export;
373aa1adbf0SMatthew Dillon
374aa1adbf0SMatthew Dillon struct mount *tm_mnt;
3757a2de9a4SMatthew Dillon };
3769fc94b5fSMatthew Dillon
377aa1adbf0SMatthew Dillon #define TMPFS_LOCK(tm) lwkt_gettoken(&(tm)->tm_mount->mnt_token)
378aa1adbf0SMatthew Dillon #define TMPFS_UNLOCK(tm) lwkt_reltoken(&(tm)->tm_mount->mnt_token)
3797a2de9a4SMatthew Dillon
3807a2de9a4SMatthew Dillon /* --------------------------------------------------------------------- */
3817a2de9a4SMatthew Dillon
3827a2de9a4SMatthew Dillon /*
3837a2de9a4SMatthew Dillon * This structure maps a file identifier to a tmpfs node. Used by the
3847a2de9a4SMatthew Dillon * NFS code.
3857a2de9a4SMatthew Dillon */
3867a2de9a4SMatthew Dillon struct tmpfs_fid {
3877a2de9a4SMatthew Dillon uint16_t tf_len;
3887a2de9a4SMatthew Dillon uint16_t tf_pad;
3897a2de9a4SMatthew Dillon ino_t tf_id;
3907a2de9a4SMatthew Dillon unsigned long tf_gen;
391513b5023SMatthew Dillon } __packed;
3927a2de9a4SMatthew Dillon
3937a2de9a4SMatthew Dillon /* --------------------------------------------------------------------- */
3947a2de9a4SMatthew Dillon
3957a2de9a4SMatthew Dillon /*
3967a2de9a4SMatthew Dillon * Prototypes for tmpfs_subr.c.
3977a2de9a4SMatthew Dillon */
3987a2de9a4SMatthew Dillon
3997a2de9a4SMatthew Dillon int tmpfs_alloc_node(struct tmpfs_mount *, enum vtype,
4006e0c5aabSMatthew Dillon uid_t uid, gid_t gid, mode_t mode, char *, int, int,
4016e0c5aabSMatthew Dillon struct tmpfs_node **);
4027a2de9a4SMatthew Dillon void tmpfs_free_node(struct tmpfs_mount *, struct tmpfs_node *);
4037a2de9a4SMatthew Dillon int tmpfs_alloc_dirent(struct tmpfs_mount *, struct tmpfs_node *,
4047a2de9a4SMatthew Dillon const char *, uint16_t, struct tmpfs_dirent **);
4050786baf1SMatthew Dillon void tmpfs_free_dirent(struct tmpfs_mount *, struct tmpfs_dirent *);
406d89a0e31SMatthew Dillon int tmpfs_alloc_vp(struct mount *, struct tmpfs_node *,
407d89a0e31SMatthew Dillon struct tmpfs_node *, int, struct vnode **);
4087a2de9a4SMatthew Dillon int tmpfs_alloc_file(struct vnode *, struct vnode **, struct vattr *,
4097a2de9a4SMatthew Dillon struct namecache *, struct ucred *, char *);
410307bf766SMatthew Dillon void tmpfs_dir_attach_locked(struct tmpfs_node *, struct tmpfs_dirent *);
411307bf766SMatthew Dillon void tmpfs_dir_detach_locked(struct tmpfs_node *, struct tmpfs_dirent *);
4127a2de9a4SMatthew Dillon struct tmpfs_dirent * tmpfs_dir_lookup(struct tmpfs_node *node,
4137a2de9a4SMatthew Dillon struct tmpfs_node *f,
4147a2de9a4SMatthew Dillon struct namecache *ncp);
4157a2de9a4SMatthew Dillon int tmpfs_dir_getdotdent(struct tmpfs_node *, struct uio *);
41622d3b394SMatthew Dillon int tmpfs_dir_getdotdotdent(struct tmpfs_mount *,
41722d3b394SMatthew Dillon struct tmpfs_node *, struct uio *);
418*e91c5b26SMatthew Dillon struct tmpfs_dirent * tmpfs_dir_lookupbycookie(struct tmpfs_node *, off_t,
419*e91c5b26SMatthew Dillon int);
4207a2de9a4SMatthew Dillon int tmpfs_dir_getdents(struct tmpfs_node *, struct uio *, off_t *);
4217a2de9a4SMatthew Dillon int tmpfs_reg_resize(struct vnode *, off_t, int);
422513a5bc4Szrj int tmpfs_chflags(struct vnode *, u_long, struct ucred *);
4237a2de9a4SMatthew Dillon int tmpfs_chmod(struct vnode *, mode_t, struct ucred *);
4247a2de9a4SMatthew Dillon int tmpfs_chown(struct vnode *, uid_t, gid_t, struct ucred *);
4257a2de9a4SMatthew Dillon int tmpfs_chsize(struct vnode *, u_quad_t, struct ucred *);
4267a2de9a4SMatthew Dillon int tmpfs_chtimes(struct vnode *, struct timespec *, struct timespec *,
4277a2de9a4SMatthew Dillon int, struct ucred *);
4287a2de9a4SMatthew Dillon void tmpfs_itimes(struct vnode *, const struct timespec *,
4297a2de9a4SMatthew Dillon const struct timespec *);
4307a2de9a4SMatthew Dillon
431e9dbfea1SMatthew Dillon void tmpfs_node_init(struct tmpfs_node *node);
432e9dbfea1SMatthew Dillon void tmpfs_node_uninit(struct tmpfs_node *node);
4337a2de9a4SMatthew Dillon void tmpfs_update(struct vnode *);
4347a2de9a4SMatthew Dillon int tmpfs_truncate(struct vnode *, off_t);
4354c154053SMatthew Dillon void tmpfs_lock4(struct tmpfs_node *node1, struct tmpfs_node *node2,
4364c154053SMatthew Dillon struct tmpfs_node *node3, struct tmpfs_node *node4);
4374c154053SMatthew Dillon void tmpfs_unlock4(struct tmpfs_node *node1, struct tmpfs_node *node2,
4384c154053SMatthew Dillon struct tmpfs_node *node3, struct tmpfs_node *node4);
4397a2de9a4SMatthew Dillon
4407a2de9a4SMatthew Dillon /* --------------------------------------------------------------------- */
4417a2de9a4SMatthew Dillon
4427a2de9a4SMatthew Dillon /*
4437a2de9a4SMatthew Dillon * Convenience macros to simplify some logical expressions.
4447a2de9a4SMatthew Dillon */
4457a2de9a4SMatthew Dillon #define IMPLIES(a, b) (!(a) || (b))
4467a2de9a4SMatthew Dillon #define IFF(a, b) (IMPLIES(a, b) && IMPLIES(b, a))
4477a2de9a4SMatthew Dillon
4487a2de9a4SMatthew Dillon /* --------------------------------------------------------------------- */
4497a2de9a4SMatthew Dillon
4507a2de9a4SMatthew Dillon /*
4517a2de9a4SMatthew Dillon * Checks that the directory entry pointed by 'de' matches the name 'name'
4527a2de9a4SMatthew Dillon * with a length of 'len'.
4537a2de9a4SMatthew Dillon */
4547a2de9a4SMatthew Dillon #define TMPFS_DIRENT_MATCHES(de, name, len) \
4557a2de9a4SMatthew Dillon (de->td_namelen == (uint16_t)len && \
4567a2de9a4SMatthew Dillon bcmp((de)->td_name, (name), (de)->td_namelen) == 0)
4577a2de9a4SMatthew Dillon
4587a2de9a4SMatthew Dillon /* --------------------------------------------------------------------- */
4597a2de9a4SMatthew Dillon
4607a2de9a4SMatthew Dillon /*
4617a2de9a4SMatthew Dillon * Ensures that the node pointed by 'node' is a directory and that its
4627a2de9a4SMatthew Dillon * contents are consistent with respect to directories.
4637a2de9a4SMatthew Dillon */
464f5f22af6SMatthew Dillon #define TMPFS_VALIDATE_DIR(node) do { \
4657a2de9a4SMatthew Dillon KKASSERT((node)->tn_type == VDIR); \
4667a2de9a4SMatthew Dillon KKASSERT((node)->tn_size % sizeof(struct tmpfs_dirent) == 0); \
467f5f22af6SMatthew Dillon } while(0)
4687a2de9a4SMatthew Dillon
4697a2de9a4SMatthew Dillon /* --------------------------------------------------------------------- */
4707a2de9a4SMatthew Dillon
4717a2de9a4SMatthew Dillon /*
4727a2de9a4SMatthew Dillon * Macros/functions to convert from generic data structures to tmpfs
473d743c0f3STomohiro Kusumi * specific ones. Kernel code use VP_TO_TMPFS_NODE() instead of VTOI().
4747a2de9a4SMatthew Dillon */
4757a2de9a4SMatthew Dillon
4767a2de9a4SMatthew Dillon static inline
4777a2de9a4SMatthew Dillon struct tmpfs_mount *
VFS_TO_TMPFS(struct mount * mp)4787a2de9a4SMatthew Dillon VFS_TO_TMPFS(struct mount *mp)
4797a2de9a4SMatthew Dillon {
4807a2de9a4SMatthew Dillon struct tmpfs_mount *tmp;
4817a2de9a4SMatthew Dillon
4827a2de9a4SMatthew Dillon KKASSERT((mp) != NULL && (mp)->mnt_data != NULL);
4837a2de9a4SMatthew Dillon tmp = (struct tmpfs_mount *)(mp)->mnt_data;
4847a2de9a4SMatthew Dillon return tmp;
4857a2de9a4SMatthew Dillon }
4867a2de9a4SMatthew Dillon
4877a2de9a4SMatthew Dillon static inline
4887a2de9a4SMatthew Dillon struct tmpfs_node *
VP_TO_TMPFS_NODE(struct vnode * vp)4897a2de9a4SMatthew Dillon VP_TO_TMPFS_NODE(struct vnode *vp)
4907a2de9a4SMatthew Dillon {
4917a2de9a4SMatthew Dillon struct tmpfs_node *node;
4927a2de9a4SMatthew Dillon
4937a2de9a4SMatthew Dillon KKASSERT((vp) != NULL && (vp)->v_data != NULL);
4947a2de9a4SMatthew Dillon node = (struct tmpfs_node *)vp->v_data;
4957a2de9a4SMatthew Dillon return node;
4967a2de9a4SMatthew Dillon }
4977a2de9a4SMatthew Dillon
4987a2de9a4SMatthew Dillon static inline
4997a2de9a4SMatthew Dillon struct tmpfs_node *
VP_TO_TMPFS_DIR(struct vnode * vp)5007a2de9a4SMatthew Dillon VP_TO_TMPFS_DIR(struct vnode *vp)
5017a2de9a4SMatthew Dillon {
5027a2de9a4SMatthew Dillon struct tmpfs_node *node;
5037a2de9a4SMatthew Dillon
5047a2de9a4SMatthew Dillon node = VP_TO_TMPFS_NODE(vp);
5057a2de9a4SMatthew Dillon TMPFS_VALIDATE_DIR(node);
5067a2de9a4SMatthew Dillon return node;
5077a2de9a4SMatthew Dillon }
5087a2de9a4SMatthew Dillon
5097a2de9a4SMatthew Dillon /* --------------------------------------------------------------------- */
5107a2de9a4SMatthew Dillon /*
5117a2de9a4SMatthew Dillon * buffer cache size
5127a2de9a4SMatthew Dillon */
5133c54bb74SMatthew Dillon #define TMPFS_BLKSIZE 16384 /* buffer cache size*/
5143c54bb74SMatthew Dillon #define TMPFS_BLKMASK (TMPFS_BLKSIZE - 1)
5153c54bb74SMatthew Dillon #define TMPFS_BLKMASK64 ((off_t)(TMPFS_BLKSIZE - 1))
5162d18109fSSascha Wildner #endif /* _KERNEL */
5177a2de9a4SMatthew Dillon
5187a2de9a4SMatthew Dillon #endif /* _VFS_TMPFS_TMPFS_H_ */
519