File: | nfs/nfs_vfsops.c |
Warning: | line 591, column 6 Access to field 'fhsize' results in a dereference of a null pointer (loaded from variable 'args') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: nfs_vfsops.c,v 1.126 2021/01/02 02:41:42 cheloha Exp $ */ | |||
2 | /* $NetBSD: nfs_vfsops.c,v 1.46.4.1 1996/05/25 22:40:35 fvdl Exp $ */ | |||
3 | ||||
4 | /* | |||
5 | * Copyright (c) 1989, 1993, 1995 | |||
6 | * The Regents of the University of California. All rights reserved. | |||
7 | * | |||
8 | * This code is derived from software contributed to Berkeley by | |||
9 | * Rick Macklem at The University of Guelph. | |||
10 | * | |||
11 | * Redistribution and use in source and binary forms, with or without | |||
12 | * modification, are permitted provided that the following conditions | |||
13 | * are met: | |||
14 | * 1. Redistributions of source code must retain the above copyright | |||
15 | * notice, this list of conditions and the following disclaimer. | |||
16 | * 2. Redistributions in binary form must reproduce the above copyright | |||
17 | * notice, this list of conditions and the following disclaimer in the | |||
18 | * documentation and/or other materials provided with the distribution. | |||
19 | * 3. Neither the name of the University nor the names of its contributors | |||
20 | * may be used to endorse or promote products derived from this software | |||
21 | * without specific prior written permission. | |||
22 | * | |||
23 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |||
24 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |||
27 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
28 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
29 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
30 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
31 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
32 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
33 | * SUCH DAMAGE. | |||
34 | * | |||
35 | * @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95 | |||
36 | */ | |||
37 | ||||
38 | #include <sys/param.h> | |||
39 | #include <sys/conf.h> | |||
40 | #include <sys/ioctl.h> | |||
41 | #include <sys/signal.h> | |||
42 | #include <sys/proc.h> | |||
43 | #include <sys/namei.h> | |||
44 | #include <sys/vnode.h> | |||
45 | #include <sys/lock.h> | |||
46 | #include <sys/kernel.h> | |||
47 | #include <sys/mount.h> | |||
48 | #include <sys/swap.h> | |||
49 | #include <sys/buf.h> | |||
50 | #include <sys/mbuf.h> | |||
51 | #include <sys/dirent.h> | |||
52 | #include <sys/socket.h> | |||
53 | #include <sys/socketvar.h> | |||
54 | #include <sys/systm.h> | |||
55 | #include <sys/sysctl.h> | |||
56 | #include <sys/queue.h> | |||
57 | ||||
58 | #include <netinet/in.h> | |||
59 | ||||
60 | #include <nfs/rpcv2.h> | |||
61 | #include <nfs/nfsproto.h> | |||
62 | #include <nfs/nfsnode.h> | |||
63 | #include <nfs/nfs.h> | |||
64 | #include <nfs/nfsmount.h> | |||
65 | #include <nfs/xdr_subs.h> | |||
66 | #include <nfs/nfsm_subs.h> | |||
67 | #include <nfs/nfsdiskless.h> | |||
68 | #include <nfs/nfs_var.h> | |||
69 | ||||
70 | extern struct nfsstats nfsstats; | |||
71 | extern int nfs_ticks; | |||
72 | extern u_int32_t nfs_procids[NFS_NPROCS23]; | |||
73 | ||||
74 | int nfs_sysctl(int *, u_int, void *, size_t *, void *, size_t, | |||
75 | struct proc *); | |||
76 | int nfs_checkexp(struct mount *, struct mbuf *, int *, struct ucred **); | |||
77 | struct mount *nfs_mount_diskless(struct nfs_dlmount *, char *, int, | |||
78 | struct vnode **, struct proc *p); | |||
79 | int mountnfs(struct nfs_args *, struct mount *, struct mbuf *, | |||
80 | const char *, char *, struct vnode **, struct proc *p); | |||
81 | int nfs_quotactl(struct mount *, int, uid_t, caddr_t, struct proc *); | |||
82 | int nfs_root(struct mount *, struct vnode **); | |||
83 | int nfs_start(struct mount *, int, struct proc *); | |||
84 | int nfs_statfs(struct mount *, struct statfs *, struct proc *); | |||
85 | int nfs_sync(struct mount *, int, int, struct ucred *, struct proc *); | |||
86 | int nfs_unmount(struct mount *, int, struct proc *); | |||
87 | void nfs_reaper(void *); | |||
88 | int nfs_vget(struct mount *, ino_t, struct vnode **); | |||
89 | int nfs_vptofh(struct vnode *, struct fid *); | |||
90 | int nfs_mountroot(void); | |||
91 | void nfs_decode_args(struct nfsmount *, struct nfs_args *, | |||
92 | struct nfs_args *); | |||
93 | int nfs_fhtovp(struct mount *, struct fid *, struct vnode **); | |||
94 | ||||
95 | /* | |||
96 | * nfs vfs operations. | |||
97 | */ | |||
98 | const struct vfsops nfs_vfsops = { | |||
99 | .vfs_mount = nfs_mount, | |||
100 | .vfs_start = nfs_start, | |||
101 | .vfs_unmount = nfs_unmount, | |||
102 | .vfs_root = nfs_root, | |||
103 | .vfs_quotactl = nfs_quotactl, | |||
104 | .vfs_statfs = nfs_statfs, | |||
105 | .vfs_sync = nfs_sync, | |||
106 | .vfs_vget = nfs_vget, | |||
107 | .vfs_fhtovp = nfs_fhtovp, | |||
108 | .vfs_vptofh = nfs_vptofh, | |||
109 | .vfs_init = nfs_vfs_init, | |||
110 | .vfs_sysctl = nfs_sysctl, | |||
111 | .vfs_checkexp = nfs_checkexp, | |||
112 | }; | |||
113 | ||||
114 | /* | |||
115 | * nfs statfs call | |||
116 | */ | |||
117 | int | |||
118 | nfs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p) | |||
119 | { | |||
120 | struct vnode *vp; | |||
121 | struct nfs_statfs *sfp = NULL((void *)0); | |||
122 | struct nfsm_info info; | |||
123 | u_int32_t *tl; | |||
124 | int32_t t1; | |||
125 | caddr_t cp2; | |||
126 | struct nfsmount *nmp = VFSTONFS(mp)((struct nfsmount *)((mp)->mnt_data)); | |||
127 | int error = 0, retattr; | |||
128 | struct ucred *cred; | |||
129 | u_quad_t tquad; | |||
130 | ||||
131 | info.nmi_v3 = (nmp->nm_flag & NFSMNT_NFSV30x00000200); | |||
132 | ||||
133 | error = nfs_root(mp, &vp); | |||
134 | if (error) | |||
135 | return (error); | |||
136 | cred = crget(); | |||
137 | cred->cr_ngroups = 0; | |||
138 | if (info.nmi_v3 && (nmp->nm_flag & NFSMNT_GOTFSINFO0x00100000) == 0) | |||
139 | (void)nfs_fsinfo(nmp, vp, cred, p); | |||
140 | nfsstats.rpccnt[NFSPROC_FSSTAT18]++; | |||
141 | info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(info.nmi_v3)((info.nmi_v3) ? (64 + 4) : 32)); | |||
142 | nfsm_fhtom(&info, vp, info.nmi_v3); | |||
143 | ||||
144 | info.nmi_procp = p; | |||
145 | info.nmi_cred = cred; | |||
146 | error = nfs_request(vp, NFSPROC_FSSTAT18, &info); | |||
147 | if (info.nmi_v3) | |||
148 | nfsm_postop_attr(vp, retattr){ if (info.nmi_mrep != ((void *)0)) { struct vnode *ttvp = (vp ); { t1 = ((caddr_t)((info.nmi_md)->m_hdr.mh_data)) + info .nmi_md->m_hdr.mh_len - info.nmi_dpos; if (t1 >= (4)) { (tl) = (u_int32_t *)(info.nmi_dpos); info.nmi_dpos += (4); } else if ((t1 = nfsm_disct(&info.nmi_md, &info.nmi_dpos , (4), t1, &cp2)) != 0) { error = t1; m_freem(info.nmi_mrep ); goto nfsmout; } else { (tl) = (u_int32_t *)cp2; } }; if (( (retattr) = ((int)(__uint32_t)(__builtin_constant_p((int32_t) (*tl)) ? (__uint32_t)(((__uint32_t)((int32_t)(*tl)) & 0xff ) << 24 | ((__uint32_t)((int32_t)(*tl)) & 0xff00) << 8 | ((__uint32_t)((int32_t)(*tl)) & 0xff0000) >> 8 | ((__uint32_t)((int32_t)(*tl)) & 0xff000000) >> 24 ) : __swap32md((int32_t)(*tl))))) != 0) { if ((t1 = nfs_loadattrcache (&ttvp, &info.nmi_md, &info.nmi_dpos, ((void *)0) )) != 0) { error = t1; (retattr) = 0; m_freem(info.nmi_mrep); goto nfsmout; } (vp) = ttvp; } } }; | |||
149 | if (error) { | |||
150 | m_freem(info.nmi_mrep); | |||
151 | goto nfsmout; | |||
152 | } | |||
153 | ||||
154 | nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(info.nmi_v3)){ t1 = ((caddr_t)((info.nmi_md)->m_hdr.mh_data)) + info.nmi_md ->m_hdr.mh_len - info.nmi_dpos; if (t1 >= (((info.nmi_v3 ) ? 52 : 20))) { (sfp) = (struct nfs_statfs *)(info.nmi_dpos) ; info.nmi_dpos += (((info.nmi_v3) ? 52 : 20)); } else if ((t1 = nfsm_disct(&info.nmi_md, &info.nmi_dpos, (((info.nmi_v3 ) ? 52 : 20)), t1, &cp2)) != 0) { error = t1; m_freem(info .nmi_mrep); goto nfsmout; } else { (sfp) = (struct nfs_statfs *)cp2; } }; | |||
155 | sbp->f_iosize = min(nmp->nm_rsize, nmp->nm_wsize); | |||
156 | if (info.nmi_v3) { | |||
157 | sbp->f_bsize = NFS_FABLKSIZE512; | |||
158 | tquad = fxdr_hyper(&sfp->sf_tbytes)((((u_quad_t)(__uint32_t)(__builtin_constant_p(((u_int32_t *) (&sfp->sf_un.sf_nfsv3.nfsv3sf_tbytes))[0]) ? (__uint32_t )(((__uint32_t)(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_tbytes ))[0]) & 0xff) << 24 | ((__uint32_t)(((u_int32_t *) (&sfp->sf_un.sf_nfsv3.nfsv3sf_tbytes))[0]) & 0xff00 ) << 8 | ((__uint32_t)(((u_int32_t *)(&sfp->sf_un .sf_nfsv3.nfsv3sf_tbytes))[0]) & 0xff0000) >> 8 | ( (__uint32_t)(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_tbytes ))[0]) & 0xff000000) >> 24) : __swap32md(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_tbytes))[0]))) << 32) | (u_quad_t)((__uint32_t)(__builtin_constant_p(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_tbytes))[1]) ? (__uint32_t )(((__uint32_t)(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_tbytes ))[1]) & 0xff) << 24 | ((__uint32_t)(((u_int32_t *) (&sfp->sf_un.sf_nfsv3.nfsv3sf_tbytes))[1]) & 0xff00 ) << 8 | ((__uint32_t)(((u_int32_t *)(&sfp->sf_un .sf_nfsv3.nfsv3sf_tbytes))[1]) & 0xff0000) >> 8 | ( (__uint32_t)(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_tbytes ))[1]) & 0xff000000) >> 24) : __swap32md(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_tbytes))[1])))); | |||
159 | sbp->f_blocks = tquad / (u_quad_t)NFS_FABLKSIZE512; | |||
160 | tquad = fxdr_hyper(&sfp->sf_fbytes)((((u_quad_t)(__uint32_t)(__builtin_constant_p(((u_int32_t *) (&sfp->sf_un.sf_nfsv3.nfsv3sf_fbytes))[0]) ? (__uint32_t )(((__uint32_t)(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_fbytes ))[0]) & 0xff) << 24 | ((__uint32_t)(((u_int32_t *) (&sfp->sf_un.sf_nfsv3.nfsv3sf_fbytes))[0]) & 0xff00 ) << 8 | ((__uint32_t)(((u_int32_t *)(&sfp->sf_un .sf_nfsv3.nfsv3sf_fbytes))[0]) & 0xff0000) >> 8 | ( (__uint32_t)(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_fbytes ))[0]) & 0xff000000) >> 24) : __swap32md(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_fbytes))[0]))) << 32) | (u_quad_t)((__uint32_t)(__builtin_constant_p(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_fbytes))[1]) ? (__uint32_t )(((__uint32_t)(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_fbytes ))[1]) & 0xff) << 24 | ((__uint32_t)(((u_int32_t *) (&sfp->sf_un.sf_nfsv3.nfsv3sf_fbytes))[1]) & 0xff00 ) << 8 | ((__uint32_t)(((u_int32_t *)(&sfp->sf_un .sf_nfsv3.nfsv3sf_fbytes))[1]) & 0xff0000) >> 8 | ( (__uint32_t)(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_fbytes ))[1]) & 0xff000000) >> 24) : __swap32md(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_fbytes))[1])))); | |||
161 | sbp->f_bfree = tquad / (u_quad_t)NFS_FABLKSIZE512; | |||
162 | tquad = fxdr_hyper(&sfp->sf_abytes)((((u_quad_t)(__uint32_t)(__builtin_constant_p(((u_int32_t *) (&sfp->sf_un.sf_nfsv3.nfsv3sf_abytes))[0]) ? (__uint32_t )(((__uint32_t)(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_abytes ))[0]) & 0xff) << 24 | ((__uint32_t)(((u_int32_t *) (&sfp->sf_un.sf_nfsv3.nfsv3sf_abytes))[0]) & 0xff00 ) << 8 | ((__uint32_t)(((u_int32_t *)(&sfp->sf_un .sf_nfsv3.nfsv3sf_abytes))[0]) & 0xff0000) >> 8 | ( (__uint32_t)(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_abytes ))[0]) & 0xff000000) >> 24) : __swap32md(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_abytes))[0]))) << 32) | (u_quad_t)((__uint32_t)(__builtin_constant_p(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_abytes))[1]) ? (__uint32_t )(((__uint32_t)(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_abytes ))[1]) & 0xff) << 24 | ((__uint32_t)(((u_int32_t *) (&sfp->sf_un.sf_nfsv3.nfsv3sf_abytes))[1]) & 0xff00 ) << 8 | ((__uint32_t)(((u_int32_t *)(&sfp->sf_un .sf_nfsv3.nfsv3sf_abytes))[1]) & 0xff0000) >> 8 | ( (__uint32_t)(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_abytes ))[1]) & 0xff000000) >> 24) : __swap32md(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_abytes))[1])))); | |||
163 | sbp->f_bavail = (quad_t)tquad / (quad_t)NFS_FABLKSIZE512; | |||
164 | ||||
165 | tquad = fxdr_hyper(&sfp->sf_tfiles)((((u_quad_t)(__uint32_t)(__builtin_constant_p(((u_int32_t *) (&sfp->sf_un.sf_nfsv3.nfsv3sf_tfiles))[0]) ? (__uint32_t )(((__uint32_t)(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_tfiles ))[0]) & 0xff) << 24 | ((__uint32_t)(((u_int32_t *) (&sfp->sf_un.sf_nfsv3.nfsv3sf_tfiles))[0]) & 0xff00 ) << 8 | ((__uint32_t)(((u_int32_t *)(&sfp->sf_un .sf_nfsv3.nfsv3sf_tfiles))[0]) & 0xff0000) >> 8 | ( (__uint32_t)(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_tfiles ))[0]) & 0xff000000) >> 24) : __swap32md(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_tfiles))[0]))) << 32) | (u_quad_t)((__uint32_t)(__builtin_constant_p(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_tfiles))[1]) ? (__uint32_t )(((__uint32_t)(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_tfiles ))[1]) & 0xff) << 24 | ((__uint32_t)(((u_int32_t *) (&sfp->sf_un.sf_nfsv3.nfsv3sf_tfiles))[1]) & 0xff00 ) << 8 | ((__uint32_t)(((u_int32_t *)(&sfp->sf_un .sf_nfsv3.nfsv3sf_tfiles))[1]) & 0xff0000) >> 8 | ( (__uint32_t)(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_tfiles ))[1]) & 0xff000000) >> 24) : __swap32md(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_tfiles))[1])))); | |||
166 | sbp->f_files = tquad; | |||
167 | tquad = fxdr_hyper(&sfp->sf_ffiles)((((u_quad_t)(__uint32_t)(__builtin_constant_p(((u_int32_t *) (&sfp->sf_un.sf_nfsv3.nfsv3sf_ffiles))[0]) ? (__uint32_t )(((__uint32_t)(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_ffiles ))[0]) & 0xff) << 24 | ((__uint32_t)(((u_int32_t *) (&sfp->sf_un.sf_nfsv3.nfsv3sf_ffiles))[0]) & 0xff00 ) << 8 | ((__uint32_t)(((u_int32_t *)(&sfp->sf_un .sf_nfsv3.nfsv3sf_ffiles))[0]) & 0xff0000) >> 8 | ( (__uint32_t)(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_ffiles ))[0]) & 0xff000000) >> 24) : __swap32md(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_ffiles))[0]))) << 32) | (u_quad_t)((__uint32_t)(__builtin_constant_p(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_ffiles))[1]) ? (__uint32_t )(((__uint32_t)(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_ffiles ))[1]) & 0xff) << 24 | ((__uint32_t)(((u_int32_t *) (&sfp->sf_un.sf_nfsv3.nfsv3sf_ffiles))[1]) & 0xff00 ) << 8 | ((__uint32_t)(((u_int32_t *)(&sfp->sf_un .sf_nfsv3.nfsv3sf_ffiles))[1]) & 0xff0000) >> 8 | ( (__uint32_t)(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_ffiles ))[1]) & 0xff000000) >> 24) : __swap32md(((u_int32_t *)(&sfp->sf_un.sf_nfsv3.nfsv3sf_ffiles))[1])))); | |||
168 | sbp->f_ffree = tquad; | |||
169 | sbp->f_favail = tquad; | |||
170 | } else { | |||
171 | sbp->f_bsize = fxdr_unsigned(int32_t, sfp->sf_bsize)((int32_t)(__uint32_t)(__builtin_constant_p((int32_t)(sfp-> sf_un.sf_nfsv2.nfsv2sf_bsize)) ? (__uint32_t)(((__uint32_t)(( int32_t)(sfp->sf_un.sf_nfsv2.nfsv2sf_bsize)) & 0xff) << 24 | ((__uint32_t)((int32_t)(sfp->sf_un.sf_nfsv2.nfsv2sf_bsize )) & 0xff00) << 8 | ((__uint32_t)((int32_t)(sfp-> sf_un.sf_nfsv2.nfsv2sf_bsize)) & 0xff0000) >> 8 | ( (__uint32_t)((int32_t)(sfp->sf_un.sf_nfsv2.nfsv2sf_bsize)) & 0xff000000) >> 24) : __swap32md((int32_t)(sfp-> sf_un.sf_nfsv2.nfsv2sf_bsize)))); | |||
172 | sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks)((int32_t)(__uint32_t)(__builtin_constant_p((int32_t)(sfp-> sf_un.sf_nfsv2.nfsv2sf_blocks)) ? (__uint32_t)(((__uint32_t)( (int32_t)(sfp->sf_un.sf_nfsv2.nfsv2sf_blocks)) & 0xff) << 24 | ((__uint32_t)((int32_t)(sfp->sf_un.sf_nfsv2 .nfsv2sf_blocks)) & 0xff00) << 8 | ((__uint32_t)((int32_t )(sfp->sf_un.sf_nfsv2.nfsv2sf_blocks)) & 0xff0000) >> 8 | ((__uint32_t)((int32_t)(sfp->sf_un.sf_nfsv2.nfsv2sf_blocks )) & 0xff000000) >> 24) : __swap32md((int32_t)(sfp-> sf_un.sf_nfsv2.nfsv2sf_blocks)))); | |||
173 | sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree)((int32_t)(__uint32_t)(__builtin_constant_p((int32_t)(sfp-> sf_un.sf_nfsv2.nfsv2sf_bfree)) ? (__uint32_t)(((__uint32_t)(( int32_t)(sfp->sf_un.sf_nfsv2.nfsv2sf_bfree)) & 0xff) << 24 | ((__uint32_t)((int32_t)(sfp->sf_un.sf_nfsv2.nfsv2sf_bfree )) & 0xff00) << 8 | ((__uint32_t)((int32_t)(sfp-> sf_un.sf_nfsv2.nfsv2sf_bfree)) & 0xff0000) >> 8 | ( (__uint32_t)((int32_t)(sfp->sf_un.sf_nfsv2.nfsv2sf_bfree)) & 0xff000000) >> 24) : __swap32md((int32_t)(sfp-> sf_un.sf_nfsv2.nfsv2sf_bfree)))); | |||
174 | sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail)((int32_t)(__uint32_t)(__builtin_constant_p((int32_t)(sfp-> sf_un.sf_nfsv2.nfsv2sf_bavail)) ? (__uint32_t)(((__uint32_t)( (int32_t)(sfp->sf_un.sf_nfsv2.nfsv2sf_bavail)) & 0xff) << 24 | ((__uint32_t)((int32_t)(sfp->sf_un.sf_nfsv2 .nfsv2sf_bavail)) & 0xff00) << 8 | ((__uint32_t)((int32_t )(sfp->sf_un.sf_nfsv2.nfsv2sf_bavail)) & 0xff0000) >> 8 | ((__uint32_t)((int32_t)(sfp->sf_un.sf_nfsv2.nfsv2sf_bavail )) & 0xff000000) >> 24) : __swap32md((int32_t)(sfp-> sf_un.sf_nfsv2.nfsv2sf_bavail)))); | |||
175 | sbp->f_files = 0; | |||
176 | sbp->f_ffree = 0; | |||
177 | sbp->f_favail = 0; | |||
178 | } | |||
179 | copy_statfs_info(sbp, mp); | |||
180 | m_freem(info.nmi_mrep); | |||
181 | nfsmout: | |||
182 | vput(vp); | |||
183 | crfree(cred); | |||
184 | return (error); | |||
185 | } | |||
186 | ||||
187 | /* | |||
188 | * nfs version 3 fsinfo rpc call | |||
189 | */ | |||
190 | int | |||
191 | nfs_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred, | |||
192 | struct proc *p) | |||
193 | { | |||
194 | struct nfsv3_fsinfo *fsp; | |||
195 | struct nfsm_info info; | |||
196 | int32_t t1; | |||
197 | u_int32_t *tl, pref, max; | |||
198 | caddr_t cp2; | |||
199 | int error = 0, retattr; | |||
200 | ||||
201 | nfsstats.rpccnt[NFSPROC_FSINFO19]++; | |||
202 | info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(1)((1) ? (64 + 4) : 32)); | |||
203 | nfsm_fhtom(&info, vp, 1); | |||
204 | ||||
205 | info.nmi_procp = p; | |||
206 | info.nmi_cred = cred; | |||
207 | error = nfs_request(vp, NFSPROC_FSINFO19, &info); | |||
208 | ||||
209 | nfsm_postop_attr(vp, retattr){ if (info.nmi_mrep != ((void *)0)) { struct vnode *ttvp = (vp ); { t1 = ((caddr_t)((info.nmi_md)->m_hdr.mh_data)) + info .nmi_md->m_hdr.mh_len - info.nmi_dpos; if (t1 >= (4)) { (tl) = (u_int32_t *)(info.nmi_dpos); info.nmi_dpos += (4); } else if ((t1 = nfsm_disct(&info.nmi_md, &info.nmi_dpos , (4), t1, &cp2)) != 0) { error = t1; m_freem(info.nmi_mrep ); goto nfsmout; } else { (tl) = (u_int32_t *)cp2; } }; if (( (retattr) = ((int)(__uint32_t)(__builtin_constant_p((int32_t) (*tl)) ? (__uint32_t)(((__uint32_t)((int32_t)(*tl)) & 0xff ) << 24 | ((__uint32_t)((int32_t)(*tl)) & 0xff00) << 8 | ((__uint32_t)((int32_t)(*tl)) & 0xff0000) >> 8 | ((__uint32_t)((int32_t)(*tl)) & 0xff000000) >> 24 ) : __swap32md((int32_t)(*tl))))) != 0) { if ((t1 = nfs_loadattrcache (&ttvp, &info.nmi_md, &info.nmi_dpos, ((void *)0) )) != 0) { error = t1; (retattr) = 0; m_freem(info.nmi_mrep); goto nfsmout; } (vp) = ttvp; } } }; | |||
210 | if (error) { | |||
211 | m_freem(info.nmi_mrep); | |||
212 | goto nfsmout; | |||
213 | } | |||
214 | ||||
215 | nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO){ t1 = ((caddr_t)((info.nmi_md)->m_hdr.mh_data)) + info.nmi_md ->m_hdr.mh_len - info.nmi_dpos; if (t1 >= (48)) { (fsp) = (struct nfsv3_fsinfo *)(info.nmi_dpos); info.nmi_dpos += ( 48); } else if ((t1 = nfsm_disct(&info.nmi_md, &info. nmi_dpos, (48), t1, &cp2)) != 0) { error = t1; m_freem(info .nmi_mrep); goto nfsmout; } else { (fsp) = (struct nfsv3_fsinfo *)cp2; } }; | |||
216 | pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref)((u_int32_t)(__uint32_t)(__builtin_constant_p((int32_t)(fsp-> fs_wtpref)) ? (__uint32_t)(((__uint32_t)((int32_t)(fsp->fs_wtpref )) & 0xff) << 24 | ((__uint32_t)((int32_t)(fsp-> fs_wtpref)) & 0xff00) << 8 | ((__uint32_t)((int32_t )(fsp->fs_wtpref)) & 0xff0000) >> 8 | ((__uint32_t )((int32_t)(fsp->fs_wtpref)) & 0xff000000) >> 24 ) : __swap32md((int32_t)(fsp->fs_wtpref)))); | |||
217 | if (pref < nmp->nm_wsize) | |||
218 | nmp->nm_wsize = (pref + NFS_FABLKSIZE512 - 1) & | |||
219 | ~(NFS_FABLKSIZE512 - 1); | |||
220 | max = fxdr_unsigned(u_int32_t, fsp->fs_wtmax)((u_int32_t)(__uint32_t)(__builtin_constant_p((int32_t)(fsp-> fs_wtmax)) ? (__uint32_t)(((__uint32_t)((int32_t)(fsp->fs_wtmax )) & 0xff) << 24 | ((__uint32_t)((int32_t)(fsp-> fs_wtmax)) & 0xff00) << 8 | ((__uint32_t)((int32_t) (fsp->fs_wtmax)) & 0xff0000) >> 8 | ((__uint32_t )((int32_t)(fsp->fs_wtmax)) & 0xff000000) >> 24) : __swap32md((int32_t)(fsp->fs_wtmax)))); | |||
221 | if (max < nmp->nm_wsize) { | |||
222 | nmp->nm_wsize = max & ~(NFS_FABLKSIZE512 - 1); | |||
223 | if (nmp->nm_wsize == 0) | |||
224 | nmp->nm_wsize = max; | |||
225 | } | |||
226 | pref = fxdr_unsigned(u_int32_t, fsp->fs_rtpref)((u_int32_t)(__uint32_t)(__builtin_constant_p((int32_t)(fsp-> fs_rtpref)) ? (__uint32_t)(((__uint32_t)((int32_t)(fsp->fs_rtpref )) & 0xff) << 24 | ((__uint32_t)((int32_t)(fsp-> fs_rtpref)) & 0xff00) << 8 | ((__uint32_t)((int32_t )(fsp->fs_rtpref)) & 0xff0000) >> 8 | ((__uint32_t )((int32_t)(fsp->fs_rtpref)) & 0xff000000) >> 24 ) : __swap32md((int32_t)(fsp->fs_rtpref)))); | |||
227 | if (pref < nmp->nm_rsize) | |||
228 | nmp->nm_rsize = (pref + NFS_FABLKSIZE512 - 1) & | |||
229 | ~(NFS_FABLKSIZE512 - 1); | |||
230 | max = fxdr_unsigned(u_int32_t, fsp->fs_rtmax)((u_int32_t)(__uint32_t)(__builtin_constant_p((int32_t)(fsp-> fs_rtmax)) ? (__uint32_t)(((__uint32_t)((int32_t)(fsp->fs_rtmax )) & 0xff) << 24 | ((__uint32_t)((int32_t)(fsp-> fs_rtmax)) & 0xff00) << 8 | ((__uint32_t)((int32_t) (fsp->fs_rtmax)) & 0xff0000) >> 8 | ((__uint32_t )((int32_t)(fsp->fs_rtmax)) & 0xff000000) >> 24) : __swap32md((int32_t)(fsp->fs_rtmax)))); | |||
231 | if (max < nmp->nm_rsize) { | |||
232 | nmp->nm_rsize = max & ~(NFS_FABLKSIZE512 - 1); | |||
233 | if (nmp->nm_rsize == 0) | |||
234 | nmp->nm_rsize = max; | |||
235 | } | |||
236 | pref = fxdr_unsigned(u_int32_t, fsp->fs_dtpref)((u_int32_t)(__uint32_t)(__builtin_constant_p((int32_t)(fsp-> fs_dtpref)) ? (__uint32_t)(((__uint32_t)((int32_t)(fsp->fs_dtpref )) & 0xff) << 24 | ((__uint32_t)((int32_t)(fsp-> fs_dtpref)) & 0xff00) << 8 | ((__uint32_t)((int32_t )(fsp->fs_dtpref)) & 0xff0000) >> 8 | ((__uint32_t )((int32_t)(fsp->fs_dtpref)) & 0xff000000) >> 24 ) : __swap32md((int32_t)(fsp->fs_dtpref)))); | |||
237 | if (pref < nmp->nm_readdirsize) | |||
238 | nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ1024 - 1) & | |||
239 | ~(NFS_DIRBLKSIZ1024 - 1); | |||
240 | if (max < nmp->nm_readdirsize) { | |||
241 | nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ1024 - 1); | |||
242 | if (nmp->nm_readdirsize == 0) | |||
243 | nmp->nm_readdirsize = max; | |||
244 | } | |||
245 | nmp->nm_flag |= NFSMNT_GOTFSINFO0x00100000; | |||
246 | ||||
247 | m_freem(info.nmi_mrep); | |||
248 | nfsmout: | |||
249 | return (error); | |||
250 | } | |||
251 | ||||
252 | struct nfs_diskless nfs_diskless; | |||
253 | ||||
254 | /* | |||
255 | * Mount a remote root fs via. NFS. It goes like this: | |||
256 | * - Call nfs_boot_init() to fill in the nfs_diskless struct | |||
257 | * (using RARP, bootparam RPC, mountd RPC) | |||
258 | * - hand craft the swap nfs vnode hanging off a fake mount point | |||
259 | * if swdevt[0].sw_dev == NODEV | |||
260 | * - build the rootfs mount point and call mountnfs() to do the rest. | |||
261 | */ | |||
262 | int | |||
263 | nfs_mountroot(void) | |||
264 | { | |||
265 | struct vattr attr; | |||
266 | struct mount *mp; | |||
267 | struct vnode *vp; | |||
268 | struct proc *procp; | |||
269 | long n; | |||
270 | int error; | |||
271 | ||||
272 | procp = curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc; /* XXX */ | |||
273 | ||||
274 | /* | |||
275 | * Call nfs_boot_init() to fill in the nfs_diskless struct. | |||
276 | * Side effect: Finds and configures a network interface. | |||
277 | */ | |||
278 | nfs_boot_init(&nfs_diskless, procp); | |||
279 | ||||
280 | /* | |||
281 | * Create the root mount point. | |||
282 | */ | |||
283 | if (nfs_boot_getfh(&nfs_diskless.nd_boot, "root", &nfs_diskless.nd_root, -1)) | |||
284 | panic("nfs_mountroot: root"); | |||
285 | mp = nfs_mount_diskless(&nfs_diskless.nd_root, "/", 0, &vp, procp); | |||
286 | printf("root on %s\n", nfs_diskless.nd_root.ndm_host); | |||
287 | ||||
288 | /* | |||
289 | * Link it into the mount list. | |||
290 | */ | |||
291 | TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list)do { (mp)->mnt_list.tqe_next = ((void *)0); (mp)->mnt_list .tqe_prev = (&mountlist)->tqh_last; *(&mountlist)-> tqh_last = (mp); (&mountlist)->tqh_last = &(mp)-> mnt_list.tqe_next; } while (0); | |||
292 | rootvp = vp; | |||
293 | vfs_unbusy(mp); | |||
294 | ||||
295 | /* Get root attributes (for the time). */ | |||
296 | error = VOP_GETATTR(rootvp, &attr, procp->p_ucred, procp); | |||
297 | if (error) panic("nfs_mountroot: getattr for root"); | |||
298 | n = attr.va_atime.tv_sec; | |||
299 | #ifdef DEBUG | |||
300 | printf("root time: 0x%lx\n", n); | |||
301 | #endif | |||
302 | inittodr(n); | |||
303 | ||||
304 | #ifdef notyet | |||
305 | /* Set up swap credentials. */ | |||
306 | proc0.p_ucred->cr_uid = ntohl(nfs_diskless.swap_ucred.cr_uid)(__uint32_t)(__builtin_constant_p(nfs_diskless.swap_ucred.cr_uid ) ? (__uint32_t)(((__uint32_t)(nfs_diskless.swap_ucred.cr_uid ) & 0xff) << 24 | ((__uint32_t)(nfs_diskless.swap_ucred .cr_uid) & 0xff00) << 8 | ((__uint32_t)(nfs_diskless .swap_ucred.cr_uid) & 0xff0000) >> 8 | ((__uint32_t )(nfs_diskless.swap_ucred.cr_uid) & 0xff000000) >> 24 ) : __swap32md(nfs_diskless.swap_ucred.cr_uid)); | |||
307 | proc0.p_ucred->cr_gid = ntohl(nfs_diskless.swap_ucred.cr_gid)(__uint32_t)(__builtin_constant_p(nfs_diskless.swap_ucred.cr_gid ) ? (__uint32_t)(((__uint32_t)(nfs_diskless.swap_ucred.cr_gid ) & 0xff) << 24 | ((__uint32_t)(nfs_diskless.swap_ucred .cr_gid) & 0xff00) << 8 | ((__uint32_t)(nfs_diskless .swap_ucred.cr_gid) & 0xff0000) >> 8 | ((__uint32_t )(nfs_diskless.swap_ucred.cr_gid) & 0xff000000) >> 24 ) : __swap32md(nfs_diskless.swap_ucred.cr_gid)); | |||
308 | if ((proc0.p_ucred->cr_ngroups = ntohs(nfs_diskless.swap_ucred.cr_ngroups)(__uint16_t)(__builtin_constant_p(nfs_diskless.swap_ucred.cr_ngroups ) ? (__uint16_t)(((__uint16_t)(nfs_diskless.swap_ucred.cr_ngroups ) & 0xffU) << 8 | ((__uint16_t)(nfs_diskless.swap_ucred .cr_ngroups) & 0xff00U) >> 8) : __swap16md(nfs_diskless .swap_ucred.cr_ngroups))) > | |||
309 | NGROUPS_MAX16) | |||
310 | proc0.p_ucred->cr_ngroups = NGROUPS_MAX16; | |||
311 | for (i = 0; i < proc0.p_ucred->cr_ngroups; i++) | |||
312 | proc0.p_ucred->cr_groups[i] = ntohl(nfs_diskless.swap_ucred.cr_groups[i])(__uint32_t)(__builtin_constant_p(nfs_diskless.swap_ucred.cr_groups [i]) ? (__uint32_t)(((__uint32_t)(nfs_diskless.swap_ucred.cr_groups [i]) & 0xff) << 24 | ((__uint32_t)(nfs_diskless.swap_ucred .cr_groups[i]) & 0xff00) << 8 | ((__uint32_t)(nfs_diskless .swap_ucred.cr_groups[i]) & 0xff0000) >> 8 | ((__uint32_t )(nfs_diskless.swap_ucred.cr_groups[i]) & 0xff000000) >> 24) : __swap32md(nfs_diskless.swap_ucred.cr_groups[i])); | |||
313 | #endif | |||
314 | ||||
315 | /* | |||
316 | * "Mount" the swap device. | |||
317 | * | |||
318 | * On a "dataless" configuration (swap on disk) we will have: | |||
319 | * (swdevt[0].sw_dev != NODEV) identifying the swap device. | |||
320 | */ | |||
321 | if (swdevt[0].sw_dev != NODEV(dev_t)(-1)) { | |||
322 | if (bdevvp(swapdev, &swapdev_vp)) | |||
323 | panic("nfs_mountroot: can't setup swap vp"); | |||
324 | printf("swap on device 0x%x\n", swdevt[0].sw_dev); | |||
325 | return (0); | |||
326 | } | |||
327 | ||||
328 | /* | |||
329 | * If swapping to an nfs node: (swdevt[0].sw_dev == NODEV) | |||
330 | * Create a fake mount point just for the swap vnode so that the | |||
331 | * swap file can be on a different server from the rootfs. | |||
332 | * | |||
333 | * Wait 5 retries, finally no swap is cool. -mickey | |||
334 | */ | |||
335 | error = nfs_boot_getfh(&nfs_diskless.nd_boot, "swap", &nfs_diskless.nd_swap, 5); | |||
336 | if (!error) { | |||
337 | mp = nfs_mount_diskless(&nfs_diskless.nd_swap, "/swap", 0, &vp, | |||
338 | procp); | |||
339 | vfs_unbusy(mp); | |||
340 | ||||
341 | /* | |||
342 | * Since the swap file is not the root dir of a file system, | |||
343 | * hack it to a regular file. | |||
344 | */ | |||
345 | vp->v_type = VREG; | |||
346 | vp->v_flag = 0; | |||
347 | ||||
348 | /* | |||
349 | * Next line is a hack to make swapmount() work on NFS | |||
350 | * swap files. | |||
351 | */ | |||
352 | swdevt[0].sw_dev = NETDEV(dev_t)(-2); | |||
353 | /* end hack */ | |||
354 | nfs_diskless.sw_vp = vp; | |||
355 | ||||
356 | /* | |||
357 | * Find out how large the swap file is. | |||
358 | */ | |||
359 | error = VOP_GETATTR(vp, &attr, procp->p_ucred, procp); | |||
360 | if (error) | |||
361 | printf("nfs_mountroot: getattr for swap\n"); | |||
362 | n = (long) (attr.va_size >> DEV_BSHIFT9); | |||
363 | ||||
364 | printf("swap on %s\n", nfs_diskless.nd_swap.ndm_host); | |||
365 | #ifdef DEBUG | |||
366 | printf("swap size: 0x%lx (blocks)\n", n); | |||
367 | #endif | |||
368 | return (0); | |||
369 | } | |||
370 | ||||
371 | printf("WARNING: no swap\n"); | |||
372 | swdevt[0].sw_dev = NODEV(dev_t)(-1); | |||
373 | return (0); | |||
374 | } | |||
375 | ||||
376 | /* | |||
377 | * Internal version of mount system call for diskless setup. | |||
378 | */ | |||
379 | struct mount * | |||
380 | nfs_mount_diskless(struct nfs_dlmount *ndmntp, char *mntname, int mntflag, | |||
381 | struct vnode **vpp, struct proc *p) | |||
382 | { | |||
383 | struct mount *mp; | |||
384 | struct mbuf *m; | |||
385 | int error; | |||
386 | ||||
387 | if (vfs_rootmountalloc("nfs", mntname, &mp)) | |||
388 | panic("nfs_mount_diskless: vfs_rootmountalloc failed"); | |||
389 | mp->mnt_flag |= mntflag; | |||
390 | ||||
391 | /* Get mbuf for server sockaddr. */ | |||
392 | m = m_get(M_WAIT0x0001, MT_SONAME3); | |||
393 | bcopy(ndmntp->ndm_args.addr, mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)), | |||
394 | (m->m_lenm_hdr.mh_len = ndmntp->ndm_args.addr->sa_len)); | |||
395 | ||||
396 | error = mountnfs(&ndmntp->ndm_args, mp, m, mntname, | |||
397 | ndmntp->ndm_args.hostname, vpp, p); | |||
398 | if (error) | |||
399 | panic("nfs_mountroot: mount %s failed: %d", mntname, error); | |||
400 | ||||
401 | return (mp); | |||
402 | } | |||
403 | ||||
404 | void | |||
405 | nfs_decode_args(struct nfsmount *nmp, struct nfs_args *argp, | |||
406 | struct nfs_args *nargp) | |||
407 | { | |||
408 | int adjsock = 0; | |||
409 | int maxio; | |||
410 | ||||
411 | #if 0 | |||
412 | /* Re-bind if rsrvd port requested and wasn't on one */ | |||
413 | adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT0x00000000) | |||
414 | && (argp->flags & NFSMNT_RESVPORT0x00000000); | |||
415 | #endif | |||
416 | /* Also re-bind if we're switching to/from a connected UDP socket */ | |||
417 | adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN0x00000080) != | |||
418 | (argp->flags & NFSMNT_NOCONN0x00000080)); | |||
419 | ||||
420 | nmp->nm_flag = | |||
421 | (argp->flags & ~NFSMNT_INTERNAL0xfffc0000) | (nmp->nm_flag & NFSMNT_INTERNAL0xfffc0000); | |||
422 | ||||
423 | if ((argp->flags & NFSMNT_TIMEO0x00000008) && argp->timeo > 0) { | |||
424 | nmp->nm_timeo = (argp->timeo * NFS_HZ(hz / nfs_ticks) + 5) / 10; | |||
425 | if (nmp->nm_timeo < NFS_MINTIMEO(1 * (hz / nfs_ticks))) | |||
426 | nmp->nm_timeo = NFS_MINTIMEO(1 * (hz / nfs_ticks)); | |||
427 | else if (nmp->nm_timeo > NFS_MAXTIMEO(60 * (hz / nfs_ticks))) | |||
428 | nmp->nm_timeo = NFS_MAXTIMEO(60 * (hz / nfs_ticks)); | |||
429 | } | |||
430 | ||||
431 | if ((argp->flags & NFSMNT_RETRANS0x00000010) && argp->retrans > 1) | |||
432 | nmp->nm_retry = MIN(argp->retrans, NFS_MAXREXMIT)(((argp->retrans)<(100))?(argp->retrans):(100)); | |||
433 | if (!(nmp->nm_flag & NFSMNT_SOFT0x00000001)) | |||
434 | nmp->nm_retry = NFS_MAXREXMIT100 + 1; /* past clip limit */ | |||
435 | ||||
436 | if (argp->flags & NFSMNT_NFSV30x00000200) { | |||
437 | if (argp->sotype == SOCK_DGRAM2) | |||
438 | maxio = NFS_MAXDGRAMDATA32768; | |||
439 | else | |||
440 | maxio = NFS_MAXDATA(64 * 1024); | |||
441 | } else | |||
442 | maxio = NFS_V2MAXDATA8192; | |||
443 | ||||
444 | if ((argp->flags & NFSMNT_WSIZE0x00000002) && argp->wsize > 0) { | |||
445 | int osize = nmp->nm_wsize; | |||
446 | nmp->nm_wsize = argp->wsize; | |||
447 | /* Round down to multiple of blocksize */ | |||
448 | nmp->nm_wsize &= ~(NFS_FABLKSIZE512 - 1); | |||
449 | if (nmp->nm_wsize <= 0) | |||
450 | nmp->nm_wsize = NFS_FABLKSIZE512; | |||
451 | adjsock |= (nmp->nm_wsize != osize); | |||
452 | } | |||
453 | if (nmp->nm_wsize > maxio) | |||
454 | nmp->nm_wsize = maxio; | |||
455 | if (nmp->nm_wsize > MAXBSIZE(64 * 1024)) | |||
456 | nmp->nm_wsize = MAXBSIZE(64 * 1024); | |||
457 | ||||
458 | if ((argp->flags & NFSMNT_RSIZE0x00000004) && argp->rsize > 0) { | |||
459 | int osize = nmp->nm_rsize; | |||
460 | nmp->nm_rsize = argp->rsize; | |||
461 | /* Round down to multiple of blocksize */ | |||
462 | nmp->nm_rsize &= ~(NFS_FABLKSIZE512 - 1); | |||
463 | if (nmp->nm_rsize <= 0) | |||
464 | nmp->nm_rsize = NFS_FABLKSIZE512; | |||
465 | adjsock |= (nmp->nm_rsize != osize); | |||
466 | } | |||
467 | if (nmp->nm_rsize > maxio) | |||
468 | nmp->nm_rsize = maxio; | |||
469 | if (nmp->nm_rsize > MAXBSIZE(64 * 1024)) | |||
470 | nmp->nm_rsize = MAXBSIZE(64 * 1024); | |||
471 | ||||
472 | if ((argp->flags & NFSMNT_READDIRSIZE0x00020000) && argp->readdirsize > 0) { | |||
473 | nmp->nm_readdirsize = argp->readdirsize; | |||
474 | /* Round down to multiple of blocksize */ | |||
475 | nmp->nm_readdirsize &= ~(NFS_DIRBLKSIZ1024 - 1); | |||
476 | if (nmp->nm_readdirsize < NFS_DIRBLKSIZ1024) | |||
477 | nmp->nm_readdirsize = NFS_DIRBLKSIZ1024; | |||
478 | } else if (argp->flags & NFSMNT_RSIZE0x00000004) | |||
479 | nmp->nm_readdirsize = nmp->nm_rsize; | |||
480 | ||||
481 | if (nmp->nm_readdirsize > maxio) | |||
482 | nmp->nm_readdirsize = maxio; | |||
483 | ||||
484 | if ((argp->flags & NFSMNT_MAXGRPS0x00000020) && argp->maxgrouplist >= 0 && | |||
485 | argp->maxgrouplist <= NFS_MAXGRPS16) | |||
486 | nmp->nm_numgrps = argp->maxgrouplist; | |||
487 | if ((argp->flags & NFSMNT_READAHEAD0x00002000) && argp->readahead >= 0 && | |||
488 | argp->readahead <= NFS_MAXRAHEAD4) | |||
489 | nmp->nm_readahead = argp->readahead; | |||
490 | if (argp->flags & NFSMNT_ACREGMIN0x00040000 && argp->acregmin >= 0) { | |||
491 | if (argp->acregmin > 0xffff) | |||
492 | nmp->nm_acregmin = 0xffff; | |||
493 | else | |||
494 | nmp->nm_acregmin = argp->acregmin; | |||
495 | } | |||
496 | if (argp->flags & NFSMNT_ACREGMAX0x00080000 && argp->acregmax >= 0) { | |||
497 | if (argp->acregmax > 0xffff) | |||
498 | nmp->nm_acregmax = 0xffff; | |||
499 | else | |||
500 | nmp->nm_acregmax = argp->acregmax; | |||
501 | } | |||
502 | if (nmp->nm_acregmin > nmp->nm_acregmax) | |||
503 | nmp->nm_acregmin = nmp->nm_acregmax; | |||
504 | ||||
505 | if (argp->flags & NFSMNT_ACDIRMIN0x00100000 && argp->acdirmin >= 0) { | |||
506 | if (argp->acdirmin > 0xffff) | |||
507 | nmp->nm_acdirmin = 0xffff; | |||
508 | else | |||
509 | nmp->nm_acdirmin = argp->acdirmin; | |||
510 | } | |||
511 | if (argp->flags & NFSMNT_ACDIRMAX0x00200000 && argp->acdirmax >= 0) { | |||
512 | if (argp->acdirmax > 0xffff) | |||
513 | nmp->nm_acdirmax = 0xffff; | |||
514 | else | |||
515 | nmp->nm_acdirmax = argp->acdirmax; | |||
516 | } | |||
517 | if (nmp->nm_acdirmin > nmp->nm_acdirmax) | |||
518 | nmp->nm_acdirmin = nmp->nm_acdirmax; | |||
519 | ||||
520 | if (nmp->nm_so && adjsock) { | |||
521 | nfs_disconnect(nmp); | |||
522 | if (nmp->nm_sotype == SOCK_DGRAM2) | |||
523 | while (nfs_connect(nmp, NULL((void *)0))) { | |||
524 | printf("nfs_args: retrying connect\n"); | |||
525 | tsleep_nsec(&nowake, PSOCK24, "nfscon", | |||
526 | SEC_TO_NSEC(1)); | |||
527 | } | |||
528 | } | |||
529 | ||||
530 | /* Update nargp based on nmp */ | |||
531 | nargp->wsize = nmp->nm_wsize; | |||
532 | nargp->rsize = nmp->nm_rsize; | |||
533 | nargp->readdirsize = nmp->nm_readdirsize; | |||
534 | nargp->timeo = nmp->nm_timeo; | |||
535 | nargp->retrans = nmp->nm_retry; | |||
536 | nargp->maxgrouplist = nmp->nm_numgrps; | |||
537 | nargp->readahead = nmp->nm_readahead; | |||
538 | nargp->acregmin = nmp->nm_acregmin; | |||
539 | nargp->acregmax = nmp->nm_acregmax; | |||
540 | nargp->acdirmin = nmp->nm_acdirmin; | |||
541 | nargp->acdirmax = nmp->nm_acdirmax; | |||
542 | } | |||
543 | ||||
544 | /* | |||
545 | * VFS Operations. | |||
546 | * | |||
547 | * mount system call | |||
548 | * It seems a bit dumb to copyinstr() the host here and then | |||
549 | * bcopy() it in mountnfs(), but I wanted to detect errors before | |||
550 | * doing the sockargs() call because sockargs() allocates an mbuf and | |||
551 | * an error after that means that I have to release the mbuf. | |||
552 | */ | |||
553 | /* ARGSUSED */ | |||
554 | int | |||
555 | nfs_mount(struct mount *mp, const char *path, void *data, | |||
556 | struct nameidata *ndp, struct proc *p) | |||
557 | { | |||
558 | int error; | |||
559 | struct nfs_args *args = data; | |||
| ||||
560 | struct mbuf *nam; | |||
561 | struct vnode *vp; | |||
562 | char hst[MNAMELEN90]; | |||
563 | size_t len; | |||
564 | u_char nfh[NFSX_V3FHMAX64]; | |||
565 | ||||
566 | if (args && | |||
567 | (args->flags & (NFSMNT_NFSV30x00000200|NFSMNT_RDIRPLUS0x00010000)) == NFSMNT_RDIRPLUS0x00010000) | |||
568 | return (EINVAL22); | |||
569 | ||||
570 | if (nfs_niothreads < 0) { | |||
571 | nfs_niothreads = 4; | |||
572 | nfs_getset_niothreads(1); | |||
573 | } | |||
574 | ||||
575 | if (mp->mnt_flag & MNT_UPDATE0x00010000) { | |||
576 | struct nfsmount *nmp = VFSTONFS(mp)((struct nfsmount *)((mp)->mnt_data)); | |||
577 | ||||
578 | if (nmp == NULL((void *)0)) | |||
579 | return (EIO5); | |||
580 | /* | |||
581 | * When doing an update, we can't change from or to | |||
582 | * v3. | |||
583 | */ | |||
584 | if (args) { | |||
585 | args->flags = (args->flags & ~(NFSMNT_NFSV30x00000200)) | | |||
586 | (nmp->nm_flag & (NFSMNT_NFSV30x00000200)); | |||
587 | nfs_decode_args(nmp, args, &mp->mnt_stat.mount_info.nfs_args); | |||
588 | } | |||
589 | return (0); | |||
590 | } | |||
591 | if (args->fhsize < 0 || args->fhsize > NFSX_V3FHMAX64) | |||
| ||||
592 | return (EINVAL22); | |||
593 | error = copyin(args->fh, nfh, args->fhsize); | |||
594 | if (error) | |||
595 | return (error); | |||
596 | error = copyinstr(args->hostname, hst, MNAMELEN90-1, &len); | |||
597 | if (error) | |||
598 | return (error); | |||
599 | memset(&hst[len], 0, MNAMELEN - len)__builtin_memset((&hst[len]), (0), (90 - len)); | |||
600 | /* sockargs() call must be after above copyin() calls */ | |||
601 | error = sockargs(&nam, args->addr, args->addrlen, MT_SONAME3); | |||
602 | if (error) | |||
603 | return (error); | |||
604 | args->fh = nfh; | |||
605 | error = mountnfs(args, mp, nam, path, hst, &vp, p); | |||
606 | return (error); | |||
607 | } | |||
608 | ||||
609 | /* | |||
610 | * Common code for mount and mountroot | |||
611 | */ | |||
612 | int | |||
613 | mountnfs(struct nfs_args *argp, struct mount *mp, struct mbuf *nam, | |||
614 | const char *pth, char *hst, struct vnode **vpp, struct proc *p) | |||
615 | { | |||
616 | struct nfsmount *nmp; | |||
617 | struct nfsnode *np; | |||
618 | struct vnode *vp; | |||
619 | struct vattr attr; | |||
620 | int error; | |||
621 | ||||
622 | if (mp->mnt_flag & MNT_UPDATE0x00010000) { | |||
623 | nmp = VFSTONFS(mp)((struct nfsmount *)((mp)->mnt_data)); | |||
624 | /* update paths, file handles, etc, here XXX */ | |||
625 | m_freem(nam); | |||
626 | return (0); | |||
627 | } else { | |||
628 | nmp = malloc(sizeof(*nmp), M_NFSMNT23, | |||
629 | M_WAITOK0x0001|M_ZERO0x0008); | |||
630 | mp->mnt_data = nmp; | |||
631 | } | |||
632 | ||||
633 | vfs_getnewfsid(mp); | |||
634 | nmp->nm_mountp = mp; | |||
635 | nmp->nm_timeo = NFS_TIMEO(1 * (hz / nfs_ticks)); | |||
636 | nmp->nm_retry = NFS_RETRANS10; | |||
637 | nmp->nm_wsize = NFS_WSIZE8192; | |||
638 | nmp->nm_rsize = NFS_RSIZE8192; | |||
639 | nmp->nm_readdirsize = NFS_READDIRSIZE8192; | |||
640 | nmp->nm_numgrps = NFS_MAXGRPS16; | |||
641 | nmp->nm_readahead = NFS_DEFRAHEAD1; | |||
642 | nmp->nm_acregmin = NFS_MINATTRTIMO5; | |||
643 | nmp->nm_acregmax = NFS_MAXATTRTIMO60; | |||
644 | nmp->nm_acdirmin = NFS_MINATTRTIMO5; | |||
645 | nmp->nm_acdirmax = NFS_MAXATTRTIMO60; | |||
646 | mp->mnt_stat.f_namemax = MAXNAMLEN255; | |||
647 | memset(mp->mnt_stat.f_mntonname, 0, MNAMELEN)__builtin_memset((mp->mnt_stat.f_mntonname), (0), (90)); | |||
648 | strlcpy(mp->mnt_stat.f_mntonname, pth, MNAMELEN90); | |||
649 | memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN)__builtin_memset((mp->mnt_stat.f_mntfromname), (0), (90)); | |||
650 | strlcpy(mp->mnt_stat.f_mntfromname, hst, MNAMELEN90); | |||
651 | memset(mp->mnt_stat.f_mntfromspec, 0, MNAMELEN)__builtin_memset((mp->mnt_stat.f_mntfromspec), (0), (90)); | |||
652 | strlcpy(mp->mnt_stat.f_mntfromspec, hst, MNAMELEN90); | |||
653 | bcopy(argp, &mp->mnt_stat.mount_info.nfs_args, sizeof(*argp)); | |||
654 | nmp->nm_nam = nam; | |||
655 | nfs_decode_args(nmp, argp, &mp->mnt_stat.mount_info.nfs_args); | |||
656 | ||||
657 | nfs_ninit(nmp); | |||
658 | TAILQ_INIT(&nmp->nm_reqsq)do { (&nmp->nm_reqsq)->tqh_first = ((void *)0); (& nmp->nm_reqsq)->tqh_last = &(&nmp->nm_reqsq) ->tqh_first; } while (0); | |||
659 | timeout_set_proc(&nmp->nm_rtimeout, nfs_timer, nmp); | |||
660 | ||||
661 | /* Set up the sockets and per-host congestion */ | |||
662 | nmp->nm_sotype = argp->sotype; | |||
663 | nmp->nm_soproto = argp->proto; | |||
664 | ||||
665 | /* | |||
666 | * For Connection based sockets (TCP,...) defer the connect until | |||
667 | * the first request, in case the server is not responding. | |||
668 | */ | |||
669 | if (nmp->nm_sotype == SOCK_DGRAM2 && | |||
670 | (error = nfs_connect(nmp, NULL((void *)0)))) | |||
671 | goto bad; | |||
672 | ||||
673 | /* | |||
674 | * This is silly, but it has to be set so that vinifod() works. | |||
675 | * We do not want to do an nfs_statfs() here since we can get | |||
676 | * stuck on a dead server and we are holding a lock on the mount | |||
677 | * point. | |||
678 | */ | |||
679 | mp->mnt_stat.f_iosize = NFS_MAXDGRAMDATA32768; | |||
680 | error = nfs_nget(mp, (nfsfh_t *)argp->fh, argp->fhsize, &np); | |||
681 | if (error) | |||
682 | goto bad; | |||
683 | vp = NFSTOV(np)((np)->n_vnode); | |||
684 | error = VOP_GETATTR(vp, &attr, p->p_ucred, p); | |||
685 | if (error) { | |||
686 | vput(vp); | |||
687 | goto bad; | |||
688 | } | |||
689 | ||||
690 | /* | |||
691 | * A reference count is needed on the nfsnode representing the | |||
692 | * remote root. If this object is not persistent, then backward | |||
693 | * traversals of the mount point (i.e. "..") will not work if | |||
694 | * the nfsnode gets flushed out of the cache. Ufs does not have | |||
695 | * this problem, because one can identify root inodes by their | |||
696 | * number == ROOTINO (2). So, just unlock, but no rele. | |||
697 | */ | |||
698 | nmp->nm_vnode = vp; | |||
699 | if (vp->v_type == VNON) | |||
700 | vp->v_type = VDIR; | |||
701 | vp->v_flag = VROOT0x0001; | |||
702 | VOP_UNLOCK(vp); | |||
703 | *vpp = vp; | |||
704 | ||||
705 | return (0); | |||
706 | bad: | |||
707 | nfs_disconnect(nmp); | |||
708 | free(nmp, M_NFSMNT23, sizeof(*nmp)); | |||
709 | m_freem(nam); | |||
710 | return (error); | |||
711 | } | |||
712 | ||||
713 | /* unmount system call */ | |||
714 | int | |||
715 | nfs_unmount(struct mount *mp, int mntflags, struct proc *p) | |||
716 | { | |||
717 | struct nfsmount *nmp; | |||
718 | struct vnode *vp; | |||
719 | int error, flags = 0; | |||
720 | ||||
721 | nmp = VFSTONFS(mp)((struct nfsmount *)((mp)->mnt_data)); | |||
722 | error = nfs_root(mp, &vp); | |||
723 | if (error) | |||
724 | return (error); | |||
725 | ||||
726 | if ((mntflags & MNT_FORCE0x00080000) == 0 && vp->v_usecount > 2) { | |||
727 | vput(vp); | |||
728 | return (EBUSY16); | |||
729 | } | |||
730 | ||||
731 | if (mntflags & MNT_FORCE0x00080000) | |||
732 | flags |= FORCECLOSE0x0002; | |||
733 | ||||
734 | error = vflush(mp, vp, flags); | |||
735 | if (error) { | |||
736 | vput(vp); | |||
737 | return (error); | |||
738 | } | |||
739 | ||||
740 | /* | |||
741 | * There are two references count to get rid of here: one | |||
742 | * from mountnfs() and one from nfs_root() above. | |||
743 | */ | |||
744 | vrele(vp); | |||
745 | vput(vp); | |||
746 | vgone(vp); | |||
747 | nfs_disconnect(nmp); | |||
748 | m_freem(nmp->nm_nam); | |||
749 | timeout_del(&nmp->nm_rtimeout); | |||
750 | timeout_set_proc(&nmp->nm_rtimeout, nfs_reaper, nmp); | |||
751 | timeout_add(&nmp->nm_rtimeout, 0); | |||
752 | mp->mnt_data = NULL((void *)0); | |||
753 | return (0); | |||
754 | } | |||
755 | ||||
756 | /* | |||
757 | * Delay nfs mount point free until pending or sleeping timeouts have finished. | |||
758 | */ | |||
759 | void | |||
760 | nfs_reaper(void *arg) | |||
761 | { | |||
762 | struct nfsmount *nmp = arg; | |||
763 | ||||
764 | free(nmp, M_NFSMNT23, sizeof(*nmp)); | |||
765 | } | |||
766 | ||||
767 | /* | |||
768 | * Return root of a filesystem | |||
769 | */ | |||
770 | int | |||
771 | nfs_root(struct mount *mp, struct vnode **vpp) | |||
772 | { | |||
773 | struct vnode *vp; | |||
774 | struct nfsmount *nmp; | |||
775 | int error; | |||
776 | ||||
777 | nmp = VFSTONFS(mp)((struct nfsmount *)((mp)->mnt_data)); | |||
778 | vp = nmp->nm_vnode; | |||
779 | vref(vp); | |||
780 | error = vn_lock(vp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL); | |||
781 | if (error) { | |||
782 | vrele(vp); | |||
783 | return (error); | |||
784 | } | |||
785 | *vpp = vp; | |||
786 | return (0); | |||
787 | } | |||
788 | ||||
789 | /* | |||
790 | * Flush out the buffer cache | |||
791 | */ | |||
792 | int | |||
793 | nfs_sync(struct mount *mp, int waitfor, int stall, struct ucred *cred, struct proc *p) | |||
794 | { | |||
795 | struct vnode *vp; | |||
796 | int error, allerror = 0; | |||
797 | ||||
798 | /* | |||
799 | * Don't traverse the vnode list if we want to skip all of them. | |||
800 | */ | |||
801 | if (waitfor == MNT_LAZY3) | |||
802 | return (allerror); | |||
803 | ||||
804 | /* | |||
805 | * Force stale buffer cache information to be flushed. | |||
806 | */ | |||
807 | loop: | |||
808 | TAILQ_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes)for((vp) = ((&mp->mnt_vnodelist)->tqh_first); (vp) != ((void *)0); (vp) = ((vp)->v_mntvnodes.tqe_next)) { | |||
809 | /* | |||
810 | * If the vnode that we are about to sync is no longer | |||
811 | * associated with this mount point, start over. | |||
812 | */ | |||
813 | if (vp->v_mount != mp) | |||
814 | goto loop; | |||
815 | if (VOP_ISLOCKED(vp) || LIST_EMPTY(&vp->v_dirtyblkhd)(((&vp->v_dirtyblkhd)->lh_first) == ((void *)0))) | |||
816 | continue; | |||
817 | if (vget(vp, LK_EXCLUSIVE0x0001UL)) | |||
818 | goto loop; | |||
819 | error = VOP_FSYNC(vp, cred, waitfor, p); | |||
820 | if (error) | |||
821 | allerror = error; | |||
822 | vput(vp); | |||
823 | } | |||
824 | ||||
825 | return (allerror); | |||
826 | } | |||
827 | ||||
828 | /* | |||
829 | * NFS flat namespace lookup. | |||
830 | * Currently unsupported. | |||
831 | */ | |||
832 | /* ARGSUSED */ | |||
833 | int | |||
834 | nfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) | |||
835 | { | |||
836 | ||||
837 | return (EOPNOTSUPP45); | |||
838 | } | |||
839 | ||||
840 | /* | |||
841 | * Do that sysctl thang... | |||
842 | */ | |||
843 | int | |||
844 | nfs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, | |||
845 | size_t newlen, struct proc *p) | |||
846 | { | |||
847 | int rv; | |||
848 | ||||
849 | /* | |||
850 | * All names at this level are terminal. | |||
851 | */ | |||
852 | if(namelen > 1) | |||
853 | return ENOTDIR20; /* overloaded */ | |||
854 | ||||
855 | switch(name[0]) { | |||
856 | case NFS_NFSSTATS1: | |||
857 | if(!oldp) { | |||
858 | *oldlenp = sizeof nfsstats; | |||
859 | return 0; | |||
860 | } | |||
861 | ||||
862 | if(*oldlenp < sizeof nfsstats) { | |||
863 | *oldlenp = sizeof nfsstats; | |||
864 | return ENOMEM12; | |||
865 | } | |||
866 | ||||
867 | rv = copyout(&nfsstats, oldp, sizeof nfsstats); | |||
868 | if(rv) return rv; | |||
869 | ||||
870 | if(newp && newlen != sizeof nfsstats) | |||
871 | return EINVAL22; | |||
872 | ||||
873 | if(newp) { | |||
874 | return copyin(newp, &nfsstats, sizeof nfsstats); | |||
875 | } | |||
876 | return 0; | |||
877 | ||||
878 | case NFS_NIOTHREADS2: | |||
879 | nfs_getset_niothreads(0); | |||
880 | ||||
881 | rv = sysctl_int(oldp, oldlenp, newp, newlen, &nfs_niothreads); | |||
882 | if (newp) | |||
883 | nfs_getset_niothreads(1); | |||
884 | ||||
885 | return rv; | |||
886 | ||||
887 | default: | |||
888 | return EOPNOTSUPP45; | |||
889 | } | |||
890 | } | |||
891 | ||||
892 | ||||
893 | /* | |||
894 | * At this point, this should never happen | |||
895 | */ | |||
896 | /* ARGSUSED */ | |||
897 | int | |||
898 | nfs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) | |||
899 | { | |||
900 | return (EINVAL22); | |||
901 | } | |||
902 | ||||
903 | /* | |||
904 | * Vnode pointer to File handle, should never happen either | |||
905 | */ | |||
906 | /* ARGSUSED */ | |||
907 | int | |||
908 | nfs_vptofh(struct vnode *vp, struct fid *fhp) | |||
909 | { | |||
910 | return (EINVAL22); | |||
911 | } | |||
912 | ||||
913 | /* | |||
914 | * Vfs start routine, a no-op. | |||
915 | */ | |||
916 | /* ARGSUSED */ | |||
917 | int | |||
918 | nfs_start(struct mount *mp, int flags, struct proc *p) | |||
919 | { | |||
920 | return (0); | |||
921 | } | |||
922 | ||||
923 | /* | |||
924 | * Do operations associated with quotas, not supported | |||
925 | */ | |||
926 | /* ARGSUSED */ | |||
927 | int | |||
928 | nfs_quotactl(struct mount *mp, int cmd, uid_t uid, caddr_t arg, struct proc *p) | |||
929 | { | |||
930 | return (EOPNOTSUPP45); | |||
931 | } | |||
932 | ||||
933 | /* | |||
934 | * check export permission, not supported | |||
935 | */ | |||
936 | /* ARGUSED */ | |||
937 | int | |||
938 | nfs_checkexp(struct mount *mp, struct mbuf *nam, int *exflagsp, | |||
939 | struct ucred **credanonp) | |||
940 | { | |||
941 | return (EOPNOTSUPP45); | |||
942 | } | |||
943 |