1*bbb1b6f9SApple OSS Distributions /*
2*bbb1b6f9SApple OSS Distributions * Copyright (c) 2019 Apple Inc. All rights reserved.
3*bbb1b6f9SApple OSS Distributions *
4*bbb1b6f9SApple OSS Distributions * @APPLE_LICENSE_HEADER_START@
5*bbb1b6f9SApple OSS Distributions *
6*bbb1b6f9SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7*bbb1b6f9SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8*bbb1b6f9SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9*bbb1b6f9SApple OSS Distributions * compliance with the License. Please obtain a copy of the License at
10*bbb1b6f9SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this
11*bbb1b6f9SApple OSS Distributions * file.
12*bbb1b6f9SApple OSS Distributions *
13*bbb1b6f9SApple OSS Distributions * The Original Code and all software distributed under the License are
14*bbb1b6f9SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15*bbb1b6f9SApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16*bbb1b6f9SApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17*bbb1b6f9SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18*bbb1b6f9SApple OSS Distributions * Please see the License for the specific language governing rights and
19*bbb1b6f9SApple OSS Distributions * limitations under the License.
20*bbb1b6f9SApple OSS Distributions *
21*bbb1b6f9SApple OSS Distributions * @APPLE_LICENSE_HEADER_END@
22*bbb1b6f9SApple OSS Distributions */
23*bbb1b6f9SApple OSS Distributions
24*bbb1b6f9SApple OSS Distributions /*-
25*bbb1b6f9SApple OSS Distributions * Portions Copyright (c) 1992, 1993
26*bbb1b6f9SApple OSS Distributions * The Regents of the University of California. All rights reserved.
27*bbb1b6f9SApple OSS Distributions *
28*bbb1b6f9SApple OSS Distributions * This code is derived from software contributed to Berkeley by
29*bbb1b6f9SApple OSS Distributions * John Heidemann of the UCLA Ficus project.
30*bbb1b6f9SApple OSS Distributions *
31*bbb1b6f9SApple OSS Distributions * Redistribution and use in source and binary forms, with or without
32*bbb1b6f9SApple OSS Distributions * modification, are permitted provided that the following conditions
33*bbb1b6f9SApple OSS Distributions * are met:
34*bbb1b6f9SApple OSS Distributions * 1. Redistributions of source code must retain the above copyright
35*bbb1b6f9SApple OSS Distributions * notice, this list of conditions and the following disclaimer.
36*bbb1b6f9SApple OSS Distributions * 2. Redistributions in binary form must reproduce the above copyright
37*bbb1b6f9SApple OSS Distributions * notice, this list of conditions and the following disclaimer in the
38*bbb1b6f9SApple OSS Distributions * documentation and/or other materials provided with the distribution.
39*bbb1b6f9SApple OSS Distributions * 4. Neither the name of the University nor the names of its contributors
40*bbb1b6f9SApple OSS Distributions * may be used to endorse or promote products derived from this software
41*bbb1b6f9SApple OSS Distributions * without specific prior written permission.
42*bbb1b6f9SApple OSS Distributions *
43*bbb1b6f9SApple OSS Distributions * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44*bbb1b6f9SApple OSS Distributions * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45*bbb1b6f9SApple OSS Distributions * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46*bbb1b6f9SApple OSS Distributions * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47*bbb1b6f9SApple OSS Distributions * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48*bbb1b6f9SApple OSS Distributions * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49*bbb1b6f9SApple OSS Distributions * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50*bbb1b6f9SApple OSS Distributions * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51*bbb1b6f9SApple OSS Distributions * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52*bbb1b6f9SApple OSS Distributions * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53*bbb1b6f9SApple OSS Distributions * SUCH DAMAGE.
54*bbb1b6f9SApple OSS Distributions *
55*bbb1b6f9SApple OSS Distributions * @(#)null_vnops.c 8.6 (Berkeley) 5/27/95
56*bbb1b6f9SApple OSS Distributions *
57*bbb1b6f9SApple OSS Distributions * Ancestors:
58*bbb1b6f9SApple OSS Distributions * @(#)lofs_vnops.c 1.2 (Berkeley) 6/18/92
59*bbb1b6f9SApple OSS Distributions * ...and...
60*bbb1b6f9SApple OSS Distributions * @(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project
61*bbb1b6f9SApple OSS Distributions *
62*bbb1b6f9SApple OSS Distributions * $FreeBSD$
63*bbb1b6f9SApple OSS Distributions */
64*bbb1b6f9SApple OSS Distributions
65*bbb1b6f9SApple OSS Distributions #include <sys/param.h>
66*bbb1b6f9SApple OSS Distributions #include <sys/systm.h>
67*bbb1b6f9SApple OSS Distributions #include <sys/conf.h>
68*bbb1b6f9SApple OSS Distributions #include <sys/kernel.h>
69*bbb1b6f9SApple OSS Distributions #include <sys/lock.h>
70*bbb1b6f9SApple OSS Distributions #include <sys/malloc.h>
71*bbb1b6f9SApple OSS Distributions #include <sys/mount.h>
72*bbb1b6f9SApple OSS Distributions #include <sys/mount_internal.h>
73*bbb1b6f9SApple OSS Distributions #include <sys/namei.h>
74*bbb1b6f9SApple OSS Distributions #include <sys/sysctl.h>
75*bbb1b6f9SApple OSS Distributions #include <sys/vnode.h>
76*bbb1b6f9SApple OSS Distributions #include <sys/xattr.h>
77*bbb1b6f9SApple OSS Distributions #include <sys/ubc.h>
78*bbb1b6f9SApple OSS Distributions #include <sys/types.h>
79*bbb1b6f9SApple OSS Distributions #include <sys/dirent.h>
80*bbb1b6f9SApple OSS Distributions #include <sys/kauth.h>
81*bbb1b6f9SApple OSS Distributions
82*bbb1b6f9SApple OSS Distributions #include "nullfs.h"
83*bbb1b6f9SApple OSS Distributions
84*bbb1b6f9SApple OSS Distributions #define NULL_ROOT_INO 2
85*bbb1b6f9SApple OSS Distributions #define NULL_SECOND_INO 3
86*bbb1b6f9SApple OSS Distributions #define NULL_THIRD_INO 4
87*bbb1b6f9SApple OSS Distributions
88*bbb1b6f9SApple OSS Distributions vop_t * nullfs_vnodeop_p = NULL;
89*bbb1b6f9SApple OSS Distributions
90*bbb1b6f9SApple OSS Distributions /* the mountpoint lock should be held going into this function */
91*bbb1b6f9SApple OSS Distributions static int
nullfs_isspecialvp(struct vnode * vp)92*bbb1b6f9SApple OSS Distributions nullfs_isspecialvp(struct vnode * vp)
93*bbb1b6f9SApple OSS Distributions {
94*bbb1b6f9SApple OSS Distributions struct null_mount * null_mp;
95*bbb1b6f9SApple OSS Distributions
96*bbb1b6f9SApple OSS Distributions null_mp = MOUNTTONULLMOUNT(vnode_mount(vp));
97*bbb1b6f9SApple OSS Distributions
98*bbb1b6f9SApple OSS Distributions /* only check for root and second here, third is special in a different way,
99*bbb1b6f9SApple OSS Distributions * related only to lookup and readdir */
100*bbb1b6f9SApple OSS Distributions if (vp && (vp == null_mp->nullm_rootvp || vp == null_mp->nullm_secondvp)) {
101*bbb1b6f9SApple OSS Distributions return 1;
102*bbb1b6f9SApple OSS Distributions }
103*bbb1b6f9SApple OSS Distributions return 0;
104*bbb1b6f9SApple OSS Distributions }
105*bbb1b6f9SApple OSS Distributions
106*bbb1b6f9SApple OSS Distributions /* helper function to handle locking where possible */
107*bbb1b6f9SApple OSS Distributions static int
nullfs_checkspecialvp(struct vnode * vp)108*bbb1b6f9SApple OSS Distributions nullfs_checkspecialvp(struct vnode* vp)
109*bbb1b6f9SApple OSS Distributions {
110*bbb1b6f9SApple OSS Distributions int result = 0;
111*bbb1b6f9SApple OSS Distributions struct null_mount * null_mp;
112*bbb1b6f9SApple OSS Distributions
113*bbb1b6f9SApple OSS Distributions null_mp = MOUNTTONULLMOUNT(vnode_mount(vp));
114*bbb1b6f9SApple OSS Distributions
115*bbb1b6f9SApple OSS Distributions lck_mtx_lock(&null_mp->nullm_lock);
116*bbb1b6f9SApple OSS Distributions result = (nullfs_isspecialvp(vp));
117*bbb1b6f9SApple OSS Distributions lck_mtx_unlock(&null_mp->nullm_lock);
118*bbb1b6f9SApple OSS Distributions
119*bbb1b6f9SApple OSS Distributions return result;
120*bbb1b6f9SApple OSS Distributions }
121*bbb1b6f9SApple OSS Distributions
122*bbb1b6f9SApple OSS Distributions vfs_context_t
nullfs_get_patched_context(struct null_mount * null_mp,vfs_context_t ctx)123*bbb1b6f9SApple OSS Distributions nullfs_get_patched_context(struct null_mount * null_mp, vfs_context_t ctx)
124*bbb1b6f9SApple OSS Distributions {
125*bbb1b6f9SApple OSS Distributions struct vfs_context *ectx = ctx;
126*bbb1b6f9SApple OSS Distributions kauth_cred_t ucred;
127*bbb1b6f9SApple OSS Distributions
128*bbb1b6f9SApple OSS Distributions if ((null_mp->nullm_flags & NULLM_UNVEIL) == NULLM_UNVEIL) {
129*bbb1b6f9SApple OSS Distributions ectx = vfs_context_create(ctx);
130*bbb1b6f9SApple OSS Distributions ucred = kauth_cred_derive(ectx->vc_ucred,
131*bbb1b6f9SApple OSS Distributions ^bool (kauth_cred_t parent __unused, kauth_cred_t model) {
132*bbb1b6f9SApple OSS Distributions return kauth_cred_model_setuidgid(model,
133*bbb1b6f9SApple OSS Distributions null_mp->uid, null_mp->gid);
134*bbb1b6f9SApple OSS Distributions });
135*bbb1b6f9SApple OSS Distributions kauth_cred_unref(&ectx->vc_ucred);
136*bbb1b6f9SApple OSS Distributions ectx->vc_ucred = ucred;
137*bbb1b6f9SApple OSS Distributions }
138*bbb1b6f9SApple OSS Distributions return ectx;
139*bbb1b6f9SApple OSS Distributions }
140*bbb1b6f9SApple OSS Distributions
141*bbb1b6f9SApple OSS Distributions void
nullfs_cleanup_patched_context(struct null_mount * null_mp,vfs_context_t ctx)142*bbb1b6f9SApple OSS Distributions nullfs_cleanup_patched_context(struct null_mount * null_mp, vfs_context_t ctx)
143*bbb1b6f9SApple OSS Distributions {
144*bbb1b6f9SApple OSS Distributions if ((null_mp->nullm_flags & NULLM_UNVEIL) == NULLM_UNVEIL) {
145*bbb1b6f9SApple OSS Distributions vfs_context_rele(ctx);
146*bbb1b6f9SApple OSS Distributions }
147*bbb1b6f9SApple OSS Distributions }
148*bbb1b6f9SApple OSS Distributions
149*bbb1b6f9SApple OSS Distributions static int
nullfs_default(__unused struct vnop_generic_args * args)150*bbb1b6f9SApple OSS Distributions nullfs_default(__unused struct vnop_generic_args * args)
151*bbb1b6f9SApple OSS Distributions {
152*bbb1b6f9SApple OSS Distributions NULLFSDEBUG("%s (default)\n", ((struct vnodeop_desc_fake *)args->a_desc)->vdesc_name);
153*bbb1b6f9SApple OSS Distributions return ENOTSUP;
154*bbb1b6f9SApple OSS Distributions }
155*bbb1b6f9SApple OSS Distributions
156*bbb1b6f9SApple OSS Distributions static int
nullfs_special_getattr(struct vnop_getattr_args * args)157*bbb1b6f9SApple OSS Distributions nullfs_special_getattr(struct vnop_getattr_args * args)
158*bbb1b6f9SApple OSS Distributions {
159*bbb1b6f9SApple OSS Distributions mount_t mp = vnode_mount(args->a_vp);
160*bbb1b6f9SApple OSS Distributions struct null_mount * null_mp = MOUNTTONULLMOUNT(mp);
161*bbb1b6f9SApple OSS Distributions
162*bbb1b6f9SApple OSS Distributions ino_t ino = NULL_ROOT_INO;
163*bbb1b6f9SApple OSS Distributions struct vnode_attr covered_rootattr;
164*bbb1b6f9SApple OSS Distributions vnode_t checkvp = null_mp->nullm_lowerrootvp;
165*bbb1b6f9SApple OSS Distributions vfs_context_t ectx = nullfs_get_patched_context(null_mp, args->a_context);
166*bbb1b6f9SApple OSS Distributions
167*bbb1b6f9SApple OSS Distributions VATTR_INIT(&covered_rootattr);
168*bbb1b6f9SApple OSS Distributions VATTR_WANTED(&covered_rootattr, va_uid);
169*bbb1b6f9SApple OSS Distributions VATTR_WANTED(&covered_rootattr, va_gid);
170*bbb1b6f9SApple OSS Distributions VATTR_WANTED(&covered_rootattr, va_create_time);
171*bbb1b6f9SApple OSS Distributions VATTR_WANTED(&covered_rootattr, va_modify_time);
172*bbb1b6f9SApple OSS Distributions VATTR_WANTED(&covered_rootattr, va_access_time);
173*bbb1b6f9SApple OSS Distributions
174*bbb1b6f9SApple OSS Distributions /* prefer to get this from the lower root vp, but if not (i.e. forced unmount
175*bbb1b6f9SApple OSS Distributions * of lower fs) try the mount point covered vnode */
176*bbb1b6f9SApple OSS Distributions if (vnode_getwithvid(checkvp, null_mp->nullm_lowerrootvid)) {
177*bbb1b6f9SApple OSS Distributions checkvp = vfs_vnodecovered(mp);
178*bbb1b6f9SApple OSS Distributions if (checkvp == NULL) {
179*bbb1b6f9SApple OSS Distributions nullfs_cleanup_patched_context(null_mp, ectx);
180*bbb1b6f9SApple OSS Distributions return EIO;
181*bbb1b6f9SApple OSS Distributions }
182*bbb1b6f9SApple OSS Distributions }
183*bbb1b6f9SApple OSS Distributions
184*bbb1b6f9SApple OSS Distributions int error = vnode_getattr(checkvp, &covered_rootattr, ectx);
185*bbb1b6f9SApple OSS Distributions
186*bbb1b6f9SApple OSS Distributions vnode_put(checkvp);
187*bbb1b6f9SApple OSS Distributions if (error) {
188*bbb1b6f9SApple OSS Distributions /* we should have been able to get attributes fore one of the two choices so
189*bbb1b6f9SApple OSS Distributions * fail if we didn't */
190*bbb1b6f9SApple OSS Distributions nullfs_cleanup_patched_context(null_mp, ectx);
191*bbb1b6f9SApple OSS Distributions return error;
192*bbb1b6f9SApple OSS Distributions }
193*bbb1b6f9SApple OSS Distributions
194*bbb1b6f9SApple OSS Distributions /* we got the attributes of the vnode we cover so plow ahead */
195*bbb1b6f9SApple OSS Distributions if (args->a_vp == null_mp->nullm_secondvp) {
196*bbb1b6f9SApple OSS Distributions ino = NULL_SECOND_INO;
197*bbb1b6f9SApple OSS Distributions }
198*bbb1b6f9SApple OSS Distributions
199*bbb1b6f9SApple OSS Distributions VATTR_RETURN(args->a_vap, va_type, vnode_vtype(args->a_vp));
200*bbb1b6f9SApple OSS Distributions VATTR_RETURN(args->a_vap, va_rdev, 0);
201*bbb1b6f9SApple OSS Distributions VATTR_RETURN(args->a_vap, va_nlink, 3); /* always just ., .., and the child */
202*bbb1b6f9SApple OSS Distributions VATTR_RETURN(args->a_vap, va_total_size, 0); // hoping this is ok
203*bbb1b6f9SApple OSS Distributions
204*bbb1b6f9SApple OSS Distributions VATTR_RETURN(args->a_vap, va_data_size, 0); // hoping this is ok
205*bbb1b6f9SApple OSS Distributions VATTR_RETURN(args->a_vap, va_data_alloc, 0);
206*bbb1b6f9SApple OSS Distributions VATTR_RETURN(args->a_vap, va_iosize, vfs_statfs(mp)->f_iosize);
207*bbb1b6f9SApple OSS Distributions VATTR_RETURN(args->a_vap, va_fileid, ino);
208*bbb1b6f9SApple OSS Distributions VATTR_RETURN(args->a_vap, va_linkid, ino);
209*bbb1b6f9SApple OSS Distributions if (VATTR_IS_ACTIVE(args->a_vap, va_fsid)) {
210*bbb1b6f9SApple OSS Distributions VATTR_RETURN(args->a_vap, va_fsid, vfs_statfs(mp)->f_fsid.val[0]); // return the fsid of the mount point
211*bbb1b6f9SApple OSS Distributions }
212*bbb1b6f9SApple OSS Distributions if (VATTR_IS_ACTIVE(args->a_vap, va_fsid64)) {
213*bbb1b6f9SApple OSS Distributions VATTR_RETURN(args->a_vap, va_fsid64, vfs_statfs(mp)->f_fsid);
214*bbb1b6f9SApple OSS Distributions }
215*bbb1b6f9SApple OSS Distributions VATTR_RETURN(args->a_vap, va_filerev, 0);
216*bbb1b6f9SApple OSS Distributions VATTR_RETURN(args->a_vap, va_gen, 0);
217*bbb1b6f9SApple OSS Distributions VATTR_RETURN(args->a_vap, va_flags, UF_HIDDEN); /* mark our fake directories as hidden. People
218*bbb1b6f9SApple OSS Distributions * shouldn't be enocouraged to poke around in them */
219*bbb1b6f9SApple OSS Distributions
220*bbb1b6f9SApple OSS Distributions if (ino == NULL_SECOND_INO) {
221*bbb1b6f9SApple OSS Distributions VATTR_RETURN(args->a_vap, va_parentid, NULL_ROOT_INO); /* no parent at the root, so
222*bbb1b6f9SApple OSS Distributions * the only other vnode that
223*bbb1b6f9SApple OSS Distributions * goes through this path is
224*bbb1b6f9SApple OSS Distributions * second and its parent is
225*bbb1b6f9SApple OSS Distributions * 1.*/
226*bbb1b6f9SApple OSS Distributions }
227*bbb1b6f9SApple OSS Distributions
228*bbb1b6f9SApple OSS Distributions if (VATTR_IS_ACTIVE(args->a_vap, va_mode)) {
229*bbb1b6f9SApple OSS Distributions /* force dr_xr_xr_x */
230*bbb1b6f9SApple OSS Distributions VATTR_RETURN(args->a_vap, va_mode, S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
231*bbb1b6f9SApple OSS Distributions }
232*bbb1b6f9SApple OSS Distributions if (VATTR_IS_ACTIVE(args->a_vap, va_uid)) {
233*bbb1b6f9SApple OSS Distributions VATTR_RETURN(args->a_vap, va_uid, covered_rootattr.va_uid);
234*bbb1b6f9SApple OSS Distributions }
235*bbb1b6f9SApple OSS Distributions if (VATTR_IS_ACTIVE(args->a_vap, va_gid)) {
236*bbb1b6f9SApple OSS Distributions VATTR_RETURN(args->a_vap, va_gid, covered_rootattr.va_gid);
237*bbb1b6f9SApple OSS Distributions }
238*bbb1b6f9SApple OSS Distributions
239*bbb1b6f9SApple OSS Distributions if (VATTR_IS_ACTIVE(args->a_vap, va_create_time)) {
240*bbb1b6f9SApple OSS Distributions VATTR_SET_SUPPORTED(args->a_vap, va_create_time);
241*bbb1b6f9SApple OSS Distributions args->a_vap->va_create_time.tv_sec = covered_rootattr.va_create_time.tv_sec;
242*bbb1b6f9SApple OSS Distributions args->a_vap->va_create_time.tv_nsec = covered_rootattr.va_create_time.tv_nsec;
243*bbb1b6f9SApple OSS Distributions }
244*bbb1b6f9SApple OSS Distributions if (VATTR_IS_ACTIVE(args->a_vap, va_modify_time)) {
245*bbb1b6f9SApple OSS Distributions VATTR_SET_SUPPORTED(args->a_vap, va_modify_time);
246*bbb1b6f9SApple OSS Distributions args->a_vap->va_modify_time.tv_sec = covered_rootattr.va_modify_time.tv_sec;
247*bbb1b6f9SApple OSS Distributions args->a_vap->va_modify_time.tv_nsec = covered_rootattr.va_modify_time.tv_nsec;
248*bbb1b6f9SApple OSS Distributions }
249*bbb1b6f9SApple OSS Distributions if (VATTR_IS_ACTIVE(args->a_vap, va_access_time)) {
250*bbb1b6f9SApple OSS Distributions VATTR_SET_SUPPORTED(args->a_vap, va_access_time);
251*bbb1b6f9SApple OSS Distributions args->a_vap->va_modify_time.tv_sec = covered_rootattr.va_access_time.tv_sec;
252*bbb1b6f9SApple OSS Distributions args->a_vap->va_modify_time.tv_nsec = covered_rootattr.va_access_time.tv_nsec;
253*bbb1b6f9SApple OSS Distributions }
254*bbb1b6f9SApple OSS Distributions
255*bbb1b6f9SApple OSS Distributions nullfs_cleanup_patched_context(null_mp, ectx);
256*bbb1b6f9SApple OSS Distributions return 0;
257*bbb1b6f9SApple OSS Distributions }
258*bbb1b6f9SApple OSS Distributions
259*bbb1b6f9SApple OSS Distributions static int
nullfs_getattr(struct vnop_getattr_args * args)260*bbb1b6f9SApple OSS Distributions nullfs_getattr(struct vnop_getattr_args * args)
261*bbb1b6f9SApple OSS Distributions {
262*bbb1b6f9SApple OSS Distributions int error;
263*bbb1b6f9SApple OSS Distributions struct null_mount * null_mp = MOUNTTONULLMOUNT(vnode_mount(args->a_vp));
264*bbb1b6f9SApple OSS Distributions kauth_cred_t cred = vfs_context_ucred(args->a_context);
265*bbb1b6f9SApple OSS Distributions NULLFSDEBUG("%s %p\n", __FUNCTION__, args->a_vp);
266*bbb1b6f9SApple OSS Distributions
267*bbb1b6f9SApple OSS Distributions if (nullfs_checkspecialvp(args->a_vp)) {
268*bbb1b6f9SApple OSS Distributions error = nullfs_special_getattr(args);
269*bbb1b6f9SApple OSS Distributions return error;
270*bbb1b6f9SApple OSS Distributions }
271*bbb1b6f9SApple OSS Distributions
272*bbb1b6f9SApple OSS Distributions /* this will return a different inode for third than read dir will */
273*bbb1b6f9SApple OSS Distributions struct vnode * lowervp = NULLVPTOLOWERVP(args->a_vp);
274*bbb1b6f9SApple OSS Distributions vfs_context_t ectx = nullfs_get_patched_context(null_mp, args->a_context);
275*bbb1b6f9SApple OSS Distributions error = vnode_getwithref(lowervp);
276*bbb1b6f9SApple OSS Distributions
277*bbb1b6f9SApple OSS Distributions if (error == 0) {
278*bbb1b6f9SApple OSS Distributions error = VNOP_GETATTR(lowervp, args->a_vap, ectx);
279*bbb1b6f9SApple OSS Distributions vnode_put(lowervp);
280*bbb1b6f9SApple OSS Distributions
281*bbb1b6f9SApple OSS Distributions if (error == 0) {
282*bbb1b6f9SApple OSS Distributions /* fix up fsid so it doesn't say the underlying fs*/
283*bbb1b6f9SApple OSS Distributions if (VATTR_IS_ACTIVE(args->a_vap, va_fsid)) {
284*bbb1b6f9SApple OSS Distributions VATTR_RETURN(args->a_vap, va_fsid, vfs_statfs(vnode_mount(args->a_vp))->f_fsid.val[0]);
285*bbb1b6f9SApple OSS Distributions }
286*bbb1b6f9SApple OSS Distributions if (VATTR_IS_ACTIVE(args->a_vap, va_fsid64)) {
287*bbb1b6f9SApple OSS Distributions VATTR_RETURN(args->a_vap, va_fsid64, vfs_statfs(vnode_mount(args->a_vp))->f_fsid);
288*bbb1b6f9SApple OSS Distributions }
289*bbb1b6f9SApple OSS Distributions
290*bbb1b6f9SApple OSS Distributions /* Conjure up permissions */
291*bbb1b6f9SApple OSS Distributions if ((null_mp->nullm_flags & NULLM_UNVEIL) == NULLM_UNVEIL) {
292*bbb1b6f9SApple OSS Distributions if (VATTR_IS_ACTIVE(args->a_vap, va_mode)) {
293*bbb1b6f9SApple OSS Distributions mode_t mode = args->a_vap->va_mode; // We will take away permisions if we don't have them
294*bbb1b6f9SApple OSS Distributions
295*bbb1b6f9SApple OSS Distributions // Check for authorizations
296*bbb1b6f9SApple OSS Distributions // If we can read:
297*bbb1b6f9SApple OSS Distributions if (vnode_authorize(lowervp, NULL, KAUTH_VNODE_GENERIC_READ_BITS, ectx) == 0) {
298*bbb1b6f9SApple OSS Distributions mode |= S_IRUSR;
299*bbb1b6f9SApple OSS Distributions } else {
300*bbb1b6f9SApple OSS Distributions mode &= ~S_IRUSR;
301*bbb1b6f9SApple OSS Distributions }
302*bbb1b6f9SApple OSS Distributions
303*bbb1b6f9SApple OSS Distributions // Or execute
304*bbb1b6f9SApple OSS Distributions // Directories need an execute bit...
305*bbb1b6f9SApple OSS Distributions if (vnode_authorize(lowervp, NULL, KAUTH_VNODE_GENERIC_EXECUTE_BITS, ectx) == 0) {
306*bbb1b6f9SApple OSS Distributions mode |= S_IXUSR;
307*bbb1b6f9SApple OSS Distributions } else {
308*bbb1b6f9SApple OSS Distributions mode &= ~S_IXUSR;
309*bbb1b6f9SApple OSS Distributions }
310*bbb1b6f9SApple OSS Distributions
311*bbb1b6f9SApple OSS Distributions NULLFSDEBUG("Settings bits to %d\n", mode);
312*bbb1b6f9SApple OSS Distributions VATTR_RETURN(args->a_vap, va_mode, mode);
313*bbb1b6f9SApple OSS Distributions }
314*bbb1b6f9SApple OSS Distributions if (VATTR_IS_ACTIVE(args->a_vap, va_uid)) {
315*bbb1b6f9SApple OSS Distributions VATTR_RETURN(args->a_vap, va_uid, kauth_cred_getuid(cred));
316*bbb1b6f9SApple OSS Distributions }
317*bbb1b6f9SApple OSS Distributions if (VATTR_IS_ACTIVE(args->a_vap, va_gid)) {
318*bbb1b6f9SApple OSS Distributions VATTR_RETURN(args->a_vap, va_gid, kauth_cred_getgid(cred));
319*bbb1b6f9SApple OSS Distributions }
320*bbb1b6f9SApple OSS Distributions }
321*bbb1b6f9SApple OSS Distributions }
322*bbb1b6f9SApple OSS Distributions }
323*bbb1b6f9SApple OSS Distributions
324*bbb1b6f9SApple OSS Distributions nullfs_cleanup_patched_context(null_mp, ectx);
325*bbb1b6f9SApple OSS Distributions return error;
326*bbb1b6f9SApple OSS Distributions }
327*bbb1b6f9SApple OSS Distributions
328*bbb1b6f9SApple OSS Distributions static int
nullfs_open(struct vnop_open_args * args)329*bbb1b6f9SApple OSS Distributions nullfs_open(struct vnop_open_args * args)
330*bbb1b6f9SApple OSS Distributions {
331*bbb1b6f9SApple OSS Distributions int error;
332*bbb1b6f9SApple OSS Distributions struct vnode *vp, *lvp;
333*bbb1b6f9SApple OSS Distributions mount_t mp = vnode_mount(args->a_vp);
334*bbb1b6f9SApple OSS Distributions struct null_mount * null_mp = MOUNTTONULLMOUNT(mp);
335*bbb1b6f9SApple OSS Distributions NULLFSDEBUG("%s %p\n", __FUNCTION__, args->a_vp);
336*bbb1b6f9SApple OSS Distributions
337*bbb1b6f9SApple OSS Distributions if (nullfs_checkspecialvp(args->a_vp)) {
338*bbb1b6f9SApple OSS Distributions return 0; /* nothing extra needed */
339*bbb1b6f9SApple OSS Distributions }
340*bbb1b6f9SApple OSS Distributions
341*bbb1b6f9SApple OSS Distributions vfs_context_t ectx = nullfs_get_patched_context(null_mp, args->a_context);
342*bbb1b6f9SApple OSS Distributions vp = args->a_vp;
343*bbb1b6f9SApple OSS Distributions lvp = NULLVPTOLOWERVP(vp);
344*bbb1b6f9SApple OSS Distributions error = vnode_getwithref(lvp);
345*bbb1b6f9SApple OSS Distributions if (error == 0) {
346*bbb1b6f9SApple OSS Distributions error = VNOP_OPEN(lvp, args->a_mode, ectx);
347*bbb1b6f9SApple OSS Distributions vnode_put(lvp);
348*bbb1b6f9SApple OSS Distributions }
349*bbb1b6f9SApple OSS Distributions
350*bbb1b6f9SApple OSS Distributions nullfs_cleanup_patched_context(null_mp, ectx);
351*bbb1b6f9SApple OSS Distributions return error;
352*bbb1b6f9SApple OSS Distributions }
353*bbb1b6f9SApple OSS Distributions
354*bbb1b6f9SApple OSS Distributions static int
nullfs_close(struct vnop_close_args * args)355*bbb1b6f9SApple OSS Distributions nullfs_close(struct vnop_close_args * args)
356*bbb1b6f9SApple OSS Distributions {
357*bbb1b6f9SApple OSS Distributions int error;
358*bbb1b6f9SApple OSS Distributions struct vnode *vp, *lvp;
359*bbb1b6f9SApple OSS Distributions mount_t mp = vnode_mount(args->a_vp);
360*bbb1b6f9SApple OSS Distributions struct null_mount * null_mp = MOUNTTONULLMOUNT(mp);
361*bbb1b6f9SApple OSS Distributions
362*bbb1b6f9SApple OSS Distributions NULLFSDEBUG("%s %p\n", __FUNCTION__, args->a_vp);
363*bbb1b6f9SApple OSS Distributions
364*bbb1b6f9SApple OSS Distributions if (nullfs_checkspecialvp(args->a_vp)) {
365*bbb1b6f9SApple OSS Distributions return 0; /* nothing extra needed */
366*bbb1b6f9SApple OSS Distributions }
367*bbb1b6f9SApple OSS Distributions
368*bbb1b6f9SApple OSS Distributions vfs_context_t ectx = nullfs_get_patched_context(null_mp, args->a_context);
369*bbb1b6f9SApple OSS Distributions vp = args->a_vp;
370*bbb1b6f9SApple OSS Distributions lvp = NULLVPTOLOWERVP(vp);
371*bbb1b6f9SApple OSS Distributions
372*bbb1b6f9SApple OSS Distributions error = vnode_getwithref(lvp);
373*bbb1b6f9SApple OSS Distributions if (error == 0) {
374*bbb1b6f9SApple OSS Distributions error = VNOP_CLOSE(lvp, args->a_fflag, ectx);
375*bbb1b6f9SApple OSS Distributions vnode_put(lvp);
376*bbb1b6f9SApple OSS Distributions }
377*bbb1b6f9SApple OSS Distributions
378*bbb1b6f9SApple OSS Distributions nullfs_cleanup_patched_context(null_mp, ectx);
379*bbb1b6f9SApple OSS Distributions return error;
380*bbb1b6f9SApple OSS Distributions }
381*bbb1b6f9SApple OSS Distributions
382*bbb1b6f9SApple OSS Distributions /* get lvp's parent, if possible, even if it isn't set.
383*bbb1b6f9SApple OSS Distributions *
384*bbb1b6f9SApple OSS Distributions * lvp is expected to have an iocount before and after this call.
385*bbb1b6f9SApple OSS Distributions *
386*bbb1b6f9SApple OSS Distributions * if a dvpp is populated the returned vnode has an iocount. */
387*bbb1b6f9SApple OSS Distributions static int
null_get_lowerparent(vnode_t lvp,vnode_t * dvpp,vfs_context_t ctx)388*bbb1b6f9SApple OSS Distributions null_get_lowerparent(vnode_t lvp, vnode_t * dvpp, vfs_context_t ctx)
389*bbb1b6f9SApple OSS Distributions {
390*bbb1b6f9SApple OSS Distributions int error = 0;
391*bbb1b6f9SApple OSS Distributions struct vnode_attr va;
392*bbb1b6f9SApple OSS Distributions mount_t mp = vnode_mount(lvp);
393*bbb1b6f9SApple OSS Distributions vnode_t dvp = vnode_parent(lvp);
394*bbb1b6f9SApple OSS Distributions
395*bbb1b6f9SApple OSS Distributions if (dvp) {
396*bbb1b6f9SApple OSS Distributions error = vnode_get(dvp);
397*bbb1b6f9SApple OSS Distributions goto end;
398*bbb1b6f9SApple OSS Distributions }
399*bbb1b6f9SApple OSS Distributions
400*bbb1b6f9SApple OSS Distributions error = ENOENT;
401*bbb1b6f9SApple OSS Distributions if (!(mp->mnt_kern_flag & MNTK_PATH_FROM_ID)) {
402*bbb1b6f9SApple OSS Distributions goto end;
403*bbb1b6f9SApple OSS Distributions }
404*bbb1b6f9SApple OSS Distributions
405*bbb1b6f9SApple OSS Distributions VATTR_INIT(&va);
406*bbb1b6f9SApple OSS Distributions VATTR_WANTED(&va, va_parentid);
407*bbb1b6f9SApple OSS Distributions
408*bbb1b6f9SApple OSS Distributions error = vnode_getattr(lvp, &va, ctx);
409*bbb1b6f9SApple OSS Distributions
410*bbb1b6f9SApple OSS Distributions if (error || !VATTR_IS_SUPPORTED(&va, va_parentid)) {
411*bbb1b6f9SApple OSS Distributions if (!error) {
412*bbb1b6f9SApple OSS Distributions error = ENOTSUP;
413*bbb1b6f9SApple OSS Distributions }
414*bbb1b6f9SApple OSS Distributions goto end;
415*bbb1b6f9SApple OSS Distributions }
416*bbb1b6f9SApple OSS Distributions
417*bbb1b6f9SApple OSS Distributions error = VFS_VGET(mp, (ino64_t)va.va_parentid, &dvp, ctx);
418*bbb1b6f9SApple OSS Distributions
419*bbb1b6f9SApple OSS Distributions end:
420*bbb1b6f9SApple OSS Distributions if (error == 0) {
421*bbb1b6f9SApple OSS Distributions *dvpp = dvp;
422*bbb1b6f9SApple OSS Distributions }
423*bbb1b6f9SApple OSS Distributions return error;
424*bbb1b6f9SApple OSS Distributions }
425*bbb1b6f9SApple OSS Distributions
426*bbb1b6f9SApple OSS Distributions /* the mountpoint lock should be held going into this function */
427*bbb1b6f9SApple OSS Distributions static int
null_special_lookup(struct vnop_lookup_args * ap)428*bbb1b6f9SApple OSS Distributions null_special_lookup(struct vnop_lookup_args * ap)
429*bbb1b6f9SApple OSS Distributions {
430*bbb1b6f9SApple OSS Distributions struct componentname * cnp = ap->a_cnp;
431*bbb1b6f9SApple OSS Distributions struct vnode * dvp = ap->a_dvp;
432*bbb1b6f9SApple OSS Distributions struct vnode * ldvp = NULL;
433*bbb1b6f9SApple OSS Distributions struct vnode * lvp = NULL;
434*bbb1b6f9SApple OSS Distributions struct vnode * vp = NULL;
435*bbb1b6f9SApple OSS Distributions struct vnode * tempvp = NULL;
436*bbb1b6f9SApple OSS Distributions struct mount * mp = vnode_mount(dvp);
437*bbb1b6f9SApple OSS Distributions struct null_mount * null_mp = MOUNTTONULLMOUNT(mp);
438*bbb1b6f9SApple OSS Distributions int error = ENOENT;
439*bbb1b6f9SApple OSS Distributions vfs_context_t ectx = nullfs_get_patched_context(null_mp, ap->a_context);
440*bbb1b6f9SApple OSS Distributions
441*bbb1b6f9SApple OSS Distributions // null_mp->nullm_lock is locked
442*bbb1b6f9SApple OSS Distributions if (dvp == null_mp->nullm_rootvp) {
443*bbb1b6f9SApple OSS Distributions /* handle . and .. */
444*bbb1b6f9SApple OSS Distributions if (cnp->cn_nameptr[0] == '.') {
445*bbb1b6f9SApple OSS Distributions if (cnp->cn_namelen == 1 || (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.')) {
446*bbb1b6f9SApple OSS Distributions /* this is the root so both . and .. give back the root */
447*bbb1b6f9SApple OSS Distributions vp = dvp;
448*bbb1b6f9SApple OSS Distributions lck_mtx_unlock(&null_mp->nullm_lock);
449*bbb1b6f9SApple OSS Distributions error = vnode_get(vp);
450*bbb1b6f9SApple OSS Distributions goto end;
451*bbb1b6f9SApple OSS Distributions }
452*bbb1b6f9SApple OSS Distributions }
453*bbb1b6f9SApple OSS Distributions
454*bbb1b6f9SApple OSS Distributions /* our virtual wrapper directory should be d but D is acceptable if the
455*bbb1b6f9SApple OSS Distributions * lower file system is case insensitive */
456*bbb1b6f9SApple OSS Distributions if (cnp->cn_namelen == 1 &&
457*bbb1b6f9SApple OSS Distributions (cnp->cn_nameptr[0] == 'd' || (null_mp->nullm_flags & NULLM_CASEINSENSITIVE ? cnp->cn_nameptr[0] == 'D' : 0))) {
458*bbb1b6f9SApple OSS Distributions error = 0;
459*bbb1b6f9SApple OSS Distributions if (null_mp->nullm_secondvp == NULL) {
460*bbb1b6f9SApple OSS Distributions // drop the lock before making a new vnode
461*bbb1b6f9SApple OSS Distributions lck_mtx_unlock(&null_mp->nullm_lock);
462*bbb1b6f9SApple OSS Distributions error = null_getnewvnode(mp, NULL, dvp, &vp, cnp, 0);
463*bbb1b6f9SApple OSS Distributions if (error) {
464*bbb1b6f9SApple OSS Distributions goto end;
465*bbb1b6f9SApple OSS Distributions }
466*bbb1b6f9SApple OSS Distributions // Get the lock before modifying nullm_secondvp
467*bbb1b6f9SApple OSS Distributions lck_mtx_lock(&null_mp->nullm_lock);
468*bbb1b6f9SApple OSS Distributions if (null_mp->nullm_secondvp == NULL) {
469*bbb1b6f9SApple OSS Distributions null_mp->nullm_secondvp = vp;
470*bbb1b6f9SApple OSS Distributions lck_mtx_unlock(&null_mp->nullm_lock);
471*bbb1b6f9SApple OSS Distributions } else {
472*bbb1b6f9SApple OSS Distributions /* Another thread already set null_mp->nullm_secondvp while the
473*bbb1b6f9SApple OSS Distributions * lock was dropped so recycle the vnode we just made */
474*bbb1b6f9SApple OSS Distributions tempvp = vp;
475*bbb1b6f9SApple OSS Distributions vp = null_mp->nullm_secondvp;
476*bbb1b6f9SApple OSS Distributions lck_mtx_unlock(&null_mp->nullm_lock);
477*bbb1b6f9SApple OSS Distributions /* recycle will call reclaim which will get rid of the internals */
478*bbb1b6f9SApple OSS Distributions vnode_recycle(tempvp);
479*bbb1b6f9SApple OSS Distributions vnode_put(tempvp);
480*bbb1b6f9SApple OSS Distributions
481*bbb1b6f9SApple OSS Distributions error = vnode_get(vp);
482*bbb1b6f9SApple OSS Distributions }
483*bbb1b6f9SApple OSS Distributions } else {
484*bbb1b6f9SApple OSS Distributions vp = null_mp->nullm_secondvp;
485*bbb1b6f9SApple OSS Distributions lck_mtx_unlock(&null_mp->nullm_lock);
486*bbb1b6f9SApple OSS Distributions error = vnode_get(vp);
487*bbb1b6f9SApple OSS Distributions }
488*bbb1b6f9SApple OSS Distributions } else {
489*bbb1b6f9SApple OSS Distributions lck_mtx_unlock(&null_mp->nullm_lock);
490*bbb1b6f9SApple OSS Distributions }
491*bbb1b6f9SApple OSS Distributions } else if (dvp == null_mp->nullm_secondvp) {
492*bbb1b6f9SApple OSS Distributions /* handle . and .. */
493*bbb1b6f9SApple OSS Distributions if (cnp->cn_nameptr[0] == '.') {
494*bbb1b6f9SApple OSS Distributions if (cnp->cn_namelen == 1) {
495*bbb1b6f9SApple OSS Distributions vp = dvp;
496*bbb1b6f9SApple OSS Distributions lck_mtx_unlock(&null_mp->nullm_lock);
497*bbb1b6f9SApple OSS Distributions error = vnode_get(vp);
498*bbb1b6f9SApple OSS Distributions goto end;
499*bbb1b6f9SApple OSS Distributions } else if (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.') {
500*bbb1b6f9SApple OSS Distributions /* parent here is the root vp */
501*bbb1b6f9SApple OSS Distributions vp = null_mp->nullm_rootvp;
502*bbb1b6f9SApple OSS Distributions lck_mtx_unlock(&null_mp->nullm_lock);
503*bbb1b6f9SApple OSS Distributions error = vnode_get(vp);
504*bbb1b6f9SApple OSS Distributions goto end;
505*bbb1b6f9SApple OSS Distributions }
506*bbb1b6f9SApple OSS Distributions }
507*bbb1b6f9SApple OSS Distributions /* nullmp->nullm_lowerrootvp was set at mount time so don't need to lock to
508*bbb1b6f9SApple OSS Distributions * access it */
509*bbb1b6f9SApple OSS Distributions /* Drop the global lock since we aren't accessing rootvp or secondvp any more */
510*bbb1b6f9SApple OSS Distributions lck_mtx_unlock(&null_mp->nullm_lock);
511*bbb1b6f9SApple OSS Distributions error = vnode_getwithvid(null_mp->nullm_lowerrootvp, null_mp->nullm_lowerrootvid);
512*bbb1b6f9SApple OSS Distributions if (error) {
513*bbb1b6f9SApple OSS Distributions goto end;
514*bbb1b6f9SApple OSS Distributions }
515*bbb1b6f9SApple OSS Distributions
516*bbb1b6f9SApple OSS Distributions /* We don't want to mess with case insensitivity and unicode, so the plan to
517*bbb1b6f9SApple OSS Distributions * check here is
518*bbb1b6f9SApple OSS Distributions * 1. try to get the lower root's parent
519*bbb1b6f9SApple OSS Distributions * 2. If we get a parent, then perform a lookup on the lower file system
520*bbb1b6f9SApple OSS Distributions * using the parent and the passed in cnp
521*bbb1b6f9SApple OSS Distributions * 3. If that worked and we got a vp, then see if the vp is lowerrootvp. If
522*bbb1b6f9SApple OSS Distributions * so we got a match
523*bbb1b6f9SApple OSS Distributions * 4. Anything else results in ENOENT.
524*bbb1b6f9SApple OSS Distributions */
525*bbb1b6f9SApple OSS Distributions error = null_get_lowerparent(null_mp->nullm_lowerrootvp, &ldvp, ectx);
526*bbb1b6f9SApple OSS Distributions
527*bbb1b6f9SApple OSS Distributions if (error == 0) {
528*bbb1b6f9SApple OSS Distributions error = VNOP_LOOKUP(ldvp, &lvp, cnp, ectx);
529*bbb1b6f9SApple OSS Distributions vnode_put(ldvp);
530*bbb1b6f9SApple OSS Distributions
531*bbb1b6f9SApple OSS Distributions if (error == 0) {
532*bbb1b6f9SApple OSS Distributions // nullm_lowerrootvp is only touched during mount and unmount so we don't need the lock to check it.
533*bbb1b6f9SApple OSS Distributions if (lvp == null_mp->nullm_lowerrootvp) {
534*bbb1b6f9SApple OSS Distributions /* always check the hashmap for a vnode for this, the root of the
535*bbb1b6f9SApple OSS Distributions * mirrored system */
536*bbb1b6f9SApple OSS Distributions error = null_nodeget(mp, lvp, dvp, &vp, cnp, 0);
537*bbb1b6f9SApple OSS Distributions } else {
538*bbb1b6f9SApple OSS Distributions error = ENOENT;
539*bbb1b6f9SApple OSS Distributions }
540*bbb1b6f9SApple OSS Distributions vnode_put(lvp);
541*bbb1b6f9SApple OSS Distributions }
542*bbb1b6f9SApple OSS Distributions }
543*bbb1b6f9SApple OSS Distributions vnode_put(null_mp->nullm_lowerrootvp);
544*bbb1b6f9SApple OSS Distributions }
545*bbb1b6f9SApple OSS Distributions
546*bbb1b6f9SApple OSS Distributions end:
547*bbb1b6f9SApple OSS Distributions nullfs_cleanup_patched_context(null_mp, ectx);
548*bbb1b6f9SApple OSS Distributions if (error == 0) {
549*bbb1b6f9SApple OSS Distributions *ap->a_vpp = vp;
550*bbb1b6f9SApple OSS Distributions }
551*bbb1b6f9SApple OSS Distributions return error;
552*bbb1b6f9SApple OSS Distributions }
553*bbb1b6f9SApple OSS Distributions
554*bbb1b6f9SApple OSS Distributions /*
555*bbb1b6f9SApple OSS Distributions * We have to carry on the locking protocol on the null layer vnodes
556*bbb1b6f9SApple OSS Distributions * as we progress through the tree. We also have to enforce read-only
557*bbb1b6f9SApple OSS Distributions * if this layer is mounted read-only.
558*bbb1b6f9SApple OSS Distributions */
559*bbb1b6f9SApple OSS Distributions static int
null_lookup(struct vnop_lookup_args * ap)560*bbb1b6f9SApple OSS Distributions null_lookup(struct vnop_lookup_args * ap)
561*bbb1b6f9SApple OSS Distributions {
562*bbb1b6f9SApple OSS Distributions struct componentname * cnp = ap->a_cnp;
563*bbb1b6f9SApple OSS Distributions struct vnode * dvp = ap->a_dvp;
564*bbb1b6f9SApple OSS Distributions struct vnode *vp, *ldvp, *lvp;
565*bbb1b6f9SApple OSS Distributions struct mount * mp;
566*bbb1b6f9SApple OSS Distributions struct null_mount * null_mp;
567*bbb1b6f9SApple OSS Distributions int error;
568*bbb1b6f9SApple OSS Distributions vfs_context_t ectx;
569*bbb1b6f9SApple OSS Distributions
570*bbb1b6f9SApple OSS Distributions NULLFSDEBUG("%s parent: %p component: %.*s\n", __FUNCTION__, ap->a_dvp, cnp->cn_namelen, cnp->cn_nameptr);
571*bbb1b6f9SApple OSS Distributions
572*bbb1b6f9SApple OSS Distributions mp = vnode_mount(dvp);
573*bbb1b6f9SApple OSS Distributions /* rename and delete are not allowed. this is a read only file system */
574*bbb1b6f9SApple OSS Distributions if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME || cnp->cn_nameiop == CREATE) {
575*bbb1b6f9SApple OSS Distributions return EROFS;
576*bbb1b6f9SApple OSS Distributions }
577*bbb1b6f9SApple OSS Distributions null_mp = MOUNTTONULLMOUNT(mp);
578*bbb1b6f9SApple OSS Distributions
579*bbb1b6f9SApple OSS Distributions
580*bbb1b6f9SApple OSS Distributions lck_mtx_lock(&null_mp->nullm_lock);
581*bbb1b6f9SApple OSS Distributions if (nullfs_isspecialvp(dvp)) {
582*bbb1b6f9SApple OSS Distributions error = null_special_lookup(ap);
583*bbb1b6f9SApple OSS Distributions // null_special_lookup drops the lock
584*bbb1b6f9SApple OSS Distributions return error;
585*bbb1b6f9SApple OSS Distributions }
586*bbb1b6f9SApple OSS Distributions lck_mtx_unlock(&null_mp->nullm_lock);
587*bbb1b6f9SApple OSS Distributions
588*bbb1b6f9SApple OSS Distributions // . and .. handling
589*bbb1b6f9SApple OSS Distributions if (cnp->cn_nameptr[0] == '.') {
590*bbb1b6f9SApple OSS Distributions if (cnp->cn_namelen == 1) {
591*bbb1b6f9SApple OSS Distributions vp = dvp;
592*bbb1b6f9SApple OSS Distributions } else if (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.') {
593*bbb1b6f9SApple OSS Distributions /* mount point crossing is handled in null_special_lookup */
594*bbb1b6f9SApple OSS Distributions vp = vnode_parent(dvp);
595*bbb1b6f9SApple OSS Distributions } else {
596*bbb1b6f9SApple OSS Distributions goto notdot;
597*bbb1b6f9SApple OSS Distributions }
598*bbb1b6f9SApple OSS Distributions
599*bbb1b6f9SApple OSS Distributions error = vp ? vnode_get(vp) : ENOENT;
600*bbb1b6f9SApple OSS Distributions
601*bbb1b6f9SApple OSS Distributions if (error == 0) {
602*bbb1b6f9SApple OSS Distributions *ap->a_vpp = vp;
603*bbb1b6f9SApple OSS Distributions }
604*bbb1b6f9SApple OSS Distributions
605*bbb1b6f9SApple OSS Distributions return error;
606*bbb1b6f9SApple OSS Distributions }
607*bbb1b6f9SApple OSS Distributions
608*bbb1b6f9SApple OSS Distributions notdot:
609*bbb1b6f9SApple OSS Distributions ectx = nullfs_get_patched_context(null_mp, ap->a_context);
610*bbb1b6f9SApple OSS Distributions ldvp = NULLVPTOLOWERVP(dvp);
611*bbb1b6f9SApple OSS Distributions vp = lvp = NULL;
612*bbb1b6f9SApple OSS Distributions
613*bbb1b6f9SApple OSS Distributions /*
614*bbb1b6f9SApple OSS Distributions * Hold ldvp. The reference on it, owned by dvp, is lost in
615*bbb1b6f9SApple OSS Distributions * case of dvp reclamation.
616*bbb1b6f9SApple OSS Distributions */
617*bbb1b6f9SApple OSS Distributions error = vnode_getwithref(ldvp);
618*bbb1b6f9SApple OSS Distributions if (error) {
619*bbb1b6f9SApple OSS Distributions nullfs_cleanup_patched_context(null_mp, ectx);
620*bbb1b6f9SApple OSS Distributions return error;
621*bbb1b6f9SApple OSS Distributions }
622*bbb1b6f9SApple OSS Distributions
623*bbb1b6f9SApple OSS Distributions error = VNOP_LOOKUP(ldvp, &lvp, cnp, ectx);
624*bbb1b6f9SApple OSS Distributions
625*bbb1b6f9SApple OSS Distributions vnode_put(ldvp);
626*bbb1b6f9SApple OSS Distributions
627*bbb1b6f9SApple OSS Distributions if ((error == 0 || error == EJUSTRETURN) && lvp != NULL) {
628*bbb1b6f9SApple OSS Distributions if (ldvp == lvp) {
629*bbb1b6f9SApple OSS Distributions vp = dvp;
630*bbb1b6f9SApple OSS Distributions error = vnode_get(vp);
631*bbb1b6f9SApple OSS Distributions } else {
632*bbb1b6f9SApple OSS Distributions error = null_nodeget(mp, lvp, dvp, &vp, cnp, 0);
633*bbb1b6f9SApple OSS Distributions }
634*bbb1b6f9SApple OSS Distributions if (error == 0) {
635*bbb1b6f9SApple OSS Distributions *ap->a_vpp = vp;
636*bbb1b6f9SApple OSS Distributions }
637*bbb1b6f9SApple OSS Distributions /* if we got lvp, drop the iocount from VNOP_LOOKUP */
638*bbb1b6f9SApple OSS Distributions if (lvp != NULL) {
639*bbb1b6f9SApple OSS Distributions vnode_put(lvp);
640*bbb1b6f9SApple OSS Distributions }
641*bbb1b6f9SApple OSS Distributions }
642*bbb1b6f9SApple OSS Distributions
643*bbb1b6f9SApple OSS Distributions nullfs_cleanup_patched_context(null_mp, ectx);
644*bbb1b6f9SApple OSS Distributions return error;
645*bbb1b6f9SApple OSS Distributions }
646*bbb1b6f9SApple OSS Distributions
647*bbb1b6f9SApple OSS Distributions /*
648*bbb1b6f9SApple OSS Distributions * Don't think this needs to do anything
649*bbb1b6f9SApple OSS Distributions */
650*bbb1b6f9SApple OSS Distributions static int
null_inactive(__unused struct vnop_inactive_args * ap)651*bbb1b6f9SApple OSS Distributions null_inactive(__unused struct vnop_inactive_args * ap)
652*bbb1b6f9SApple OSS Distributions {
653*bbb1b6f9SApple OSS Distributions NULLFSDEBUG("%s %p\n", __FUNCTION__, ap->a_vp);
654*bbb1b6f9SApple OSS Distributions
655*bbb1b6f9SApple OSS Distributions return 0;
656*bbb1b6f9SApple OSS Distributions }
657*bbb1b6f9SApple OSS Distributions
658*bbb1b6f9SApple OSS Distributions static int
null_reclaim(struct vnop_reclaim_args * ap)659*bbb1b6f9SApple OSS Distributions null_reclaim(struct vnop_reclaim_args * ap)
660*bbb1b6f9SApple OSS Distributions {
661*bbb1b6f9SApple OSS Distributions struct vnode * vp;
662*bbb1b6f9SApple OSS Distributions struct null_node * xp;
663*bbb1b6f9SApple OSS Distributions struct vnode * lowervp;
664*bbb1b6f9SApple OSS Distributions struct null_mount * null_mp = MOUNTTONULLMOUNT(vnode_mount(ap->a_vp));
665*bbb1b6f9SApple OSS Distributions
666*bbb1b6f9SApple OSS Distributions NULLFSDEBUG("%s %p\n", __FUNCTION__, ap->a_vp);
667*bbb1b6f9SApple OSS Distributions
668*bbb1b6f9SApple OSS Distributions vp = ap->a_vp;
669*bbb1b6f9SApple OSS Distributions
670*bbb1b6f9SApple OSS Distributions xp = VTONULL(vp);
671*bbb1b6f9SApple OSS Distributions lowervp = xp->null_lowervp;
672*bbb1b6f9SApple OSS Distributions
673*bbb1b6f9SApple OSS Distributions lck_mtx_lock(&null_mp->nullm_lock);
674*bbb1b6f9SApple OSS Distributions
675*bbb1b6f9SApple OSS Distributions vnode_removefsref(vp);
676*bbb1b6f9SApple OSS Distributions
677*bbb1b6f9SApple OSS Distributions if (lowervp != NULL) {
678*bbb1b6f9SApple OSS Distributions /* root and second don't have a lowervp, so nothing to release and nothing
679*bbb1b6f9SApple OSS Distributions * got hashed */
680*bbb1b6f9SApple OSS Distributions if (xp->null_flags & NULL_FLAG_HASHED) {
681*bbb1b6f9SApple OSS Distributions /* only call this if we actually made it into the hash list. reclaim gets
682*bbb1b6f9SApple OSS Distributions * called also to
683*bbb1b6f9SApple OSS Distributions * clean up a vnode that got created when it didn't need to under race
684*bbb1b6f9SApple OSS Distributions * conditions */
685*bbb1b6f9SApple OSS Distributions null_hashrem(xp);
686*bbb1b6f9SApple OSS Distributions }
687*bbb1b6f9SApple OSS Distributions vnode_rele(lowervp);
688*bbb1b6f9SApple OSS Distributions }
689*bbb1b6f9SApple OSS Distributions
690*bbb1b6f9SApple OSS Distributions if (vp == null_mp->nullm_rootvp) {
691*bbb1b6f9SApple OSS Distributions null_mp->nullm_rootvp = NULL;
692*bbb1b6f9SApple OSS Distributions } else if (vp == null_mp->nullm_secondvp) {
693*bbb1b6f9SApple OSS Distributions null_mp->nullm_secondvp = NULL;
694*bbb1b6f9SApple OSS Distributions }
695*bbb1b6f9SApple OSS Distributions
696*bbb1b6f9SApple OSS Distributions lck_mtx_unlock(&null_mp->nullm_lock);
697*bbb1b6f9SApple OSS Distributions
698*bbb1b6f9SApple OSS Distributions cache_purge(vp);
699*bbb1b6f9SApple OSS Distributions vnode_clearfsnode(vp);
700*bbb1b6f9SApple OSS Distributions
701*bbb1b6f9SApple OSS Distributions kfree_type(struct null_node, xp);
702*bbb1b6f9SApple OSS Distributions
703*bbb1b6f9SApple OSS Distributions return 0;
704*bbb1b6f9SApple OSS Distributions }
705*bbb1b6f9SApple OSS Distributions
706*bbb1b6f9SApple OSS Distributions #define DIRENT_SZ(dp) ((sizeof(struct dirent) - NAME_MAX) + (((dp)->d_namlen + 1 + 3) & ~3))
707*bbb1b6f9SApple OSS Distributions
708*bbb1b6f9SApple OSS Distributions static int
store_entry_special(ino_t ino,const char * name,struct uio * uio)709*bbb1b6f9SApple OSS Distributions store_entry_special(ino_t ino, const char * name, struct uio * uio)
710*bbb1b6f9SApple OSS Distributions {
711*bbb1b6f9SApple OSS Distributions struct dirent e;
712*bbb1b6f9SApple OSS Distributions size_t namelen = strlen(name);
713*bbb1b6f9SApple OSS Distributions int error = EINVAL;
714*bbb1b6f9SApple OSS Distributions
715*bbb1b6f9SApple OSS Distributions if (namelen + 1 <= NAME_MAX) {
716*bbb1b6f9SApple OSS Distributions memset(&e, 0, sizeof(e));
717*bbb1b6f9SApple OSS Distributions
718*bbb1b6f9SApple OSS Distributions e.d_ino = ino;
719*bbb1b6f9SApple OSS Distributions e.d_type = DT_DIR;
720*bbb1b6f9SApple OSS Distributions
721*bbb1b6f9SApple OSS Distributions e.d_namlen = namelen; /* don't include NUL */
722*bbb1b6f9SApple OSS Distributions e.d_reclen = DIRENT_SZ(&e);
723*bbb1b6f9SApple OSS Distributions if (uio_resid(uio) >= e.d_reclen) {
724*bbb1b6f9SApple OSS Distributions strlcpy(e.d_name, name, NAME_MAX);
725*bbb1b6f9SApple OSS Distributions error = uiomove((caddr_t)&e, e.d_reclen, uio);
726*bbb1b6f9SApple OSS Distributions } else {
727*bbb1b6f9SApple OSS Distributions error = EMSGSIZE;
728*bbb1b6f9SApple OSS Distributions }
729*bbb1b6f9SApple OSS Distributions }
730*bbb1b6f9SApple OSS Distributions return error;
731*bbb1b6f9SApple OSS Distributions }
732*bbb1b6f9SApple OSS Distributions
733*bbb1b6f9SApple OSS Distributions static int
nullfs_special_readdir(struct vnop_readdir_args * ap)734*bbb1b6f9SApple OSS Distributions nullfs_special_readdir(struct vnop_readdir_args * ap)
735*bbb1b6f9SApple OSS Distributions {
736*bbb1b6f9SApple OSS Distributions struct vnode * vp = ap->a_vp;
737*bbb1b6f9SApple OSS Distributions struct uio * uio = ap->a_uio;
738*bbb1b6f9SApple OSS Distributions struct null_mount * null_mp = MOUNTTONULLMOUNT(vnode_mount(vp));
739*bbb1b6f9SApple OSS Distributions off_t offset = uio_offset(uio);
740*bbb1b6f9SApple OSS Distributions int error = ERANGE;
741*bbb1b6f9SApple OSS Distributions int items = 0;
742*bbb1b6f9SApple OSS Distributions ino_t ino = 0;
743*bbb1b6f9SApple OSS Distributions const char * name = NULL;
744*bbb1b6f9SApple OSS Distributions boolean_t locked = TRUE;
745*bbb1b6f9SApple OSS Distributions
746*bbb1b6f9SApple OSS Distributions if (ap->a_flags & (VNODE_READDIR_EXTENDED | VNODE_READDIR_REQSEEKOFF)) {
747*bbb1b6f9SApple OSS Distributions lck_mtx_unlock(&null_mp->nullm_lock);
748*bbb1b6f9SApple OSS Distributions return EINVAL;
749*bbb1b6f9SApple OSS Distributions }
750*bbb1b6f9SApple OSS Distributions
751*bbb1b6f9SApple OSS Distributions if (offset == 0) {
752*bbb1b6f9SApple OSS Distributions /* . case */
753*bbb1b6f9SApple OSS Distributions if (vp == null_mp->nullm_rootvp) {
754*bbb1b6f9SApple OSS Distributions ino = NULL_ROOT_INO;
755*bbb1b6f9SApple OSS Distributions } else { /* only get here if vp matches nullm_rootvp or nullm_secondvp */
756*bbb1b6f9SApple OSS Distributions ino = NULL_SECOND_INO;
757*bbb1b6f9SApple OSS Distributions }
758*bbb1b6f9SApple OSS Distributions error = store_entry_special(ino, ".", uio);
759*bbb1b6f9SApple OSS Distributions if (error) {
760*bbb1b6f9SApple OSS Distributions goto out;
761*bbb1b6f9SApple OSS Distributions }
762*bbb1b6f9SApple OSS Distributions offset++;
763*bbb1b6f9SApple OSS Distributions items++;
764*bbb1b6f9SApple OSS Distributions }
765*bbb1b6f9SApple OSS Distributions if (offset == 1) {
766*bbb1b6f9SApple OSS Distributions /* .. case */
767*bbb1b6f9SApple OSS Distributions /* only get here if vp matches nullm_rootvp or nullm_secondvp */
768*bbb1b6f9SApple OSS Distributions ino = NULL_ROOT_INO;
769*bbb1b6f9SApple OSS Distributions
770*bbb1b6f9SApple OSS Distributions error = store_entry_special(ino, "..", uio);
771*bbb1b6f9SApple OSS Distributions if (error) {
772*bbb1b6f9SApple OSS Distributions goto out;
773*bbb1b6f9SApple OSS Distributions }
774*bbb1b6f9SApple OSS Distributions offset++;
775*bbb1b6f9SApple OSS Distributions items++;
776*bbb1b6f9SApple OSS Distributions }
777*bbb1b6f9SApple OSS Distributions if (offset == 2) {
778*bbb1b6f9SApple OSS Distributions /* the directory case */
779*bbb1b6f9SApple OSS Distributions if (vp == null_mp->nullm_rootvp) {
780*bbb1b6f9SApple OSS Distributions ino = NULL_SECOND_INO;
781*bbb1b6f9SApple OSS Distributions name = "d";
782*bbb1b6f9SApple OSS Distributions } else { /* only get here if vp matches nullm_rootvp or nullm_secondvp */
783*bbb1b6f9SApple OSS Distributions // drop the lock before performing operations on nullm_lowerrootvp
784*bbb1b6f9SApple OSS Distributions lck_mtx_unlock(&null_mp->nullm_lock);
785*bbb1b6f9SApple OSS Distributions locked = FALSE;
786*bbb1b6f9SApple OSS Distributions ino = NULL_THIRD_INO;
787*bbb1b6f9SApple OSS Distributions if (vnode_getwithvid(null_mp->nullm_lowerrootvp, null_mp->nullm_lowerrootvid)) {
788*bbb1b6f9SApple OSS Distributions /* In this case the lower file system has been ripped out from under us,
789*bbb1b6f9SApple OSS Distributions * but we don't want to error out
790*bbb1b6f9SApple OSS Distributions * Instead we just want d to look empty. */
791*bbb1b6f9SApple OSS Distributions error = 0;
792*bbb1b6f9SApple OSS Distributions goto out;
793*bbb1b6f9SApple OSS Distributions }
794*bbb1b6f9SApple OSS Distributions name = vnode_getname_printable(null_mp->nullm_lowerrootvp);
795*bbb1b6f9SApple OSS Distributions }
796*bbb1b6f9SApple OSS Distributions error = store_entry_special(ino, name, uio);
797*bbb1b6f9SApple OSS Distributions
798*bbb1b6f9SApple OSS Distributions if (ino == NULL_THIRD_INO) {
799*bbb1b6f9SApple OSS Distributions vnode_putname_printable(name);
800*bbb1b6f9SApple OSS Distributions vnode_put(null_mp->nullm_lowerrootvp);
801*bbb1b6f9SApple OSS Distributions }
802*bbb1b6f9SApple OSS Distributions
803*bbb1b6f9SApple OSS Distributions if (error) {
804*bbb1b6f9SApple OSS Distributions goto out;
805*bbb1b6f9SApple OSS Distributions }
806*bbb1b6f9SApple OSS Distributions offset++;
807*bbb1b6f9SApple OSS Distributions items++;
808*bbb1b6f9SApple OSS Distributions }
809*bbb1b6f9SApple OSS Distributions
810*bbb1b6f9SApple OSS Distributions out:
811*bbb1b6f9SApple OSS Distributions if (locked) {
812*bbb1b6f9SApple OSS Distributions lck_mtx_unlock(&null_mp->nullm_lock);
813*bbb1b6f9SApple OSS Distributions }
814*bbb1b6f9SApple OSS Distributions if (error == EMSGSIZE) {
815*bbb1b6f9SApple OSS Distributions error = 0; /* return success if we ran out of space, but we wanted to make
816*bbb1b6f9SApple OSS Distributions * sure that we didn't update offset and items incorrectly */
817*bbb1b6f9SApple OSS Distributions }
818*bbb1b6f9SApple OSS Distributions uio_setoffset(uio, offset);
819*bbb1b6f9SApple OSS Distributions if (ap->a_numdirent) {
820*bbb1b6f9SApple OSS Distributions *ap->a_numdirent = items;
821*bbb1b6f9SApple OSS Distributions }
822*bbb1b6f9SApple OSS Distributions return error;
823*bbb1b6f9SApple OSS Distributions }
824*bbb1b6f9SApple OSS Distributions
825*bbb1b6f9SApple OSS Distributions static int
nullfs_readdir(struct vnop_readdir_args * ap)826*bbb1b6f9SApple OSS Distributions nullfs_readdir(struct vnop_readdir_args * ap)
827*bbb1b6f9SApple OSS Distributions {
828*bbb1b6f9SApple OSS Distributions struct vnode *vp, *lvp;
829*bbb1b6f9SApple OSS Distributions int error;
830*bbb1b6f9SApple OSS Distributions struct null_mount * null_mp = MOUNTTONULLMOUNT(vnode_mount(ap->a_vp));
831*bbb1b6f9SApple OSS Distributions
832*bbb1b6f9SApple OSS Distributions NULLFSDEBUG("%s %p\n", __FUNCTION__, ap->a_vp);
833*bbb1b6f9SApple OSS Distributions /* assumption is that any vp that comes through here had to go through lookup
834*bbb1b6f9SApple OSS Distributions */
835*bbb1b6f9SApple OSS Distributions
836*bbb1b6f9SApple OSS Distributions lck_mtx_lock(&null_mp->nullm_lock);
837*bbb1b6f9SApple OSS Distributions if (nullfs_isspecialvp(ap->a_vp)) {
838*bbb1b6f9SApple OSS Distributions error = nullfs_special_readdir(ap);
839*bbb1b6f9SApple OSS Distributions // nullfs_special_readdir drops the lock
840*bbb1b6f9SApple OSS Distributions return error;
841*bbb1b6f9SApple OSS Distributions }
842*bbb1b6f9SApple OSS Distributions lck_mtx_unlock(&null_mp->nullm_lock);
843*bbb1b6f9SApple OSS Distributions
844*bbb1b6f9SApple OSS Distributions vfs_context_t ectx = nullfs_get_patched_context(null_mp, ap->a_context);
845*bbb1b6f9SApple OSS Distributions vp = ap->a_vp;
846*bbb1b6f9SApple OSS Distributions lvp = NULLVPTOLOWERVP(vp);
847*bbb1b6f9SApple OSS Distributions error = vnode_getwithref(lvp);
848*bbb1b6f9SApple OSS Distributions if (error == 0) {
849*bbb1b6f9SApple OSS Distributions error = VNOP_READDIR(lvp, ap->a_uio, ap->a_flags, ap->a_eofflag, ap->a_numdirent, ectx);
850*bbb1b6f9SApple OSS Distributions vnode_put(lvp);
851*bbb1b6f9SApple OSS Distributions }
852*bbb1b6f9SApple OSS Distributions
853*bbb1b6f9SApple OSS Distributions nullfs_cleanup_patched_context(null_mp, ectx);
854*bbb1b6f9SApple OSS Distributions return error;
855*bbb1b6f9SApple OSS Distributions }
856*bbb1b6f9SApple OSS Distributions
857*bbb1b6f9SApple OSS Distributions static int
nullfs_readlink(struct vnop_readlink_args * ap)858*bbb1b6f9SApple OSS Distributions nullfs_readlink(struct vnop_readlink_args * ap)
859*bbb1b6f9SApple OSS Distributions {
860*bbb1b6f9SApple OSS Distributions NULLFSDEBUG("%s %p\n", __FUNCTION__, ap->a_vp);
861*bbb1b6f9SApple OSS Distributions int error;
862*bbb1b6f9SApple OSS Distributions struct vnode *vp, *lvp;
863*bbb1b6f9SApple OSS Distributions struct null_mount * null_mp = MOUNTTONULLMOUNT(vnode_mount(ap->a_vp));
864*bbb1b6f9SApple OSS Distributions
865*bbb1b6f9SApple OSS Distributions if (nullfs_checkspecialvp(ap->a_vp)) {
866*bbb1b6f9SApple OSS Distributions return ENOTSUP; /* the special vnodes aren't links */
867*bbb1b6f9SApple OSS Distributions }
868*bbb1b6f9SApple OSS Distributions
869*bbb1b6f9SApple OSS Distributions vfs_context_t ectx = nullfs_get_patched_context(null_mp, ap->a_context);
870*bbb1b6f9SApple OSS Distributions vp = ap->a_vp;
871*bbb1b6f9SApple OSS Distributions lvp = NULLVPTOLOWERVP(vp);
872*bbb1b6f9SApple OSS Distributions
873*bbb1b6f9SApple OSS Distributions error = vnode_getwithref(lvp);
874*bbb1b6f9SApple OSS Distributions if (error == 0) {
875*bbb1b6f9SApple OSS Distributions error = VNOP_READLINK(lvp, ap->a_uio, ectx);
876*bbb1b6f9SApple OSS Distributions vnode_put(lvp);
877*bbb1b6f9SApple OSS Distributions
878*bbb1b6f9SApple OSS Distributions if (error) {
879*bbb1b6f9SApple OSS Distributions NULLFSDEBUG("readlink failed: %d\n", error);
880*bbb1b6f9SApple OSS Distributions }
881*bbb1b6f9SApple OSS Distributions }
882*bbb1b6f9SApple OSS Distributions
883*bbb1b6f9SApple OSS Distributions nullfs_cleanup_patched_context(null_mp, ectx);
884*bbb1b6f9SApple OSS Distributions return error;
885*bbb1b6f9SApple OSS Distributions }
886*bbb1b6f9SApple OSS Distributions
887*bbb1b6f9SApple OSS Distributions static int
nullfs_pathconf(__unused struct vnop_pathconf_args * args)888*bbb1b6f9SApple OSS Distributions nullfs_pathconf(__unused struct vnop_pathconf_args * args)
889*bbb1b6f9SApple OSS Distributions {
890*bbb1b6f9SApple OSS Distributions NULLFSDEBUG("%s %p\n", __FUNCTION__, args->a_vp);
891*bbb1b6f9SApple OSS Distributions return EINVAL;
892*bbb1b6f9SApple OSS Distributions }
893*bbb1b6f9SApple OSS Distributions
894*bbb1b6f9SApple OSS Distributions static int
nullfs_fsync(__unused struct vnop_fsync_args * args)895*bbb1b6f9SApple OSS Distributions nullfs_fsync(__unused struct vnop_fsync_args * args)
896*bbb1b6f9SApple OSS Distributions {
897*bbb1b6f9SApple OSS Distributions NULLFSDEBUG("%s %p\n", __FUNCTION__, args->a_vp);
898*bbb1b6f9SApple OSS Distributions return 0;
899*bbb1b6f9SApple OSS Distributions }
900*bbb1b6f9SApple OSS Distributions
901*bbb1b6f9SApple OSS Distributions static int
nullfs_mmap(struct vnop_mmap_args * args)902*bbb1b6f9SApple OSS Distributions nullfs_mmap(struct vnop_mmap_args * args)
903*bbb1b6f9SApple OSS Distributions {
904*bbb1b6f9SApple OSS Distributions int error;
905*bbb1b6f9SApple OSS Distributions struct vnode *vp, *lvp;
906*bbb1b6f9SApple OSS Distributions struct null_mount * null_mp = MOUNTTONULLMOUNT(vnode_mount(args->a_vp));
907*bbb1b6f9SApple OSS Distributions
908*bbb1b6f9SApple OSS Distributions NULLFSDEBUG("%s %p\n", __FUNCTION__, args->a_vp);
909*bbb1b6f9SApple OSS Distributions
910*bbb1b6f9SApple OSS Distributions if (nullfs_checkspecialvp(args->a_vp)) {
911*bbb1b6f9SApple OSS Distributions return 0; /* nothing extra needed */
912*bbb1b6f9SApple OSS Distributions }
913*bbb1b6f9SApple OSS Distributions
914*bbb1b6f9SApple OSS Distributions vfs_context_t ectx = nullfs_get_patched_context(null_mp, args->a_context);
915*bbb1b6f9SApple OSS Distributions vp = args->a_vp;
916*bbb1b6f9SApple OSS Distributions lvp = NULLVPTOLOWERVP(vp);
917*bbb1b6f9SApple OSS Distributions error = vnode_getwithref(lvp);
918*bbb1b6f9SApple OSS Distributions if (error == 0) {
919*bbb1b6f9SApple OSS Distributions error = VNOP_MMAP(lvp, args->a_fflags, ectx);
920*bbb1b6f9SApple OSS Distributions vnode_put(lvp);
921*bbb1b6f9SApple OSS Distributions }
922*bbb1b6f9SApple OSS Distributions
923*bbb1b6f9SApple OSS Distributions nullfs_cleanup_patched_context(null_mp, ectx);
924*bbb1b6f9SApple OSS Distributions return error;
925*bbb1b6f9SApple OSS Distributions }
926*bbb1b6f9SApple OSS Distributions
927*bbb1b6f9SApple OSS Distributions static int
nullfs_mnomap(struct vnop_mnomap_args * args)928*bbb1b6f9SApple OSS Distributions nullfs_mnomap(struct vnop_mnomap_args * args)
929*bbb1b6f9SApple OSS Distributions {
930*bbb1b6f9SApple OSS Distributions int error;
931*bbb1b6f9SApple OSS Distributions struct vnode *vp, *lvp;
932*bbb1b6f9SApple OSS Distributions struct null_mount * null_mp = MOUNTTONULLMOUNT(vnode_mount(args->a_vp));
933*bbb1b6f9SApple OSS Distributions
934*bbb1b6f9SApple OSS Distributions NULLFSDEBUG("%s %p\n", __FUNCTION__, args->a_vp);
935*bbb1b6f9SApple OSS Distributions
936*bbb1b6f9SApple OSS Distributions if (nullfs_checkspecialvp(args->a_vp)) {
937*bbb1b6f9SApple OSS Distributions return 0; /* nothing extra needed */
938*bbb1b6f9SApple OSS Distributions }
939*bbb1b6f9SApple OSS Distributions
940*bbb1b6f9SApple OSS Distributions vfs_context_t ectx = nullfs_get_patched_context(null_mp, args->a_context);
941*bbb1b6f9SApple OSS Distributions vp = args->a_vp;
942*bbb1b6f9SApple OSS Distributions lvp = NULLVPTOLOWERVP(vp);
943*bbb1b6f9SApple OSS Distributions error = vnode_getwithref(lvp);
944*bbb1b6f9SApple OSS Distributions if (error == 0) {
945*bbb1b6f9SApple OSS Distributions error = VNOP_MNOMAP(lvp, ectx);
946*bbb1b6f9SApple OSS Distributions vnode_put(lvp);
947*bbb1b6f9SApple OSS Distributions }
948*bbb1b6f9SApple OSS Distributions
949*bbb1b6f9SApple OSS Distributions nullfs_cleanup_patched_context(null_mp, ectx);
950*bbb1b6f9SApple OSS Distributions return error;
951*bbb1b6f9SApple OSS Distributions }
952*bbb1b6f9SApple OSS Distributions
953*bbb1b6f9SApple OSS Distributions static int
nullfs_getxattr(struct vnop_getxattr_args * args)954*bbb1b6f9SApple OSS Distributions nullfs_getxattr(struct vnop_getxattr_args * args)
955*bbb1b6f9SApple OSS Distributions {
956*bbb1b6f9SApple OSS Distributions int error;
957*bbb1b6f9SApple OSS Distributions struct vnode *vp, *lvp;
958*bbb1b6f9SApple OSS Distributions struct null_mount * null_mp = MOUNTTONULLMOUNT(vnode_mount(args->a_vp));
959*bbb1b6f9SApple OSS Distributions
960*bbb1b6f9SApple OSS Distributions NULLFSDEBUG("%s %p\n", __FUNCTION__, args->a_vp);
961*bbb1b6f9SApple OSS Distributions
962*bbb1b6f9SApple OSS Distributions if (nullfs_checkspecialvp(args->a_vp)) {
963*bbb1b6f9SApple OSS Distributions return ENOATTR; /* no xattrs on the special vnodes */
964*bbb1b6f9SApple OSS Distributions }
965*bbb1b6f9SApple OSS Distributions
966*bbb1b6f9SApple OSS Distributions vfs_context_t ectx = nullfs_get_patched_context(null_mp, args->a_context);
967*bbb1b6f9SApple OSS Distributions vp = args->a_vp;
968*bbb1b6f9SApple OSS Distributions lvp = NULLVPTOLOWERVP(vp);
969*bbb1b6f9SApple OSS Distributions error = vnode_getwithref(lvp);
970*bbb1b6f9SApple OSS Distributions if (error == 0) {
971*bbb1b6f9SApple OSS Distributions error = VNOP_GETXATTR(lvp, args->a_name, args->a_uio, args->a_size, args->a_options, ectx);
972*bbb1b6f9SApple OSS Distributions vnode_put(lvp);
973*bbb1b6f9SApple OSS Distributions }
974*bbb1b6f9SApple OSS Distributions
975*bbb1b6f9SApple OSS Distributions nullfs_cleanup_patched_context(null_mp, ectx);
976*bbb1b6f9SApple OSS Distributions return error;
977*bbb1b6f9SApple OSS Distributions }
978*bbb1b6f9SApple OSS Distributions
979*bbb1b6f9SApple OSS Distributions static int
nullfs_listxattr(struct vnop_listxattr_args * args)980*bbb1b6f9SApple OSS Distributions nullfs_listxattr(struct vnop_listxattr_args * args)
981*bbb1b6f9SApple OSS Distributions {
982*bbb1b6f9SApple OSS Distributions int error;
983*bbb1b6f9SApple OSS Distributions struct vnode *vp, *lvp;
984*bbb1b6f9SApple OSS Distributions struct null_mount * null_mp = MOUNTTONULLMOUNT(vnode_mount(args->a_vp));
985*bbb1b6f9SApple OSS Distributions
986*bbb1b6f9SApple OSS Distributions NULLFSDEBUG("%s %p\n", __FUNCTION__, args->a_vp);
987*bbb1b6f9SApple OSS Distributions
988*bbb1b6f9SApple OSS Distributions if (nullfs_checkspecialvp(args->a_vp)) {
989*bbb1b6f9SApple OSS Distributions return 0; /* no xattrs on the special vnodes */
990*bbb1b6f9SApple OSS Distributions }
991*bbb1b6f9SApple OSS Distributions
992*bbb1b6f9SApple OSS Distributions vfs_context_t ectx = nullfs_get_patched_context(null_mp, args->a_context);
993*bbb1b6f9SApple OSS Distributions vp = args->a_vp;
994*bbb1b6f9SApple OSS Distributions lvp = NULLVPTOLOWERVP(vp);
995*bbb1b6f9SApple OSS Distributions error = vnode_getwithref(lvp);
996*bbb1b6f9SApple OSS Distributions if (error == 0) {
997*bbb1b6f9SApple OSS Distributions error = VNOP_LISTXATTR(lvp, args->a_uio, args->a_size, args->a_options, ectx);
998*bbb1b6f9SApple OSS Distributions vnode_put(lvp);
999*bbb1b6f9SApple OSS Distributions }
1000*bbb1b6f9SApple OSS Distributions
1001*bbb1b6f9SApple OSS Distributions nullfs_cleanup_patched_context(null_mp, ectx);
1002*bbb1b6f9SApple OSS Distributions return error;
1003*bbb1b6f9SApple OSS Distributions }
1004*bbb1b6f9SApple OSS Distributions
1005*bbb1b6f9SApple OSS Distributions /* relies on v1 paging */
1006*bbb1b6f9SApple OSS Distributions static int
nullfs_pagein(struct vnop_pagein_args * ap)1007*bbb1b6f9SApple OSS Distributions nullfs_pagein(struct vnop_pagein_args * ap)
1008*bbb1b6f9SApple OSS Distributions {
1009*bbb1b6f9SApple OSS Distributions int error = EIO;
1010*bbb1b6f9SApple OSS Distributions struct vnode *vp, *lvp;
1011*bbb1b6f9SApple OSS Distributions struct null_mount * null_mp = MOUNTTONULLMOUNT(vnode_mount(ap->a_vp));
1012*bbb1b6f9SApple OSS Distributions NULLFSDEBUG("%s %p\n", __FUNCTION__, ap->a_vp);
1013*bbb1b6f9SApple OSS Distributions
1014*bbb1b6f9SApple OSS Distributions vp = ap->a_vp;
1015*bbb1b6f9SApple OSS Distributions lvp = NULLVPTOLOWERVP(vp);
1016*bbb1b6f9SApple OSS Distributions
1017*bbb1b6f9SApple OSS Distributions if (vnode_vtype(vp) != VREG) {
1018*bbb1b6f9SApple OSS Distributions return ENOTSUP;
1019*bbb1b6f9SApple OSS Distributions }
1020*bbb1b6f9SApple OSS Distributions
1021*bbb1b6f9SApple OSS Distributions vfs_context_t ectx = nullfs_get_patched_context(null_mp, ap->a_context);
1022*bbb1b6f9SApple OSS Distributions /*
1023*bbb1b6f9SApple OSS Distributions * Ask VM/UBC/VFS to do our bidding
1024*bbb1b6f9SApple OSS Distributions */
1025*bbb1b6f9SApple OSS Distributions if (vnode_getwithvid(lvp, NULLVPTOLOWERVID(vp)) == 0) {
1026*bbb1b6f9SApple OSS Distributions vm_offset_t ioaddr;
1027*bbb1b6f9SApple OSS Distributions uio_t auio;
1028*bbb1b6f9SApple OSS Distributions kern_return_t kret;
1029*bbb1b6f9SApple OSS Distributions off_t bytes_to_commit;
1030*bbb1b6f9SApple OSS Distributions off_t lowersize;
1031*bbb1b6f9SApple OSS Distributions upl_t upl = ap->a_pl;
1032*bbb1b6f9SApple OSS Distributions user_ssize_t bytes_remaining = 0;
1033*bbb1b6f9SApple OSS Distributions
1034*bbb1b6f9SApple OSS Distributions auio = uio_create(1, ap->a_f_offset, UIO_SYSSPACE, UIO_READ);
1035*bbb1b6f9SApple OSS Distributions if (auio == NULL) {
1036*bbb1b6f9SApple OSS Distributions error = EIO;
1037*bbb1b6f9SApple OSS Distributions goto exit_no_unmap;
1038*bbb1b6f9SApple OSS Distributions }
1039*bbb1b6f9SApple OSS Distributions
1040*bbb1b6f9SApple OSS Distributions kret = ubc_upl_map(upl, &ioaddr);
1041*bbb1b6f9SApple OSS Distributions if (KERN_SUCCESS != kret) {
1042*bbb1b6f9SApple OSS Distributions panic("nullfs_pagein: ubc_upl_map() failed with (%d)", kret);
1043*bbb1b6f9SApple OSS Distributions }
1044*bbb1b6f9SApple OSS Distributions
1045*bbb1b6f9SApple OSS Distributions ioaddr += ap->a_pl_offset;
1046*bbb1b6f9SApple OSS Distributions
1047*bbb1b6f9SApple OSS Distributions error = uio_addiov(auio, (user_addr_t)ioaddr, ap->a_size);
1048*bbb1b6f9SApple OSS Distributions if (error) {
1049*bbb1b6f9SApple OSS Distributions goto exit;
1050*bbb1b6f9SApple OSS Distributions }
1051*bbb1b6f9SApple OSS Distributions
1052*bbb1b6f9SApple OSS Distributions lowersize = ubc_getsize(lvp);
1053*bbb1b6f9SApple OSS Distributions if (lowersize != ubc_getsize(vp)) {
1054*bbb1b6f9SApple OSS Distributions (void)ubc_setsize(vp, lowersize); /* ignore failures, nothing can be done */
1055*bbb1b6f9SApple OSS Distributions }
1056*bbb1b6f9SApple OSS Distributions
1057*bbb1b6f9SApple OSS Distributions error = VNOP_READ(lvp, auio, ((ap->a_flags & UPL_IOSYNC) ? IO_SYNC : 0), ectx);
1058*bbb1b6f9SApple OSS Distributions
1059*bbb1b6f9SApple OSS Distributions bytes_remaining = uio_resid(auio);
1060*bbb1b6f9SApple OSS Distributions if (bytes_remaining > 0 && bytes_remaining <= (user_ssize_t)ap->a_size) {
1061*bbb1b6f9SApple OSS Distributions /* zero bytes that weren't read in to the upl */
1062*bbb1b6f9SApple OSS Distributions bzero((void*)((uintptr_t)(ioaddr + ap->a_size - bytes_remaining)), (size_t) bytes_remaining);
1063*bbb1b6f9SApple OSS Distributions }
1064*bbb1b6f9SApple OSS Distributions
1065*bbb1b6f9SApple OSS Distributions exit:
1066*bbb1b6f9SApple OSS Distributions kret = ubc_upl_unmap(upl);
1067*bbb1b6f9SApple OSS Distributions if (KERN_SUCCESS != kret) {
1068*bbb1b6f9SApple OSS Distributions panic("nullfs_pagein: ubc_upl_unmap() failed with (%d)", kret);
1069*bbb1b6f9SApple OSS Distributions }
1070*bbb1b6f9SApple OSS Distributions
1071*bbb1b6f9SApple OSS Distributions if (auio != NULL) {
1072*bbb1b6f9SApple OSS Distributions uio_free(auio);
1073*bbb1b6f9SApple OSS Distributions }
1074*bbb1b6f9SApple OSS Distributions
1075*bbb1b6f9SApple OSS Distributions exit_no_unmap:
1076*bbb1b6f9SApple OSS Distributions if ((ap->a_flags & UPL_NOCOMMIT) == 0) {
1077*bbb1b6f9SApple OSS Distributions if (!error && (bytes_remaining >= 0) && (bytes_remaining <= (user_ssize_t)ap->a_size)) {
1078*bbb1b6f9SApple OSS Distributions /* only commit what was read in (page aligned)*/
1079*bbb1b6f9SApple OSS Distributions bytes_to_commit = ap->a_size - bytes_remaining;
1080*bbb1b6f9SApple OSS Distributions if (bytes_to_commit) {
1081*bbb1b6f9SApple OSS Distributions /* need to make sure bytes_to_commit and byte_remaining are page aligned before calling ubc_upl_commit_range*/
1082*bbb1b6f9SApple OSS Distributions if (bytes_to_commit & PAGE_MASK) {
1083*bbb1b6f9SApple OSS Distributions bytes_to_commit = (bytes_to_commit & (~PAGE_MASK)) + (PAGE_MASK + 1);
1084*bbb1b6f9SApple OSS Distributions assert(bytes_to_commit <= (off_t)ap->a_size);
1085*bbb1b6f9SApple OSS Distributions
1086*bbb1b6f9SApple OSS Distributions bytes_remaining = ap->a_size - bytes_to_commit;
1087*bbb1b6f9SApple OSS Distributions }
1088*bbb1b6f9SApple OSS Distributions ubc_upl_commit_range(upl, ap->a_pl_offset, (upl_size_t)bytes_to_commit, UPL_COMMIT_FREE_ON_EMPTY);
1089*bbb1b6f9SApple OSS Distributions }
1090*bbb1b6f9SApple OSS Distributions
1091*bbb1b6f9SApple OSS Distributions /* abort anything thats left */
1092*bbb1b6f9SApple OSS Distributions if (bytes_remaining) {
1093*bbb1b6f9SApple OSS Distributions ubc_upl_abort_range(upl, ap->a_pl_offset + bytes_to_commit, (upl_size_t)bytes_remaining, UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
1094*bbb1b6f9SApple OSS Distributions }
1095*bbb1b6f9SApple OSS Distributions } else {
1096*bbb1b6f9SApple OSS Distributions ubc_upl_abort_range(upl, ap->a_pl_offset, (upl_size_t)ap->a_size, UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
1097*bbb1b6f9SApple OSS Distributions }
1098*bbb1b6f9SApple OSS Distributions }
1099*bbb1b6f9SApple OSS Distributions vnode_put(lvp);
1100*bbb1b6f9SApple OSS Distributions } else if ((ap->a_flags & UPL_NOCOMMIT) == 0) {
1101*bbb1b6f9SApple OSS Distributions ubc_upl_abort_range(ap->a_pl, ap->a_pl_offset, (upl_size_t)ap->a_size, UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
1102*bbb1b6f9SApple OSS Distributions }
1103*bbb1b6f9SApple OSS Distributions
1104*bbb1b6f9SApple OSS Distributions nullfs_cleanup_patched_context(null_mp, ectx);
1105*bbb1b6f9SApple OSS Distributions return error;
1106*bbb1b6f9SApple OSS Distributions }
1107*bbb1b6f9SApple OSS Distributions
1108*bbb1b6f9SApple OSS Distributions static int
nullfs_read(struct vnop_read_args * ap)1109*bbb1b6f9SApple OSS Distributions nullfs_read(struct vnop_read_args * ap)
1110*bbb1b6f9SApple OSS Distributions {
1111*bbb1b6f9SApple OSS Distributions int error = EIO;
1112*bbb1b6f9SApple OSS Distributions
1113*bbb1b6f9SApple OSS Distributions struct vnode *vp, *lvp;
1114*bbb1b6f9SApple OSS Distributions struct null_mount * null_mp = MOUNTTONULLMOUNT(vnode_mount(ap->a_vp));
1115*bbb1b6f9SApple OSS Distributions NULLFSDEBUG("%s %p\n", __FUNCTION__, ap->a_vp);
1116*bbb1b6f9SApple OSS Distributions
1117*bbb1b6f9SApple OSS Distributions if (nullfs_checkspecialvp(ap->a_vp)) {
1118*bbb1b6f9SApple OSS Distributions return ENOTSUP; /* the special vnodes can't be read */
1119*bbb1b6f9SApple OSS Distributions }
1120*bbb1b6f9SApple OSS Distributions
1121*bbb1b6f9SApple OSS Distributions vfs_context_t ectx = nullfs_get_patched_context(null_mp, ap->a_context);
1122*bbb1b6f9SApple OSS Distributions vp = ap->a_vp;
1123*bbb1b6f9SApple OSS Distributions lvp = NULLVPTOLOWERVP(vp);
1124*bbb1b6f9SApple OSS Distributions
1125*bbb1b6f9SApple OSS Distributions /*
1126*bbb1b6f9SApple OSS Distributions * First some house keeping
1127*bbb1b6f9SApple OSS Distributions */
1128*bbb1b6f9SApple OSS Distributions if (vnode_getwithvid(lvp, NULLVPTOLOWERVID(vp)) == 0) {
1129*bbb1b6f9SApple OSS Distributions if (!vnode_isreg(lvp) && !vnode_islnk(lvp)) {
1130*bbb1b6f9SApple OSS Distributions error = EPERM;
1131*bbb1b6f9SApple OSS Distributions goto end;
1132*bbb1b6f9SApple OSS Distributions }
1133*bbb1b6f9SApple OSS Distributions
1134*bbb1b6f9SApple OSS Distributions if (uio_resid(ap->a_uio) == 0) {
1135*bbb1b6f9SApple OSS Distributions error = 0;
1136*bbb1b6f9SApple OSS Distributions goto end;
1137*bbb1b6f9SApple OSS Distributions }
1138*bbb1b6f9SApple OSS Distributions
1139*bbb1b6f9SApple OSS Distributions /*
1140*bbb1b6f9SApple OSS Distributions * Now ask VM/UBC/VFS to do our bidding
1141*bbb1b6f9SApple OSS Distributions */
1142*bbb1b6f9SApple OSS Distributions
1143*bbb1b6f9SApple OSS Distributions error = VNOP_READ(lvp, ap->a_uio, ap->a_ioflag, ectx);
1144*bbb1b6f9SApple OSS Distributions if (error) {
1145*bbb1b6f9SApple OSS Distributions NULLFSDEBUG("VNOP_READ failed: %d\n", error);
1146*bbb1b6f9SApple OSS Distributions }
1147*bbb1b6f9SApple OSS Distributions end:
1148*bbb1b6f9SApple OSS Distributions vnode_put(lvp);
1149*bbb1b6f9SApple OSS Distributions }
1150*bbb1b6f9SApple OSS Distributions
1151*bbb1b6f9SApple OSS Distributions nullfs_cleanup_patched_context(null_mp, ectx);
1152*bbb1b6f9SApple OSS Distributions return error;
1153*bbb1b6f9SApple OSS Distributions }
1154*bbb1b6f9SApple OSS Distributions
1155*bbb1b6f9SApple OSS Distributions /*
1156*bbb1b6f9SApple OSS Distributions * Global vfs data structures
1157*bbb1b6f9SApple OSS Distributions */
1158*bbb1b6f9SApple OSS Distributions
1159*bbb1b6f9SApple OSS Distributions static const struct vnodeopv_entry_desc nullfs_vnodeop_entries[] = {
1160*bbb1b6f9SApple OSS Distributions {.opve_op = &vnop_default_desc, .opve_impl = (vop_t)nullfs_default}, {.opve_op = &vnop_getattr_desc, .opve_impl = (vop_t)nullfs_getattr},
1161*bbb1b6f9SApple OSS Distributions {.opve_op = &vnop_open_desc, .opve_impl = (vop_t)nullfs_open}, {.opve_op = &vnop_close_desc, .opve_impl = (vop_t)nullfs_close},
1162*bbb1b6f9SApple OSS Distributions {.opve_op = &vnop_inactive_desc, .opve_impl = (vop_t)null_inactive}, {.opve_op = &vnop_reclaim_desc, .opve_impl = (vop_t)null_reclaim},
1163*bbb1b6f9SApple OSS Distributions {.opve_op = &vnop_lookup_desc, .opve_impl = (vop_t)null_lookup}, {.opve_op = &vnop_readdir_desc, .opve_impl = (vop_t)nullfs_readdir},
1164*bbb1b6f9SApple OSS Distributions {.opve_op = &vnop_readlink_desc, .opve_impl = (vop_t)nullfs_readlink}, {.opve_op = &vnop_pathconf_desc, .opve_impl = (vop_t)nullfs_pathconf},
1165*bbb1b6f9SApple OSS Distributions {.opve_op = &vnop_fsync_desc, .opve_impl = (vop_t)nullfs_fsync}, {.opve_op = &vnop_mmap_desc, .opve_impl = (vop_t)nullfs_mmap},
1166*bbb1b6f9SApple OSS Distributions {.opve_op = &vnop_mnomap_desc, .opve_impl = (vop_t)nullfs_mnomap}, {.opve_op = &vnop_getxattr_desc, .opve_impl = (vop_t)nullfs_getxattr},
1167*bbb1b6f9SApple OSS Distributions {.opve_op = &vnop_pagein_desc, .opve_impl = (vop_t)nullfs_pagein}, {.opve_op = &vnop_read_desc, .opve_impl = (vop_t)nullfs_read},
1168*bbb1b6f9SApple OSS Distributions {.opve_op = &vnop_listxattr_desc, .opve_impl = (vop_t)nullfs_listxattr}, {.opve_op = NULL, .opve_impl = NULL},
1169*bbb1b6f9SApple OSS Distributions };
1170*bbb1b6f9SApple OSS Distributions
1171*bbb1b6f9SApple OSS Distributions const struct vnodeopv_desc nullfs_vnodeop_opv_desc = {.opv_desc_vector_p = &nullfs_vnodeop_p, .opv_desc_ops = nullfs_vnodeop_entries};
1172*bbb1b6f9SApple OSS Distributions
1173*bbb1b6f9SApple OSS Distributions //NULLFS Specific helper function
1174*bbb1b6f9SApple OSS Distributions
1175*bbb1b6f9SApple OSS Distributions int
nullfs_getbackingvnode(vnode_t in_vp,vnode_t * out_vpp)1176*bbb1b6f9SApple OSS Distributions nullfs_getbackingvnode(vnode_t in_vp, vnode_t* out_vpp)
1177*bbb1b6f9SApple OSS Distributions {
1178*bbb1b6f9SApple OSS Distributions int result = EINVAL;
1179*bbb1b6f9SApple OSS Distributions
1180*bbb1b6f9SApple OSS Distributions if (out_vpp == NULL || in_vp == NULL) {
1181*bbb1b6f9SApple OSS Distributions goto end;
1182*bbb1b6f9SApple OSS Distributions }
1183*bbb1b6f9SApple OSS Distributions
1184*bbb1b6f9SApple OSS Distributions struct vfsstatfs * sp = NULL;
1185*bbb1b6f9SApple OSS Distributions mount_t mp = vnode_mount(in_vp);
1186*bbb1b6f9SApple OSS Distributions
1187*bbb1b6f9SApple OSS Distributions sp = vfs_statfs(mp);
1188*bbb1b6f9SApple OSS Distributions //If this isn't a nullfs vnode or it is but it's a special vnode
1189*bbb1b6f9SApple OSS Distributions if (strcmp(sp->f_fstypename, "nullfs") != 0 || nullfs_checkspecialvp(in_vp)) {
1190*bbb1b6f9SApple OSS Distributions *out_vpp = NULLVP;
1191*bbb1b6f9SApple OSS Distributions result = ENOENT;
1192*bbb1b6f9SApple OSS Distributions goto end;
1193*bbb1b6f9SApple OSS Distributions }
1194*bbb1b6f9SApple OSS Distributions
1195*bbb1b6f9SApple OSS Distributions vnode_t lvp = NULLVPTOLOWERVP(in_vp);
1196*bbb1b6f9SApple OSS Distributions if ((result = vnode_getwithvid(lvp, NULLVPTOLOWERVID(in_vp)))) {
1197*bbb1b6f9SApple OSS Distributions goto end;
1198*bbb1b6f9SApple OSS Distributions }
1199*bbb1b6f9SApple OSS Distributions
1200*bbb1b6f9SApple OSS Distributions *out_vpp = lvp;
1201*bbb1b6f9SApple OSS Distributions
1202*bbb1b6f9SApple OSS Distributions end:
1203*bbb1b6f9SApple OSS Distributions return result;
1204*bbb1b6f9SApple OSS Distributions }
1205