2 * Copyright (c) 2013 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Antonio Huete Jimenez <tuxillo@quantumachine.net>
6 * by Matthew Dillon <dillon@dragonflybsd.org>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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
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.
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
37 #ifndef _SYS_VFS_DIRFS_DIRFS_H_
38 #define _SYS_VFS_DIRFS_DIRFS_H_
42 #include <sys/lockf.h>
44 #include <sys/vnode.h>
48 MALLOC_DECLARE(M_DIRFS);
49 MALLOC_DECLARE(M_DIRFS_NODE);
50 MALLOC_DECLARE(M_DIRFS_MISC);
54 #define KTR_DIRFS KTR_ALL
57 #define DIRFS_NOFD -1 /* No fd present */
59 #define DIRFS_ROOT 0x00000001
60 #define DIRFS_PASVFD 0x00000002
61 #define DIRFS_NODE_RD 0x00000004
62 #define DIRFS_NODE_WR 0x00000008
63 #define DIRFS_NODE_EXE 0x00000010
65 #define DIRFS_TXTFLG "pasvfd"
67 /* Used for buffer cache operations */
69 #define BMASK (BSIZE - 1)
72 * XXX This should be temporary. A semi-proper solution would be to expose
73 * below prototypes in the _KERNEL_VIRTUAL case.
75 extern int getdirentries(int, char *, int, long *);
76 extern int statfs(const char *, struct statfs *);
83 * 1 Calls to VFS operations (mount, umount, ...)
84 * 3 Calls to VN operations (open, close, read, ...)
85 * 5 Calls to subroutines
89 #define dbg(lvl, fmt, ...) do { \
90 debug(lvl, "%s: " fmt, __func__, ##__VA_ARGS__); \
93 #define debug_node(s) do { \
94 dbg(9, "mode=%u flags=%u dn_name=%s " \
95 "uid=%u gid=%u objtype=%u nlinks=%d " \
96 "size=%jd ctime=%ju atime=%ju mtime=%ju\n", \
97 s->dn_mode, s->dn_flags, s->dn_name, \
98 s->dn_uid, s->dn_gid, s->dn_type, \
99 s->dn_links, s->dn_size, \
100 s->dn_ctime, s->dn_atime, \
104 #define debug_node2(n) do { \
105 dbg(9, "dnp=%p name=%s fd=%d parent=%p vnode=%p " \
106 "refcnt=%d state=%s\n", \
107 n, n->dn_name, n->dn_fd, n->dn_parent, n->dn_vnode, \
108 n->dn_refcnt, dirfs_flag2str(n)); \
114 #define dirfs_node_islocked(n) (lockstatus(&(n)->dn_lock,curthread) == LK_EXCLUSIVE)
115 #define dirfs_node_lock(n) lockmgr(&(n)->dn_lock, LK_EXCLUSIVE|LK_RETRY)
116 #define dirfs_node_unlock(n) lockmgr(&(n)->dn_lock, LK_RELEASE)
117 #define dirfs_mount_lock(m) lockmgr(&(m)->dm_lock, LK_EXCLUSIVE|LK_RETRY)
118 #define dirfs_mount_unlock(m) lockmgr(&(m)->dm_lock, LK_RELEASE)
119 #define dirfs_mount_gettoken(m) lwkt_gettoken(&(m)->dm_token)
120 #define dirfs_mount_reltoken(m) lwkt_reltoken(&(m)->dm_token)
125 #define dirfs_node_isroot(n) (n->dn_state & DIRFS_ROOT)
128 * Main in-memory node structure which will represent a host file when active.
129 * Upon VOP_NRESOLVE() an attempt to initialize its generic fields will be made
130 * via a fstatat(2)/lstat(2) call.
133 enum vtype dn_type; /* Node type. Same as vnode
134 type for simplicty */
136 int dn_state; /* Node state flags */
138 TAILQ_ENTRY(dirfs_node) dn_fdentry; /* Passive fd cache */
139 RB_ENTRY(dirfs_node) dn_rbentry; /* Inode no. lookup */
141 int dn_refcnt; /* Refs from children */
142 int dn_fd; /* File des. for open(2) */
144 struct dirfs_node * dn_parent; /* Pointer to parent node */
146 struct vnode * dn_vnode; /* Reference to its vnode on
151 struct lockf dn_advlock;
154 uint32_t dn_st_dev; /* Device number */
156 /* Generic attributes */
165 int32_t dn_atimensec;
167 int32_t dn_mtimensec;
169 int32_t dn_ctimensec;
170 unsigned long dn_gen;
173 typedef struct dirfs_node *dirfs_node_t;
176 * In-memory dirfs mount structure. It corresponds to a mounted
180 RB_HEAD(, dn_rbentry) dm_inotree;
181 TAILQ_HEAD(, dirfs_node) dm_fdlist;
184 struct lwkt_token dm_token;
185 dirfs_node_t dm_root; /* Root dirfs node */
186 struct mount * dm_mount;
189 int dm_fd_used; /* Opened file descriptors */
191 uid_t dm_uid; /* User running the vkernel */
194 char dm_path[MAXPATHLEN];
196 typedef struct dirfs_mount *dirfs_mount_t;
199 * VFS <-> DIRFS conversion macros
201 #define VFS_TO_DIRFS(mp) ((dirfs_mount_t)((mp)->mnt_data))
202 #define DIRFS_TO_VFS(dmp) ((struct mount *)((dmp)->dm_mount))
203 #define VP_TO_NODE(vp) ((dirfs_node_t)((vp)->v_data))
204 #define NODE_TO_VP(dnp) ((dnp)->dn_vnode)
208 extern int dirfs_fd_limit;
209 extern int dirfs_fd_used;
210 extern long passive_fd_list_miss;
211 extern long passive_fd_list_hits;
213 extern struct vop_ops dirfs_vnode_vops;
217 * Misc functions for node operations
220 dirfs_node_ref(dirfs_node_t dnp)
222 atomic_add_int(&dnp->dn_refcnt, 1);
226 dirfs_node_unref(dirfs_node_t dnp)
229 * Returns non-zero on last unref.
231 KKASSERT(dnp->dn_refcnt > 0);
232 return (atomic_fetchadd_int(&dnp->dn_refcnt, -1) == 1);
236 dirfs_node_setflags(dirfs_node_t dnp, int flags)
238 atomic_set_int(&dnp->dn_state, flags);
242 dirfs_node_clrflags(dirfs_node_t dnp, int flags)
244 atomic_clear_int(&dnp->dn_state, flags);
252 dirfs_node_t dirfs_node_alloc(struct mount *);
253 int dirfs_node_stat(int, const char *, dirfs_node_t);
254 int dirfs_nodetype(struct stat *);
255 void dirfs_node_setname(dirfs_node_t, const char *, int);
256 char *dirfs_node_fullpath(dirfs_mount_t, const char *);
257 int dirfs_node_free(dirfs_mount_t, dirfs_node_t);
258 void dirfs_node_drop(dirfs_mount_t dmp, dirfs_node_t dnp);
259 void dirfs_node_setpassive(dirfs_mount_t dmp, dirfs_node_t dnp, int state);
260 void dirfs_alloc_vp(struct mount *, struct vnode **, int, dirfs_node_t);
261 void dirfs_free_vp(dirfs_mount_t, dirfs_node_t);
262 int dirfs_alloc_file(dirfs_mount_t, dirfs_node_t *, dirfs_node_t,
263 struct namecache *, struct vnode **, struct vattr *, int);
264 dirfs_node_t dirfs_findfd(dirfs_mount_t dmp, dirfs_node_t cur,
265 char **pathto, char **pathfree);
266 void dirfs_dropfd(dirfs_mount_t dmp, dirfs_node_t dnp1, char *pathfree);
267 char *dirfs_node_absolute_path(dirfs_mount_t, dirfs_node_t, char **);
268 char *dirfs_node_absolute_path_plus(dirfs_mount_t, dirfs_node_t,
270 int dirfs_open_helper(dirfs_mount_t, dirfs_node_t, int, char *);
271 int dirfs_close_helper(dirfs_node_t);
272 int dirfs_node_refcnt(dirfs_node_t);
273 char *dirfs_flag2str(dirfs_node_t);
274 int dirfs_node_getperms(dirfs_node_t, int *);
275 int dirfs_node_chflags(dirfs_node_t, u_long, struct ucred *);
276 int dirfs_node_chtimes(dirfs_node_t);
277 int dirfs_node_chmod(dirfs_mount_t, dirfs_node_t, mode_t cur_mode);
278 int dirfs_node_chown(dirfs_mount_t, dirfs_node_t,
279 uid_t cur_uid, uid_t cur_gid, mode_t cur_mode);
280 int dirfs_node_chsize(dirfs_node_t, off_t);
281 void debug(int, const char *, ...);
283 #endif /* _SYS_VFS_DIRFS_DIRFS_H_ */