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