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