1 /* 2 * Copyright (c) 2013 The DragonFly Project. All rights reserved. 3 * 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> 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 #ifndef _SYS_VFS_DIRFS_DIRFS_H_ 38 #define _SYS_VFS_DIRFS_DIRFS_H_ 39 40 #include <unistd.h> 41 42 #include <sys/lockf.h> 43 #include <sys/stat.h> 44 #include <sys/vnode.h> 45 #include <sys/file.h> 46 47 #ifdef MALLOC_DECLARE 48 MALLOC_DECLARE(M_DIRFS); 49 MALLOC_DECLARE(M_DIRFS_NODE); 50 MALLOC_DECLARE(M_DIRFS_MISC); 51 #endif 52 53 #ifndef KTR_DIRFS 54 #define KTR_DIRFS KTR_ALL 55 #endif 56 57 #define DIRFS_NOFD -1 /* No fd present */ 58 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 64 65 #define DIRFS_TXTFLG "pasvfd" 66 67 /* Used for buffer cache operations */ 68 #define BSIZE 16384 69 #define BMASK (BSIZE - 1) 70 71 /* 72 * XXX This should be temporary. A semi-proper solution would be to expose 73 * below prototypes in the _KERNEL_VIRTUAL case. 74 */ 75 extern int getdirentries(int, char *, int, long *); 76 extern int statfs(const char *, struct statfs *); 77 78 /* 79 * Debugging macros. 80 * 81 * LEVEL USED FOR 82 * 83 * 1 Calls to VFS operations (mount, umount, ...) 84 * 3 Calls to VN operations (open, close, read, ...) 85 * 5 Calls to subroutines 86 * 9 Everything 87 * 88 */ 89 #define dbg(lvl, fmt, ...) do { \ 90 debug(lvl, "%s: " fmt, __func__, ##__VA_ARGS__); \ 91 } while(0) 92 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, \ 101 s->dn_mtime); \ 102 } while(0) 103 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)); \ 109 } while(0) 110 111 /* 112 * Locking macros 113 */ 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) 121 122 /* 123 * Misc macros 124 */ 125 #define dirfs_node_isroot(n) (n->dn_state & DIRFS_ROOT) 126 127 /* 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. 131 */ 132 struct dirfs_node { 133 enum vtype dn_type; /* Node type. Same as vnode 134 type for simplicty */ 135 136 int dn_state; /* Node state flags */ 137 138 TAILQ_ENTRY(dirfs_node) dn_fdentry; /* Passive fd cache */ 139 RB_ENTRY(dirfs_node) dn_rbentry; /* Inode no. lookup */ 140 141 int dn_refcnt; /* Refs from children */ 142 int dn_fd; /* File des. for open(2) */ 143 144 struct dirfs_node * dn_parent; /* Pointer to parent node */ 145 146 struct vnode * dn_vnode; /* Reference to its vnode on 147 the vkernel scope */ 148 char * dn_name; 149 int dn_namelen; 150 151 struct lockf dn_advlock; 152 struct lock dn_lock; 153 154 uint32_t dn_st_dev; /* Device number */ 155 156 /* Generic attributes */ 157 ino_t dn_ino; 158 long dn_blocksize; 159 uid_t dn_uid; 160 gid_t dn_gid; 161 mode_t dn_mode; 162 u_int dn_flags; 163 nlink_t dn_links; 164 int32_t dn_atime; 165 int32_t dn_atimensec; 166 int32_t dn_mtime; 167 int32_t dn_mtimensec; 168 int32_t dn_ctime; 169 int32_t dn_ctimensec; 170 unsigned long dn_gen; 171 off_t dn_size; 172 }; 173 typedef struct dirfs_node *dirfs_node_t; 174 175 /* 176 * In-memory dirfs mount structure. It corresponds to a mounted 177 * dirfs filesystem. 178 */ 179 struct dirfs_mount { 180 RB_HEAD(, dn_rbentry) dm_inotree; 181 TAILQ_HEAD(, dirfs_node) dm_fdlist; 182 183 struct lock dm_lock; 184 struct lwkt_token dm_token; 185 dirfs_node_t dm_root; /* Root dirfs node */ 186 struct mount * dm_mount; 187 int dm_rdonly; 188 189 int dm_fd_used; /* Opened file descriptors */ 190 191 uid_t dm_uid; /* User running the vkernel */ 192 gid_t dm_gid; 193 194 char dm_path[MAXPATHLEN]; 195 }; 196 typedef struct dirfs_mount *dirfs_mount_t; 197 198 /* 199 * VFS <-> DIRFS conversion macros 200 */ 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) 205 206 /* Misc stuff */ 207 extern int debuglvl; 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; 212 213 extern struct vop_ops dirfs_vnode_vops; 214 215 #ifdef _KERNEL 216 /* 217 * Misc functions for node operations 218 */ 219 static __inline void 220 dirfs_node_ref(dirfs_node_t dnp) 221 { 222 atomic_add_int(&dnp->dn_refcnt, 1); 223 } 224 225 static __inline int 226 dirfs_node_unref(dirfs_node_t dnp) 227 { 228 /* 229 * Returns non-zero on last unref. 230 */ 231 KKASSERT(dnp->dn_refcnt > 0); 232 return (atomic_fetchadd_int(&dnp->dn_refcnt, -1) == 1); 233 } 234 235 static __inline void 236 dirfs_node_setflags(dirfs_node_t dnp, int flags) 237 { 238 atomic_set_int(&dnp->dn_state, flags); 239 } 240 241 static __inline void 242 dirfs_node_clrflags(dirfs_node_t dnp, int flags) 243 { 244 atomic_clear_int(&dnp->dn_state, flags); 245 } 246 247 #endif 248 249 /* 250 * Prototypes 251 */ 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, 269 char *, char **); 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 *, ...); 282 283 #endif /* _SYS_VFS_DIRFS_DIRFS_H_ */ 284