tmpfs.h revision 1.45.2.1 1 1.45.2.1 yamt /* $NetBSD: tmpfs.h,v 1.45.2.1 2014/05/22 11:41:02 yamt Exp $ */
2 1.1 jmmv
3 1.1 jmmv /*
4 1.30 ad * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc.
5 1.1 jmmv * All rights reserved.
6 1.1 jmmv *
7 1.1 jmmv * This code is derived from software contributed to The NetBSD Foundation
8 1.6 jmmv * by Julio M. Merino Vidal, developed as part of Google's Summer of Code
9 1.6 jmmv * 2005 program.
10 1.1 jmmv *
11 1.1 jmmv * Redistribution and use in source and binary forms, with or without
12 1.1 jmmv * modification, are permitted provided that the following conditions
13 1.1 jmmv * are met:
14 1.1 jmmv * 1. Redistributions of source code must retain the above copyright
15 1.1 jmmv * notice, this list of conditions and the following disclaimer.
16 1.1 jmmv * 2. Redistributions in binary form must reproduce the above copyright
17 1.1 jmmv * notice, this list of conditions and the following disclaimer in the
18 1.1 jmmv * documentation and/or other materials provided with the distribution.
19 1.1 jmmv *
20 1.1 jmmv * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 1.1 jmmv * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 1.1 jmmv * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 1.1 jmmv * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 1.1 jmmv * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 1.1 jmmv * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 1.1 jmmv * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 1.1 jmmv * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 1.1 jmmv * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 1.1 jmmv * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 1.1 jmmv * POSSIBILITY OF SUCH DAMAGE.
31 1.1 jmmv */
32 1.1 jmmv
33 1.43 christos #ifndef _FS_TMPFS_TMPFS_H_
34 1.43 christos #define _FS_TMPFS_TMPFS_H_
35 1.42 rmind
36 1.42 rmind #if !defined(_KERNEL) && !defined(_KMEMUSER)
37 1.42 rmind #error "not supposed to be exposed to userland"
38 1.42 rmind #endif
39 1.1 jmmv
40 1.1 jmmv #include <sys/dirent.h>
41 1.1 jmmv #include <sys/mount.h>
42 1.38 rmind #include <sys/pool.h>
43 1.1 jmmv #include <sys/queue.h>
44 1.1 jmmv #include <sys/vnode.h>
45 1.1 jmmv
46 1.37 pooka /*
47 1.37 pooka * Internal representation of a tmpfs directory entry.
48 1.41 rmind *
49 1.41 rmind * All fields are protected by vnode lock.
50 1.37 pooka */
51 1.41 rmind typedef struct tmpfs_dirent {
52 1.37 pooka TAILQ_ENTRY(tmpfs_dirent) td_entries;
53 1.37 pooka
54 1.41 rmind /* Pointer to the inode this entry refers to. */
55 1.41 rmind struct tmpfs_node * td_node;
56 1.37 pooka
57 1.45.2.1 yamt /* Sequence number, see tmpfs_dir_getseq(). */
58 1.45.2.1 yamt uint32_t td_seq;
59 1.45.2.1 yamt
60 1.41 rmind /* Name and its length. */
61 1.37 pooka char * td_name;
62 1.41 rmind uint16_t td_namelen;
63 1.41 rmind } tmpfs_dirent_t;
64 1.37 pooka
65 1.37 pooka TAILQ_HEAD(tmpfs_dir, tmpfs_dirent);
66 1.37 pooka
67 1.37 pooka /*
68 1.41 rmind * Internal representation of a tmpfs file system node -- inode.
69 1.37 pooka *
70 1.45.2.1 yamt * This structure is split in two parts: one holds attributes common
71 1.37 pooka * to all file types and the other holds data that is only applicable to
72 1.41 rmind * a particular type.
73 1.41 rmind *
74 1.41 rmind * All fields are protected by vnode lock. The vnode association itself
75 1.41 rmind * is protected by tmpfs_node_t::tn_vlock.
76 1.37 pooka */
77 1.41 rmind typedef struct tmpfs_node {
78 1.37 pooka LIST_ENTRY(tmpfs_node) tn_entries;
79 1.37 pooka
80 1.44 rmind /*
81 1.44 rmind * Each inode has a corresponding vnode. It is a bi-directional
82 1.44 rmind * association. Whenever vnode is allocated, its v_data field is
83 1.44 rmind * set to the inode it reference, and tmpfs_node_t::tn_vnode is
84 1.44 rmind * set to point to the said vnode.
85 1.44 rmind *
86 1.44 rmind * Further attempts to allocate a vnode for this same node will
87 1.44 rmind * result in returning a new reference to the value stored in
88 1.44 rmind * tn_vnode. It may be NULL when the node is unused (that is,
89 1.44 rmind * no vnode has been allocated or it has been reclaimed).
90 1.44 rmind */
91 1.44 rmind kmutex_t tn_vlock;
92 1.44 rmind vnode_t * tn_vnode;
93 1.44 rmind
94 1.44 rmind /* Directory entry. Only a hint, since hard link can have multiple. */
95 1.44 rmind tmpfs_dirent_t * tn_dirent_hint;
96 1.44 rmind
97 1.41 rmind /* The inode type: VBLK, VCHR, VDIR, VFIFO, VLNK, VREG or VSOCK. */
98 1.37 pooka enum vtype tn_type;
99 1.37 pooka
100 1.44 rmind /* Inode identifier and generation number. */
101 1.37 pooka ino_t tn_id;
102 1.45.2.1 yamt uint32_t tn_gen;
103 1.37 pooka
104 1.41 rmind /* The inode size. */
105 1.37 pooka off_t tn_size;
106 1.37 pooka
107 1.37 pooka /* Generic node attributes. */
108 1.37 pooka uid_t tn_uid;
109 1.37 pooka gid_t tn_gid;
110 1.37 pooka mode_t tn_mode;
111 1.37 pooka int tn_flags;
112 1.37 pooka nlink_t tn_links;
113 1.37 pooka struct timespec tn_atime;
114 1.37 pooka struct timespec tn_mtime;
115 1.37 pooka struct timespec tn_ctime;
116 1.37 pooka struct timespec tn_birthtime;
117 1.37 pooka
118 1.37 pooka /* Head of byte-level lock list (used by tmpfs_advlock). */
119 1.37 pooka struct lockf * tn_lockf;
120 1.37 pooka
121 1.37 pooka union {
122 1.41 rmind /* Type case: VBLK or VCHR. */
123 1.37 pooka struct {
124 1.37 pooka dev_t tn_rdev;
125 1.37 pooka } tn_dev;
126 1.37 pooka
127 1.41 rmind /* Type case: VDIR. */
128 1.37 pooka struct {
129 1.41 rmind /* Parent directory (root inode points to itself). */
130 1.37 pooka struct tmpfs_node * tn_parent;
131 1.37 pooka
132 1.41 rmind /* List of directory entries. */
133 1.37 pooka struct tmpfs_dir tn_dir;
134 1.37 pooka
135 1.45.2.1 yamt /* Last given sequence number and their arena. */
136 1.45.2.1 yamt uint32_t tn_next_seq;
137 1.45.2.1 yamt void * tn_seq_arena;
138 1.45.2.1 yamt
139 1.41 rmind /*
140 1.45.2.1 yamt * Pointer of the last directory entry returned
141 1.45.2.1 yamt * by the readdir(3) operation.
142 1.41 rmind */
143 1.37 pooka struct tmpfs_dirent * tn_readdir_lastp;
144 1.37 pooka } tn_dir;
145 1.37 pooka
146 1.41 rmind /* Type case: VLNK. */
147 1.37 pooka struct tn_lnk {
148 1.41 rmind /* The link's target. */
149 1.37 pooka char * tn_link;
150 1.37 pooka } tn_lnk;
151 1.37 pooka
152 1.41 rmind /* Type case: VREG. */
153 1.37 pooka struct tn_reg {
154 1.41 rmind /* Underlying UVM object to store contents. */
155 1.37 pooka struct uvm_object * tn_aobj;
156 1.37 pooka size_t tn_aobj_pages;
157 1.37 pooka } tn_reg;
158 1.37 pooka } tn_spec;
159 1.41 rmind } tmpfs_node_t;
160 1.37 pooka
161 1.37 pooka #if defined(_KERNEL)
162 1.41 rmind
163 1.1 jmmv LIST_HEAD(tmpfs_node_list, tmpfs_node);
164 1.1 jmmv
165 1.45.2.1 yamt #define TMPFS_MAXNAMLEN 255
166 1.45.2.1 yamt /* Validate maximum td_namelen length. */
167 1.45.2.1 yamt CTASSERT(TMPFS_MAXNAMLEN < UINT16_MAX);
168 1.45.2.1 yamt
169 1.45.2.1 yamt /*
170 1.45.2.1 yamt * Reserved values for the virtual entries (the first must be 0) and EOF.
171 1.45.2.1 yamt * The start/end of the incremental range, see tmpfs_dir_getseq().
172 1.45.2.1 yamt */
173 1.45.2.1 yamt #define TMPFS_DIRSEQ_DOT 0
174 1.45.2.1 yamt #define TMPFS_DIRSEQ_DOTDOT 1
175 1.45.2.1 yamt #define TMPFS_DIRSEQ_EOF 2
176 1.45.2.1 yamt
177 1.45.2.1 yamt #define TMPFS_DIRSEQ_START 3 /* inclusive */
178 1.45.2.1 yamt #define TMPFS_DIRSEQ_END (1U << 30) /* exclusive */
179 1.45.2.1 yamt
180 1.45.2.1 yamt /* Mark to indicate that the number is not set. */
181 1.45.2.1 yamt #define TMPFS_DIRSEQ_NONE (1U << 31)
182 1.41 rmind
183 1.45.2.1 yamt /* Flags: time update requests. */
184 1.45.2.1 yamt #define TMPFS_UPDATE_ATIME 0x01
185 1.45.2.1 yamt #define TMPFS_UPDATE_MTIME 0x02
186 1.45.2.1 yamt #define TMPFS_UPDATE_CTIME 0x04
187 1.41 rmind
188 1.44 rmind /*
189 1.45.2.1 yamt * Bits indicating vnode reclamation and whiteout use for the directory.
190 1.44 rmind * We abuse tmpfs_node_t::tn_gen for that.
191 1.44 rmind */
192 1.45.2.1 yamt #define TMPFS_RECLAIMING_BIT (1U << 31)
193 1.45.2.1 yamt #define TMPFS_WHITEOUT_BIT (1U << 30)
194 1.45.2.1 yamt #define TMPFS_NODE_GEN_MASK (TMPFS_WHITEOUT_BIT - 1)
195 1.44 rmind
196 1.44 rmind #define TMPFS_NODE_RECLAIMING(node) \
197 1.44 rmind (((node)->tn_gen & TMPFS_RECLAIMING_BIT) != 0)
198 1.44 rmind
199 1.44 rmind #define TMPFS_NODE_GEN(node) \
200 1.44 rmind ((node)->tn_gen & TMPFS_NODE_GEN_MASK)
201 1.44 rmind
202 1.41 rmind /* White-out inode indicator. */
203 1.42 rmind #define TMPFS_NODE_WHITEOUT ((tmpfs_node_t *)-1)
204 1.1 jmmv
205 1.1 jmmv /*
206 1.6 jmmv * Internal representation of a tmpfs mount point.
207 1.1 jmmv */
208 1.41 rmind typedef struct tmpfs_mount {
209 1.38 rmind /* Limit and number of bytes in use by the file system. */
210 1.38 rmind uint64_t tm_mem_limit;
211 1.38 rmind uint64_t tm_bytes_used;
212 1.38 rmind kmutex_t tm_acc_lock;
213 1.1 jmmv
214 1.41 rmind /* Pointer to the root inode. */
215 1.41 rmind tmpfs_node_t * tm_root;
216 1.41 rmind
217 1.41 rmind /* Maximum number of possible nodes for this file system. */
218 1.32 jmmv unsigned int tm_nodes_max;
219 1.6 jmmv
220 1.41 rmind /* Number of nodes currently allocated. */
221 1.32 jmmv unsigned int tm_nodes_cnt;
222 1.6 jmmv
223 1.41 rmind /* List of inodes and the lock protecting it. */
224 1.30 ad kmutex_t tm_lock;
225 1.30 ad struct tmpfs_node_list tm_nodes;
226 1.41 rmind } tmpfs_mount_t;
227 1.1 jmmv
228 1.1 jmmv /*
229 1.1 jmmv * This structure maps a file identifier to a tmpfs node. Used by the
230 1.1 jmmv * NFS code.
231 1.1 jmmv */
232 1.41 rmind typedef struct tmpfs_fid {
233 1.1 jmmv uint16_t tf_len;
234 1.1 jmmv uint16_t tf_pad;
235 1.18 riz uint32_t tf_gen;
236 1.1 jmmv ino_t tf_id;
237 1.41 rmind } tmpfs_fid_t;
238 1.1 jmmv
239 1.1 jmmv /*
240 1.1 jmmv * Prototypes for tmpfs_subr.c.
241 1.1 jmmv */
242 1.1 jmmv
243 1.42 rmind int tmpfs_alloc_node(tmpfs_mount_t *, enum vtype, uid_t, gid_t,
244 1.44 rmind mode_t, char *, dev_t, tmpfs_node_t **);
245 1.42 rmind void tmpfs_free_node(tmpfs_mount_t *, tmpfs_node_t *);
246 1.42 rmind
247 1.45.2.1 yamt int tmpfs_construct_node(vnode_t *, vnode_t **, struct vattr *,
248 1.42 rmind struct componentname *, char *);
249 1.42 rmind
250 1.44 rmind int tmpfs_vnode_get(struct mount *, tmpfs_node_t *, vnode_t **);
251 1.42 rmind
252 1.44 rmind int tmpfs_alloc_dirent(tmpfs_mount_t *, const char *, uint16_t,
253 1.44 rmind tmpfs_dirent_t **);
254 1.44 rmind void tmpfs_free_dirent(tmpfs_mount_t *, tmpfs_dirent_t *);
255 1.45.2.1 yamt void tmpfs_dir_attach(tmpfs_node_t *, tmpfs_dirent_t *, tmpfs_node_t *);
256 1.45.2.1 yamt void tmpfs_dir_detach(tmpfs_node_t *, tmpfs_dirent_t *);
257 1.42 rmind
258 1.42 rmind tmpfs_dirent_t *tmpfs_dir_lookup(tmpfs_node_t *, struct componentname *);
259 1.44 rmind tmpfs_dirent_t *tmpfs_dir_cached(tmpfs_node_t *);
260 1.44 rmind
261 1.45.2.1 yamt uint32_t tmpfs_dir_getseq(tmpfs_node_t *, tmpfs_dirent_t *);
262 1.45.2.1 yamt tmpfs_dirent_t *tmpfs_dir_lookupbyseq(tmpfs_node_t *, off_t);
263 1.42 rmind int tmpfs_dir_getdents(tmpfs_node_t *, struct uio *, off_t *);
264 1.42 rmind
265 1.42 rmind int tmpfs_reg_resize(vnode_t *, off_t);
266 1.42 rmind
267 1.42 rmind int tmpfs_chflags(vnode_t *, int, kauth_cred_t, lwp_t *);
268 1.42 rmind int tmpfs_chmod(vnode_t *, mode_t, kauth_cred_t, lwp_t *);
269 1.42 rmind int tmpfs_chown(vnode_t *, uid_t, gid_t, kauth_cred_t, lwp_t *);
270 1.42 rmind int tmpfs_chsize(vnode_t *, u_quad_t, kauth_cred_t, lwp_t *);
271 1.42 rmind int tmpfs_chtimes(vnode_t *, const struct timespec *,
272 1.42 rmind const struct timespec *, const struct timespec *, int,
273 1.42 rmind kauth_cred_t, lwp_t *);
274 1.45.2.1 yamt void tmpfs_update(vnode_t *, unsigned);
275 1.9 yamt
276 1.38 rmind /*
277 1.38 rmind * Prototypes for tmpfs_mem.c.
278 1.38 rmind */
279 1.38 rmind
280 1.42 rmind void tmpfs_mntmem_init(tmpfs_mount_t *, uint64_t);
281 1.42 rmind void tmpfs_mntmem_destroy(tmpfs_mount_t *);
282 1.45.2.1 yamt int tmpfs_mntmem_set(tmpfs_mount_t *, uint64_t);
283 1.38 rmind
284 1.38 rmind size_t tmpfs_mem_info(bool);
285 1.42 rmind uint64_t tmpfs_bytes_max(tmpfs_mount_t *);
286 1.42 rmind size_t tmpfs_pages_avail(tmpfs_mount_t *);
287 1.42 rmind bool tmpfs_mem_incr(tmpfs_mount_t *, size_t);
288 1.42 rmind void tmpfs_mem_decr(tmpfs_mount_t *, size_t);
289 1.38 rmind
290 1.42 rmind tmpfs_dirent_t *tmpfs_dirent_get(tmpfs_mount_t *);
291 1.42 rmind void tmpfs_dirent_put(tmpfs_mount_t *, tmpfs_dirent_t *);
292 1.38 rmind
293 1.42 rmind tmpfs_node_t * tmpfs_node_get(tmpfs_mount_t *);
294 1.42 rmind void tmpfs_node_put(tmpfs_mount_t *, tmpfs_node_t *);
295 1.38 rmind
296 1.42 rmind char * tmpfs_strname_alloc(tmpfs_mount_t *, size_t);
297 1.42 rmind void tmpfs_strname_free(tmpfs_mount_t *, char *, size_t);
298 1.38 rmind bool tmpfs_strname_neqlen(struct componentname *, struct componentname *);
299 1.38 rmind
300 1.1 jmmv /*
301 1.1 jmmv * Ensures that the node pointed by 'node' is a directory and that its
302 1.1 jmmv * contents are consistent with respect to directories.
303 1.1 jmmv */
304 1.45.2.1 yamt #define TMPFS_VALIDATE_DIR(node) \
305 1.45.2.1 yamt KASSERT((node)->tn_vnode == NULL || VOP_ISLOCKED((node)->tn_vnode)); \
306 1.1 jmmv KASSERT((node)->tn_type == VDIR); \
307 1.45.2.1 yamt KASSERT((node)->tn_size % sizeof(tmpfs_dirent_t) == 0);
308 1.1 jmmv
309 1.1 jmmv /*
310 1.1 jmmv * Memory management stuff.
311 1.1 jmmv */
312 1.1 jmmv
313 1.41 rmind /* Amount of memory pages to reserve for the system. */
314 1.41 rmind #define TMPFS_PAGES_RESERVED (4 * 1024 * 1024 / PAGE_SIZE)
315 1.1 jmmv
316 1.1 jmmv /*
317 1.41 rmind * Routines to convert VFS structures to tmpfs internal ones.
318 1.1 jmmv */
319 1.1 jmmv
320 1.41 rmind static inline tmpfs_mount_t *
321 1.1 jmmv VFS_TO_TMPFS(struct mount *mp)
322 1.1 jmmv {
323 1.41 rmind tmpfs_mount_t *tmp = mp->mnt_data;
324 1.1 jmmv
325 1.41 rmind KASSERT(tmp != NULL);
326 1.1 jmmv return tmp;
327 1.1 jmmv }
328 1.1 jmmv
329 1.41 rmind static inline tmpfs_node_t *
330 1.41 rmind VP_TO_TMPFS_DIR(vnode_t *vp)
331 1.37 pooka {
332 1.41 rmind tmpfs_node_t *node = vp->v_data;
333 1.37 pooka
334 1.41 rmind KASSERT(node != NULL);
335 1.41 rmind TMPFS_VALIDATE_DIR(node);
336 1.37 pooka return node;
337 1.37 pooka }
338 1.37 pooka
339 1.41 rmind #endif /* defined(_KERNEL) */
340 1.37 pooka
341 1.41 rmind static __inline tmpfs_node_t *
342 1.42 rmind VP_TO_TMPFS_NODE(vnode_t *vp)
343 1.1 jmmv {
344 1.41 rmind tmpfs_node_t *node = vp->v_data;
345 1.14 christos #ifdef KASSERT
346 1.41 rmind KASSERT(node != NULL);
347 1.14 christos #endif
348 1.1 jmmv return node;
349 1.1 jmmv }
350 1.37 pooka
351 1.43 christos #endif /* _FS_TMPFS_TMPFS_H_ */
352