File: | nfs/nfs_vfsops.c |
Warning: | line 362, column 3 Value stored to 'n' is never read |
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); |
Value stored to 'n' is never read | |
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 |