Merge branches 'hammer2' and 'master' of ssh://crater.dragonflybsd.org/repository...
[dragonfly.git] / sys / vfs / hammer2 / hammer2.h
1 /*
2  * Copyright (c) 2011-2012 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@dragonflybsd.org>
6  * by Venkatesh Srinivas <vsrinivas@dragonflybsd.org>
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  * 3. Neither the name of The DragonFly Project nor the names of its
19  *    contributors may be used to endorse or promote products derived
20  *    from this software without specific, prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
26  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35
36 /*
37  * This header file contains structures used internally by the HAMMER2
38  * implementation.  See hammer2_disk.h for on-disk structures.
39  */
40
41 #ifndef _VFS_HAMMER2_HAMMER2_H_
42 #define _VFS_HAMMER2_HAMMER2_H_
43
44 #include <sys/param.h>
45 #include <sys/types.h>
46 #include <sys/kernel.h>
47 #include <sys/conf.h>
48 #include <sys/systm.h>
49 #include <sys/tree.h>
50 #include <sys/malloc.h>
51 #include <sys/mount.h>
52 #include <sys/vnode.h>
53 #include <sys/proc.h>
54 #include <sys/mountctl.h>
55 #include <sys/priv.h>
56 #include <sys/stat.h>
57 #include <sys/globaldata.h>
58 #include <sys/lockf.h>
59 #include <sys/buf.h>
60 #include <sys/queue.h>
61 #include <sys/limits.h>
62 #include <sys/buf2.h>
63 #include <sys/signal2.h>
64 #include <sys/tree.h>
65
66 #include "hammer2_disk.h"
67 #include "hammer2_mount.h"
68
69 struct hammer2_inode;
70 struct hammer2_mount;
71
72 struct hammer2_node;
73
74 /*
75  * A hammer2 inode.
76  */
77 struct hammer2_inode {
78         struct hammer2_mount    *mp;
79         struct lock             lk;
80         struct vnode            *vp;
81         hammer2_tid_t           inum;
82         unsigned char           type;
83         int                     busy;
84 };
85
86 #define HAMMER2_INODE_TYPE_DIR  0x01
87 #define HAMMER2_INODE_TYPE_FILE 0x02
88 #define HAMMER2_INODE_TYPE_ROOT 0x10
89 #define HAMMER2_INODE_TYPE_MASK 0x07
90
91 /* --------------------------------------------------------------------- */
92
93 /*
94  * Internal representation of a hammer2 directory entry.
95  */
96 struct hammer2_dirent {
97         TAILQ_ENTRY(hammer2_dirent)     td_entries;
98
99         /* Length of the name stored in this directory entry.  This avoids
100          * the need to recalculate it every time the name is used. */
101         uint16_t                        td_namelen;
102
103         /* The name of the entry, allocated from a string pool.  This
104          * string is not required to be zero-terminated; therefore, the
105          * td_namelen field must always be used when accessing its value. */
106         char *                          td_name;
107
108         /* Pointer to the node this entry refers to. */
109         struct hammer2_node *           td_node;
110 };
111
112 /* A directory in hammer2 holds a sorted list of directory entries, which in
113  * turn point to other files (which can be directories themselves).
114  *
115  * In hammer2, this list is managed by a tail queue, whose head is defined by
116  * the struct hammer2_dir type.
117  *
118  * It is imporant to notice that directories do not have entries for . and
119  * .. as other file systems do.  These can be generated when requested
120  * based on information available by other means, such as the pointer to
121  * the node itself in the former case or the pointer to the parent directory
122  * in the latter case.  This is done to simplify hammer2's code and, more
123  * importantly, to remove redundancy. */
124 TAILQ_HEAD(hammer2_dir, hammer2_dirent);
125
126 /* --------------------------------------------------------------------- */
127
128
129
130 /* --------------------------------------------------------------------- */
131
132 /*
133  * Internal representation of a hammer2 file system node.
134  *
135  * This structure is splitted in two parts: one holds attributes common
136  * to all file types and the other holds data that is only applicable to
137  * a particular type.  The code must be careful to only access those
138  * attributes that are actually allowed by the node's type.
139  *
140  *
141  * Below is the key of locks used to protected the fields in the following
142  * structures.
143  *
144  */
145 struct hammer2_node {
146         /* Doubly-linked list entry which links all existing nodes for a
147          * single file system.  This is provided to ease the removal of
148          * all nodes during the unmount operation. */
149         LIST_ENTRY(hammer2_node)        tn_entries;
150
151         /* The node's type.  Any of 'VBLK', 'VCHR', 'VDIR', 'VFIFO',
152          * 'VLNK', 'VREG' and 'VSOCK' is allowed.  The usage of vnode
153          * types instead of a custom enumeration is to make things simpler
154          * and faster, as we do not need to convert between two types. */
155         enum vtype              tn_type;
156
157         /* Node identifier. */
158         ino_t                   tn_id;
159
160         /* Node's internal status.  This is used by several file system
161          * operations to do modifications to the node in a delayed
162          * fashion. */
163         int                     tn_status;
164 #define TMPFS_NODE_ACCESSED     (1 << 1)
165 #define TMPFS_NODE_MODIFIED     (1 << 2)
166 #define TMPFS_NODE_CHANGED      (1 << 3)
167
168         /* The node size.  It does not necessarily match the real amount
169          * of memory consumed by it. */
170         off_t                   tn_size;
171
172         /* Generic node attributes. */
173         uid_t                   tn_uid;
174         gid_t                   tn_gid;
175         mode_t                  tn_mode;
176         int                     tn_flags;
177         nlink_t                 tn_links;
178         int32_t                 tn_atime;
179         int32_t                 tn_atimensec;
180         int32_t                 tn_mtime;
181         int32_t                 tn_mtimensec;
182         int32_t                 tn_ctime;
183         int32_t                 tn_ctimensec;
184         unsigned long           tn_gen;
185         struct lockf            tn_advlock;
186
187         /* As there is a single vnode for each active file within the
188          * system, care has to be taken to avoid allocating more than one
189          * vnode per file.  In order to do this, a bidirectional association
190          * is kept between vnodes and nodes.
191          *
192          * Whenever a vnode is allocated, its v_data field is updated to
193          * point to the node it references.  At the same time, the node's
194          * tn_vnode field is modified to point to the new vnode representing
195          * it.  Further attempts to allocate a vnode for this same node will
196          * result in returning a new reference to the value stored in
197          * tn_vnode.
198          *
199          * May be NULL when the node is unused (that is, no vnode has been
200          * allocated for it or it has been reclaimed). */
201         struct vnode *          tn_vnode;
202
203         /* interlock to protect tn_vpstate */
204         struct lock             tn_interlock;
205
206         /* Identify if current node has vnode assiocate with
207          * or allocating vnode.
208          */
209         int             tn_vpstate;
210
211         /* misc data field for different tn_type node */
212         union {
213                 /* Valid when tn_type == VBLK || tn_type == VCHR. */
214                 dev_t                   tn_rdev; /*int32_t ?*/
215
216                 /* Valid when tn_type == VDIR. */
217                 struct tn_dir{
218                         /* Pointer to the parent directory.  The root
219                          * directory has a pointer to itself in this field;
220                          * this property identifies the root node. */
221                         struct hammer2_node *   tn_parent;
222
223                         /* Head of a tail-queue that links the contents of
224                          * the directory together.  See above for a
225                          * description of its contents. */
226                         struct hammer2_dir      tn_dirhead;
227
228                         /* Number and pointer of the first directory entry
229                          * returned by the readdir operation if it were
230                          * called again to continue reading data from the
231                          * same directory as before.  This is used to speed
232                          * up reads of long directories, assuming that no
233                          * more than one read is in progress at a given time.
234                          * Otherwise, these values are discarded and a linear
235                          * scan is performed from the beginning up to the
236                          * point where readdir starts returning values. */
237                         off_t                   tn_readdir_lastn;
238                         struct hammer2_dirent * tn_readdir_lastp;
239                 }tn_dir;
240
241                 /* Valid when tn_type == VLNK. */
242                 /* The link's target, allocated from a string pool. */
243                 char *                  tn_link;
244
245                 /* Valid when tn_type == VREG. */
246                 struct tn_reg {
247                         /* The contents of regular files stored in a tmpfs
248                          * file system are represented by a single anonymous
249                          * memory object (aobj, for short).  The aobj provides
250                          * direct access to any position within the file,
251                          * because its contents are always mapped in a
252                          * contiguous region of virtual memory.  It is a task
253                          * of the memory management subsystem (see uvm(9)) to
254                          * issue the required page ins or page outs whenever
255                          * a position within the file is accessed. */
256                         vm_object_t             tn_aobj;
257                         size_t                  tn_aobj_pages;
258
259                 }tn_reg;
260
261                 /* Valid when tn_type = VFIFO */
262                 struct tn_fifo {
263                         int (*tn_fo_read)  (struct file *fp, struct uio *uio,
264                                             struct ucred *cred, int flags);
265                         int (*tn_fo_write) (struct file *fp, struct uio *uio,
266                                             struct ucred *cred, int flags);
267                 }tn_fifo;
268         }tn_spec;
269 };
270 LIST_HEAD(tmpfs_node_list, hammer2_node);
271
272 #define tn_rdev tn_spec.tn_rdev
273 #define tn_dir tn_spec.tn_dir
274 #define tn_link tn_spec.tn_link
275 #define tn_reg tn_spec.tn_reg
276 #define tn_fifo tn_spec.tn_fifo
277
278 #define TMPFS_NODE_LOCK(node) lockmgr(&(node)->tn_interlock, LK_EXCLUSIVE|LK_RETRY)
279 #define TMPFS_NODE_UNLOCK(node) lockmgr(&(node)->tn_interlock, LK_RELEASE)
280 #define TMPFS_NODE_MTX(node) (&(node)->tn_interlock)
281
282 #ifdef INVARIANTS
283 #define TMPFS_ASSERT_LOCKED(node) do {                                  \
284 KKASSERT(node != NULL);                                 \
285 KKASSERT(node->tn_vnode != NULL);                       \
286 if (!vn_islocked(node->tn_vnode) &&                     \
287 (lockstatus(TMPFS_NODE_MTX(node), curthread) == LK_EXCLUSIVE ))         \
288 panic("tmpfs: node is not locked: %p", node);   \
289 } while (0)
290 #define TMPFS_ASSERT_ELOCKED(node) do {                                 \
291 KKASSERT((node) != NULL);                               \
292 KKASSERT(lockstatus(TMPFS_NODE_MTX(node), curthread) == LK_EXCLUSIVE);          \
293 } while (0)
294 #else
295 #define TMPFS_ASSERT_LOCKED(node) (void)0
296 #define TMPFS_ASSERT_ELOCKED(node) (void)0
297 #endif
298
299 #define TMPFS_VNODE_ALLOCATING  1
300 #define TMPFS_VNODE_WANT        2
301 #define TMPFS_VNODE_DOOMED      4
302 /* --------------------------------------------------------------------- */
303
304
305
306 /*
307  * Governing mount structure for filesystem (aka vp->v_mount)
308  */
309 struct hammer2_mount {
310         struct mount    *hm_mp;
311         int             hm_ronly;       /* block device mounted read-only */
312         struct vnode    *hm_devvp;      /* device vnode */
313         struct lock     hm_lk;
314
315         /* Root inode */
316         struct hammer2_inode    *hm_iroot;
317
318         /* Per-mount inode zone */
319         struct malloc_type *hm_inodes;
320         int             hm_ninodes;
321         int             hm_maxinodes;
322
323         struct malloc_type *hm_ipstacks;
324         int             hm_nipstacks;
325         int             hm_maxipstacks;
326
327         struct hammer2_volume_data hm_sb;
328
329
330         /*** TMPFS_MOUNT ***/
331
332
333         /* Maximum number of memory pages available for use by the file
334          * system, set during mount time.  This variable must never be
335          * used directly as it may be bigger than the current amount of
336          * free memory; in the extreme case, it will hold the SIZE_MAX
337          * value.  Instead, use the TMPFS_PAGES_MAX macro. */
338         vm_pindex_t             tm_pages_max;
339
340         /* Number of pages in use by the file system.  Cannot be bigger
341          * than the value returned by TMPFS_PAGES_MAX in any case. */
342         vm_pindex_t             tm_pages_used;
343
344         /* Pointer to the node representing the root directory of this
345          * file system. */
346         struct hammer2_node *   tm_root;
347
348         /* Maximum number of possible nodes for this file system; set
349          * during mount time.  We need a hard limit on the maximum number
350          * of nodes to avoid allocating too much of them; their objects
351          * cannot be released until the file system is unmounted.
352          * Otherwise, we could easily run out of memory by creating lots
353          * of empty files and then simply removing them. */
354         ino_t                   tm_nodes_max;
355
356         /* Number of nodes currently that are in use. */
357         ino_t                   tm_nodes_inuse;
358
359         /* maximum representable file size */
360         u_int64_t               tm_maxfilesize;
361
362         /* Nodes are organized in two different lists.  The used list
363          * contains all nodes that are currently used by the file system;
364          * i.e., they refer to existing files.  The available list contains
365          * all nodes that are currently available for use by new files.
366          * Nodes must be kept in this list (instead of deleting them)
367          * because we need to keep track of their generation number (tn_gen
368          * field).
369          *
370          * Note that nodes are lazily allocated: if the available list is
371          * empty and we have enough space to create more nodes, they will be
372          * created and inserted in the used list.  Once these are released,
373          * they will go into the available list, remaining alive until the
374          * file system is unmounted. */
375         struct tmpfs_node_list  tm_nodes_used;
376
377         /* All node lock to protect the node list and tmp_pages_used */
378         struct lock              allnode_lock;
379
380         /* Per-mount malloc zones for tmpfs nodes, names, and dirents */
381         struct malloc_type      *tm_node_zone;
382         struct malloc_type      *tm_dirent_zone;
383         struct malloc_type      *tm_name_zone;
384
385         struct objcache_malloc_args tm_node_zone_malloc_args;
386         struct objcache_malloc_args tm_dirent_zone_malloc_args;
387
388         /* Pools used to store file system meta data.  These are not shared
389          * across several instances of tmpfs for the reasons described in
390          * tmpfs_pool.c. */
391         struct objcache         *tm_dirent_pool;
392         struct objcache         *tm_node_pool;
393
394         int                     tm_flags;
395 };
396
397 #if defined(_KERNEL)
398
399 MALLOC_DECLARE(M_HAMMER2);
400
401
402 static inline struct mount *
403 H2TOMP(struct hammer2_mount *hmp)
404 {
405         return (struct mount *) hmp->hm_mp;
406 }
407
408 #define VTOI(vp)        ((struct hammer2_inode *) (vp)->v_data)
409 #define ITOV(ip)        ((ip)->vp)
410
411 extern struct vop_ops hammer2_vnode_vops;
412 extern struct vop_ops hammer2_spec_vops;
413 extern struct vop_ops hammer2_fifo_vops;
414
415 /* hammer2_inode.c */
416
417 extern int hammer2_inactive(struct vop_inactive_args *);
418 extern int hammer2_reclaim(struct vop_reclaim_args *);
419
420 /* hammer2_subr.c */
421
422 extern struct vnode *igetv(struct hammer2_inode *, int *);
423
424 extern void hammer2_mount_exlock(struct hammer2_mount *);
425 extern void hammer2_mount_shlock(struct hammer2_mount *);
426 extern void hammer2_mount_unlock(struct hammer2_mount *);
427
428
429
430 #endif  /* kernel */
431 #endif
432
433 #ifndef _VFS_TMPFS_TMPFS_H_
434 #define _VFS_TMPFS_TMPFS_H_
435
436 /* ---------------------------------------------------------------------
437  * KERNEL-SPECIFIC DEFINITIONS
438  * --------------------------------------------------------------------- */
439 #include <sys/dirent.h>
440 #include <sys/mount.h>
441 #include <sys/queue.h>
442 #include <sys/vnode.h>
443 #include <sys/file.h>
444 #include <sys/lock.h>
445 #include <sys/lockf.h>
446 #include <sys/mutex.h>
447 #include <sys/objcache.h>
448
449 /* --------------------------------------------------------------------- */
450 #include <sys/malloc.h>
451 #include <sys/systm.h>
452 #include <sys/vmmeter.h>
453 #include <vm/swap_pager.h>
454
455 MALLOC_DECLARE(M_TMPFSMNT);
456
457 /* Each entry in a directory has a cookie that identifies it.  Cookies
458  * supersede offsets within directories because, given how tmpfs stores
459  * directories in memory, there is no such thing as an offset.  (Emulating
460  * a real offset could be very difficult.)
461  *
462  * The '.', '..' and the end of directory markers have fixed cookies which
463  * cannot collide with the cookies generated by other entries.  The cookies
464  * for the other entries are generated based on the memory address on which
465  * stores their information is stored.
466  *
467  * Ideally, using the entry's memory pointer as the cookie would be enough
468  * to represent it and it wouldn't cause collisions in any system.
469  * Unfortunately, this results in "offsets" with very large values which
470  * later raise problems in the Linux compatibility layer (and maybe in other
471  * places) as described in PR kern/32034.  Hence we need to workaround this
472  * with a rather ugly hack.
473  *
474  * Linux 32-bit binaries, unless built with _FILE_OFFSET_BITS=64, have off_t
475  * set to 'long', which is a 32-bit *signed* long integer.  Regardless of
476  * the macro value, GLIBC (2.3 at least) always uses the getdents64
477  * system call (when calling readdir) which internally returns off64_t
478  * offsets.  In order to make 32-bit binaries work, *GLIBC* converts the
479  * 64-bit values returned by the kernel to 32-bit ones and aborts with
480  * EOVERFLOW if the conversion results in values that won't fit in 32-bit
481  * integers (which it assumes is because the directory is extremely large).
482  * This wouldn't cause problems if we were dealing with unsigned integers,
483  * but as we have signed integers, this check fails due to sign expansion.
484  *
485  * For example, consider that the kernel returns the 0xc1234567 cookie to
486  * userspace in a off64_t integer.  Later on, GLIBC casts this value to
487  * off_t (remember, signed) with code similar to:
488  *     system call returns the offset in kernel_value;
489  *     off_t casted_value = kernel_value;
490  *     if (sizeof(off_t) != sizeof(off64_t) &&
491  *         kernel_value != casted_value)
492  *             error!
493  * In this case, casted_value still has 0xc1234567, but when it is compared
494  * for equality against kernel_value, it is promoted to a 64-bit integer and
495  * becomes 0xffffffffc1234567, which is different than 0x00000000c1234567.
496  * Then, GLIBC assumes this is because the directory is very large.
497  *
498  * Given that all the above happens in user-space, we have no control over
499  * it; therefore we must workaround the issue here.  We do this by
500  * truncating the pointer value to a 32-bit integer and hope that there
501  * won't be collisions.  In fact, this will not cause any problems in
502  * 32-bit platforms but some might arise in 64-bit machines (I'm not sure
503  * if they can happen at all in practice).
504  *
505  * XXX A nicer solution shall be attempted. */
506 #ifdef _KERNEL
507 #define TMPFS_DIRCOOKIE_DOT     0
508 #define TMPFS_DIRCOOKIE_DOTDOT  1
509 #define TMPFS_DIRCOOKIE_EOF     2
510 static __inline
511 off_t
512 tmpfs_dircookie(struct hammer2_dirent *de)
513 {
514         off_t cookie;
515
516         cookie = ((off_t)(uintptr_t)de >> 1) & 0x7FFFFFFF;
517         KKASSERT(cookie != TMPFS_DIRCOOKIE_DOT);
518         KKASSERT(cookie != TMPFS_DIRCOOKIE_DOTDOT);
519         KKASSERT(cookie != TMPFS_DIRCOOKIE_EOF);
520
521         return cookie;
522 }
523 #endif
524
525
526 /*
527  * Internal representation of a tmpfs mount point.
528  */
529
530 #define TMPFS_LOCK(tm) lockmgr(&(tm)->allnode_lock, LK_EXCLUSIVE|LK_RETRY)
531 #define TMPFS_UNLOCK(tm) lockmgr(&(tm)->allnode_lock, LK_RELEASE)
532
533 /* --------------------------------------------------------------------- */
534
535 /*
536  * This structure maps a file identifier to a tmpfs node.  Used by the
537  * NFS code.
538  */
539 struct tmpfs_fid {
540         uint16_t                tf_len;
541         uint16_t                tf_pad;
542         ino_t                   tf_id;
543         unsigned long           tf_gen;
544 };
545
546 /* --------------------------------------------------------------------- */
547
548 #ifdef _KERNEL
549 /*
550  * Prototypes for tmpfs_subr.c.
551  */
552
553 int     tmpfs_alloc_node(struct hammer2_mount *, enum vtype,
554                          uid_t uid, gid_t gid, mode_t mode, struct hammer2_node *,
555                          char *, int, int, struct hammer2_node **);
556 void    tmpfs_free_node(struct hammer2_mount *, struct hammer2_node *);
557 int     tmpfs_alloc_dirent(struct hammer2_mount *, struct hammer2_node *,
558                            const char *, uint16_t, struct hammer2_dirent **);
559 void    tmpfs_free_dirent(struct hammer2_mount *, struct hammer2_dirent *);
560 int     tmpfs_alloc_vp(struct mount *, struct hammer2_node *, int,
561                        struct vnode **);
562 void    tmpfs_free_vp(struct vnode *);
563 int     tmpfs_alloc_file(struct vnode *, struct vnode **, struct vattr *,
564                          struct namecache *, struct ucred *, char *);
565 void    tmpfs_dir_attach(struct hammer2_node *, struct hammer2_dirent *);
566 void    tmpfs_dir_detach(struct hammer2_node *, struct hammer2_dirent *);
567 struct hammer2_dirent * tmpfs_dir_lookup(struct hammer2_node *node,
568                                          struct hammer2_node *f,
569                                          struct namecache *ncp);
570 int     tmpfs_dir_getdotdent(struct hammer2_node *, struct uio *);
571 int     tmpfs_dir_getdotdotdent(struct hammer2_mount *,
572                                 struct hammer2_node *, struct uio *);
573 struct hammer2_dirent * tmpfs_dir_lookupbycookie(struct hammer2_node *, off_t);
574 int     tmpfs_dir_getdents(struct hammer2_node *, struct uio *, off_t *);
575 int     tmpfs_reg_resize(struct vnode *, off_t, int);
576 int     tmpfs_chflags(struct vnode *, int, struct ucred *);
577 int     tmpfs_chmod(struct vnode *, mode_t, struct ucred *);
578 int     tmpfs_chown(struct vnode *, uid_t, gid_t, struct ucred *);
579 int     tmpfs_chsize(struct vnode *, u_quad_t, struct ucred *);
580 int     tmpfs_chtimes(struct vnode *, struct timespec *, struct timespec *,
581                       int, struct ucred *);
582 void    tmpfs_itimes(struct vnode *, const struct timespec *,
583                      const struct timespec *);
584
585 void    tmpfs_update(struct vnode *);
586 int     tmpfs_truncate(struct vnode *, off_t);
587 int     tmpfs_node_ctor(void *obj, void *privdata, int flags);
588
589 /* --------------------------------------------------------------------- */
590
591 /*
592  * Convenience macros to simplify some logical expressions.
593  */
594 #define IMPLIES(a, b) (!(a) || (b))
595 #define IFF(a, b) (IMPLIES(a, b) && IMPLIES(b, a))
596
597 /* --------------------------------------------------------------------- */
598
599 /*
600  * Checks that the directory entry pointed by 'de' matches the name 'name'
601  * with a length of 'len'.
602  */
603 #define TMPFS_DIRENT_MATCHES(de, name, len) \
604 (de->td_namelen == (uint16_t)len && \
605 bcmp((de)->td_name, (name), (de)->td_namelen) == 0)
606
607 /* --------------------------------------------------------------------- */
608
609 /*
610  * Ensures that the node pointed by 'node' is a directory and that its
611  * contents are consistent with respect to directories.
612  */
613 #define TMPFS_VALIDATE_DIR(node) \
614 KKASSERT((node)->tn_type == VDIR); \
615 KKASSERT((node)->tn_size % sizeof(struct hammer2_dirent) == 0); \
616 KKASSERT((node)->tn_dir.tn_readdir_lastp == NULL || \
617 tmpfs_dircookie((node)->tn_dir.tn_readdir_lastp) == (node)->tn_dir.tn_readdir_lastn);
618
619 #endif
620
621 /* --------------------------------------------------------------------- */
622
623 /*
624  * Macros/functions to convert from generic data structures to tmpfs
625  * specific ones.
626  */
627
628 static inline
629 struct hammer2_mount *
630 VFS_TO_TMPFS(struct mount *mp)
631 {
632         struct hammer2_mount *tmp;
633
634         KKASSERT((mp) != NULL && (mp)->mnt_data != NULL);
635         tmp = (struct hammer2_mount *)(mp)->mnt_data;
636         return tmp;
637 }
638
639 static inline
640 struct hammer2_node *
641 VP_TO_TMPFS_NODE(struct vnode *vp)
642 {
643         struct hammer2_node *node;
644
645         KKASSERT((vp) != NULL && (vp)->v_data != NULL);
646         node = (struct hammer2_node *)vp->v_data;
647         return node;
648 }
649
650 static inline
651 struct hammer2_node *
652 VP_TO_TMPFS_DIR(struct vnode *vp)
653 {
654         struct hammer2_node *node;
655
656         node = VP_TO_TMPFS_NODE(vp);
657         TMPFS_VALIDATE_DIR(node);
658         return node;
659 }
660
661 /* --------------------------------------------------------------------- */
662 /*
663  * buffer cache size
664  */
665 #define BSIZE (off_t)16384          /* buffer cache size*/
666 #define BMASK (off_t)(BSIZE - 1)
667
668 extern struct vop_ops tmpfs_vnode_vops;
669 extern struct vop_ops tmpfs_fifo_vops;
670
671 /*
672  * Declarations for tmpfs_vnops.c.
673  */
674
675 int tmpfs_access(struct vop_access_args *);
676 int tmpfs_getattr(struct vop_getattr_args *);
677 int tmpfs_setattr(struct vop_setattr_args *);
678 int tmpfs_reclaim(struct vop_reclaim_args *);
679
680
681 #endif /* _VFS_TMPFS_TMPFS_H_ */
682
683 #ifndef _MORE_HAMMER2_
684 #define _MORE_HAMMER2_
685 static inline struct hammer2_mount *
686 MPTOH2(struct mount *mp)
687 {
688         return (struct hammer2_mount *) mp->mnt_data;
689 }
690 #endif