]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/fs/tmpfs/tmpfs.h
This commit was generated by cvs2svn to compensate for changes in r171577,
[FreeBSD/FreeBSD.git] / sys / fs / tmpfs / tmpfs.h
1 /*      $NetBSD: tmpfs.h,v 1.18 2006/03/31 20:27:49 riz Exp $   */
2
3 /*
4  * Copyright (c) 2005 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Julio M. Merino Vidal, developed as part of Google's Summer of Code
9  * 2005 program.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *        This product includes software developed by the NetBSD
22  *        Foundation, Inc. and its contributors.
23  * 4. Neither the name of The NetBSD Foundation nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  *
39  * $FreeBSD$
40  */
41
42 #ifndef _FS_TMPFS_TMPFS_H_
43 #define _FS_TMPFS_TMPFS_H_
44
45 /* ---------------------------------------------------------------------
46  * KERNEL-SPECIFIC DEFINITIONS
47  * --------------------------------------------------------------------- */
48 #include <sys/dirent.h>
49 #include <sys/mount.h>
50 #include <sys/queue.h>
51 #include <sys/vnode.h>
52 #include <sys/file.h>
53 #include <sys/lock.h>
54 #include <sys/mutex.h>
55
56 /* --------------------------------------------------------------------- */
57 #include <sys/malloc.h>
58 #include <sys/systm.h>
59 #include <sys/vmmeter.h>
60 #include <vm/swap_pager.h>
61
62 MALLOC_DECLARE(M_TMPFSMNT);
63 MALLOC_DECLARE(M_TMPFSNAME);
64
65 /* --------------------------------------------------------------------- */
66
67 /*
68  * Internal representation of a tmpfs directory entry.
69  */
70 struct tmpfs_dirent {
71         TAILQ_ENTRY(tmpfs_dirent)       td_entries;
72
73         /* Length of the name stored in this directory entry.  This avoids
74          * the need to recalculate it every time the name is used. */
75         uint16_t                        td_namelen;
76
77         /* The name of the entry, allocated from a string pool.  This
78         * string is not required to be zero-terminated; therefore, the
79         * td_namelen field must always be used when accessing its value. */
80         char *                          td_name;
81
82         /* Pointer to the node this entry refers to. */
83         struct tmpfs_node *             td_node;
84 };
85
86 /* A directory in tmpfs holds a sorted list of directory entries, which in
87  * turn point to other files (which can be directories themselves).
88  *
89  * In tmpfs, this list is managed by a tail queue, whose head is defined by
90  * the struct tmpfs_dir type.
91  *
92  * It is imporant to notice that directories do not have entries for . and
93  * .. as other file systems do.  These can be generated when requested
94  * based on information available by other means, such as the pointer to
95  * the node itself in the former case or the pointer to the parent directory
96  * in the latter case.  This is done to simplify tmpfs's code and, more
97  * importantly, to remove redundancy. */
98 TAILQ_HEAD(tmpfs_dir, tmpfs_dirent);
99
100 #define TMPFS_DIRCOOKIE(dirent) ((off_t)(uintptr_t)(dirent))
101 #define TMPFS_DIRCOOKIE_DOT     0
102 #define TMPFS_DIRCOOKIE_DOTDOT  1
103 #define TMPFS_DIRCOOKIE_EOF     2
104
105 /* --------------------------------------------------------------------- */
106
107 /*
108  * Internal representation of a tmpfs file system node.
109  *
110  * This structure is splitted in two parts: one holds attributes common
111  * to all file types and the other holds data that is only applicable to
112  * a particular type.  The code must be careful to only access those
113  * attributes that are actually allowed by the node's type.
114  *
115  *
116  * Below is the key of locks used to protected the fields in the following
117  * structures.
118  *
119  */
120 struct tmpfs_node {
121         /* Doubly-linked list entry which links all existing nodes for a
122          * single file system.  This is provided to ease the removal of
123          * all nodes during the unmount operation. */
124         LIST_ENTRY(tmpfs_node)  tn_entries;
125
126         /* The node's type.  Any of 'VBLK', 'VCHR', 'VDIR', 'VFIFO',
127          * 'VLNK', 'VREG' and 'VSOCK' is allowed.  The usage of vnode
128          * types instead of a custom enumeration is to make things simpler
129          * and faster, as we do not need to convert between two types. */
130         enum vtype              tn_type;
131
132         /* Node identifier. */
133         ino_t                   tn_id;
134
135         /* Node's internal status.  This is used by several file system
136          * operations to do modifications to the node in a delayed
137          * fashion. */
138         int                     tn_status;
139 #define TMPFS_NODE_ACCESSED     (1 << 1)
140 #define TMPFS_NODE_MODIFIED     (1 << 2)
141 #define TMPFS_NODE_CHANGED      (1 << 3)
142
143         /* The node size.  It does not necessarily match the real amount
144          * of memory consumed by it. */
145         off_t                   tn_size;
146
147         /* Generic node attributes. */
148         uid_t                   tn_uid;
149         gid_t                   tn_gid;
150         mode_t                  tn_mode;
151         int                     tn_flags;
152         nlink_t                 tn_links;
153         struct timespec         tn_atime;
154         struct timespec         tn_mtime;
155         struct timespec         tn_ctime;
156         struct timespec         tn_birthtime;
157         unsigned long           tn_gen;
158
159         /* Head of byte-level lock list (used by tmpfs_advlock). */
160         struct lockf *          tn_lockf;
161
162         /* As there is a single vnode for each active file within the
163          * system, care has to be taken to avoid allocating more than one
164          * vnode per file.  In order to do this, a bidirectional association
165          * is kept between vnodes and nodes.
166          *
167          * Whenever a vnode is allocated, its v_data field is updated to
168          * point to the node it references.  At the same time, the node's
169          * tn_vnode field is modified to point to the new vnode representing
170          * it.  Further attempts to allocate a vnode for this same node will
171          * result in returning a new reference to the value stored in
172          * tn_vnode.
173          *
174          * May be NULL when the node is unused (that is, no vnode has been
175          * allocated for it or it has been reclaimed). */
176         struct vnode *          tn_vnode;
177
178         /* Pointer to the node returned by tmpfs_lookup() after doing a
179          * delete or a rename lookup; its value is only valid in these two
180          * situations.  In case we were looking up . or .., it holds a null
181          * pointer. */
182         struct tmpfs_dirent *   tn_lookup_dirent;
183
184         /* interlock to protect tn_vpstate */
185         struct mtx      tn_interlock;
186
187         /* Identify if current node has vnode assiocate with
188          * or allocating vnode.
189          */
190         int             tn_vpstate;
191
192         /* misc data field for different tn_type node */
193         union {
194                 /* Valid when tn_type == VBLK || tn_type == VCHR. */
195                 dev_t                   tn_rdev;
196
197                 /* Valid when tn_type == VDIR. */
198                 struct tn_dir{
199                         /* Pointer to the parent directory.  The root
200                          * directory has a pointer to itself in this field;
201                          * this property identifies the root node. */
202                         struct tmpfs_node *     tn_parent;
203
204                         /* Head of a tail-queue that links the contents of
205                          * the directory together.  See above for a
206                          * description of its contents. */
207                         struct tmpfs_dir        tn_dirhead;
208
209                         /* Number and pointer of the first directory entry
210                          * returned by the readdir operation if it were
211                          * called again to continue reading data from the
212                          * same directory as before.  This is used to speed
213                          * up reads of long directories, assuming that no
214                          * more than one read is in progress at a given time.
215                          * Otherwise, these values are discarded and a linear
216                          * scan is performed from the beginning up to the
217                          * point where readdir starts returning values. */
218                         off_t                   tn_readdir_lastn;
219                         struct tmpfs_dirent *   tn_readdir_lastp;
220                 }tn_dir;
221
222                 /* Valid when tn_type == VLNK. */
223                 /* The link's target, allocated from a string pool. */
224                 char *                  tn_link;
225
226                 /* Valid when tn_type == VREG. */
227                 struct tn_reg {
228                         /* The contents of regular files stored in a tmpfs
229                          * file system are represented by a single anonymous
230                          * memory object (aobj, for short).  The aobj provides
231                          * direct access to any position within the file,
232                          * because its contents are always mapped in a
233                          * contiguous region of virtual memory.  It is a task
234                          * of the memory management subsystem (see uvm(9)) to
235                          * issue the required page ins or page outs whenever
236                          * a position within the file is accessed. */
237                         vm_object_t             tn_aobj;
238                         size_t                  tn_aobj_pages;
239
240                 }tn_reg;
241
242                 /* Valid when tn_type = VFIFO */
243                 struct tn_fifo {
244                         fo_rdwr_t               *tn_fo_read;
245                         fo_rdwr_t               *tn_fo_write;
246                 }tn_fifo;
247         }tn_spec;
248 };
249 LIST_HEAD(tmpfs_node_list, tmpfs_node);
250
251 #define tn_rdev tn_spec.tn_rdev
252 #define tn_dir tn_spec.tn_dir
253 #define tn_link tn_spec.tn_link
254 #define tn_reg tn_spec.tn_reg
255 #define tn_fifo tn_spec.tn_fifo
256
257 #define TMPFS_NODE_LOCK(node) mtx_lock(&(node)->tn_interlock)
258 #define TMPFS_NODE_UNLOCK(node) mtx_unlock(&(node)->tn_interlock)
259
260 #define TMPFS_VNODE_ALLOCATING  1
261 #define TMPFS_VNODE_WANT        2
262 /* --------------------------------------------------------------------- */
263
264 /*
265  * Internal representation of a tmpfs mount point.
266  */
267 struct tmpfs_mount {
268         /* Maximum number of memory pages available for use by the file
269          * system, set during mount time.  This variable must never be
270          * used directly as it may be bigger than the current amount of
271          * free memory; in the extreme case, it will hold the SIZE_MAX
272          * value.  Instead, use the TMPFS_PAGES_MAX macro. */
273         size_t                  tm_pages_max;
274
275         /* Number of pages in use by the file system.  Cannot be bigger
276          * than the value returned by TMPFS_PAGES_MAX in any case. */
277         size_t                  tm_pages_used;
278
279         /* Pointer to the node representing the root directory of this
280          * file system. */
281         struct tmpfs_node *     tm_root;
282
283         /* Maximum number of possible nodes for this file system; set
284          * during mount time.  We need a hard limit on the maximum number
285          * of nodes to avoid allocating too much of them; their objects
286          * cannot be released until the file system is unmounted.
287          * Otherwise, we could easily run out of memory by creating lots
288          * of empty files and then simply removing them. */
289         ino_t                   tm_nodes_max;
290
291         /* unrhdr used to allocate inode numbers */
292         struct unrhdr *         tm_ino_unr;
293
294         /* Number of nodes currently that are in use. */
295         ino_t                   tm_nodes_inuse;
296
297         /* maximum representable file size */
298         u_int64_t               tm_maxfilesize;
299
300         /* Nodes are organized in two different lists.  The used list
301          * contains all nodes that are currently used by the file system;
302          * i.e., they refer to existing files.  The available list contains
303          * all nodes that are currently available for use by new files.
304          * Nodes must be kept in this list (instead of deleting them)
305          * because we need to keep track of their generation number (tn_gen
306          * field).
307          *
308          * Note that nodes are lazily allocated: if the available list is
309          * empty and we have enough space to create more nodes, they will be
310          * created and inserted in the used list.  Once these are released,
311          * they will go into the available list, remaining alive until the
312          * file system is unmounted. */
313         struct tmpfs_node_list  tm_nodes_used;
314
315         /* All node lock to protect the node list and tmp_pages_used */
316         struct mtx allnode_lock;
317
318         /* Pools used to store file system meta data.  These are not shared
319          * across several instances of tmpfs for the reasons described in
320          * tmpfs_pool.c. */
321         uma_zone_t              tm_dirent_pool;
322         uma_zone_t              tm_node_pool;
323 };
324 #define TMPFS_LOCK(tm) mtx_lock(&(tm)->allnode_lock)
325 #define TMPFS_UNLOCK(tm) mtx_unlock(&(tm)->allnode_lock)
326
327 /* --------------------------------------------------------------------- */
328
329 /*
330  * This structure maps a file identifier to a tmpfs node.  Used by the
331  * NFS code.
332  */
333 struct tmpfs_fid {
334         uint16_t                tf_len;
335         uint16_t                tf_pad;
336         ino_t                   tf_id;
337         unsigned long           tf_gen;
338 };
339
340 /* --------------------------------------------------------------------- */
341
342 #ifdef _KERNEL
343 /*
344  * Prototypes for tmpfs_subr.c.
345  */
346
347 int     tmpfs_alloc_node(struct tmpfs_mount *, enum vtype,
348             uid_t uid, gid_t gid, mode_t mode, struct tmpfs_node *,
349             char *, dev_t, struct thread *, struct tmpfs_node **);
350 void    tmpfs_free_node(struct tmpfs_mount *, struct tmpfs_node *);
351 int     tmpfs_alloc_dirent(struct tmpfs_mount *, struct tmpfs_node *,
352             const char *, uint16_t, struct tmpfs_dirent **);
353 void    tmpfs_free_dirent(struct tmpfs_mount *, struct tmpfs_dirent *,
354             boolean_t);
355 int     tmpfs_alloc_vp(struct mount *, struct tmpfs_node *, struct vnode **,
356             struct thread *td);
357 void    tmpfs_free_vp(struct vnode *);
358 int     tmpfs_alloc_file(struct vnode *, struct vnode **, struct vattr *,
359             struct componentname *, char *);
360 void    tmpfs_dir_attach(struct vnode *, struct tmpfs_dirent *);
361 void    tmpfs_dir_detach(struct vnode *, struct tmpfs_dirent *);
362 struct tmpfs_dirent *   tmpfs_dir_lookup(struct tmpfs_node *node,
363                             struct componentname *cnp);
364 int     tmpfs_dir_getdotdent(struct tmpfs_node *, struct uio *);
365 int     tmpfs_dir_getdotdotdent(struct tmpfs_node *, struct uio *);
366 struct tmpfs_dirent *   tmpfs_dir_lookupbycookie(struct tmpfs_node *, off_t);
367 int     tmpfs_dir_getdents(struct tmpfs_node *, struct uio *, off_t *);
368 int     tmpfs_reg_resize(struct vnode *, off_t);
369 int     tmpfs_chflags(struct vnode *, int, struct ucred *, struct thread *);
370 int     tmpfs_chmod(struct vnode *, mode_t, struct ucred *, struct thread *);
371 int     tmpfs_chown(struct vnode *, uid_t, gid_t, struct ucred *,
372             struct thread *);
373 int     tmpfs_chsize(struct vnode *, u_quad_t, struct ucred *, struct thread *);
374 int     tmpfs_chtimes(struct vnode *, struct timespec *, struct timespec *,
375             struct timespec *, int, struct ucred *, struct thread *);
376 void    tmpfs_itimes(struct vnode *, const struct timespec *,
377             const struct timespec *);
378
379 void    tmpfs_update(struct vnode *);
380 int     tmpfs_truncate(struct vnode *, off_t);
381
382 /* --------------------------------------------------------------------- */
383
384 /*
385  * Convenience macros to simplify some logical expressions.
386  */
387 #define IMPLIES(a, b) (!(a) || (b))
388 #define IFF(a, b) (IMPLIES(a, b) && IMPLIES(b, a))
389
390 /* --------------------------------------------------------------------- */
391
392 /*
393  * Checks that the directory entry pointed by 'de' matches the name 'name'
394  * with a length of 'len'.
395  */
396 #define TMPFS_DIRENT_MATCHES(de, name, len) \
397     (de->td_namelen == (uint16_t)len && \
398     memcmp((de)->td_name, (name), (de)->td_namelen) == 0)
399
400 /* --------------------------------------------------------------------- */
401
402 /*
403  * Ensures that the node pointed by 'node' is a directory and that its
404  * contents are consistent with respect to directories.
405  */
406 #define TMPFS_VALIDATE_DIR(node) \
407     MPASS((node)->tn_type == VDIR); \
408     MPASS((node)->tn_size % sizeof(struct tmpfs_dirent) == 0); \
409     MPASS((node)->tn_dir.tn_readdir_lastp == NULL || \
410         TMPFS_DIRCOOKIE((node)->tn_dir.tn_readdir_lastp) == (node)->tn_dir.tn_readdir_lastn);
411
412 /* --------------------------------------------------------------------- */
413
414 /*
415  * Memory management stuff.
416  */
417
418 /* Amount of memory pages to reserve for the system (e.g., to not use by
419  * tmpfs).
420  * XXX: Should this be tunable through sysctl, for instance? */
421 #define TMPFS_PAGES_RESERVED (4 * 1024 * 1024 / PAGE_SIZE)
422
423 /*
424  * Returns information about the number of available memory pages,
425  * including physical and virtual ones.
426  *
427  * If 'total' is TRUE, the value returned is the total amount of memory
428  * pages configured for the system (either in use or free).
429  * If it is FALSE, the value returned is the amount of free memory pages.
430  *
431  * Remember to remove TMPFS_PAGES_RESERVED from the returned value to avoid
432  * excessive memory usage.
433  *
434  */
435 static __inline size_t
436 tmpfs_mem_info(void)
437 {
438         size_t size;
439
440         size = swap_pager_avail + cnt.v_free_count + cnt.v_inactive_count;
441         size -= size > cnt.v_wire_count ? cnt.v_wire_count : size;
442         return size;
443 }
444
445 /* Returns the maximum size allowed for a tmpfs file system.  This macro
446  * must be used instead of directly retrieving the value from tm_pages_max.
447  * The reason is that the size of a tmpfs file system is dynamic: it lets
448  * the user store files as long as there is enough free memory (including
449  * physical memory and swap space).  Therefore, the amount of memory to be
450  * used is either the limit imposed by the user during mount time or the
451  * amount of available memory, whichever is lower.  To avoid consuming all
452  * the memory for a given mount point, the system will always reserve a
453  * minimum of TMPFS_PAGES_RESERVED pages, which is also taken into account
454  * by this macro (see above). */
455 static __inline size_t
456 TMPFS_PAGES_MAX(struct tmpfs_mount *tmp)
457 {
458         size_t freepages;
459
460         freepages = tmpfs_mem_info();
461         freepages -= freepages < TMPFS_PAGES_RESERVED ?
462             freepages : TMPFS_PAGES_RESERVED;
463
464         return MIN(tmp->tm_pages_max, freepages + tmp->tm_pages_used);
465 }
466
467 /* Returns the available space for the given file system. */
468 #define TMPFS_META_PAGES(tmp) (howmany((tmp)->tm_nodes_inuse * (sizeof(struct tmpfs_node) \
469                                 + sizeof(struct tmpfs_dirent)), PAGE_SIZE))
470 #define TMPFS_FILE_PAGES(tmp) ((tmp)->tm_pages_used)
471
472 #define TMPFS_PAGES_AVAIL(tmp) (TMPFS_PAGES_MAX(tmp) > \
473                         TMPFS_META_PAGES(tmp)+TMPFS_FILE_PAGES(tmp)? \
474                         TMPFS_PAGES_MAX(tmp) - TMPFS_META_PAGES(tmp) \
475                         - TMPFS_FILE_PAGES(tmp):0)
476
477 #endif
478
479 /* --------------------------------------------------------------------- */
480
481 /*
482  * Macros/functions to convert from generic data structures to tmpfs
483  * specific ones.
484  */
485
486 static inline
487 struct tmpfs_mount *
488 VFS_TO_TMPFS(struct mount *mp)
489 {
490         struct tmpfs_mount *tmp;
491
492         MPASS((mp) != NULL && (mp)->mnt_data != NULL);
493         tmp = (struct tmpfs_mount *)(mp)->mnt_data;
494         return tmp;
495 }
496
497 static inline
498 struct tmpfs_node *
499 VP_TO_TMPFS_NODE(struct vnode *vp)
500 {
501         struct tmpfs_node *node;
502
503         MPASS((vp) != NULL && (vp)->v_data != NULL);
504         node = (struct tmpfs_node *)vp->v_data;
505         return node;
506 }
507
508 static inline
509 struct tmpfs_node *
510 VP_TO_TMPFS_DIR(struct vnode *vp)
511 {
512         struct tmpfs_node *node;
513
514         node = VP_TO_TMPFS_NODE(vp);
515         TMPFS_VALIDATE_DIR(node);
516         return node;
517 }
518
519 #endif /* _FS_TMPFS_TMPFS_H_ */