Merge branch 'vendor/DIFFUTILS'
[dragonfly.git] / sys / vfs / dirfs / dirfs.h
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 MALLOC_DECLARE(M_DIRFS);
48 MALLOC_DECLARE(M_DIRFS_NODE);
49 MALLOC_DECLARE(M_DIRFS_MISC);
50
51 #ifndef KTR_DIRFS
52 #define KTR_DIRFS KTR_ALL
53 #endif
54
55 #define DIRFS_NOFD      -1      /* No fd present */
56
57 #define DIRFS_ROOT      0x00000001
58 #define DIRFS_PASVFD    0x00000002
59 #define DIRFS_NODE_RD   0x00000004
60 #define DIRFS_NODE_WR   0x00000008
61 #define DIRFS_NODE_EXE  0x00000010
62
63 #define DIRFS_TXTFLG "pasvfd"
64
65 /* Used for buffer cache operations */
66 #define BSIZE   16384
67 #define BMASK   (BSIZE - 1)
68
69 /*
70  * XXX This should be temporary. A semi-proper solution would be to expose
71  * below prototypes in the _KERNEL_VIRTUAL case.
72  */
73 extern int getdirentries(int, char *, int, long *);
74 extern int statfs(const char *, struct statfs *);
75
76 /*
77  * Debugging macros.
78  *
79  * LEVEL        USED FOR
80  *
81  *     1        Calls to VFS operations (mount, umount, ...)
82  *     3        Calls to VN operations (open, close, read, ...)
83  *     5        Calls to subroutines
84  *     9        Everything
85  *
86  */
87 #define dbg(lvl, fmt, ...) do {                                 \
88                 debug(lvl, "%s: " fmt, __func__, ##__VA_ARGS__);        \
89 } while(0)
90
91 #define debug_node(s) do {                                              \
92                 dbg(9, "mode=%u flags=%u dn_name=%s "                   \
93                     "uid=%u gid=%u objtype=%u nlinks=%d "               \
94                     "size=%jd ctime=%ju atime=%ju mtime=%ju\n",         \
95                     s->dn_mode, s->dn_flags, s->dn_name,                \
96                     s->dn_uid, s->dn_gid, s->dn_type,                   \
97                     s->dn_links, s->dn_size,                            \
98                     s->dn_ctime, s->dn_atime,                           \
99                     s->dn_mtime);                                       \
100 } while(0)
101
102 #define debug_node2(n) do {                                             \
103                 dbg(9, "dnp=%p name=%s fd=%d parent=%p vnode=%p "       \
104                     "refcnt=%d state=%s\n",                             \
105                     n, n->dn_name, n->dn_fd, n->dn_parent, n->dn_vnode, \
106                     n->dn_refcnt, dirfs_flag2str(n));                   \
107 } while(0)
108
109 /*
110  * Locking macros
111  */
112 #define dirfs_node_islocked(n)  (lockstatus(&(n)->dn_lock,curthread) == LK_EXCLUSIVE)
113 #define dirfs_node_lock(n)      lockmgr(&(n)->dn_lock, LK_EXCLUSIVE|LK_RETRY)
114 #define dirfs_node_unlock(n)    lockmgr(&(n)->dn_lock, LK_RELEASE)
115 #define dirfs_mount_lock(m)     lockmgr(&(m)->dm_lock, LK_EXCLUSIVE|LK_RETRY)
116 #define dirfs_mount_unlock(m)   lockmgr(&(m)->dm_lock, LK_RELEASE)
117 #define dirfs_mount_gettoken(m) lwkt_gettoken(&(m)->dm_token)
118 #define dirfs_mount_reltoken(m) lwkt_reltoken(&(m)->dm_token)
119
120 /*
121  * Misc macros
122  */
123 #define dirfs_node_isroot(n)    (n->dn_state & DIRFS_ROOT)
124
125 /*
126  * Main in-memory node structure which will represent a host file when active.
127  * Upon VOP_NRESOLVE() an attempt to initialize its generic fields will be made
128  * via a fstatat(2)/lstat(2) call.
129  */
130 struct dirfs_node {
131         enum vtype              dn_type;        /* Node type. Same as vnode
132                                                    type for simplicty */
133
134         int                     dn_state;       /* Node state flags */
135
136         TAILQ_ENTRY(dirfs_node) dn_fdentry;     /* Passive fd cache */
137         RB_ENTRY(dirfs_node)    dn_rbentry;     /* Inode no. lookup */
138
139         int                     dn_refcnt;      /* Refs from children */
140         int                     dn_fd;          /* File des. for open(2) */
141
142         struct dirfs_node *     dn_parent;      /* Pointer to parent node */
143
144         struct vnode *          dn_vnode;       /* Reference to its vnode on
145                                                    the vkernel scope */
146         char *                  dn_name;
147         int                     dn_namelen;
148
149         struct lockf            dn_advlock;
150         struct lock             dn_lock;
151
152         uint32_t                dn_st_dev;      /* Device number */
153
154         /* Generic attributes */
155         ino_t                   dn_ino;
156         long                    dn_blocksize;
157         uid_t                   dn_uid;
158         gid_t                   dn_gid;
159         mode_t                  dn_mode;
160         int                     dn_flags;
161         nlink_t                 dn_links;
162         int32_t                 dn_atime;
163         int32_t                 dn_atimensec;
164         int32_t                 dn_mtime;
165         int32_t                 dn_mtimensec;
166         int32_t                 dn_ctime;
167         int32_t                 dn_ctimensec;
168         unsigned long           dn_gen;
169         off_t                   dn_size;
170 };
171 typedef struct dirfs_node *dirfs_node_t;
172
173 /*
174  * In-memory dirfs mount structure. It corresponds to a mounted
175  * dirfs filesystem.
176  */
177 struct dirfs_mount {
178         RB_HEAD(, dn_rbentry) dm_inotree;
179         TAILQ_HEAD(, dirfs_node) dm_fdlist;
180
181         struct lock             dm_lock;
182         struct lwkt_token       dm_token;
183         dirfs_node_t            dm_root;        /* Root dirfs node */
184         struct mount *          dm_mount;
185         int                     dm_rdonly;
186
187         int                     dm_fd_used;     /* Opened file descriptors */
188
189         uid_t                   dm_uid; /* User running the vkernel */
190         gid_t                   dm_gid;
191
192         char                    dm_path[MAXPATHLEN];
193 };
194 typedef struct dirfs_mount *dirfs_mount_t;
195
196 /*
197  * VFS <-> DIRFS conversion macros
198  */
199 #define VFS_TO_DIRFS(mp)        ((dirfs_mount_t)((mp)->mnt_data))
200 #define DIRFS_TO_VFS(dmp)       ((struct mount *)((dmp)->dm_mount))
201 #define VP_TO_NODE(vp)          ((dirfs_node_t)((vp)->v_data))
202 #define NODE_TO_VP(dnp)         ((dnp)->dn_vnode)
203
204 /* Misc stuff */
205 extern int debuglvl;
206 extern int dirfs_fd_limit;
207 extern int dirfs_fd_used;
208 extern long passive_fd_list_miss;
209 extern long passive_fd_list_hits;
210
211 extern struct vop_ops dirfs_vnode_vops;
212
213 #ifdef _KERNEL
214 /*
215  * Misc functions for node operations
216  */
217 static __inline void
218 dirfs_node_ref(dirfs_node_t dnp)
219 {
220         atomic_add_int(&dnp->dn_refcnt, 1);
221 }
222
223 static __inline int
224 dirfs_node_unref(dirfs_node_t dnp)
225 {
226         /*
227          * Returns non-zero on last unref.
228          */
229         KKASSERT(dnp->dn_refcnt > 0);
230         return (atomic_fetchadd_int(&dnp->dn_refcnt, -1) == 1);
231 }
232
233 static __inline void
234 dirfs_node_setflags(dirfs_node_t dnp, int flags)
235 {
236         atomic_set_int(&dnp->dn_state, flags);
237 }
238
239 static __inline void
240 dirfs_node_clrflags(dirfs_node_t dnp, int flags)
241 {
242         atomic_clear_int(&dnp->dn_state, flags);
243 }
244
245 #endif
246
247 /*
248  * Prototypes
249  */
250 dirfs_node_t dirfs_node_alloc(struct mount *);
251 int dirfs_node_stat(int, const char *, dirfs_node_t);
252 int dirfs_nodetype(struct stat *);
253 void dirfs_node_setname(dirfs_node_t, const char *, int);
254 char *dirfs_node_fullpath(dirfs_mount_t, const char *);
255 int dirfs_node_free(dirfs_mount_t, dirfs_node_t);
256 void dirfs_node_drop(dirfs_mount_t dmp, dirfs_node_t dnp);
257 void dirfs_node_setpassive(dirfs_mount_t dmp, dirfs_node_t dnp, int state);
258 void dirfs_alloc_vp(struct mount *, struct vnode **, int, dirfs_node_t);
259 void dirfs_free_vp(dirfs_mount_t, dirfs_node_t);
260 int dirfs_alloc_file(dirfs_mount_t, dirfs_node_t *, dirfs_node_t,
261     struct namecache *, struct vnode **, struct vattr *, int);
262 dirfs_node_t dirfs_findfd(dirfs_mount_t dmp, dirfs_node_t cur,
263                         char **pathto, char **pathfree);
264 void dirfs_dropfd(dirfs_mount_t dmp, dirfs_node_t dnp1, char *pathfree);
265 char *dirfs_node_absolute_path(dirfs_mount_t, dirfs_node_t, char **);
266 char *dirfs_node_absolute_path_plus(dirfs_mount_t, dirfs_node_t,
267                         char *, char **);
268 int dirfs_open_helper(dirfs_mount_t, dirfs_node_t, int, char *);
269 int dirfs_close_helper(dirfs_node_t);
270 int dirfs_node_refcnt(dirfs_node_t);
271 char *dirfs_flag2str(dirfs_node_t);
272 int dirfs_node_getperms(dirfs_node_t, int *);
273 int dirfs_node_chflags(dirfs_node_t, int, struct ucred *);
274 int dirfs_node_chtimes(dirfs_node_t);
275 int dirfs_node_chmod(dirfs_mount_t, dirfs_node_t, mode_t cur_mode);
276 int dirfs_node_chown(dirfs_mount_t, dirfs_node_t,
277                         uid_t cur_uid, uid_t cur_gid, mode_t cur_mode);
278 int dirfs_node_chsize(dirfs_node_t, off_t);
279 void debug(int, const char *, ...);
280
281 #endif /* _SYS_VFS_DIRFS_DIRFS_H_ */