xref: /dragonfly/sys/vfs/dirfs/dirfs_vnops.c (revision 08905fc5)
1509bc517SAntonio Huete Jimenez /*
2509bc517SAntonio Huete Jimenez  * Copyright (c) 2013 The DragonFly Project.  All rights reserved.
3509bc517SAntonio Huete Jimenez  *
4509bc517SAntonio Huete Jimenez  * This code is derived from software contributed to The DragonFly Project
5509bc517SAntonio Huete Jimenez  * by Antonio Huete Jimenez <tuxillo@quantumachine.net>
6509bc517SAntonio Huete Jimenez  * by Matthew Dillon <dillon@dragonflybsd.org>
7509bc517SAntonio Huete Jimenez  *
8509bc517SAntonio Huete Jimenez  * Redistribution and use in source and binary forms, with or without
9509bc517SAntonio Huete Jimenez  * modification, are permitted provided that the following conditions
10509bc517SAntonio Huete Jimenez  * are met:
11509bc517SAntonio Huete Jimenez  *
12509bc517SAntonio Huete Jimenez  * 1. Redistributions of source code must retain the above copyright
13509bc517SAntonio Huete Jimenez  *    notice, this list of conditions and the following disclaimer.
14509bc517SAntonio Huete Jimenez  * 2. Redistributions in binary form must reproduce the above copyright
15509bc517SAntonio Huete Jimenez  *    notice, this list of conditions and the following disclaimer in
16509bc517SAntonio Huete Jimenez  *    the documentation and/or other materials provided with the
17509bc517SAntonio Huete Jimenez  *    distribution.
18509bc517SAntonio Huete Jimenez  * 3. Neither the name of The DragonFly Project nor the names of its
19509bc517SAntonio Huete Jimenez  *    contributors may be used to endorse or promote products derived
20509bc517SAntonio Huete Jimenez  *    from this software without specific, prior written permission.
21509bc517SAntonio Huete Jimenez  *
22509bc517SAntonio Huete Jimenez  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23509bc517SAntonio Huete Jimenez  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24509bc517SAntonio Huete Jimenez  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25509bc517SAntonio Huete Jimenez  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
26509bc517SAntonio Huete Jimenez  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27509bc517SAntonio Huete Jimenez  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
28509bc517SAntonio Huete Jimenez  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29509bc517SAntonio Huete Jimenez  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30509bc517SAntonio Huete Jimenez  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31509bc517SAntonio Huete Jimenez  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32509bc517SAntonio Huete Jimenez  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33509bc517SAntonio Huete Jimenez  * SUCH DAMAGE.
34509bc517SAntonio Huete Jimenez  *
35509bc517SAntonio Huete Jimenez  */
36509bc517SAntonio Huete Jimenez 
37509bc517SAntonio Huete Jimenez #include <stdio.h>
38509bc517SAntonio Huete Jimenez #include <errno.h>
39509bc517SAntonio Huete Jimenez #include <strings.h>
40509bc517SAntonio Huete Jimenez #include <unistd.h>
41509bc517SAntonio Huete Jimenez 
42509bc517SAntonio Huete Jimenez #include <sys/vfsops.h>
43509bc517SAntonio Huete Jimenez #include <sys/vnode.h>
44509bc517SAntonio Huete Jimenez #include <sys/stat.h>
45509bc517SAntonio Huete Jimenez #include <sys/namecache.h>
46509bc517SAntonio Huete Jimenez #include <sys/queue.h>
47509bc517SAntonio Huete Jimenez #include <sys/systm.h>
48509bc517SAntonio Huete Jimenez #include <sys/dirent.h>
49509bc517SAntonio Huete Jimenez #include <sys/mount.h>
50509bc517SAntonio Huete Jimenez #include <sys/signalvar.h>
51509bc517SAntonio Huete Jimenez #include <sys/resource.h>
52509bc517SAntonio Huete Jimenez #include <sys/buf2.h>
53509bc517SAntonio Huete Jimenez #include <sys/kern_syscall.h>
54509bc517SAntonio Huete Jimenez #include <sys/ktr.h>
55509bc517SAntonio Huete Jimenez 
56509bc517SAntonio Huete Jimenez #include "dirfs.h"
57509bc517SAntonio Huete Jimenez 
58509bc517SAntonio Huete Jimenez /*
59509bc517SAntonio Huete Jimenez  * Kernel tracing facilities
60509bc517SAntonio Huete Jimenez  */
61509bc517SAntonio Huete Jimenez KTR_INFO_MASTER_EXTERN(dirfs);
62509bc517SAntonio Huete Jimenez 
63509bc517SAntonio Huete Jimenez KTR_INFO(KTR_DIRFS, dirfs, unsupported, 0,
64509bc517SAntonio Huete Jimenez     "DIRFS(func=%s)",
65509bc517SAntonio Huete Jimenez     const char *func);
66509bc517SAntonio Huete Jimenez 
67509bc517SAntonio Huete Jimenez KTR_INFO(KTR_DIRFS, dirfs, nresolve, 0,
68509bc517SAntonio Huete Jimenez     "DIRFS(dnp=%p ncp_name=%s parent=%p pfd=%d error=%d)",
69509bc517SAntonio Huete Jimenez     dirfs_node_t dnp, char *name, dirfs_node_t pdnp, int pfd, int error);
70509bc517SAntonio Huete Jimenez 
71509bc517SAntonio Huete Jimenez KTR_INFO(KTR_DIRFS, dirfs, ncreate, 1,
72509bc517SAntonio Huete Jimenez     "DIRFS(dnp=%p ncp_name=%s parent=%p pfd=%d error=%d)",
73509bc517SAntonio Huete Jimenez     dirfs_node_t dnp, char *name, dirfs_node_t pdnp, int pfd, int error);
74509bc517SAntonio Huete Jimenez 
75509bc517SAntonio Huete Jimenez KTR_INFO(KTR_DIRFS, dirfs, open, 2,
763cc8dd41SAntonio Huete Jimenez     "DIRFS(dnp=%p dn_name=%s nfd=%d)",
773cc8dd41SAntonio Huete Jimenez     dirfs_node_t dnp, char *name, int fd);
78509bc517SAntonio Huete Jimenez 
79509bc517SAntonio Huete Jimenez KTR_INFO(KTR_DIRFS, dirfs, close, 3,
803cc8dd41SAntonio Huete Jimenez     "DIRFS(dnp=%p fd=%d opencount=%d writecount=%d vfsync error=%d)",
813cc8dd41SAntonio Huete Jimenez     dirfs_node_t dnp, int fd, int oc, int wc, int error);
82509bc517SAntonio Huete Jimenez 
83509bc517SAntonio Huete Jimenez KTR_INFO(KTR_DIRFS, dirfs, readdir, 4,
84509bc517SAntonio Huete Jimenez     "DIRFS(dnp=%p fd=%d startoff=%jd uio_offset=%jd)",
85509bc517SAntonio Huete Jimenez     dirfs_node_t dnp, int fd, off_t startoff, off_t uoff);
86509bc517SAntonio Huete Jimenez 
87509bc517SAntonio Huete Jimenez KTR_INFO(KTR_DIRFS, dirfs, access, 5,
88509bc517SAntonio Huete Jimenez     "DIRFS(dnp=%p error=%d)",
89509bc517SAntonio Huete Jimenez     dirfs_node_t dnp, int error);
90509bc517SAntonio Huete Jimenez 
91509bc517SAntonio Huete Jimenez KTR_INFO(KTR_DIRFS, dirfs, getattr, 6,
92509bc517SAntonio Huete Jimenez     "DIRFS(dnp=%p error=%d)",
93509bc517SAntonio Huete Jimenez     dirfs_node_t dnp, int error);
94509bc517SAntonio Huete Jimenez 
95509bc517SAntonio Huete Jimenez KTR_INFO(KTR_DIRFS, dirfs, setattr, 7,
96509bc517SAntonio Huete Jimenez     "DIRFS(dnp=%p action=%s error=%d)",
97509bc517SAntonio Huete Jimenez     dirfs_node_t dnp, const char *action, int error);
98509bc517SAntonio Huete Jimenez 
99509bc517SAntonio Huete Jimenez KTR_INFO(KTR_DIRFS, dirfs, fsync, 8,
100509bc517SAntonio Huete Jimenez     "DIRFS(dnp=%p error=%d)",
101509bc517SAntonio Huete Jimenez     dirfs_node_t dnp, int error);
102509bc517SAntonio Huete Jimenez 
103509bc517SAntonio Huete Jimenez KTR_INFO(KTR_DIRFS, dirfs, read, 9,
104509bc517SAntonio Huete Jimenez     "DIRFS(dnp=%p size=%jd error=%d)",
105509bc517SAntonio Huete Jimenez     dirfs_node_t dnp, size_t size, int error);
106509bc517SAntonio Huete Jimenez 
107509bc517SAntonio Huete Jimenez KTR_INFO(KTR_DIRFS, dirfs, write, 10,
108509bc517SAntonio Huete Jimenez     "DIRFS(dnp=%p size=%jd boff=%jd uio_resid=%jd error=%d)",
109509bc517SAntonio Huete Jimenez     dirfs_node_t dnp, off_t boff, size_t resid, size_t size, int error);
110509bc517SAntonio Huete Jimenez 
111509bc517SAntonio Huete Jimenez KTR_INFO(KTR_DIRFS, dirfs, strategy, 11,
112509bc517SAntonio Huete Jimenez     "DIRFS(dnp=%p dnp_size=%jd iosize=%jd b_cmd=%d b_error=%d "
113509bc517SAntonio Huete Jimenez     "b_resid=%d bio_off=%jd error=%d)",
114509bc517SAntonio Huete Jimenez     dirfs_node_t dnp, size_t size, size_t iosize, int cmd, int berror,
115509bc517SAntonio Huete Jimenez     int bresid, off_t biooff, int error);
116509bc517SAntonio Huete Jimenez 
117509bc517SAntonio Huete Jimenez KTR_INFO(KTR_DIRFS, dirfs, nremove, 12,
118509bc517SAntonio Huete Jimenez     "DIRFS(dnp=%p pdnp=%p error=%d)",
119509bc517SAntonio Huete Jimenez     dirfs_node_t dnp, dirfs_node_t pdnp, int error);
120509bc517SAntonio Huete Jimenez 
121509bc517SAntonio Huete Jimenez KTR_INFO(KTR_DIRFS, dirfs, nmkdir, 13,
122509bc517SAntonio Huete Jimenez     "DIRFS(pdnp=%p dnp=%p nc_name=%p error=%d)",
123509bc517SAntonio Huete Jimenez     dirfs_node_t dnp, dirfs_node_t pdnp, char *n, int error);
124509bc517SAntonio Huete Jimenez 
125509bc517SAntonio Huete Jimenez KTR_INFO(KTR_DIRFS, dirfs, nrmdir, 13,
126509bc517SAntonio Huete Jimenez     "DIRFS(pdnp=%p dnp=%p error=%d)",
127509bc517SAntonio Huete Jimenez     dirfs_node_t dnp, dirfs_node_t pdnp, int error);
128509bc517SAntonio Huete Jimenez 
129509bc517SAntonio Huete Jimenez KTR_INFO(KTR_DIRFS, dirfs, nsymlink, 14,
130509bc517SAntonio Huete Jimenez     "DIRFS(dnp=%p target=%s symlink=%s error=%d)",
131509bc517SAntonio Huete Jimenez     dirfs_node_t dnp, char *tgt, char *lnk, int error);
132509bc517SAntonio Huete Jimenez 
133509bc517SAntonio Huete Jimenez /* Needed prototypes */
134509bc517SAntonio Huete Jimenez int dirfs_access(struct vop_access_args *);
135509bc517SAntonio Huete Jimenez int dirfs_getattr(struct vop_getattr_args *);
136509bc517SAntonio Huete Jimenez int dirfs_setattr(struct vop_setattr_args *);
137509bc517SAntonio Huete Jimenez int dirfs_reclaim(struct vop_reclaim_args *);
138509bc517SAntonio Huete Jimenez 
139*08905fc5SAntonio Huete Jimenez static __inline
140*08905fc5SAntonio Huete Jimenez void
dirfs_knote(struct vnode * vp,int flags)141*08905fc5SAntonio Huete Jimenez dirfs_knote(struct vnode *vp, int flags)
142*08905fc5SAntonio Huete Jimenez {
143*08905fc5SAntonio Huete Jimenez 	if (flags)
144*08905fc5SAntonio Huete Jimenez 		KNOTE(&vp->v_pollinfo.vpi_kqinfo.ki_note, flags);
145*08905fc5SAntonio Huete Jimenez }
146*08905fc5SAntonio Huete Jimenez 
147509bc517SAntonio Huete Jimenez static int
dirfs_nresolve(struct vop_nresolve_args * ap)148509bc517SAntonio Huete Jimenez dirfs_nresolve(struct vop_nresolve_args *ap)
149509bc517SAntonio Huete Jimenez {
150509bc517SAntonio Huete Jimenez 	dirfs_node_t pdnp, dnp, d1, d2;
151509bc517SAntonio Huete Jimenez 	dirfs_mount_t dmp;
152509bc517SAntonio Huete Jimenez 	struct namecache *ncp;
153509bc517SAntonio Huete Jimenez 	struct nchandle *nch;
154509bc517SAntonio Huete Jimenez 	struct vnode *dvp;
155509bc517SAntonio Huete Jimenez 	struct vnode *vp;
156509bc517SAntonio Huete Jimenez 	struct mount *mp;
157509bc517SAntonio Huete Jimenez 	int error;
158509bc517SAntonio Huete Jimenez 
15926ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
160509bc517SAntonio Huete Jimenez 
161509bc517SAntonio Huete Jimenez 	error = 0;
162509bc517SAntonio Huete Jimenez 	nch = ap->a_nch;
163509bc517SAntonio Huete Jimenez 	ncp = nch->ncp;
164509bc517SAntonio Huete Jimenez 	mp = nch->mount;
165509bc517SAntonio Huete Jimenez 	dvp = ap->a_dvp;
166509bc517SAntonio Huete Jimenez 	vp = NULL;
167509bc517SAntonio Huete Jimenez 	dnp = d1 = d2 = NULL;
168509bc517SAntonio Huete Jimenez 	pdnp = VP_TO_NODE(dvp);
169509bc517SAntonio Huete Jimenez 	dmp = VFS_TO_DIRFS(mp);
170509bc517SAntonio Huete Jimenez 
171509bc517SAntonio Huete Jimenez 	dirfs_node_lock(pdnp);
172509bc517SAntonio Huete Jimenez 	TAILQ_FOREACH_MUTABLE(d1, &dmp->dm_fdlist, dn_fdentry, d2) {
173509bc517SAntonio Huete Jimenez 		if (d1->dn_parent == pdnp &&
174509bc517SAntonio Huete Jimenez 		    (strcmp(d1->dn_name, ncp->nc_name) == 0)) {
175509bc517SAntonio Huete Jimenez 			dnp = d1;
176509bc517SAntonio Huete Jimenez 			dirfs_node_ref(dnp);
177509bc517SAntonio Huete Jimenez 			passive_fd_list_hits++;
178509bc517SAntonio Huete Jimenez 			break;
179509bc517SAntonio Huete Jimenez 		}
180509bc517SAntonio Huete Jimenez 	}
181509bc517SAntonio Huete Jimenez 	dirfs_node_unlock(pdnp);
182509bc517SAntonio Huete Jimenez 
183509bc517SAntonio Huete Jimenez 	if (dnp) {
184509bc517SAntonio Huete Jimenez 		dirfs_alloc_vp(mp, &vp, LK_CANRECURSE, dnp);
185509bc517SAntonio Huete Jimenez 		dirfs_node_drop(dmp, dnp);
186509bc517SAntonio Huete Jimenez 	} else {
187509bc517SAntonio Huete Jimenez 		passive_fd_list_miss++;
188509bc517SAntonio Huete Jimenez 		error = dirfs_alloc_file(dmp, &dnp, pdnp, ncp, &vp, NULL, 0);
189509bc517SAntonio Huete Jimenez 	}
190509bc517SAntonio Huete Jimenez 
191509bc517SAntonio Huete Jimenez 	if (vp) {
192509bc517SAntonio Huete Jimenez 		if (error && error == ENOENT) {
193509bc517SAntonio Huete Jimenez 			cache_setvp(nch, NULL);
194509bc517SAntonio Huete Jimenez 		} else {
195509bc517SAntonio Huete Jimenez 			vn_unlock(vp);
196509bc517SAntonio Huete Jimenez 			cache_setvp(nch, vp);
197509bc517SAntonio Huete Jimenez 			vrele(vp);
198509bc517SAntonio Huete Jimenez 		}
199509bc517SAntonio Huete Jimenez 	}
200509bc517SAntonio Huete Jimenez 
201509bc517SAntonio Huete Jimenez 	KTR_LOG(dirfs_nresolve, dnp, ncp->nc_name, pdnp, pdnp->dn_fd, error);
202509bc517SAntonio Huete Jimenez 
203509bc517SAntonio Huete Jimenez 	return error;
204509bc517SAntonio Huete Jimenez }
205509bc517SAntonio Huete Jimenez 
206509bc517SAntonio Huete Jimenez static int
dirfs_nlookupdotdot(struct vop_nlookupdotdot_args * ap)207509bc517SAntonio Huete Jimenez dirfs_nlookupdotdot(struct vop_nlookupdotdot_args *ap)
208509bc517SAntonio Huete Jimenez {
20926ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
210509bc517SAntonio Huete Jimenez 
211509bc517SAntonio Huete Jimenez 	KTR_LOG(dirfs_unsupported, __func__);
212509bc517SAntonio Huete Jimenez 
213509bc517SAntonio Huete Jimenez 	return EOPNOTSUPP;
214509bc517SAntonio Huete Jimenez }
215509bc517SAntonio Huete Jimenez 
216509bc517SAntonio Huete Jimenez static int
dirfs_ncreate(struct vop_ncreate_args * ap)217509bc517SAntonio Huete Jimenez dirfs_ncreate(struct vop_ncreate_args *ap)
218509bc517SAntonio Huete Jimenez {
219509bc517SAntonio Huete Jimenez 	dirfs_node_t pdnp;
220509bc517SAntonio Huete Jimenez 	dirfs_node_t dnp;
221509bc517SAntonio Huete Jimenez 	dirfs_mount_t dmp;
222509bc517SAntonio Huete Jimenez 	struct namecache *ncp;
223509bc517SAntonio Huete Jimenez 	struct vnode *dvp;
224509bc517SAntonio Huete Jimenez 	struct vnode **vpp;
225509bc517SAntonio Huete Jimenez 	struct vattr *vap;
22683837cefSAntonio Huete Jimenez 	int perms = 0;
227509bc517SAntonio Huete Jimenez 	int error;
228509bc517SAntonio Huete Jimenez 
22926ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
230509bc517SAntonio Huete Jimenez 
231509bc517SAntonio Huete Jimenez 	error = 0;
232509bc517SAntonio Huete Jimenez 	dnp = NULL;
233509bc517SAntonio Huete Jimenez 	dvp = ap->a_dvp;
234509bc517SAntonio Huete Jimenez 	pdnp = VP_TO_NODE(dvp);
235509bc517SAntonio Huete Jimenez 	dmp = VFS_TO_DIRFS(dvp->v_mount);
236509bc517SAntonio Huete Jimenez 	vap = ap->a_vap;
237509bc517SAntonio Huete Jimenez 	ncp = ap->a_nch->ncp;
238509bc517SAntonio Huete Jimenez 	vpp = ap->a_vpp;
239509bc517SAntonio Huete Jimenez 
24083837cefSAntonio Huete Jimenez 	dirfs_node_getperms(pdnp, &perms);
24183837cefSAntonio Huete Jimenez 	if ((perms & DIRFS_NODE_WR) == 0)
242509bc517SAntonio Huete Jimenez 		error = EPERM;
243509bc517SAntonio Huete Jimenez 
244509bc517SAntonio Huete Jimenez 	error = dirfs_alloc_file(dmp, &dnp, pdnp, ncp, vpp, vap,
245509bc517SAntonio Huete Jimenez 	    (O_CREAT | O_RDWR));
246509bc517SAntonio Huete Jimenez 
247509bc517SAntonio Huete Jimenez 	if (error == 0) {
248509bc517SAntonio Huete Jimenez 		cache_setunresolved(ap->a_nch);
249509bc517SAntonio Huete Jimenez 		cache_setvp(ap->a_nch, *vpp);
250*08905fc5SAntonio Huete Jimenez 		dirfs_knote(dvp, NOTE_WRITE);
251509bc517SAntonio Huete Jimenez 	}
252509bc517SAntonio Huete Jimenez 
253509bc517SAntonio Huete Jimenez 	KTR_LOG(dirfs_ncreate, dnp, ncp->nc_name, pdnp, pdnp->dn_fd, error);
254509bc517SAntonio Huete Jimenez 
255509bc517SAntonio Huete Jimenez 	return error;
256509bc517SAntonio Huete Jimenez }
257509bc517SAntonio Huete Jimenez 
258509bc517SAntonio Huete Jimenez static int
dirfs_nmknod(struct vop_nmknod_args * v)259509bc517SAntonio Huete Jimenez dirfs_nmknod(struct vop_nmknod_args *v)
260509bc517SAntonio Huete Jimenez {
26126ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
262509bc517SAntonio Huete Jimenez 
263509bc517SAntonio Huete Jimenez 	return EOPNOTSUPP;
264509bc517SAntonio Huete Jimenez }
265509bc517SAntonio Huete Jimenez 
266509bc517SAntonio Huete Jimenez static int
dirfs_open(struct vop_open_args * ap)267509bc517SAntonio Huete Jimenez dirfs_open(struct vop_open_args *ap)
268509bc517SAntonio Huete Jimenez {
269509bc517SAntonio Huete Jimenez 	dirfs_node_t dnp;
270509bc517SAntonio Huete Jimenez 	dirfs_mount_t dmp;
271509bc517SAntonio Huete Jimenez 	struct vnode *vp;
272509bc517SAntonio Huete Jimenez 	int error;
273509bc517SAntonio Huete Jimenez 
27426ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
275509bc517SAntonio Huete Jimenez 
276509bc517SAntonio Huete Jimenez 	vp = ap->a_vp;
277509bc517SAntonio Huete Jimenez 	dnp = VP_TO_NODE(vp);
278509bc517SAntonio Huete Jimenez 	dmp = VFS_TO_DIRFS(vp->v_mount);
279509bc517SAntonio Huete Jimenez 	error = 0;
280509bc517SAntonio Huete Jimenez 
281509bc517SAntonio Huete Jimenez 	/*
282509bc517SAntonio Huete Jimenez 	 * Root inode has been allocated and opened in VFS_ROOT() so
283509bc517SAntonio Huete Jimenez 	 * no reason to attempt to open it again.
284509bc517SAntonio Huete Jimenez 	 */
285509bc517SAntonio Huete Jimenez 	if (dmp->dm_root != dnp && dnp->dn_fd == DIRFS_NOFD) {
286509bc517SAntonio Huete Jimenez 		error = dirfs_open_helper(dmp, dnp, DIRFS_NOFD, NULL);
287509bc517SAntonio Huete Jimenez 		if (error)
288509bc517SAntonio Huete Jimenez 			return error;
289509bc517SAntonio Huete Jimenez 	}
290509bc517SAntonio Huete Jimenez 
2913cc8dd41SAntonio Huete Jimenez 	KTR_LOG(dirfs_open, dnp, dnp->dn_name, dnp->dn_fd);
292509bc517SAntonio Huete Jimenez 
293509bc517SAntonio Huete Jimenez 	return vop_stdopen(ap);
294509bc517SAntonio Huete Jimenez }
295509bc517SAntonio Huete Jimenez 
296509bc517SAntonio Huete Jimenez static int
dirfs_close(struct vop_close_args * ap)297509bc517SAntonio Huete Jimenez dirfs_close(struct vop_close_args *ap)
298509bc517SAntonio Huete Jimenez {
299509bc517SAntonio Huete Jimenez 	struct vnode *vp;
300509bc517SAntonio Huete Jimenez 	dirfs_node_t dnp;
301509bc517SAntonio Huete Jimenez 	int error;
302509bc517SAntonio Huete Jimenez 
30326ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
304509bc517SAntonio Huete Jimenez 
305509bc517SAntonio Huete Jimenez 	error = 0;
306509bc517SAntonio Huete Jimenez 	vp = ap->a_vp;
307509bc517SAntonio Huete Jimenez 	dnp = VP_TO_NODE(vp);
308509bc517SAntonio Huete Jimenez 
309509bc517SAntonio Huete Jimenez 	if (vp->v_type == VREG) {
310509bc517SAntonio Huete Jimenez 		error = vfsync(vp, 0, 1, NULL, NULL);
311509bc517SAntonio Huete Jimenez 		if (error)
31226ec059cSAntonio Huete Jimenez 			dbg(9, "vfsync error=%d\n", error);
313509bc517SAntonio Huete Jimenez 	}
3143cc8dd41SAntonio Huete Jimenez 	vop_stdclose(ap);
315509bc517SAntonio Huete Jimenez 
3163cc8dd41SAntonio Huete Jimenez 	KTR_LOG(dirfs_close, dnp, dnp->dn_fd, vp->v_opencount,
3173cc8dd41SAntonio Huete Jimenez 	    vp->v_writecount, error);
318509bc517SAntonio Huete Jimenez 
3193cc8dd41SAntonio Huete Jimenez 	return 0;
320509bc517SAntonio Huete Jimenez }
321509bc517SAntonio Huete Jimenez 
322509bc517SAntonio Huete Jimenez int
dirfs_access(struct vop_access_args * ap)323509bc517SAntonio Huete Jimenez dirfs_access(struct vop_access_args *ap)
324509bc517SAntonio Huete Jimenez {
325509bc517SAntonio Huete Jimenez 	struct vnode *vp = ap->a_vp;
326509bc517SAntonio Huete Jimenez 	int error;
327509bc517SAntonio Huete Jimenez 	dirfs_node_t dnp;
328509bc517SAntonio Huete Jimenez 
32926ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
330509bc517SAntonio Huete Jimenez 
331509bc517SAntonio Huete Jimenez 	dnp = VP_TO_NODE(vp);
332509bc517SAntonio Huete Jimenez 
333509bc517SAntonio Huete Jimenez 	switch (vp->v_type) {
334509bc517SAntonio Huete Jimenez 	case VDIR:
335509bc517SAntonio Huete Jimenez 		/* FALLTHROUGH */
336509bc517SAntonio Huete Jimenez 	case VLNK:
337509bc517SAntonio Huete Jimenez 		/* FALLTHROUGH */
338509bc517SAntonio Huete Jimenez 	case VREG:
339509bc517SAntonio Huete Jimenez 		if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
340509bc517SAntonio Huete Jimenez 			error = EROFS;
341509bc517SAntonio Huete Jimenez 			goto out;
342509bc517SAntonio Huete Jimenez 		}
343509bc517SAntonio Huete Jimenez 		break;
344509bc517SAntonio Huete Jimenez 	case VBLK:
345509bc517SAntonio Huete Jimenez 		/* FALLTHROUGH */
346509bc517SAntonio Huete Jimenez 	case VCHR:
347509bc517SAntonio Huete Jimenez 		/* FALLTHROUGH */
348509bc517SAntonio Huete Jimenez 	case VSOCK:
349509bc517SAntonio Huete Jimenez 		/* FALLTHROUGH */
350509bc517SAntonio Huete Jimenez 	case VFIFO:
351509bc517SAntonio Huete Jimenez 		break;
352509bc517SAntonio Huete Jimenez 
353509bc517SAntonio Huete Jimenez 	default:
354509bc517SAntonio Huete Jimenez 		error = EINVAL;
355509bc517SAntonio Huete Jimenez 		goto out;
356509bc517SAntonio Huete Jimenez 	}
357509bc517SAntonio Huete Jimenez 
358509bc517SAntonio Huete Jimenez 	error = vop_helper_access(ap, dnp->dn_uid,
359509bc517SAntonio Huete Jimenez 	    dnp->dn_gid, dnp->dn_mode, 0);
360509bc517SAntonio Huete Jimenez 
361509bc517SAntonio Huete Jimenez out:
362509bc517SAntonio Huete Jimenez 	KTR_LOG(dirfs_access, dnp, error);
363509bc517SAntonio Huete Jimenez 
364509bc517SAntonio Huete Jimenez 	return error;
365509bc517SAntonio Huete Jimenez }
366509bc517SAntonio Huete Jimenez 
367509bc517SAntonio Huete Jimenez int
dirfs_getattr(struct vop_getattr_args * ap)368509bc517SAntonio Huete Jimenez dirfs_getattr(struct vop_getattr_args *ap)
369509bc517SAntonio Huete Jimenez {
370509bc517SAntonio Huete Jimenez 	dirfs_mount_t dmp;
371509bc517SAntonio Huete Jimenez 	dirfs_node_t dnp;
372509bc517SAntonio Huete Jimenez 	dirfs_node_t pathnp;
373509bc517SAntonio Huete Jimenez 	struct vnode *vp;
374509bc517SAntonio Huete Jimenez 	struct vattr *vap;
375509bc517SAntonio Huete Jimenez 	char *tmp;
376509bc517SAntonio Huete Jimenez 	char *pathfree;
377509bc517SAntonio Huete Jimenez 	int error;
378509bc517SAntonio Huete Jimenez 
37926ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
380509bc517SAntonio Huete Jimenez 
381509bc517SAntonio Huete Jimenez 	vp = ap->a_vp;
382509bc517SAntonio Huete Jimenez 	vap = ap->a_vap;
383509bc517SAntonio Huete Jimenez 	dnp = VP_TO_NODE(vp);
384509bc517SAntonio Huete Jimenez 	dmp = VFS_TO_DIRFS(vp->v_mount);
385509bc517SAntonio Huete Jimenez 
386509bc517SAntonio Huete Jimenez 	KKASSERT(dnp);	/* This must not happen */
387509bc517SAntonio Huete Jimenez 
388509bc517SAntonio Huete Jimenez 	if (!dirfs_node_isroot(dnp)) {
389509bc517SAntonio Huete Jimenez 		pathnp = dirfs_findfd(dmp, dnp, &tmp, &pathfree);
390509bc517SAntonio Huete Jimenez 
391509bc517SAntonio Huete Jimenez 		KKASSERT(pathnp->dn_fd != DIRFS_NOFD);
392509bc517SAntonio Huete Jimenez 
393509bc517SAntonio Huete Jimenez 		error = dirfs_node_stat(pathnp->dn_fd, tmp, dnp);
394509bc517SAntonio Huete Jimenez 		dirfs_dropfd(dmp, pathnp, pathfree);
395509bc517SAntonio Huete Jimenez 	} else {
396509bc517SAntonio Huete Jimenez 		error = dirfs_node_stat(DIRFS_NOFD, dmp->dm_path, dnp);
397509bc517SAntonio Huete Jimenez 	}
398509bc517SAntonio Huete Jimenez 
399509bc517SAntonio Huete Jimenez 	if (error == 0) {
400509bc517SAntonio Huete Jimenez 		dirfs_node_lock(dnp);
401509bc517SAntonio Huete Jimenez 		vap->va_nlink = dnp->dn_links;
402509bc517SAntonio Huete Jimenez 		vap->va_type = dnp->dn_type;
403509bc517SAntonio Huete Jimenez 		vap->va_mode = dnp->dn_mode;
404509bc517SAntonio Huete Jimenez 		vap->va_uid = dnp->dn_uid;
405509bc517SAntonio Huete Jimenez 		vap->va_gid = dnp->dn_gid;
406509bc517SAntonio Huete Jimenez 		vap->va_fileid = dnp->dn_ino;
407509bc517SAntonio Huete Jimenez 		vap->va_size = dnp->dn_size;
408509bc517SAntonio Huete Jimenez 		vap->va_blocksize = dnp->dn_blocksize;
409509bc517SAntonio Huete Jimenez 		vap->va_atime.tv_sec = dnp->dn_atime;
410509bc517SAntonio Huete Jimenez 		vap->va_atime.tv_nsec = dnp->dn_atimensec;
411509bc517SAntonio Huete Jimenez 		vap->va_mtime.tv_sec = dnp->dn_mtime;
412509bc517SAntonio Huete Jimenez 		vap->va_mtime.tv_nsec = dnp->dn_mtimensec;
413509bc517SAntonio Huete Jimenez 		vap->va_ctime.tv_sec = dnp->dn_ctime;
414509bc517SAntonio Huete Jimenez 		vap->va_ctime.tv_nsec = dnp->dn_ctimensec;
415509bc517SAntonio Huete Jimenez 		vap->va_bytes = dnp->dn_size;
416509bc517SAntonio Huete Jimenez 		vap->va_gen = dnp->dn_gen;
417509bc517SAntonio Huete Jimenez 		vap->va_flags = dnp->dn_flags;
418509bc517SAntonio Huete Jimenez 		vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
419509bc517SAntonio Huete Jimenez 		dirfs_node_unlock(dnp);
420509bc517SAntonio Huete Jimenez 	}
421509bc517SAntonio Huete Jimenez 
422509bc517SAntonio Huete Jimenez 	KTR_LOG(dirfs_getattr, dnp, error);
423509bc517SAntonio Huete Jimenez 
424509bc517SAntonio Huete Jimenez 	return 0;
425509bc517SAntonio Huete Jimenez }
426509bc517SAntonio Huete Jimenez 
427509bc517SAntonio Huete Jimenez int
dirfs_setattr(struct vop_setattr_args * ap)428509bc517SAntonio Huete Jimenez dirfs_setattr(struct vop_setattr_args *ap)
429509bc517SAntonio Huete Jimenez {
430509bc517SAntonio Huete Jimenez 	dirfs_mount_t dmp;
431509bc517SAntonio Huete Jimenez 	dirfs_node_t dnp;
432509bc517SAntonio Huete Jimenez 	struct vnode *vp;
433509bc517SAntonio Huete Jimenez 	struct vattr *vap;
434509bc517SAntonio Huete Jimenez 	struct ucred *cred;
435509bc517SAntonio Huete Jimenez 	int error;
436*08905fc5SAntonio Huete Jimenez 	int kflags = 0;
437509bc517SAntonio Huete Jimenez #ifdef KTR
438509bc517SAntonio Huete Jimenez 	const char *msg[6] = {
439509bc517SAntonio Huete Jimenez 		"invalid",
440509bc517SAntonio Huete Jimenez 		"chflags",
441509bc517SAntonio Huete Jimenez 		"chsize",
442509bc517SAntonio Huete Jimenez 		"chown",
443509bc517SAntonio Huete Jimenez 		"chmod",
444509bc517SAntonio Huete Jimenez 		"chtimes"
445509bc517SAntonio Huete Jimenez 	};
446509bc517SAntonio Huete Jimenez #endif
447509bc517SAntonio Huete Jimenez 	int msgno;
448509bc517SAntonio Huete Jimenez 
44926ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
450509bc517SAntonio Huete Jimenez 
451509bc517SAntonio Huete Jimenez 	error = msgno = 0;
452509bc517SAntonio Huete Jimenez 	vp = ap->a_vp;
453509bc517SAntonio Huete Jimenez 	vap = ap->a_vap;
454509bc517SAntonio Huete Jimenez 	cred = ap->a_cred;
455509bc517SAntonio Huete Jimenez 	dnp = VP_TO_NODE(vp);
456509bc517SAntonio Huete Jimenez 	dmp = VFS_TO_DIRFS(vp->v_mount);
457509bc517SAntonio Huete Jimenez 
458509bc517SAntonio Huete Jimenez 	/*
459509bc517SAntonio Huete Jimenez 	 * Check for unsettable attributes.
460509bc517SAntonio Huete Jimenez 	 */
461509bc517SAntonio Huete Jimenez 	if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
462509bc517SAntonio Huete Jimenez 	    (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
463509bc517SAntonio Huete Jimenez 	    (vap->va_blocksize != VNOVAL) || (vap->va_rmajor != VNOVAL) ||
464509bc517SAntonio Huete Jimenez 	    ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
465509bc517SAntonio Huete Jimenez 		msgno = 0;
466509bc517SAntonio Huete Jimenez 		error = EINVAL;
467509bc517SAntonio Huete Jimenez 		goto out;
468509bc517SAntonio Huete Jimenez 	}
469509bc517SAntonio Huete Jimenez 
470509bc517SAntonio Huete Jimenez 	/*
471509bc517SAntonio Huete Jimenez 	 * Change file flags
472509bc517SAntonio Huete Jimenez 	 */
473509bc517SAntonio Huete Jimenez 	if (error == 0 && (vap->va_flags != VNOVAL)) {
474*08905fc5SAntonio Huete Jimenez 		if (vp->v_mount->mnt_flag & MNT_RDONLY) {
475509bc517SAntonio Huete Jimenez 			error = EROFS;
476*08905fc5SAntonio Huete Jimenez 		} else {
477509bc517SAntonio Huete Jimenez 			error = dirfs_node_chflags(dnp, vap->va_flags, cred);
478*08905fc5SAntonio Huete Jimenez 			kflags |= NOTE_ATTRIB;
479*08905fc5SAntonio Huete Jimenez 		}
480509bc517SAntonio Huete Jimenez 		msgno = 1;
481509bc517SAntonio Huete Jimenez 		goto out;
482509bc517SAntonio Huete Jimenez 	}
483509bc517SAntonio Huete Jimenez 
484509bc517SAntonio Huete Jimenez 	/*
485509bc517SAntonio Huete Jimenez 	 * Extend or truncate a file
486509bc517SAntonio Huete Jimenez 	 */
487509bc517SAntonio Huete Jimenez 	if (error == 0 && (vap->va_size != VNOVAL)) {
488*08905fc5SAntonio Huete Jimenez 		if (vp->v_mount->mnt_flag & MNT_RDONLY) {
489509bc517SAntonio Huete Jimenez 			error = EROFS;
490*08905fc5SAntonio Huete Jimenez 		} else {
491*08905fc5SAntonio Huete Jimenez 			if (vap->va_size > dnp->dn_size)
492*08905fc5SAntonio Huete Jimenez 				kflags |= NOTE_WRITE | NOTE_EXTEND;
493509bc517SAntonio Huete Jimenez 			else
494*08905fc5SAntonio Huete Jimenez 				kflags |= NOTE_WRITE;
495509bc517SAntonio Huete Jimenez 			error = dirfs_node_chsize(dnp, vap->va_size);
496*08905fc5SAntonio Huete Jimenez 		}
49726ec059cSAntonio Huete Jimenez 		dbg(9, "dnp size=%jd vap size=%jd\n", dnp->dn_size, vap->va_size);
498509bc517SAntonio Huete Jimenez 		msgno = 2;
499509bc517SAntonio Huete Jimenez 		goto out;
500509bc517SAntonio Huete Jimenez 	}
501509bc517SAntonio Huete Jimenez 
502509bc517SAntonio Huete Jimenez 	/*
503509bc517SAntonio Huete Jimenez 	 * Change file owner or group
504509bc517SAntonio Huete Jimenez 	 */
505509bc517SAntonio Huete Jimenez 	if (error == 0 && (vap->va_uid != (uid_t)VNOVAL ||
506509bc517SAntonio Huete Jimenez 		vap->va_gid != (gid_t)VNOVAL)) {
507509bc517SAntonio Huete Jimenez 		if (vp->v_mount->mnt_flag & MNT_RDONLY) {
508509bc517SAntonio Huete Jimenez 			error = EROFS;
509509bc517SAntonio Huete Jimenez 		} else {
510509bc517SAntonio Huete Jimenez 			mode_t cur_mode = dnp->dn_mode;
511509bc517SAntonio Huete Jimenez 			uid_t cur_uid = dnp->dn_uid;
512509bc517SAntonio Huete Jimenez 			gid_t cur_gid = dnp->dn_gid;
513509bc517SAntonio Huete Jimenez 
514509bc517SAntonio Huete Jimenez 			error = vop_helper_chown(ap->a_vp, vap->va_uid,
515509bc517SAntonio Huete Jimenez 						 vap->va_gid, ap->a_cred,
516509bc517SAntonio Huete Jimenez 						 &cur_uid, &cur_gid, &cur_mode);
517509bc517SAntonio Huete Jimenez 			if (error == 0 &&
518509bc517SAntonio Huete Jimenez 			    (cur_mode != dnp->dn_mode ||
519509bc517SAntonio Huete Jimenez 			     cur_uid != dnp->dn_uid ||
520509bc517SAntonio Huete Jimenez 			     cur_gid != dnp->dn_gid)) {
521509bc517SAntonio Huete Jimenez 				error = dirfs_node_chown(dmp, dnp, cur_uid,
522509bc517SAntonio Huete Jimenez 							 cur_gid, cur_mode);
523*08905fc5SAntonio Huete Jimenez 				kflags |= NOTE_ATTRIB;
524509bc517SAntonio Huete Jimenez 			}
525509bc517SAntonio Huete Jimenez 		}
526509bc517SAntonio Huete Jimenez 		msgno = 3;
527509bc517SAntonio Huete Jimenez 		goto out;
528509bc517SAntonio Huete Jimenez 	}
529509bc517SAntonio Huete Jimenez 
530509bc517SAntonio Huete Jimenez 	/*
531509bc517SAntonio Huete Jimenez 	 * Change file mode
532509bc517SAntonio Huete Jimenez 	 */
533509bc517SAntonio Huete Jimenez 	if (error == 0 && (vap->va_mode != (mode_t)VNOVAL)) {
534509bc517SAntonio Huete Jimenez 		if (vp->v_mount->mnt_flag & MNT_RDONLY) {
535509bc517SAntonio Huete Jimenez 			error = EROFS;
536509bc517SAntonio Huete Jimenez 		} else {
537509bc517SAntonio Huete Jimenez 			mode_t cur_mode = dnp->dn_mode;
538509bc517SAntonio Huete Jimenez 			uid_t cur_uid = dnp->dn_uid;
539509bc517SAntonio Huete Jimenez 			gid_t cur_gid = dnp->dn_gid;
540509bc517SAntonio Huete Jimenez 
541509bc517SAntonio Huete Jimenez 			error = vop_helper_chmod(ap->a_vp, vap->va_mode,
542509bc517SAntonio Huete Jimenez 						 ap->a_cred,
543509bc517SAntonio Huete Jimenez 						 cur_uid, cur_gid, &cur_mode);
544509bc517SAntonio Huete Jimenez 			if (error == 0 && cur_mode != dnp->dn_mode) {
545509bc517SAntonio Huete Jimenez 				error = dirfs_node_chmod(dmp, dnp, cur_mode);
546*08905fc5SAntonio Huete Jimenez 				kflags |= NOTE_ATTRIB;
547509bc517SAntonio Huete Jimenez 			}
548509bc517SAntonio Huete Jimenez 		}
549509bc517SAntonio Huete Jimenez 		msgno = 4;
550509bc517SAntonio Huete Jimenez 		goto out;
551509bc517SAntonio Huete Jimenez 	}
552509bc517SAntonio Huete Jimenez 
553509bc517SAntonio Huete Jimenez 	/*
554509bc517SAntonio Huete Jimenez 	 * Change file times
555509bc517SAntonio Huete Jimenez 	 */
556509bc517SAntonio Huete Jimenez 	if (error == 0 && ((vap->va_atime.tv_sec != VNOVAL &&
557509bc517SAntonio Huete Jimenez 		vap->va_atime.tv_nsec != VNOVAL) ||
558509bc517SAntonio Huete Jimenez 		(vap->va_mtime.tv_sec != VNOVAL &&
559509bc517SAntonio Huete Jimenez 		vap->va_mtime.tv_nsec != VNOVAL) )) {
560*08905fc5SAntonio Huete Jimenez 		if (vp->v_mount->mnt_flag & MNT_RDONLY) {
561509bc517SAntonio Huete Jimenez 			error = EROFS;
562*08905fc5SAntonio Huete Jimenez 		} else {
563509bc517SAntonio Huete Jimenez 			error = dirfs_node_chtimes(dnp);
564*08905fc5SAntonio Huete Jimenez 			kflags |= NOTE_ATTRIB;
565*08905fc5SAntonio Huete Jimenez 		}
566509bc517SAntonio Huete Jimenez 		msgno = 5;
567509bc517SAntonio Huete Jimenez 		goto out;
568509bc517SAntonio Huete Jimenez 
569509bc517SAntonio Huete Jimenez 	}
570509bc517SAntonio Huete Jimenez out:
571509bc517SAntonio Huete Jimenez 	KTR_LOG(dirfs_setattr, dnp, msg[msgno], error);
572509bc517SAntonio Huete Jimenez 
573*08905fc5SAntonio Huete Jimenez 	dirfs_knote(vp, kflags);
574*08905fc5SAntonio Huete Jimenez 
575509bc517SAntonio Huete Jimenez 	return error;
576509bc517SAntonio Huete Jimenez }
577509bc517SAntonio Huete Jimenez 
578509bc517SAntonio Huete Jimenez static int
dirfs_fsync(struct vop_fsync_args * ap)579509bc517SAntonio Huete Jimenez dirfs_fsync(struct vop_fsync_args *ap)
580509bc517SAntonio Huete Jimenez {
581509bc517SAntonio Huete Jimenez 	dirfs_node_t dnp = VP_TO_NODE(ap->a_vp);
582509bc517SAntonio Huete Jimenez 	int error = 0;
583509bc517SAntonio Huete Jimenez 
58426ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
585509bc517SAntonio Huete Jimenez 
586509bc517SAntonio Huete Jimenez 	vfsync(ap->a_vp, ap->a_waitfor, 1, NULL, NULL);
587509bc517SAntonio Huete Jimenez 
588509bc517SAntonio Huete Jimenez 	if (dnp->dn_fd != DIRFS_NOFD) {
589509bc517SAntonio Huete Jimenez 		if (fsync(dnp->dn_fd) == -1)
590509bc517SAntonio Huete Jimenez 			error = fsync(dnp->dn_fd);
591509bc517SAntonio Huete Jimenez 	}
592509bc517SAntonio Huete Jimenez 
593509bc517SAntonio Huete Jimenez 	KTR_LOG(dirfs_fsync, dnp, error);
594509bc517SAntonio Huete Jimenez 
595509bc517SAntonio Huete Jimenez 	return 0;
596509bc517SAntonio Huete Jimenez }
597509bc517SAntonio Huete Jimenez 
598509bc517SAntonio Huete Jimenez static int
dirfs_read(struct vop_read_args * ap)599509bc517SAntonio Huete Jimenez dirfs_read(struct vop_read_args *ap)
600509bc517SAntonio Huete Jimenez {
601509bc517SAntonio Huete Jimenez 	struct buf *bp;
602509bc517SAntonio Huete Jimenez 	struct vnode *vp = ap->a_vp;
603509bc517SAntonio Huete Jimenez 	struct uio *uio = ap->a_uio;
604509bc517SAntonio Huete Jimenez 	dirfs_node_t dnp;
605509bc517SAntonio Huete Jimenez 	off_t base_offset;
606509bc517SAntonio Huete Jimenez 	size_t offset;
607509bc517SAntonio Huete Jimenez 	size_t len;
608509bc517SAntonio Huete Jimenez 	int error;
609509bc517SAntonio Huete Jimenez 
61026ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
611509bc517SAntonio Huete Jimenez 
612509bc517SAntonio Huete Jimenez 	error = 0;
613509bc517SAntonio Huete Jimenez 	if (uio->uio_resid == 0) {
61426ec059cSAntonio Huete Jimenez 		dbg(9, "zero len uio->uio_resid\n");
615509bc517SAntonio Huete Jimenez 		return error;
616509bc517SAntonio Huete Jimenez 	}
617509bc517SAntonio Huete Jimenez 
618509bc517SAntonio Huete Jimenez 	dnp = VP_TO_NODE(vp);
619509bc517SAntonio Huete Jimenez 
620509bc517SAntonio Huete Jimenez 	if (uio->uio_offset < 0)
621509bc517SAntonio Huete Jimenez 		return (EINVAL);
622509bc517SAntonio Huete Jimenez 	if (vp->v_type != VREG)
623509bc517SAntonio Huete Jimenez 		return (EINVAL);
624509bc517SAntonio Huete Jimenez 
625509bc517SAntonio Huete Jimenez 	while (uio->uio_resid > 0 && uio->uio_offset < dnp->dn_size) {
626509bc517SAntonio Huete Jimenez 		/*
627509bc517SAntonio Huete Jimenez 		 * Use buffer cache I/O (via dirfs_strategy)
628509bc517SAntonio Huete Jimenez 		 */
629509bc517SAntonio Huete Jimenez 		offset = (size_t)uio->uio_offset & BMASK;
630509bc517SAntonio Huete Jimenez 		base_offset = (off_t)uio->uio_offset - offset;
631509bc517SAntonio Huete Jimenez 		bp = getcacheblk(vp, base_offset, BSIZE, 0);
632509bc517SAntonio Huete Jimenez 		if (bp == NULL) {
633509bc517SAntonio Huete Jimenez 			lwkt_gettoken(&vp->v_mount->mnt_token);
634509bc517SAntonio Huete Jimenez 			error = bread(vp, base_offset, BSIZE, &bp);
635509bc517SAntonio Huete Jimenez 			if (error) {
636509bc517SAntonio Huete Jimenez 				brelse(bp);
637509bc517SAntonio Huete Jimenez 				lwkt_reltoken(&vp->v_mount->mnt_token);
63826ec059cSAntonio Huete Jimenez 				dbg(9, "dirfs_read bread error %d\n", error);
639509bc517SAntonio Huete Jimenez 				break;
640509bc517SAntonio Huete Jimenez 			}
641509bc517SAntonio Huete Jimenez 			lwkt_reltoken(&vp->v_mount->mnt_token);
642509bc517SAntonio Huete Jimenez 		}
643509bc517SAntonio Huete Jimenez 
644509bc517SAntonio Huete Jimenez 		/*
645509bc517SAntonio Huete Jimenez 		 * Figure out how many bytes we can actually copy this loop.
646509bc517SAntonio Huete Jimenez 		 */
647509bc517SAntonio Huete Jimenez 		len = BSIZE - offset;
648509bc517SAntonio Huete Jimenez 		if (len > uio->uio_resid)
649509bc517SAntonio Huete Jimenez 			len = uio->uio_resid;
650509bc517SAntonio Huete Jimenez 		if (len > dnp->dn_size - uio->uio_offset)
651509bc517SAntonio Huete Jimenez 			len = (size_t)(dnp->dn_size - uio->uio_offset);
652509bc517SAntonio Huete Jimenez 
653509bc517SAntonio Huete Jimenez 		error = uiomovebp(bp, (char *)bp->b_data + offset, len, uio);
654509bc517SAntonio Huete Jimenez 		bqrelse(bp);
655509bc517SAntonio Huete Jimenez 		if (error) {
65626ec059cSAntonio Huete Jimenez 			dbg(9, "dirfs_read uiomove error %d\n", error);
657509bc517SAntonio Huete Jimenez 			break;
658509bc517SAntonio Huete Jimenez 		}
659509bc517SAntonio Huete Jimenez 	}
660509bc517SAntonio Huete Jimenez 
661509bc517SAntonio Huete Jimenez 	KTR_LOG(dirfs_read, dnp, dnp->dn_size, error);
662509bc517SAntonio Huete Jimenez 
663509bc517SAntonio Huete Jimenez 	return(error);
664509bc517SAntonio Huete Jimenez }
665509bc517SAntonio Huete Jimenez 
666509bc517SAntonio Huete Jimenez static int
dirfs_write(struct vop_write_args * ap)667509bc517SAntonio Huete Jimenez dirfs_write (struct vop_write_args *ap)
668509bc517SAntonio Huete Jimenez {
669509bc517SAntonio Huete Jimenez 	dirfs_node_t dnp;
670509bc517SAntonio Huete Jimenez 	dirfs_mount_t dmp;
671509bc517SAntonio Huete Jimenez 	struct buf *bp;
672509bc517SAntonio Huete Jimenez 	struct vnode *vp = ap->a_vp;
673509bc517SAntonio Huete Jimenez 	struct uio *uio = ap->a_uio;
674509bc517SAntonio Huete Jimenez 	struct thread *td = uio->uio_td;
675509bc517SAntonio Huete Jimenez 	int error;
676*08905fc5SAntonio Huete Jimenez 	int kflags = 0;
677509bc517SAntonio Huete Jimenez 	off_t osize;
678509bc517SAntonio Huete Jimenez 	off_t nsize;
679509bc517SAntonio Huete Jimenez 	off_t base_offset;
680509bc517SAntonio Huete Jimenez 	size_t offset;
681509bc517SAntonio Huete Jimenez 	size_t len;
682509bc517SAntonio Huete Jimenez 	struct rlimit limit;
683509bc517SAntonio Huete Jimenez 
68426ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
685509bc517SAntonio Huete Jimenez 
686509bc517SAntonio Huete Jimenez 	error = 0;
687509bc517SAntonio Huete Jimenez 	if (uio->uio_resid == 0) {
68826ec059cSAntonio Huete Jimenez 		dbg(9, "zero-length uio->uio_resid\n");
689509bc517SAntonio Huete Jimenez 		return error;
690509bc517SAntonio Huete Jimenez 	}
691509bc517SAntonio Huete Jimenez 
692509bc517SAntonio Huete Jimenez 	dnp = VP_TO_NODE(vp);
693509bc517SAntonio Huete Jimenez 	dmp = VFS_TO_DIRFS(vp->v_mount);
694509bc517SAntonio Huete Jimenez 
695509bc517SAntonio Huete Jimenez 	if (vp->v_type != VREG)
696509bc517SAntonio Huete Jimenez 		return (EINVAL);
697509bc517SAntonio Huete Jimenez 
698509bc517SAntonio Huete Jimenez 	if (vp->v_type == VREG && td != NULL) {
699509bc517SAntonio Huete Jimenez 		error = kern_getrlimit(RLIMIT_FSIZE, &limit);
700509bc517SAntonio Huete Jimenez 		if (error != 0) {
70126ec059cSAntonio Huete Jimenez 			dbg(9, "rlimit failure\n");
702509bc517SAntonio Huete Jimenez 			return error;
703509bc517SAntonio Huete Jimenez 		}
704509bc517SAntonio Huete Jimenez 		if (uio->uio_offset + uio->uio_resid > limit.rlim_cur) {
70526ec059cSAntonio Huete Jimenez 			dbg(9, "file too big\n");
706509bc517SAntonio Huete Jimenez 			ksignal(td->td_proc, SIGXFSZ);
707509bc517SAntonio Huete Jimenez 			return (EFBIG);
708509bc517SAntonio Huete Jimenez 		}
709509bc517SAntonio Huete Jimenez 	}
710509bc517SAntonio Huete Jimenez 
711509bc517SAntonio Huete Jimenez 	if (ap->a_ioflag & IO_APPEND)
712509bc517SAntonio Huete Jimenez 		uio->uio_offset = dnp->dn_size;
713509bc517SAntonio Huete Jimenez 
714509bc517SAntonio Huete Jimenez 	/*
715509bc517SAntonio Huete Jimenez 	 * buffer cache operations may be deferred, make sure
716509bc517SAntonio Huete Jimenez 	 * the file is correctly sized right now.
717509bc517SAntonio Huete Jimenez 	 */
718509bc517SAntonio Huete Jimenez 	osize = dnp->dn_size;
719509bc517SAntonio Huete Jimenez 	nsize = uio->uio_offset + uio->uio_resid;
720509bc517SAntonio Huete Jimenez 	if (nsize > osize && uio->uio_resid) {
721509bc517SAntonio Huete Jimenez 		KKASSERT(dnp->dn_fd >= 0);
722509bc517SAntonio Huete Jimenez 		dnp->dn_size = nsize;
723509bc517SAntonio Huete Jimenez 		ftruncate(dnp->dn_fd, nsize);
724509bc517SAntonio Huete Jimenez 		nvextendbuf(vp, osize, nsize,
725509bc517SAntonio Huete Jimenez 			    BSIZE, BSIZE, -1, -1, 0);
726*08905fc5SAntonio Huete Jimenez 		kflags |= NOTE_EXTEND;
727509bc517SAntonio Huete Jimenez 	} /* else nsize = osize; NOT USED */
728509bc517SAntonio Huete Jimenez 
729509bc517SAntonio Huete Jimenez 	while (uio->uio_resid > 0) {
730509bc517SAntonio Huete Jimenez 		/*
731509bc517SAntonio Huete Jimenez 		 * Use buffer cache I/O (via dirfs_strategy)
732509bc517SAntonio Huete Jimenez 		 */
733509bc517SAntonio Huete Jimenez 		offset = (size_t)uio->uio_offset & BMASK;
734509bc517SAntonio Huete Jimenez 		base_offset = (off_t)uio->uio_offset - offset;
735509bc517SAntonio Huete Jimenez 		len = BSIZE - offset;
736509bc517SAntonio Huete Jimenez 
737509bc517SAntonio Huete Jimenez 		if (len > uio->uio_resid)
738509bc517SAntonio Huete Jimenez 			len = uio->uio_resid;
739509bc517SAntonio Huete Jimenez 
740509bc517SAntonio Huete Jimenez 		error = bread(vp, base_offset, BSIZE, &bp);
741509bc517SAntonio Huete Jimenez 		error = uiomovebp(bp, (char *)bp->b_data + offset, len, uio);
742509bc517SAntonio Huete Jimenez 		if (error) {
743509bc517SAntonio Huete Jimenez 			brelse(bp);
74426ec059cSAntonio Huete Jimenez 			dbg(9, "WRITE uiomove failed\n");
745509bc517SAntonio Huete Jimenez 			break;
746509bc517SAntonio Huete Jimenez 		}
747*08905fc5SAntonio Huete Jimenez 		kflags |= NOTE_WRITE;
748509bc517SAntonio Huete Jimenez 
74926ec059cSAntonio Huete Jimenez 		dbg(9, "WRITE dn_size=%jd uio_offset=%jd uio_resid=%jd base_offset=%jd\n",
75026ec059cSAntonio Huete Jimenez 		    dnp->dn_size, uio->uio_offset, uio->uio_resid, base_offset);
751509bc517SAntonio Huete Jimenez 
752509bc517SAntonio Huete Jimenez 		if (ap->a_ioflag & IO_SYNC)
753509bc517SAntonio Huete Jimenez 			bwrite(bp);
754509bc517SAntonio Huete Jimenez 		else
755509bc517SAntonio Huete Jimenez 			bdwrite(bp);
756509bc517SAntonio Huete Jimenez 	}
757509bc517SAntonio Huete Jimenez 
758509bc517SAntonio Huete Jimenez 	KTR_LOG(dirfs_write, dnp, base_offset, uio->uio_resid,
759509bc517SAntonio Huete Jimenez 	    dnp->dn_size, error);
760509bc517SAntonio Huete Jimenez 
761*08905fc5SAntonio Huete Jimenez 	if (kflags)
762*08905fc5SAntonio Huete Jimenez 		dirfs_knote(vp, kflags);
763509bc517SAntonio Huete Jimenez 	return error;
764509bc517SAntonio Huete Jimenez }
765509bc517SAntonio Huete Jimenez 
766509bc517SAntonio Huete Jimenez static int
dirfs_advlock(struct vop_advlock_args * ap)767509bc517SAntonio Huete Jimenez dirfs_advlock (struct vop_advlock_args *ap)
768509bc517SAntonio Huete Jimenez {
769509bc517SAntonio Huete Jimenez 	struct vnode *vp = ap->a_vp;
770509bc517SAntonio Huete Jimenez 	dirfs_node_t dnp = VP_TO_NODE(vp);
771509bc517SAntonio Huete Jimenez 
77226ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
773509bc517SAntonio Huete Jimenez 
774509bc517SAntonio Huete Jimenez 	return (lf_advlock(ap, &dnp->dn_advlock, dnp->dn_size));
775509bc517SAntonio Huete Jimenez }
776509bc517SAntonio Huete Jimenez 
777509bc517SAntonio Huete Jimenez static int
dirfs_strategy(struct vop_strategy_args * ap)778509bc517SAntonio Huete Jimenez dirfs_strategy(struct vop_strategy_args *ap)
779509bc517SAntonio Huete Jimenez {
780509bc517SAntonio Huete Jimenez 	dirfs_node_t dnp;
781509bc517SAntonio Huete Jimenez 	dirfs_mount_t dmp;
782509bc517SAntonio Huete Jimenez 	struct bio *bio = ap->a_bio;
783509bc517SAntonio Huete Jimenez 	struct buf *bp = bio->bio_buf;
784509bc517SAntonio Huete Jimenez 	struct vnode *vp = ap->a_vp;
785509bc517SAntonio Huete Jimenez 	int error;
786509bc517SAntonio Huete Jimenez 	size_t iosize;
787509bc517SAntonio Huete Jimenez 	char *tmp;
788509bc517SAntonio Huete Jimenez 	char *pathfree;
789509bc517SAntonio Huete Jimenez 
79026ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
791509bc517SAntonio Huete Jimenez 
792509bc517SAntonio Huete Jimenez 	dnp = VP_TO_NODE(vp);
793509bc517SAntonio Huete Jimenez 	dmp = VFS_TO_DIRFS(vp->v_mount);
794509bc517SAntonio Huete Jimenez 
795509bc517SAntonio Huete Jimenez 	error = 0;
796509bc517SAntonio Huete Jimenez 
797509bc517SAntonio Huete Jimenez 	if (vp->v_type != VREG)  {
79826ec059cSAntonio Huete Jimenez 		dbg(9, "not VREG\n");
799509bc517SAntonio Huete Jimenez 		bp->b_resid = bp->b_bcount;
800509bc517SAntonio Huete Jimenez 		bp->b_flags |= B_ERROR | B_INVAL;
801509bc517SAntonio Huete Jimenez 		bp->b_error = EINVAL;
802509bc517SAntonio Huete Jimenez 		biodone(bio);
803509bc517SAntonio Huete Jimenez 		return(0);
804509bc517SAntonio Huete Jimenez 	}
805509bc517SAntonio Huete Jimenez 
806509bc517SAntonio Huete Jimenez 	if (dnp->dn_fd == DIRFS_NOFD) {
807509bc517SAntonio Huete Jimenez 		print_backtrace(-1);
808509bc517SAntonio Huete Jimenez 		panic("Meh, no fd to write to. dnp=%p\n", dnp);
809509bc517SAntonio Huete Jimenez 	}
810509bc517SAntonio Huete Jimenez 
811509bc517SAntonio Huete Jimenez 	if (bio->bio_offset + bp->b_bcount > dnp->dn_size)
812509bc517SAntonio Huete Jimenez 		iosize = dnp->dn_size - bio->bio_offset;
813509bc517SAntonio Huete Jimenez 	else
814509bc517SAntonio Huete Jimenez 		iosize = bp->b_bcount;
815509bc517SAntonio Huete Jimenez 	KKASSERT((ssize_t)iosize >= 0);
816509bc517SAntonio Huete Jimenez 
817509bc517SAntonio Huete Jimenez 	switch (bp->b_cmd) {
818509bc517SAntonio Huete Jimenez 	case BUF_CMD_WRITE:
819509bc517SAntonio Huete Jimenez 		error = pwrite(dnp->dn_fd, bp->b_data, iosize, bio->bio_offset);
820509bc517SAntonio Huete Jimenez 		break;
821509bc517SAntonio Huete Jimenez 	case BUF_CMD_READ:
822509bc517SAntonio Huete Jimenez 		error = pread(dnp->dn_fd, bp->b_data, iosize, bio->bio_offset);
823509bc517SAntonio Huete Jimenez 		break;
824509bc517SAntonio Huete Jimenez 	default:
825509bc517SAntonio Huete Jimenez 		bp->b_error = error = EINVAL;
826509bc517SAntonio Huete Jimenez 		bp->b_flags |= B_ERROR;
827509bc517SAntonio Huete Jimenez 		break;
828509bc517SAntonio Huete Jimenez 	}
829509bc517SAntonio Huete Jimenez 
830509bc517SAntonio Huete Jimenez 	if (error >= 0 && error < bp->b_bcount)
831509bc517SAntonio Huete Jimenez 		bzero(bp->b_data + error, bp->b_bcount - error);
832509bc517SAntonio Huete Jimenez 
833509bc517SAntonio Huete Jimenez 	if (error < 0 && errno != EINTR) {
83426ec059cSAntonio Huete Jimenez 		dbg(9, "error=%d dnp=%p dnp->dn_fd=%d "
835509bc517SAntonio Huete Jimenez 		    "bio->bio_offset=%ld bcount=%d resid=%d iosize=%zd\n",
836509bc517SAntonio Huete Jimenez 		    errno, dnp, dnp->dn_fd, bio->bio_offset, bp->b_bcount,
837509bc517SAntonio Huete Jimenez 		    bp->b_resid, iosize);
838509bc517SAntonio Huete Jimenez 		bp->b_error = errno;
839509bc517SAntonio Huete Jimenez 		bp->b_resid = bp->b_bcount;
840509bc517SAntonio Huete Jimenez 		bp->b_flags |= B_ERROR;
841509bc517SAntonio Huete Jimenez 	} else {
842509bc517SAntonio Huete Jimenez 		tmp = dirfs_node_absolute_path(dmp, dnp, &pathfree);
843509bc517SAntonio Huete Jimenez 		dirfs_node_stat(DIRFS_NOFD, tmp, dnp);
844509bc517SAntonio Huete Jimenez 		dirfs_dropfd(dmp, NULL, pathfree);
845509bc517SAntonio Huete Jimenez 	}
846509bc517SAntonio Huete Jimenez 
847509bc517SAntonio Huete Jimenez 	KTR_LOG(dirfs_strategy, dnp, dnp->dn_size, iosize, bp->b_cmd,
848509bc517SAntonio Huete Jimenez 	    bp->b_error, bp->b_resid, bio->bio_offset, error);
849509bc517SAntonio Huete Jimenez 
850509bc517SAntonio Huete Jimenez 	biodone(bio);
851509bc517SAntonio Huete Jimenez 
852509bc517SAntonio Huete Jimenez 	return 0;
853509bc517SAntonio Huete Jimenez }
854509bc517SAntonio Huete Jimenez 
855509bc517SAntonio Huete Jimenez static int
dirfs_bmap(struct vop_bmap_args * ap)856509bc517SAntonio Huete Jimenez dirfs_bmap(struct vop_bmap_args *ap)
857509bc517SAntonio Huete Jimenez {
85826ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
859509bc517SAntonio Huete Jimenez 
860509bc517SAntonio Huete Jimenez 	if (ap->a_doffsetp != NULL)
861509bc517SAntonio Huete Jimenez 		*ap->a_doffsetp = ap->a_loffset;
862509bc517SAntonio Huete Jimenez 	if (ap->a_runp != NULL)
863509bc517SAntonio Huete Jimenez 		*ap->a_runp = 0;
864509bc517SAntonio Huete Jimenez 	if (ap->a_runb != NULL)
865509bc517SAntonio Huete Jimenez 		*ap->a_runb = 0;
866509bc517SAntonio Huete Jimenez 
867509bc517SAntonio Huete Jimenez 	return 0;
868509bc517SAntonio Huete Jimenez }
869509bc517SAntonio Huete Jimenez 
870509bc517SAntonio Huete Jimenez static int
dirfs_nremove(struct vop_nremove_args * ap)871509bc517SAntonio Huete Jimenez dirfs_nremove(struct vop_nremove_args *ap)
872509bc517SAntonio Huete Jimenez {
873509bc517SAntonio Huete Jimenez 	dirfs_node_t dnp, pdnp;
874509bc517SAntonio Huete Jimenez 	dirfs_node_t pathnp;
875509bc517SAntonio Huete Jimenez 	dirfs_mount_t dmp;
876509bc517SAntonio Huete Jimenez 	struct vnode *dvp;
877509bc517SAntonio Huete Jimenez 	struct nchandle *nch;
878509bc517SAntonio Huete Jimenez 	struct namecache *ncp;
879509bc517SAntonio Huete Jimenez 	struct mount *mp;
880509bc517SAntonio Huete Jimenez 	struct vnode *vp;
881509bc517SAntonio Huete Jimenez 	int error;
882509bc517SAntonio Huete Jimenez 	char *tmp;
883509bc517SAntonio Huete Jimenez 	char *pathfree;
88426ec059cSAntonio Huete Jimenez 
88526ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
886509bc517SAntonio Huete Jimenez 
887509bc517SAntonio Huete Jimenez 	error = 0;
888509bc517SAntonio Huete Jimenez 	tmp = NULL;
889509bc517SAntonio Huete Jimenez 	vp = NULL;
890509bc517SAntonio Huete Jimenez 	dvp = ap->a_dvp;
891509bc517SAntonio Huete Jimenez 	nch = ap->a_nch;
892509bc517SAntonio Huete Jimenez 	ncp = nch->ncp;
893509bc517SAntonio Huete Jimenez 
894509bc517SAntonio Huete Jimenez 	mp = dvp->v_mount;
895509bc517SAntonio Huete Jimenez 	dmp = VFS_TO_DIRFS(mp);
896509bc517SAntonio Huete Jimenez 
897509bc517SAntonio Huete Jimenez 	lwkt_gettoken(&mp->mnt_token);
898509bc517SAntonio Huete Jimenez 	cache_vget(nch, ap->a_cred, LK_SHARED, &vp);
899509bc517SAntonio Huete Jimenez 	vn_unlock(vp);
900509bc517SAntonio Huete Jimenez 
901509bc517SAntonio Huete Jimenez 	pdnp = VP_TO_NODE(dvp);
902509bc517SAntonio Huete Jimenez 	dnp = VP_TO_NODE(vp);
903509bc517SAntonio Huete Jimenez 
904509bc517SAntonio Huete Jimenez 	if (vp->v_type == VDIR) {
905509bc517SAntonio Huete Jimenez 		error = EISDIR;
906509bc517SAntonio Huete Jimenez 	} else {
907509bc517SAntonio Huete Jimenez 		pathnp = dirfs_findfd(dmp, dnp, &tmp, &pathfree);
908509bc517SAntonio Huete Jimenez 		dirfs_node_lock(pdnp);
909509bc517SAntonio Huete Jimenez 		error = unlinkat(pathnp->dn_fd, tmp, 0);
910509bc517SAntonio Huete Jimenez 		if (error == 0) {
911509bc517SAntonio Huete Jimenez 			cache_unlink(nch);
912*08905fc5SAntonio Huete Jimenez 			dirfs_knote(vp, NOTE_DELETE);
913509bc517SAntonio Huete Jimenez 			dirfs_node_setpassive(dmp, dnp, 0);
914509bc517SAntonio Huete Jimenez 			if (dnp->dn_parent) {
915509bc517SAntonio Huete Jimenez 				dirfs_node_drop(dmp, dnp->dn_parent);
916509bc517SAntonio Huete Jimenez 				dnp->dn_parent = NULL;
917509bc517SAntonio Huete Jimenez 			}
918509bc517SAntonio Huete Jimenez 		} else {
919509bc517SAntonio Huete Jimenez 			error = errno;
920509bc517SAntonio Huete Jimenez 		}
921509bc517SAntonio Huete Jimenez 		dirfs_node_unlock(pdnp);
922509bc517SAntonio Huete Jimenez 		dirfs_dropfd(dmp, pathnp, pathfree);
923509bc517SAntonio Huete Jimenez 	}
924*08905fc5SAntonio Huete Jimenez 	dirfs_knote(dvp, NOTE_WRITE);
925509bc517SAntonio Huete Jimenez 	vrele(vp);
926509bc517SAntonio Huete Jimenez 	lwkt_reltoken(&mp->mnt_token);
927509bc517SAntonio Huete Jimenez 
928509bc517SAntonio Huete Jimenez 	KTR_LOG(dirfs_nremove, dnp, pdnp, error);
929509bc517SAntonio Huete Jimenez 
930509bc517SAntonio Huete Jimenez 	return error;
931509bc517SAntonio Huete Jimenez }
932509bc517SAntonio Huete Jimenez 
933509bc517SAntonio Huete Jimenez static int
dirfs_nlink(struct vop_nlink_args * ap)934509bc517SAntonio Huete Jimenez dirfs_nlink(struct vop_nlink_args *ap)
935509bc517SAntonio Huete Jimenez {
93626ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
937509bc517SAntonio Huete Jimenez 
938509bc517SAntonio Huete Jimenez 	KTR_LOG(dirfs_unsupported, __func__);
939509bc517SAntonio Huete Jimenez 
940509bc517SAntonio Huete Jimenez 	return EOPNOTSUPP;
941509bc517SAntonio Huete Jimenez }
942509bc517SAntonio Huete Jimenez 
943509bc517SAntonio Huete Jimenez static int
dirfs_nrename(struct vop_nrename_args * ap)944509bc517SAntonio Huete Jimenez dirfs_nrename(struct vop_nrename_args *ap)
945509bc517SAntonio Huete Jimenez {
946509bc517SAntonio Huete Jimenez 	dirfs_node_t dnp, fdnp, tdnp;
947509bc517SAntonio Huete Jimenez 	dirfs_mount_t dmp;
948509bc517SAntonio Huete Jimenez 	struct namecache *fncp, *tncp;
949509bc517SAntonio Huete Jimenez 	struct vnode *fdvp, *tdvp, *vp;
950509bc517SAntonio Huete Jimenez 	struct mount *mp;
951509bc517SAntonio Huete Jimenez 	char *fpath, *fpathfree;
952509bc517SAntonio Huete Jimenez 	char *tpath, *tpathfree;
953509bc517SAntonio Huete Jimenez 	int error;
954509bc517SAntonio Huete Jimenez 
95526ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
956509bc517SAntonio Huete Jimenez 
957509bc517SAntonio Huete Jimenez 	error = 0;
958509bc517SAntonio Huete Jimenez 	fdvp = ap->a_fdvp;
959509bc517SAntonio Huete Jimenez 	tdvp = ap->a_tdvp;
960509bc517SAntonio Huete Jimenez 	fncp = ap->a_fnch->ncp;
961509bc517SAntonio Huete Jimenez 	tncp = ap->a_tnch->ncp;
962509bc517SAntonio Huete Jimenez 	mp = fdvp->v_mount;
963509bc517SAntonio Huete Jimenez 	dmp = VFS_TO_DIRFS(mp);
964509bc517SAntonio Huete Jimenez 	fdnp = VP_TO_NODE(fdvp);
965509bc517SAntonio Huete Jimenez 	tdnp = VP_TO_NODE(tdvp);
966509bc517SAntonio Huete Jimenez 
96726ec059cSAntonio Huete Jimenez 	dbg(9, "fdnp=%p tdnp=%p from=%s to=%s\n", fdnp, tdnp, fncp->nc_name,
968509bc517SAntonio Huete Jimenez 	    tncp->nc_name);
969509bc517SAntonio Huete Jimenez 
970509bc517SAntonio Huete Jimenez 	if (fdvp->v_mount != tdvp->v_mount)
971509bc517SAntonio Huete Jimenez 		return(EXDEV);
972509bc517SAntonio Huete Jimenez 	if (fdvp->v_mount != fncp->nc_vp->v_mount)
973509bc517SAntonio Huete Jimenez 		return(EXDEV);
974509bc517SAntonio Huete Jimenez 	if (fdvp->v_mount->mnt_flag & MNT_RDONLY)
975509bc517SAntonio Huete Jimenez 		return (EROFS);
976509bc517SAntonio Huete Jimenez 
977509bc517SAntonio Huete Jimenez 	tpath = dirfs_node_absolute_path_plus(dmp, tdnp,
978509bc517SAntonio Huete Jimenez 					      tncp->nc_name, &tpathfree);
979509bc517SAntonio Huete Jimenez 	fpath = dirfs_node_absolute_path_plus(dmp, fdnp,
980509bc517SAntonio Huete Jimenez 					      fncp->nc_name, &fpathfree);
981509bc517SAntonio Huete Jimenez 	error = rename(fpath, tpath);
982509bc517SAntonio Huete Jimenez 	if (error < 0)
983509bc517SAntonio Huete Jimenez 		error = errno;
984509bc517SAntonio Huete Jimenez 	if (error == 0) {
985509bc517SAntonio Huete Jimenez 		vp = fncp->nc_vp;	/* file being renamed */
986509bc517SAntonio Huete Jimenez 		dnp = VP_TO_NODE(vp);
987509bc517SAntonio Huete Jimenez 		dirfs_node_setname(dnp, tncp->nc_name, tncp->nc_nlen);
988*08905fc5SAntonio Huete Jimenez 		dirfs_knote(fdvp, NOTE_RENAME);
989509bc517SAntonio Huete Jimenez 		/*
990509bc517SAntonio Huete Jimenez 		 * We have to mark the target file that was replaced by
991509bc517SAntonio Huete Jimenez 		 * the rename as having been unlinked.
992509bc517SAntonio Huete Jimenez 		 */
993509bc517SAntonio Huete Jimenez 		vp = tncp->nc_vp;
994509bc517SAntonio Huete Jimenez 		if (vp) {
99526ec059cSAntonio Huete Jimenez 			dbg(9, "RENAME2\n");
996509bc517SAntonio Huete Jimenez 			dnp = VP_TO_NODE(vp);
997509bc517SAntonio Huete Jimenez 			cache_unlink(ap->a_tnch);
998*08905fc5SAntonio Huete Jimenez 			dirfs_knote(vp, NOTE_DELETE);
999509bc517SAntonio Huete Jimenez 			dirfs_node_setpassive(dmp, dnp, 0);
1000509bc517SAntonio Huete Jimenez 			if (dnp->dn_parent) {
1001509bc517SAntonio Huete Jimenez 				dirfs_node_drop(dmp, dnp->dn_parent);
1002509bc517SAntonio Huete Jimenez 				dnp->dn_parent = NULL;
1003509bc517SAntonio Huete Jimenez 			}
1004509bc517SAntonio Huete Jimenez 
1005509bc517SAntonio Huete Jimenez 			/*
1006509bc517SAntonio Huete Jimenez 			 * nlinks on directories can be a bit weird.  Zero
1007509bc517SAntonio Huete Jimenez 			 * it out.
1008509bc517SAntonio Huete Jimenez 			 */
1009509bc517SAntonio Huete Jimenez 			dnp->dn_links = 0;
1010509bc517SAntonio Huete Jimenez 			cache_inval_vp(vp, CINV_DESTROY);
1011509bc517SAntonio Huete Jimenez 		}
1012509bc517SAntonio Huete Jimenez 		cache_rename(ap->a_fnch, ap->a_tnch);
1013*08905fc5SAntonio Huete Jimenez 		dirfs_knote(fdvp, NOTE_WRITE);
1014*08905fc5SAntonio Huete Jimenez 		dirfs_knote(tdvp, NOTE_WRITE);
1015*08905fc5SAntonio Huete Jimenez 
1016509bc517SAntonio Huete Jimenez 	}
1017509bc517SAntonio Huete Jimenez 	dirfs_dropfd(dmp, NULL, fpathfree);
1018509bc517SAntonio Huete Jimenez 	dirfs_dropfd(dmp, NULL, tpathfree);
1019509bc517SAntonio Huete Jimenez 
1020509bc517SAntonio Huete Jimenez 	return error;
1021509bc517SAntonio Huete Jimenez }
1022509bc517SAntonio Huete Jimenez 
1023509bc517SAntonio Huete Jimenez static int
dirfs_nmkdir(struct vop_nmkdir_args * ap)1024509bc517SAntonio Huete Jimenez dirfs_nmkdir(struct vop_nmkdir_args *ap)
1025509bc517SAntonio Huete Jimenez {
1026509bc517SAntonio Huete Jimenez 	dirfs_mount_t dmp;
1027509bc517SAntonio Huete Jimenez 	dirfs_node_t dnp, pdnp, dnp1;
1028509bc517SAntonio Huete Jimenez 	struct namecache *ncp;
1029509bc517SAntonio Huete Jimenez 	struct vattr *vap;
1030509bc517SAntonio Huete Jimenez 	struct vnode *dvp;
1031509bc517SAntonio Huete Jimenez 	struct vnode **vpp;
1032509bc517SAntonio Huete Jimenez 	char *tmp, *pathfree;
1033509bc517SAntonio Huete Jimenez 	char *path;
1034509bc517SAntonio Huete Jimenez 	int pfd, error;
1035509bc517SAntonio Huete Jimenez 	int extrapath;
1036509bc517SAntonio Huete Jimenez 
103726ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
1038509bc517SAntonio Huete Jimenez 
1039509bc517SAntonio Huete Jimenez 	extrapath = error = 0;
1040509bc517SAntonio Huete Jimenez 	dvp = ap->a_dvp;
1041509bc517SAntonio Huete Jimenez 	vpp = ap->a_vpp;
1042509bc517SAntonio Huete Jimenez 	dmp = VFS_TO_DIRFS(dvp->v_mount);
1043509bc517SAntonio Huete Jimenez 	pdnp = VP_TO_NODE(dvp);
1044509bc517SAntonio Huete Jimenez 	ncp = ap->a_nch->ncp;
1045509bc517SAntonio Huete Jimenez 	vap = ap->a_vap;
1046509bc517SAntonio Huete Jimenez 	pathfree = tmp = path = NULL;
1047509bc517SAntonio Huete Jimenez 	dnp = NULL;
1048509bc517SAntonio Huete Jimenez 
1049509bc517SAntonio Huete Jimenez 	dirfs_node_lock(pdnp);
1050509bc517SAntonio Huete Jimenez 	if (pdnp->dn_fd != DIRFS_NOFD) {
1051509bc517SAntonio Huete Jimenez 		pfd = pdnp->dn_fd;
1052509bc517SAntonio Huete Jimenez 		path = ncp->nc_name;
1053509bc517SAntonio Huete Jimenez 	} else {
1054509bc517SAntonio Huete Jimenez 		dnp1 = dirfs_findfd(dmp, pdnp, &tmp, &pathfree);
1055509bc517SAntonio Huete Jimenez 		pfd = dnp1->dn_fd;
1056509bc517SAntonio Huete Jimenez 		/* XXX check there is room to copy the path */
1057509bc517SAntonio Huete Jimenez 		path = kmalloc(MAXPATHLEN, M_DIRFS_MISC, M_ZERO | M_WAITOK);
1058509bc517SAntonio Huete Jimenez 		ksnprintf(path, MAXPATHLEN, "%s/%s", tmp, ncp->nc_name);
1059509bc517SAntonio Huete Jimenez 		extrapath = 1;
1060509bc517SAntonio Huete Jimenez 		dirfs_dropfd(dmp, dnp1, pathfree);
1061509bc517SAntonio Huete Jimenez 	}
1062509bc517SAntonio Huete Jimenez 
1063509bc517SAntonio Huete Jimenez 	error = mkdirat(pfd, path, vap->va_mode);
1064509bc517SAntonio Huete Jimenez 	if (error) {
1065509bc517SAntonio Huete Jimenez 		error = errno;
1066509bc517SAntonio Huete Jimenez 	} else { /* Directory has been made */
1067509bc517SAntonio Huete Jimenez 		error = dirfs_alloc_file(dmp, &dnp, pdnp, ncp, vpp,
1068509bc517SAntonio Huete Jimenez 		    vap, O_DIRECTORY);
1069509bc517SAntonio Huete Jimenez 		if (error)
1070509bc517SAntonio Huete Jimenez 			error = errno;
1071509bc517SAntonio Huete Jimenez 		cache_setunresolved(ap->a_nch);
1072509bc517SAntonio Huete Jimenez 		cache_setvp(ap->a_nch, *vpp);
1073*08905fc5SAntonio Huete Jimenez 		dirfs_knote(dvp, NOTE_WRITE | NOTE_LINK);
1074509bc517SAntonio Huete Jimenez 	}
1075509bc517SAntonio Huete Jimenez 	dirfs_node_unlock(pdnp);
1076509bc517SAntonio Huete Jimenez 
1077509bc517SAntonio Huete Jimenez 	if (extrapath)
1078509bc517SAntonio Huete Jimenez 		kfree(path, M_DIRFS_MISC);
1079509bc517SAntonio Huete Jimenez 
1080509bc517SAntonio Huete Jimenez 	KTR_LOG(dirfs_nmkdir, pdnp, dnp, ncp->nc_name, error);
1081509bc517SAntonio Huete Jimenez 
1082509bc517SAntonio Huete Jimenez 	return error;
1083509bc517SAntonio Huete Jimenez }
1084509bc517SAntonio Huete Jimenez 
1085509bc517SAntonio Huete Jimenez static int
dirfs_nrmdir(struct vop_nrmdir_args * ap)1086509bc517SAntonio Huete Jimenez dirfs_nrmdir(struct vop_nrmdir_args *ap)
1087509bc517SAntonio Huete Jimenez {
1088509bc517SAntonio Huete Jimenez 	dirfs_node_t dnp, pdnp;
1089509bc517SAntonio Huete Jimenez 	dirfs_mount_t dmp;
1090509bc517SAntonio Huete Jimenez 	struct vnode *dvp;
1091509bc517SAntonio Huete Jimenez 	struct nchandle *nch;
1092509bc517SAntonio Huete Jimenez 	struct namecache *ncp;
1093509bc517SAntonio Huete Jimenez 	struct mount *mp;
1094509bc517SAntonio Huete Jimenez 	struct vnode *vp;
1095509bc517SAntonio Huete Jimenez 	int error;
1096509bc517SAntonio Huete Jimenez 	char *tmp;
1097509bc517SAntonio Huete Jimenez 	char *pathfree;
1098509bc517SAntonio Huete Jimenez 
109926ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
1100509bc517SAntonio Huete Jimenez 
1101509bc517SAntonio Huete Jimenez 	error = 0;
1102509bc517SAntonio Huete Jimenez 	tmp = NULL;
1103509bc517SAntonio Huete Jimenez 	vp = NULL;
1104509bc517SAntonio Huete Jimenez 	dvp = ap->a_dvp;
1105509bc517SAntonio Huete Jimenez 	nch = ap->a_nch;
1106509bc517SAntonio Huete Jimenez 	ncp = nch->ncp;
1107509bc517SAntonio Huete Jimenez 
1108509bc517SAntonio Huete Jimenez 	mp = dvp->v_mount;
1109509bc517SAntonio Huete Jimenez 	dmp = VFS_TO_DIRFS(mp);
1110509bc517SAntonio Huete Jimenez 
1111509bc517SAntonio Huete Jimenez 	lwkt_gettoken(&mp->mnt_token);
1112509bc517SAntonio Huete Jimenez 	cache_vget(nch, ap->a_cred, LK_SHARED, &vp);
1113509bc517SAntonio Huete Jimenez 	vn_unlock(vp);
1114509bc517SAntonio Huete Jimenez 
1115509bc517SAntonio Huete Jimenez 	pdnp = VP_TO_NODE(dvp);
1116509bc517SAntonio Huete Jimenez 	dnp = VP_TO_NODE(vp);
1117509bc517SAntonio Huete Jimenez 
1118509bc517SAntonio Huete Jimenez 	if (vp->v_type != VDIR) {
1119509bc517SAntonio Huete Jimenez 		error = ENOTDIR;
1120509bc517SAntonio Huete Jimenez 	} else {
1121509bc517SAntonio Huete Jimenez 		tmp = dirfs_node_absolute_path(dmp, dnp, &pathfree);
1122509bc517SAntonio Huete Jimenez 		dirfs_node_lock(pdnp);
1123509bc517SAntonio Huete Jimenez 		error = rmdir(tmp);
1124509bc517SAntonio Huete Jimenez 		if (error == 0) {
1125509bc517SAntonio Huete Jimenez 			cache_unlink(nch);
1126*08905fc5SAntonio Huete Jimenez 			dirfs_knote(dvp, NOTE_WRITE | NOTE_LINK);
1127509bc517SAntonio Huete Jimenez 			dirfs_node_setpassive(dmp, dnp, 0);
1128509bc517SAntonio Huete Jimenez 			if (dnp->dn_parent) {
1129509bc517SAntonio Huete Jimenez 				dirfs_node_drop(dmp, dnp->dn_parent);
1130509bc517SAntonio Huete Jimenez 				dnp->dn_parent = NULL;
1131509bc517SAntonio Huete Jimenez 			}
1132509bc517SAntonio Huete Jimenez 
1133509bc517SAntonio Huete Jimenez 			/*
1134509bc517SAntonio Huete Jimenez 			 * nlinks on directories can be a bit weird.  Zero
1135509bc517SAntonio Huete Jimenez 			 * it out.
1136509bc517SAntonio Huete Jimenez 			 */
1137509bc517SAntonio Huete Jimenez 			dnp->dn_links = 0;
1138509bc517SAntonio Huete Jimenez 			cache_inval_vp(vp, CINV_DESTROY);
1139509bc517SAntonio Huete Jimenez 		} else {
1140509bc517SAntonio Huete Jimenez 			error = errno;
1141509bc517SAntonio Huete Jimenez 		}
1142509bc517SAntonio Huete Jimenez 		dirfs_node_unlock(pdnp);
1143509bc517SAntonio Huete Jimenez 		dirfs_dropfd(dmp, NULL, pathfree);
1144509bc517SAntonio Huete Jimenez 	}
1145509bc517SAntonio Huete Jimenez 	vrele(vp);
1146509bc517SAntonio Huete Jimenez 	lwkt_reltoken(&mp->mnt_token);
1147509bc517SAntonio Huete Jimenez 
1148509bc517SAntonio Huete Jimenez 	KTR_LOG(dirfs_nrmdir, dnp, pdnp, error);
1149509bc517SAntonio Huete Jimenez 
1150509bc517SAntonio Huete Jimenez 	return error;
1151509bc517SAntonio Huete Jimenez }
1152509bc517SAntonio Huete Jimenez 
1153509bc517SAntonio Huete Jimenez static int
dirfs_nsymlink(struct vop_nsymlink_args * ap)1154509bc517SAntonio Huete Jimenez dirfs_nsymlink(struct vop_nsymlink_args *ap)
1155509bc517SAntonio Huete Jimenez {
1156509bc517SAntonio Huete Jimenez 	dirfs_mount_t dmp;
1157509bc517SAntonio Huete Jimenez 	dirfs_node_t dnp, pdnp;
1158509bc517SAntonio Huete Jimenez 	struct mount *mp;
1159509bc517SAntonio Huete Jimenez 	struct namecache *ncp;
1160509bc517SAntonio Huete Jimenez 	struct vattr *vap;
1161509bc517SAntonio Huete Jimenez 	struct vnode *dvp;
1162509bc517SAntonio Huete Jimenez 	struct vnode **vpp;
1163509bc517SAntonio Huete Jimenez 	char *tmp, *pathfree;
1164509bc517SAntonio Huete Jimenez 	char *path;
1165509bc517SAntonio Huete Jimenez 	int error;
1166509bc517SAntonio Huete Jimenez 
116726ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
1168509bc517SAntonio Huete Jimenez 
1169509bc517SAntonio Huete Jimenez 	error = 0;
1170509bc517SAntonio Huete Jimenez 	dvp = ap->a_dvp;
1171509bc517SAntonio Huete Jimenez 	vpp = ap->a_vpp;
1172509bc517SAntonio Huete Jimenez 	mp = dvp->v_mount;
1173509bc517SAntonio Huete Jimenez 	dmp = VFS_TO_DIRFS(dvp->v_mount);
1174509bc517SAntonio Huete Jimenez 	pdnp = VP_TO_NODE(dvp);
1175509bc517SAntonio Huete Jimenez 	ncp = ap->a_nch->ncp;
1176509bc517SAntonio Huete Jimenez 	vap = ap->a_vap;
1177509bc517SAntonio Huete Jimenez 	pathfree = tmp = path = NULL;
1178509bc517SAntonio Huete Jimenez 	dnp = NULL;
1179509bc517SAntonio Huete Jimenez 
1180509bc517SAntonio Huete Jimenez 	lwkt_gettoken(&mp->mnt_token);
1181509bc517SAntonio Huete Jimenez 	vap->va_type = VLNK;
1182509bc517SAntonio Huete Jimenez 
1183509bc517SAntonio Huete Jimenez 	/* Find out the whole path of our new symbolic link */
1184509bc517SAntonio Huete Jimenez 	tmp = dirfs_node_absolute_path(dmp, pdnp, &pathfree);
1185509bc517SAntonio Huete Jimenez 	/* XXX check there is room to copy the path */
1186509bc517SAntonio Huete Jimenez 	path = kmalloc(MAXPATHLEN, M_DIRFS_MISC, M_ZERO | M_WAITOK);
1187509bc517SAntonio Huete Jimenez 	ksnprintf(path, MAXPATHLEN, "%s/%s", tmp, ncp->nc_name);
1188509bc517SAntonio Huete Jimenez 	dirfs_dropfd(dmp, NULL, pathfree);
1189509bc517SAntonio Huete Jimenez 
1190509bc517SAntonio Huete Jimenez 	error = symlink(ap->a_target, path);
1191509bc517SAntonio Huete Jimenez 	if (error) {
1192509bc517SAntonio Huete Jimenez 		error = errno;
1193509bc517SAntonio Huete Jimenez 	} else { /* Symlink has been made */
1194509bc517SAntonio Huete Jimenez 		error = dirfs_alloc_file(dmp, &dnp, pdnp, ncp, vpp,
1195509bc517SAntonio Huete Jimenez 		    NULL, 0);
1196509bc517SAntonio Huete Jimenez 		if (error)
1197509bc517SAntonio Huete Jimenez 			error = errno;
1198509bc517SAntonio Huete Jimenez 		cache_setunresolved(ap->a_nch);
1199509bc517SAntonio Huete Jimenez 		cache_setvp(ap->a_nch, *vpp);
1200*08905fc5SAntonio Huete Jimenez 		dirfs_knote(*vpp, NOTE_WRITE);
1201509bc517SAntonio Huete Jimenez 	}
1202509bc517SAntonio Huete Jimenez 	dbg(5, "path=%s a_target=%s\n", path, ap->a_target);
1203509bc517SAntonio Huete Jimenez 
1204509bc517SAntonio Huete Jimenez 	KTR_LOG(dirfs_nsymlink, dnp, ap->a_target, path, error);
1205509bc517SAntonio Huete Jimenez 	kfree(path, M_DIRFS_MISC);
1206509bc517SAntonio Huete Jimenez 	lwkt_reltoken(&mp->mnt_token);
1207509bc517SAntonio Huete Jimenez 
1208509bc517SAntonio Huete Jimenez 	return error;
1209509bc517SAntonio Huete Jimenez 
1210509bc517SAntonio Huete Jimenez }
1211509bc517SAntonio Huete Jimenez 
1212509bc517SAntonio Huete Jimenez static int
dirfs_readdir(struct vop_readdir_args * ap)1213509bc517SAntonio Huete Jimenez dirfs_readdir(struct vop_readdir_args *ap)
1214509bc517SAntonio Huete Jimenez {
1215509bc517SAntonio Huete Jimenez 
1216509bc517SAntonio Huete Jimenez 	struct dirent *dp, *dpn;
1217509bc517SAntonio Huete Jimenez 	off_t __unused **cookies = ap->a_cookies;
1218509bc517SAntonio Huete Jimenez 	int *ncookies = ap->a_ncookies;
1219509bc517SAntonio Huete Jimenez 	int bytes;
1220509bc517SAntonio Huete Jimenez 	char *buf;
1221509bc517SAntonio Huete Jimenez 	long base;
1222509bc517SAntonio Huete Jimenez 	struct vnode *vp = ap->a_vp;
1223509bc517SAntonio Huete Jimenez 	struct uio *uio;
1224509bc517SAntonio Huete Jimenez 	dirfs_node_t dnp;
1225509bc517SAntonio Huete Jimenez 	off_t startoff;
1226509bc517SAntonio Huete Jimenez 	off_t cnt;
1227509bc517SAntonio Huete Jimenez 	int error, r;
1228509bc517SAntonio Huete Jimenez 	size_t bufsiz;
1229509bc517SAntonio Huete Jimenez 	off_t curoff;
1230509bc517SAntonio Huete Jimenez 
123126ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
1232509bc517SAntonio Huete Jimenez 
1233509bc517SAntonio Huete Jimenez 	if (ncookies)
1234509bc517SAntonio Huete Jimenez 		debug(1, "ncookies=%d\n", *ncookies);
1235509bc517SAntonio Huete Jimenez 
1236509bc517SAntonio Huete Jimenez 	dnp = VP_TO_NODE(vp);
1237509bc517SAntonio Huete Jimenez 	uio = ap->a_uio;
1238509bc517SAntonio Huete Jimenez 	startoff = uio->uio_offset;
1239509bc517SAntonio Huete Jimenez 	cnt = 0;
1240509bc517SAntonio Huete Jimenez 	error = 0;
1241509bc517SAntonio Huete Jimenez 	base = 0;
1242509bc517SAntonio Huete Jimenez 	bytes = 0;
1243509bc517SAntonio Huete Jimenez 
1244509bc517SAntonio Huete Jimenez 	if (vp->v_type != VDIR)
1245509bc517SAntonio Huete Jimenez 		return ENOTDIR;
1246509bc517SAntonio Huete Jimenez 	if (uio->uio_resid < 0)
1247509bc517SAntonio Huete Jimenez 		return EINVAL;
1248509bc517SAntonio Huete Jimenez 	if ((bufsiz = uio->uio_resid) > 4096)
1249509bc517SAntonio Huete Jimenez 		bufsiz = 4096;
1250509bc517SAntonio Huete Jimenez 	buf = kmalloc(bufsiz, M_DIRFS_MISC, M_WAITOK | M_ZERO);
1251509bc517SAntonio Huete Jimenez 
1252509bc517SAntonio Huete Jimenez 	/*
1253509bc517SAntonio Huete Jimenez 	 * Generally speaking we have to be able to process ALL the
1254509bc517SAntonio Huete Jimenez 	 * entries returned by getdirentries() in order for the seek
1255509bc517SAntonio Huete Jimenez 	 * position to be correct.  For now try to size the buffer
1256509bc517SAntonio Huete Jimenez 	 * to make this happen.  A smaller buffer always works.  For
1257509bc517SAntonio Huete Jimenez 	 * now just use an appropriate size.
1258509bc517SAntonio Huete Jimenez 	 */
1259509bc517SAntonio Huete Jimenez 	dirfs_node_lock(dnp);
1260509bc517SAntonio Huete Jimenez 	lseek(dnp->dn_fd, startoff, SEEK_SET);
1261509bc517SAntonio Huete Jimenez 	bytes = getdirentries(dnp->dn_fd, buf, bufsiz, &base);
126226ec059cSAntonio Huete Jimenez 	dbg(9, "seek %016jx %016jx %016jx\n",
1263509bc517SAntonio Huete Jimenez 		(intmax_t)startoff, (intmax_t)base,
1264509bc517SAntonio Huete Jimenez 		(intmax_t)lseek(dnp->dn_fd, 0, SEEK_CUR));
1265509bc517SAntonio Huete Jimenez 	if (bytes < 0) {
1266509bc517SAntonio Huete Jimenez 		if (errno == EINVAL)
1267509bc517SAntonio Huete Jimenez 			panic("EINVAL on readdir\n");
1268509bc517SAntonio Huete Jimenez 		error = errno;
1269509bc517SAntonio Huete Jimenez 		curoff = startoff;
1270509bc517SAntonio Huete Jimenez 		goto out;
1271509bc517SAntonio Huete Jimenez 	} else if (bytes == 0) {
1272509bc517SAntonio Huete Jimenez 		*ap->a_eofflag = 1;
1273509bc517SAntonio Huete Jimenez 		curoff = startoff;
1274509bc517SAntonio Huete Jimenez 		goto out;
1275509bc517SAntonio Huete Jimenez 	}
1276509bc517SAntonio Huete Jimenez 
1277509bc517SAntonio Huete Jimenez 	for (dp = (struct dirent *)buf; bytes > 0 && uio->uio_resid > 0;
1278509bc517SAntonio Huete Jimenez 	    bytes -= _DIRENT_DIRSIZ(dp), dp = dpn) {
1279509bc517SAntonio Huete Jimenez 		r = vop_write_dirent(&error, uio, dp->d_ino, dp->d_type,
1280509bc517SAntonio Huete Jimenez 		    dp->d_namlen, dp->d_name);
1281509bc517SAntonio Huete Jimenez 		if (error || r)
1282509bc517SAntonio Huete Jimenez 			break;
1283509bc517SAntonio Huete Jimenez 		dpn = _DIRENT_NEXT(dp);
1284509bc517SAntonio Huete Jimenez 		dp = dpn;
1285509bc517SAntonio Huete Jimenez 		cnt++;
1286509bc517SAntonio Huete Jimenez 	}
1287509bc517SAntonio Huete Jimenez 	curoff = lseek(dnp->dn_fd, 0, SEEK_CUR);
1288509bc517SAntonio Huete Jimenez 
1289509bc517SAntonio Huete Jimenez out:
1290509bc517SAntonio Huete Jimenez 	kfree(buf, M_DIRFS_MISC);
1291509bc517SAntonio Huete Jimenez 	uio->uio_offset = curoff;
1292509bc517SAntonio Huete Jimenez 	dirfs_node_unlock(dnp);
1293509bc517SAntonio Huete Jimenez 
1294509bc517SAntonio Huete Jimenez 	KTR_LOG(dirfs_readdir, dnp, dnp->dn_fd, startoff, uio->uio_offset);
1295509bc517SAntonio Huete Jimenez 
1296509bc517SAntonio Huete Jimenez 	return error;
1297509bc517SAntonio Huete Jimenez }
1298509bc517SAntonio Huete Jimenez 
1299509bc517SAntonio Huete Jimenez static int
dirfs_readlink(struct vop_readlink_args * ap)1300509bc517SAntonio Huete Jimenez dirfs_readlink(struct vop_readlink_args *ap)
1301509bc517SAntonio Huete Jimenez {
1302509bc517SAntonio Huete Jimenez 	dirfs_node_t dnp, pathnp;
1303509bc517SAntonio Huete Jimenez 	dirfs_mount_t dmp;
1304509bc517SAntonio Huete Jimenez 	struct vnode *vp;
1305509bc517SAntonio Huete Jimenez 	struct mount *mp;
1306509bc517SAntonio Huete Jimenez 	struct uio *uio;
1307509bc517SAntonio Huete Jimenez 	char *tmp, *pathfree, *buf;
1308509bc517SAntonio Huete Jimenez 	ssize_t nlen;
1309509bc517SAntonio Huete Jimenez 	int error;
1310509bc517SAntonio Huete Jimenez 
131126ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
1312509bc517SAntonio Huete Jimenez 
1313509bc517SAntonio Huete Jimenez 	vp = ap->a_vp;
1314509bc517SAntonio Huete Jimenez 
1315509bc517SAntonio Huete Jimenez 	KKASSERT(vp->v_type == VLNK);
1316509bc517SAntonio Huete Jimenez 
1317509bc517SAntonio Huete Jimenez 	error = 0;
1318509bc517SAntonio Huete Jimenez 	tmp = pathfree = NULL;
1319509bc517SAntonio Huete Jimenez 	uio = ap->a_uio;
1320509bc517SAntonio Huete Jimenez 	mp = vp->v_mount;
1321509bc517SAntonio Huete Jimenez 	dmp = VFS_TO_DIRFS(mp);
1322509bc517SAntonio Huete Jimenez 	dnp = VP_TO_NODE(vp);
1323509bc517SAntonio Huete Jimenez 
1324509bc517SAntonio Huete Jimenez 	lwkt_gettoken(&mp->mnt_token);
1325509bc517SAntonio Huete Jimenez 
1326509bc517SAntonio Huete Jimenez 	pathnp = dirfs_findfd(dmp, dnp, &tmp, &pathfree);
1327509bc517SAntonio Huete Jimenez 
1328509bc517SAntonio Huete Jimenez 	buf = kmalloc(uio->uio_resid, M_DIRFS_MISC, M_WAITOK | M_ZERO);
1329509bc517SAntonio Huete Jimenez 	nlen = readlinkat(pathnp->dn_fd, dnp->dn_name, buf, uio->uio_resid);
1330509bc517SAntonio Huete Jimenez 	if (nlen == -1 ) {
1331509bc517SAntonio Huete Jimenez 		error = errno;
1332509bc517SAntonio Huete Jimenez 	} else {
1333509bc517SAntonio Huete Jimenez 		error = uiomove(buf, nlen + 1, uio);
1334509bc517SAntonio Huete Jimenez 		buf[nlen] = '\0';
1335509bc517SAntonio Huete Jimenez 		if (error)
1336509bc517SAntonio Huete Jimenez 			error = errno;
1337509bc517SAntonio Huete Jimenez 	}
1338509bc517SAntonio Huete Jimenez 	dirfs_dropfd(dmp, pathnp, pathfree);
1339509bc517SAntonio Huete Jimenez 	kfree(buf, M_DIRFS_MISC);
1340509bc517SAntonio Huete Jimenez 
1341509bc517SAntonio Huete Jimenez 	lwkt_reltoken(&mp->mnt_token);
1342509bc517SAntonio Huete Jimenez 
1343509bc517SAntonio Huete Jimenez 	return error;
1344509bc517SAntonio Huete Jimenez }
1345509bc517SAntonio Huete Jimenez 
1346509bc517SAntonio Huete Jimenez /*
1347509bc517SAntonio Huete Jimenez  * Main tasks to be performed.
1348509bc517SAntonio Huete Jimenez  * 1) When inode is NULL recycle the vnode
1349509bc517SAntonio Huete Jimenez  * 2) When the inode has 0 links:
1350509bc517SAntonio Huete Jimenez  *	- Check if in the TAILQ, if so remove.
1351509bc517SAntonio Huete Jimenez  *	- Destroy the inode.
1352509bc517SAntonio Huete Jimenez  *	- Recycle the vnode.
1353509bc517SAntonio Huete Jimenez  * 3) If none of the above, add the node to the TAILQ
1354509bc517SAntonio Huete Jimenez  *    when it has a valid fd and there is room on the
1355509bc517SAntonio Huete Jimenez  *    queue.
1356509bc517SAntonio Huete Jimenez  *
1357509bc517SAntonio Huete Jimenez  */
1358509bc517SAntonio Huete Jimenez static int
dirfs_inactive(struct vop_inactive_args * ap)1359509bc517SAntonio Huete Jimenez dirfs_inactive(struct vop_inactive_args *ap)
1360509bc517SAntonio Huete Jimenez {
1361509bc517SAntonio Huete Jimenez 	struct vnode *vp;
1362509bc517SAntonio Huete Jimenez 	dirfs_mount_t dmp;
1363509bc517SAntonio Huete Jimenez 	dirfs_node_t dnp;
1364509bc517SAntonio Huete Jimenez 
136526ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
1366509bc517SAntonio Huete Jimenez 
1367509bc517SAntonio Huete Jimenez 	vp = ap->a_vp;
1368509bc517SAntonio Huete Jimenez 	dmp = VFS_TO_DIRFS(vp->v_mount);
1369509bc517SAntonio Huete Jimenez 	dnp = VP_TO_NODE(vp);
1370509bc517SAntonio Huete Jimenez 
1371509bc517SAntonio Huete Jimenez 	/* Degenerate case */
1372509bc517SAntonio Huete Jimenez 	if (dnp == NULL) {
1373509bc517SAntonio Huete Jimenez 		dbg(5, "dnp was NULL\n");
1374509bc517SAntonio Huete Jimenez 		vrecycle(vp);
1375509bc517SAntonio Huete Jimenez 		return 0;
1376509bc517SAntonio Huete Jimenez 	}
1377509bc517SAntonio Huete Jimenez 
1378509bc517SAntonio Huete Jimenez 	/*
1379509bc517SAntonio Huete Jimenez 	 * Deal with the case the inode has 0 links which means it was unlinked.
1380509bc517SAntonio Huete Jimenez 	 */
1381509bc517SAntonio Huete Jimenez 	if (dnp->dn_links == 0) {
1382509bc517SAntonio Huete Jimenez 		vrecycle(vp);
1383509bc517SAntonio Huete Jimenez 		dbg(5, "recycled a vnode of an unlinked dnp\n");
1384509bc517SAntonio Huete Jimenez 
1385509bc517SAntonio Huete Jimenez 		goto out;
1386509bc517SAntonio Huete Jimenez 	}
1387509bc517SAntonio Huete Jimenez 
1388509bc517SAntonio Huete Jimenez 	/*
1389509bc517SAntonio Huete Jimenez 	 * Try to retain the fd in our fd cache.
1390509bc517SAntonio Huete Jimenez 	 */
1391509bc517SAntonio Huete Jimenez 	dirfs_node_setpassive(dmp, dnp, 1);
1392509bc517SAntonio Huete Jimenez out:
1393509bc517SAntonio Huete Jimenez 
1394509bc517SAntonio Huete Jimenez 	return 0;
1395509bc517SAntonio Huete Jimenez 
1396509bc517SAntonio Huete Jimenez }
1397509bc517SAntonio Huete Jimenez 
1398509bc517SAntonio Huete Jimenez int
dirfs_reclaim(struct vop_reclaim_args * ap)1399509bc517SAntonio Huete Jimenez dirfs_reclaim(struct vop_reclaim_args *ap)
1400509bc517SAntonio Huete Jimenez {
1401509bc517SAntonio Huete Jimenez 	struct vnode *vp;
1402509bc517SAntonio Huete Jimenez 	dirfs_node_t dnp;
1403509bc517SAntonio Huete Jimenez 	dirfs_mount_t dmp;
1404509bc517SAntonio Huete Jimenez 
140526ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
1406509bc517SAntonio Huete Jimenez 
1407509bc517SAntonio Huete Jimenez 	vp = ap->a_vp;
1408509bc517SAntonio Huete Jimenez 	dnp = VP_TO_NODE(vp);
1409509bc517SAntonio Huete Jimenez 	dmp = VFS_TO_DIRFS(vp->v_mount);
1410509bc517SAntonio Huete Jimenez 
1411509bc517SAntonio Huete Jimenez 	dirfs_free_vp(dmp, dnp);
1412509bc517SAntonio Huete Jimenez 	/* dnp is now invalid, may have been destroyed */
1413509bc517SAntonio Huete Jimenez 
1414509bc517SAntonio Huete Jimenez 	return 0;
1415509bc517SAntonio Huete Jimenez }
1416509bc517SAntonio Huete Jimenez 
1417509bc517SAntonio Huete Jimenez static int
dirfs_mountctl(struct vop_mountctl_args * ap)1418509bc517SAntonio Huete Jimenez dirfs_mountctl(struct vop_mountctl_args *ap)
1419509bc517SAntonio Huete Jimenez {
142026ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
1421509bc517SAntonio Huete Jimenez 
1422509bc517SAntonio Huete Jimenez 	KTR_LOG(dirfs_unsupported, __func__);
1423509bc517SAntonio Huete Jimenez 
1424509bc517SAntonio Huete Jimenez 	return EOPNOTSUPP;
1425509bc517SAntonio Huete Jimenez }
1426509bc517SAntonio Huete Jimenez 
1427509bc517SAntonio Huete Jimenez static int
dirfs_print(struct vop_print_args * v)1428509bc517SAntonio Huete Jimenez dirfs_print(struct vop_print_args *v)
1429509bc517SAntonio Huete Jimenez {
143026ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
1431509bc517SAntonio Huete Jimenez 
1432509bc517SAntonio Huete Jimenez 	KTR_LOG(dirfs_unsupported, __func__);
1433509bc517SAntonio Huete Jimenez 
1434509bc517SAntonio Huete Jimenez 	return EOPNOTSUPP;
1435509bc517SAntonio Huete Jimenez }
1436509bc517SAntonio Huete Jimenez 
1437509bc517SAntonio Huete Jimenez static int __unused
dirfs_pathconf(struct vop_pathconf_args * v)1438509bc517SAntonio Huete Jimenez dirfs_pathconf(struct vop_pathconf_args *v)
1439509bc517SAntonio Huete Jimenez {
144026ec059cSAntonio Huete Jimenez 	dbg(3, "called\n");
1441509bc517SAntonio Huete Jimenez 
1442509bc517SAntonio Huete Jimenez 	return EOPNOTSUPP;
1443509bc517SAntonio Huete Jimenez }
1444509bc517SAntonio Huete Jimenez 
1445*08905fc5SAntonio Huete Jimenez /************************************************************************
1446*08905fc5SAntonio Huete Jimenez  *                          KQFILTER OPS                                *
1447*08905fc5SAntonio Huete Jimenez  ************************************************************************/
1448*08905fc5SAntonio Huete Jimenez 
1449*08905fc5SAntonio Huete Jimenez static void filt_dirfsdetach(struct knote *kn);
1450*08905fc5SAntonio Huete Jimenez static int filt_dirfsread(struct knote *kn, long hint);
1451*08905fc5SAntonio Huete Jimenez static int filt_dirfswrite(struct knote *kn, long hint);
1452*08905fc5SAntonio Huete Jimenez static int filt_dirfsvnode(struct knote *kn, long hint);
1453*08905fc5SAntonio Huete Jimenez 
1454*08905fc5SAntonio Huete Jimenez static struct filterops dirfsread_filtops =
1455*08905fc5SAntonio Huete Jimenez 	{ FILTEROP_ISFD | FILTEROP_MPSAFE,
1456*08905fc5SAntonio Huete Jimenez 	  NULL, filt_dirfsdetach, filt_dirfsread };
1457*08905fc5SAntonio Huete Jimenez static struct filterops dirfswrite_filtops =
1458*08905fc5SAntonio Huete Jimenez 	{ FILTEROP_ISFD | FILTEROP_MPSAFE,
1459*08905fc5SAntonio Huete Jimenez 	  NULL, filt_dirfsdetach, filt_dirfswrite };
1460*08905fc5SAntonio Huete Jimenez static struct filterops dirfsvnode_filtops =
1461*08905fc5SAntonio Huete Jimenez 	{ FILTEROP_ISFD | FILTEROP_MPSAFE,
1462*08905fc5SAntonio Huete Jimenez 	  NULL, filt_dirfsdetach, filt_dirfsvnode };
1463*08905fc5SAntonio Huete Jimenez 
1464509bc517SAntonio Huete Jimenez static int
dirfs_kqfilter(struct vop_kqfilter_args * ap)1465509bc517SAntonio Huete Jimenez dirfs_kqfilter (struct vop_kqfilter_args *ap)
1466509bc517SAntonio Huete Jimenez {
1467*08905fc5SAntonio Huete Jimenez 	struct vnode *vp = ap->a_vp;
1468*08905fc5SAntonio Huete Jimenez 	struct knote *kn = ap->a_kn;
1469509bc517SAntonio Huete Jimenez 
1470*08905fc5SAntonio Huete Jimenez 	switch (kn->kn_filter) {
1471*08905fc5SAntonio Huete Jimenez 	case EVFILT_READ:
1472*08905fc5SAntonio Huete Jimenez 		kn->kn_fop = &dirfsread_filtops;
1473*08905fc5SAntonio Huete Jimenez 		break;
1474*08905fc5SAntonio Huete Jimenez 	case EVFILT_WRITE:
1475*08905fc5SAntonio Huete Jimenez 		kn->kn_fop = &dirfswrite_filtops;
1476*08905fc5SAntonio Huete Jimenez 		break;
1477*08905fc5SAntonio Huete Jimenez 	case EVFILT_VNODE:
1478*08905fc5SAntonio Huete Jimenez 		kn->kn_fop = &dirfsvnode_filtops;
1479*08905fc5SAntonio Huete Jimenez 		break;
1480*08905fc5SAntonio Huete Jimenez 	default:
1481*08905fc5SAntonio Huete Jimenez 		return (EOPNOTSUPP);
1482509bc517SAntonio Huete Jimenez 	}
1483509bc517SAntonio Huete Jimenez 
1484*08905fc5SAntonio Huete Jimenez 	kn->kn_hook = (caddr_t)vp;
1485*08905fc5SAntonio Huete Jimenez 
1486*08905fc5SAntonio Huete Jimenez 	knote_insert(&vp->v_pollinfo.vpi_kqinfo.ki_note, kn);
1487*08905fc5SAntonio Huete Jimenez 
1488*08905fc5SAntonio Huete Jimenez 	return(0);
1489*08905fc5SAntonio Huete Jimenez }
1490*08905fc5SAntonio Huete Jimenez 
1491*08905fc5SAntonio Huete Jimenez static void
filt_dirfsdetach(struct knote * kn)1492*08905fc5SAntonio Huete Jimenez filt_dirfsdetach(struct knote *kn)
1493*08905fc5SAntonio Huete Jimenez {
1494*08905fc5SAntonio Huete Jimenez 	struct vnode *vp = (void *)kn->kn_hook;
1495*08905fc5SAntonio Huete Jimenez 
1496*08905fc5SAntonio Huete Jimenez 	knote_remove(&vp->v_pollinfo.vpi_kqinfo.ki_note, kn);
1497*08905fc5SAntonio Huete Jimenez }
1498*08905fc5SAntonio Huete Jimenez 
1499*08905fc5SAntonio Huete Jimenez static int
filt_dirfsread(struct knote * kn,long hint)1500*08905fc5SAntonio Huete Jimenez filt_dirfsread(struct knote *kn, long hint)
1501*08905fc5SAntonio Huete Jimenez {
1502*08905fc5SAntonio Huete Jimenez 	struct vnode *vp = (void *)kn->kn_hook;
1503*08905fc5SAntonio Huete Jimenez 	dirfs_node_t dnp  = VP_TO_NODE(vp);
1504*08905fc5SAntonio Huete Jimenez 	off_t off;
1505*08905fc5SAntonio Huete Jimenez 
1506*08905fc5SAntonio Huete Jimenez 	if (hint == NOTE_REVOKE) {
1507*08905fc5SAntonio Huete Jimenez 		kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT);
1508*08905fc5SAntonio Huete Jimenez 		return(1);
1509*08905fc5SAntonio Huete Jimenez 	}
1510*08905fc5SAntonio Huete Jimenez 
1511*08905fc5SAntonio Huete Jimenez 	/*
1512*08905fc5SAntonio Huete Jimenez 	 * Interlock against MP races when performing this function.
1513*08905fc5SAntonio Huete Jimenez 	 */
1514*08905fc5SAntonio Huete Jimenez 	dirfs_node_lock(dnp);
1515*08905fc5SAntonio Huete Jimenez 	off = dnp->dn_size - kn->kn_fp->f_offset;
1516*08905fc5SAntonio Huete Jimenez 	kn->kn_data = (off < INTPTR_MAX) ? off : INTPTR_MAX;
1517*08905fc5SAntonio Huete Jimenez 	if (kn->kn_sfflags & NOTE_OLDAPI) {
1518*08905fc5SAntonio Huete Jimenez 		dirfs_node_unlock(dnp);
1519*08905fc5SAntonio Huete Jimenez 		return(1);
1520*08905fc5SAntonio Huete Jimenez 	}
1521*08905fc5SAntonio Huete Jimenez 	if (kn->kn_data == 0) {
1522*08905fc5SAntonio Huete Jimenez 		kn->kn_data = (off < INTPTR_MAX) ? off : INTPTR_MAX;
1523*08905fc5SAntonio Huete Jimenez 	}
1524*08905fc5SAntonio Huete Jimenez 	dirfs_node_unlock(dnp);
1525*08905fc5SAntonio Huete Jimenez 	return (kn->kn_data != 0);
1526*08905fc5SAntonio Huete Jimenez }
1527*08905fc5SAntonio Huete Jimenez 
1528*08905fc5SAntonio Huete Jimenez static int
filt_dirfswrite(struct knote * kn,long hint)1529*08905fc5SAntonio Huete Jimenez filt_dirfswrite(struct knote *kn, long hint)
1530*08905fc5SAntonio Huete Jimenez {
1531*08905fc5SAntonio Huete Jimenez 	if (hint == NOTE_REVOKE)
1532*08905fc5SAntonio Huete Jimenez 		kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT);
1533*08905fc5SAntonio Huete Jimenez 	kn->kn_data = 0;
1534*08905fc5SAntonio Huete Jimenez 	return (1);
1535*08905fc5SAntonio Huete Jimenez }
1536*08905fc5SAntonio Huete Jimenez 
1537*08905fc5SAntonio Huete Jimenez static int
filt_dirfsvnode(struct knote * kn,long hint)1538*08905fc5SAntonio Huete Jimenez filt_dirfsvnode(struct knote *kn, long hint)
1539*08905fc5SAntonio Huete Jimenez {
1540*08905fc5SAntonio Huete Jimenez 	if (kn->kn_sfflags & hint)
1541*08905fc5SAntonio Huete Jimenez 		kn->kn_fflags |= hint;
1542*08905fc5SAntonio Huete Jimenez 	if (hint == NOTE_REVOKE) {
1543*08905fc5SAntonio Huete Jimenez 		kn->kn_flags |= (EV_EOF | EV_NODATA);
1544*08905fc5SAntonio Huete Jimenez 		return (1);
1545*08905fc5SAntonio Huete Jimenez 	}
1546*08905fc5SAntonio Huete Jimenez 	return (kn->kn_fflags != 0);
1547*08905fc5SAntonio Huete Jimenez }
1548*08905fc5SAntonio Huete Jimenez 
1549*08905fc5SAntonio Huete Jimenez 
1550*08905fc5SAntonio Huete Jimenez /* --------------------------------------------------------------------- */
1551*08905fc5SAntonio Huete Jimenez 
1552509bc517SAntonio Huete Jimenez struct vop_ops dirfs_vnode_vops = {
1553509bc517SAntonio Huete Jimenez 	.vop_default =			vop_defaultop,
1554509bc517SAntonio Huete Jimenez 	.vop_nwhiteout =		vop_compat_nwhiteout,
1555509bc517SAntonio Huete Jimenez 	.vop_ncreate =			dirfs_ncreate,
1556509bc517SAntonio Huete Jimenez 	.vop_nresolve =			dirfs_nresolve,
1557509bc517SAntonio Huete Jimenez 	.vop_markatime =		vop_stdmarkatime,
1558509bc517SAntonio Huete Jimenez 	.vop_nlookupdotdot =		dirfs_nlookupdotdot,
1559509bc517SAntonio Huete Jimenez 	.vop_nmknod =			dirfs_nmknod,
1560509bc517SAntonio Huete Jimenez 	.vop_open =			dirfs_open,
1561509bc517SAntonio Huete Jimenez 	.vop_close =			dirfs_close,
1562509bc517SAntonio Huete Jimenez 	.vop_access =			dirfs_access,
1563509bc517SAntonio Huete Jimenez 	.vop_getattr =			dirfs_getattr,
1564509bc517SAntonio Huete Jimenez 	.vop_setattr =			dirfs_setattr,
1565509bc517SAntonio Huete Jimenez 	.vop_read =			dirfs_read,
1566509bc517SAntonio Huete Jimenez 	.vop_write =			dirfs_write,
1567509bc517SAntonio Huete Jimenez 	.vop_fsync =			dirfs_fsync,
1568509bc517SAntonio Huete Jimenez 	.vop_mountctl =			dirfs_mountctl,
1569509bc517SAntonio Huete Jimenez 	.vop_nremove =			dirfs_nremove,
1570509bc517SAntonio Huete Jimenez 	.vop_nlink =			dirfs_nlink,
1571509bc517SAntonio Huete Jimenez 	.vop_nrename =			dirfs_nrename,
1572509bc517SAntonio Huete Jimenez 	.vop_nmkdir =			dirfs_nmkdir,
1573509bc517SAntonio Huete Jimenez 	.vop_nrmdir =			dirfs_nrmdir,
1574509bc517SAntonio Huete Jimenez 	.vop_nsymlink =			dirfs_nsymlink,
1575509bc517SAntonio Huete Jimenez 	.vop_readdir =			dirfs_readdir,
1576509bc517SAntonio Huete Jimenez 	.vop_readlink =			dirfs_readlink,
1577509bc517SAntonio Huete Jimenez 	.vop_inactive =			dirfs_inactive,
1578509bc517SAntonio Huete Jimenez 	.vop_reclaim =			dirfs_reclaim,
1579509bc517SAntonio Huete Jimenez 	.vop_print =			dirfs_print,
1580509bc517SAntonio Huete Jimenez 	.vop_pathconf =			vop_stdpathconf,
1581509bc517SAntonio Huete Jimenez 	.vop_bmap =			dirfs_bmap,
1582509bc517SAntonio Huete Jimenez 	.vop_strategy =			dirfs_strategy,
1583509bc517SAntonio Huete Jimenez 	.vop_advlock =			dirfs_advlock,
1584509bc517SAntonio Huete Jimenez 	.vop_kqfilter =			dirfs_kqfilter,
1585509bc517SAntonio Huete Jimenez 	.vop_getpages =			vop_stdgetpages,
1586509bc517SAntonio Huete Jimenez 	.vop_putpages =			vop_stdputpages
1587509bc517SAntonio Huete Jimenez };
1588