1/* 2 * Copyright (c) 1989, 1993, 1995 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95
| 1/* 2 * Copyright (c) 1989, 1993, 1995 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95
|
37 * $Id: nfs_vfsops.c,v 1.55 1998/03/01 22:46:30 msmith Exp $
| 37 * $Id: nfs_vfsops.c,v 1.56 1998/03/14 03:25:18 tegge Exp $
|
38 */ 39 40#include <sys/param.h> 41#include <sys/sockio.h> 42#include <sys/proc.h> 43#include <sys/vnode.h> 44#include <sys/kernel.h> 45#include <sys/sysctl.h> 46#include <sys/malloc.h> 47#include <sys/mount.h> 48#include <sys/mbuf.h> 49#include <sys/socket.h> 50#include <sys/socketvar.h> 51#include <sys/systm.h> 52 53#include <vm/vm.h> 54#include <vm/vm_extern.h> 55 56#include <net/if.h> 57#include <net/route.h> 58#include <netinet/in.h> 59 60#include <nfs/rpcv2.h> 61#include <nfs/nfsproto.h> 62#include <nfs/nfs.h> 63#include <nfs/nfsnode.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/nqnfs.h> 69 70extern int nfs_mountroot __P((struct mount *mp)); 71 72extern int nfs_ticks; 73 74MALLOC_DEFINE(M_NFSREQ, "NFS req", "NFS request header"); 75MALLOC_DEFINE(M_NFSMNT, "NFS mount", "NFS mount structure"); 76MALLOC_DEFINE(M_NFSBIGFH, "NFSV3 bigfh", "NFS version 3 file handle"); 77MALLOC_DEFINE(M_NFSD, "NFS daemon", "Nfs server daemon structure"); 78MALLOC_DEFINE(M_NFSDIROFF, "NFSV3 diroff", "NFS directory offset data"); 79MALLOC_DEFINE(M_NFSRVDESC, "NFSV3 srvdesc", "NFS server socket descriptor"); 80MALLOC_DEFINE(M_NFSUID, "NFS uid", "Nfs uid mapping structure"); 81MALLOC_DEFINE(M_NQLEASE, "NQNFS Lease", "Nqnfs lease"); 82 83struct nfsstats nfsstats; 84SYSCTL_NODE(_vfs, MOUNT_NFS, nfs, CTLFLAG_RW, 0, "NFS filesystem"); 85SYSCTL_STRUCT(_vfs_nfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RD, 86 &nfsstats, nfsstats, ""); 87#ifdef NFS_DEBUG 88int nfs_debug; 89SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0, ""); 90#endif 91 92static int nfs_iosize __P((struct nfsmount *nmp)); 93static int mountnfs __P((struct nfs_args *,struct mount *, 94 struct sockaddr *,char *,char *,struct vnode **)); 95static int nfs_mount __P(( struct mount *mp, char *path, caddr_t data, 96 struct nameidata *ndp, struct proc *p)); 97static int nfs_start __P(( struct mount *mp, int flags, 98 struct proc *p)); 99static int nfs_unmount __P(( struct mount *mp, int mntflags, 100 struct proc *p)); 101static int nfs_root __P(( struct mount *mp, struct vnode **vpp)); 102static int nfs_quotactl __P(( struct mount *mp, int cmds, uid_t uid, 103 caddr_t arg, struct proc *p)); 104static int nfs_statfs __P(( struct mount *mp, struct statfs *sbp, 105 struct proc *p)); 106static int nfs_sync __P(( struct mount *mp, int waitfor, 107 struct ucred *cred, struct proc *p)); 108static int nfs_vptofh __P(( struct vnode *vp, struct fid *fhp)); 109static int nfs_fhtovp __P((struct mount *mp, struct fid *fhp, 110 struct sockaddr *nam, struct vnode **vpp, 111 int *exflagsp, struct ucred **credanonp)); 112static int nfs_vget __P((struct mount *, ino_t, struct vnode **)); 113 114 115/* 116 * nfs vfs operations. 117 */ 118static struct vfsops nfs_vfsops = { 119 nfs_mount, 120 nfs_start, 121 nfs_unmount, 122 nfs_root, 123 nfs_quotactl, 124 nfs_statfs, 125 nfs_sync, 126 nfs_vget, 127 vfs_vrele, 128 nfs_fhtovp, 129 nfs_vptofh, 130 nfs_init 131}; 132VFS_SET(nfs_vfsops, nfs, MOUNT_NFS, VFCF_NETWORK); 133 134/* 135 * This structure must be filled in by a primary bootstrap or bootstrap 136 * server for a diskless/dataless machine. It is initialized below just 137 * to ensure that it is allocated to initialized data (.data not .bss). 138 */ 139struct nfs_diskless nfs_diskless = { 0 }; 140struct nfsv3_diskless nfsv3_diskless = { 0 }; 141int nfs_diskless_valid = 0; 142 143SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD, 144 &nfs_diskless_valid, 0, ""); 145 146SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD, 147 nfsv3_diskless.root_hostnam, 0, ""); 148 149SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD, 150 &nfsv3_diskless.root_saddr, sizeof nfsv3_diskless.root_saddr, 151 "%Ssockaddr_in", ""); 152 153SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_swappath, CTLFLAG_RD, 154 nfsv3_diskless.swap_hostnam, 0, ""); 155 156SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_swapaddr, CTLFLAG_RD, 157 &nfsv3_diskless.swap_saddr, sizeof nfsv3_diskless.swap_saddr, 158 "%Ssockaddr_in",""); 159 160 161void nfsargs_ntoh __P((struct nfs_args *)); 162static int nfs_mountdiskless __P((char *, char *, int, 163 struct sockaddr_in *, struct nfs_args *, 164 struct proc *, struct vnode **, 165 struct mount **)); 166static void nfs_convert_diskless __P((void)); 167static void nfs_convert_oargs __P((struct nfs_args *args, 168 struct onfs_args *oargs)); 169 170static int nfs_iosize(nmp) 171 struct nfsmount* nmp; 172{ 173 int iosize; 174 175 /* 176 * Calculate the size used for io buffers. Use the larger 177 * of the two sizes to minimise nfs requests but make sure 178 * that it is at least one VM page to avoid wasting buffer 179 * space. 180 */ 181 iosize = max(nmp->nm_rsize, nmp->nm_wsize); 182 if (iosize < PAGE_SIZE) iosize = PAGE_SIZE; 183 return iosize; 184} 185 186static void nfs_convert_oargs(args,oargs) 187 struct nfs_args *args; 188 struct onfs_args *oargs; 189{ 190 args->version = NFS_ARGSVERSION; 191 args->addr = oargs->addr; 192 args->addrlen = oargs->addrlen; 193 args->sotype = oargs->sotype; 194 args->proto = oargs->proto; 195 args->fh = oargs->fh; 196 args->fhsize = oargs->fhsize; 197 args->flags = oargs->flags; 198 args->wsize = oargs->wsize; 199 args->rsize = oargs->rsize; 200 args->readdirsize = oargs->readdirsize; 201 args->timeo = oargs->timeo; 202 args->retrans = oargs->retrans; 203 args->maxgrouplist = oargs->maxgrouplist; 204 args->readahead = oargs->readahead; 205 args->leaseterm = oargs->leaseterm; 206 args->deadthresh = oargs->deadthresh; 207 args->hostname = oargs->hostname; 208} 209 210static void 211nfs_convert_diskless() 212{ 213 bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif, 214 sizeof(struct ifaliasreq)); 215 bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway, 216 sizeof(struct sockaddr_in)); 217 nfs_convert_oargs(&nfsv3_diskless.swap_args,&nfs_diskless.swap_args); 218 nfsv3_diskless.swap_fhsize = NFSX_V2FH; 219 bcopy(nfs_diskless.swap_fh,nfsv3_diskless.swap_fh,NFSX_V2FH); 220 bcopy(&nfs_diskless.swap_saddr,&nfsv3_diskless.swap_saddr, 221 sizeof(struct sockaddr_in)); 222 bcopy(nfs_diskless.swap_hostnam,nfsv3_diskless.swap_hostnam, 223 MNAMELEN); 224 nfsv3_diskless.swap_nblks = nfs_diskless.swap_nblks; 225 bcopy(&nfs_diskless.swap_ucred, &nfsv3_diskless.swap_ucred, 226 sizeof(struct ucred)); 227 nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args); 228 nfsv3_diskless.root_fhsize = NFSX_V2FH; 229 bcopy(nfs_diskless.root_fh,nfsv3_diskless.root_fh,NFSX_V2FH); 230 bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr, 231 sizeof(struct sockaddr_in)); 232 bcopy(nfs_diskless.root_hostnam,nfsv3_diskless.root_hostnam, 233 MNAMELEN); 234 nfsv3_diskless.root_time = nfs_diskless.root_time; 235 bcopy(nfs_diskless.my_hostnam,nfsv3_diskless.my_hostnam, 236 MAXHOSTNAMELEN); 237 nfs_diskless_valid = 3; 238} 239 240/* 241 * nfs statfs call 242 */ 243int 244nfs_statfs(mp, sbp, p) 245 struct mount *mp; 246 register struct statfs *sbp; 247 struct proc *p; 248{ 249 register struct vnode *vp; 250 register struct nfs_statfs *sfp; 251 register caddr_t cp; 252 register u_long *tl; 253 register long t1, t2; 254 caddr_t bpos, dpos, cp2; 255 struct nfsmount *nmp = VFSTONFS(mp); 256 int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr; 257 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 258 struct ucred *cred; 259 struct nfsnode *np; 260 u_quad_t tquad; 261 262#ifndef nolint 263 sfp = (struct nfs_statfs *)0; 264#endif 265 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); 266 if (error) 267 return (error); 268 vp = NFSTOV(np); 269 cred = crget(); 270 cred->cr_ngroups = 1; 271 if (v3 && (nmp->nm_flag & NFSMNT_GOTFSINFO) == 0) 272 (void)nfs_fsinfo(nmp, vp, cred, p); 273 nfsstats.rpccnt[NFSPROC_FSSTAT]++; 274 nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3)); 275 nfsm_fhtom(vp, v3); 276 nfsm_request(vp, NFSPROC_FSSTAT, p, cred); 277 if (v3) 278 nfsm_postop_attr(vp, retattr); 279 if (!error) { 280 nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3)); 281 } else 282 goto nfsmout; 283 284 sbp->f_type = MOUNT_NFS; 285 sbp->f_flags = nmp->nm_flag; 286 sbp->f_iosize = nfs_iosize(nmp); 287 if (v3) { 288 sbp->f_bsize = NFS_FABLKSIZE; 289 fxdr_hyper(&sfp->sf_tbytes, &tquad); 290 sbp->f_blocks = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); 291 fxdr_hyper(&sfp->sf_fbytes, &tquad); 292 sbp->f_bfree = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); 293 fxdr_hyper(&sfp->sf_abytes, &tquad); 294 sbp->f_bavail = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); 295 sbp->f_files = (fxdr_unsigned(long, sfp->sf_tfiles.nfsuquad[1]) 296 & 0x7fffffff); 297 sbp->f_ffree = (fxdr_unsigned(long, sfp->sf_ffiles.nfsuquad[1]) 298 & 0x7fffffff); 299 } else { 300 sbp->f_bsize = fxdr_unsigned(long, sfp->sf_bsize); 301 sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks); 302 sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree); 303 sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail); 304 sbp->f_files = 0; 305 sbp->f_ffree = 0; 306 } 307 if (sbp != &mp->mnt_stat) { 308 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 309 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 310 } 311 nfsm_reqdone; 312 vput(vp); 313 crfree(cred); 314 return (error); 315} 316 317/* 318 * nfs version 3 fsinfo rpc call 319 */ 320int 321nfs_fsinfo(nmp, vp, cred, p) 322 register struct nfsmount *nmp; 323 register struct vnode *vp; 324 struct ucred *cred; 325 struct proc *p; 326{ 327 register struct nfsv3_fsinfo *fsp; 328 register caddr_t cp; 329 register long t1, t2; 330 register u_long *tl, pref, max; 331 caddr_t bpos, dpos, cp2; 332 int error = 0, retattr; 333 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 334 335 nfsstats.rpccnt[NFSPROC_FSINFO]++; 336 nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1)); 337 nfsm_fhtom(vp, 1); 338 nfsm_request(vp, NFSPROC_FSINFO, p, cred); 339 nfsm_postop_attr(vp, retattr); 340 if (!error) { 341 nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO); 342 pref = fxdr_unsigned(u_long, fsp->fs_wtpref); 343 if (pref < nmp->nm_wsize) 344 nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) & 345 ~(NFS_FABLKSIZE - 1); 346 max = fxdr_unsigned(u_long, fsp->fs_wtmax); 347 if (max < nmp->nm_wsize) { 348 nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1); 349 if (nmp->nm_wsize == 0) 350 nmp->nm_wsize = max; 351 } 352 pref = fxdr_unsigned(u_long, fsp->fs_rtpref); 353 if (pref < nmp->nm_rsize) 354 nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) & 355 ~(NFS_FABLKSIZE - 1); 356 max = fxdr_unsigned(u_long, fsp->fs_rtmax); 357 if (max < nmp->nm_rsize) { 358 nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1); 359 if (nmp->nm_rsize == 0) 360 nmp->nm_rsize = max; 361 } 362 pref = fxdr_unsigned(u_long, fsp->fs_dtpref); 363 if (pref < nmp->nm_readdirsize) 364 nmp->nm_readdirsize = pref; 365 if (max < nmp->nm_readdirsize) { 366 nmp->nm_readdirsize = max; 367 } 368 nmp->nm_flag |= NFSMNT_GOTFSINFO; 369 } 370 nfsm_reqdone; 371 return (error); 372} 373 374/* 375 * Mount a remote root fs via. nfs. This depends on the info in the 376 * nfs_diskless structure that has been filled in properly by some primary 377 * bootstrap. 378 * It goes something like this: 379 * - do enough of "ifconfig" by calling ifioctl() so that the system 380 * can talk to the server 381 * - If nfs_diskless.mygateway is filled in, use that address as 382 * a default gateway. 383 * - build the rootfs mount point and call mountnfs() to do the rest. 384 */ 385int 386nfs_mountroot(mp) 387 struct mount *mp; 388{ 389 struct mount *swap_mp; 390 struct nfsv3_diskless *nd = &nfsv3_diskless; 391 struct socket *so; 392 struct vnode *vp; 393 struct proc *p = curproc; /* XXX */ 394 int error, i; 395 u_long l; 396 char buf[128]; 397 398 /* 399 * XXX time must be non-zero when we init the interface or else 400 * the arp code will wedge... 401 */
| 38 */ 39 40#include <sys/param.h> 41#include <sys/sockio.h> 42#include <sys/proc.h> 43#include <sys/vnode.h> 44#include <sys/kernel.h> 45#include <sys/sysctl.h> 46#include <sys/malloc.h> 47#include <sys/mount.h> 48#include <sys/mbuf.h> 49#include <sys/socket.h> 50#include <sys/socketvar.h> 51#include <sys/systm.h> 52 53#include <vm/vm.h> 54#include <vm/vm_extern.h> 55 56#include <net/if.h> 57#include <net/route.h> 58#include <netinet/in.h> 59 60#include <nfs/rpcv2.h> 61#include <nfs/nfsproto.h> 62#include <nfs/nfs.h> 63#include <nfs/nfsnode.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/nqnfs.h> 69 70extern int nfs_mountroot __P((struct mount *mp)); 71 72extern int nfs_ticks; 73 74MALLOC_DEFINE(M_NFSREQ, "NFS req", "NFS request header"); 75MALLOC_DEFINE(M_NFSMNT, "NFS mount", "NFS mount structure"); 76MALLOC_DEFINE(M_NFSBIGFH, "NFSV3 bigfh", "NFS version 3 file handle"); 77MALLOC_DEFINE(M_NFSD, "NFS daemon", "Nfs server daemon structure"); 78MALLOC_DEFINE(M_NFSDIROFF, "NFSV3 diroff", "NFS directory offset data"); 79MALLOC_DEFINE(M_NFSRVDESC, "NFSV3 srvdesc", "NFS server socket descriptor"); 80MALLOC_DEFINE(M_NFSUID, "NFS uid", "Nfs uid mapping structure"); 81MALLOC_DEFINE(M_NQLEASE, "NQNFS Lease", "Nqnfs lease"); 82 83struct nfsstats nfsstats; 84SYSCTL_NODE(_vfs, MOUNT_NFS, nfs, CTLFLAG_RW, 0, "NFS filesystem"); 85SYSCTL_STRUCT(_vfs_nfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RD, 86 &nfsstats, nfsstats, ""); 87#ifdef NFS_DEBUG 88int nfs_debug; 89SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0, ""); 90#endif 91 92static int nfs_iosize __P((struct nfsmount *nmp)); 93static int mountnfs __P((struct nfs_args *,struct mount *, 94 struct sockaddr *,char *,char *,struct vnode **)); 95static int nfs_mount __P(( struct mount *mp, char *path, caddr_t data, 96 struct nameidata *ndp, struct proc *p)); 97static int nfs_start __P(( struct mount *mp, int flags, 98 struct proc *p)); 99static int nfs_unmount __P(( struct mount *mp, int mntflags, 100 struct proc *p)); 101static int nfs_root __P(( struct mount *mp, struct vnode **vpp)); 102static int nfs_quotactl __P(( struct mount *mp, int cmds, uid_t uid, 103 caddr_t arg, struct proc *p)); 104static int nfs_statfs __P(( struct mount *mp, struct statfs *sbp, 105 struct proc *p)); 106static int nfs_sync __P(( struct mount *mp, int waitfor, 107 struct ucred *cred, struct proc *p)); 108static int nfs_vptofh __P(( struct vnode *vp, struct fid *fhp)); 109static int nfs_fhtovp __P((struct mount *mp, struct fid *fhp, 110 struct sockaddr *nam, struct vnode **vpp, 111 int *exflagsp, struct ucred **credanonp)); 112static int nfs_vget __P((struct mount *, ino_t, struct vnode **)); 113 114 115/* 116 * nfs vfs operations. 117 */ 118static struct vfsops nfs_vfsops = { 119 nfs_mount, 120 nfs_start, 121 nfs_unmount, 122 nfs_root, 123 nfs_quotactl, 124 nfs_statfs, 125 nfs_sync, 126 nfs_vget, 127 vfs_vrele, 128 nfs_fhtovp, 129 nfs_vptofh, 130 nfs_init 131}; 132VFS_SET(nfs_vfsops, nfs, MOUNT_NFS, VFCF_NETWORK); 133 134/* 135 * This structure must be filled in by a primary bootstrap or bootstrap 136 * server for a diskless/dataless machine. It is initialized below just 137 * to ensure that it is allocated to initialized data (.data not .bss). 138 */ 139struct nfs_diskless nfs_diskless = { 0 }; 140struct nfsv3_diskless nfsv3_diskless = { 0 }; 141int nfs_diskless_valid = 0; 142 143SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD, 144 &nfs_diskless_valid, 0, ""); 145 146SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD, 147 nfsv3_diskless.root_hostnam, 0, ""); 148 149SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD, 150 &nfsv3_diskless.root_saddr, sizeof nfsv3_diskless.root_saddr, 151 "%Ssockaddr_in", ""); 152 153SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_swappath, CTLFLAG_RD, 154 nfsv3_diskless.swap_hostnam, 0, ""); 155 156SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_swapaddr, CTLFLAG_RD, 157 &nfsv3_diskless.swap_saddr, sizeof nfsv3_diskless.swap_saddr, 158 "%Ssockaddr_in",""); 159 160 161void nfsargs_ntoh __P((struct nfs_args *)); 162static int nfs_mountdiskless __P((char *, char *, int, 163 struct sockaddr_in *, struct nfs_args *, 164 struct proc *, struct vnode **, 165 struct mount **)); 166static void nfs_convert_diskless __P((void)); 167static void nfs_convert_oargs __P((struct nfs_args *args, 168 struct onfs_args *oargs)); 169 170static int nfs_iosize(nmp) 171 struct nfsmount* nmp; 172{ 173 int iosize; 174 175 /* 176 * Calculate the size used for io buffers. Use the larger 177 * of the two sizes to minimise nfs requests but make sure 178 * that it is at least one VM page to avoid wasting buffer 179 * space. 180 */ 181 iosize = max(nmp->nm_rsize, nmp->nm_wsize); 182 if (iosize < PAGE_SIZE) iosize = PAGE_SIZE; 183 return iosize; 184} 185 186static void nfs_convert_oargs(args,oargs) 187 struct nfs_args *args; 188 struct onfs_args *oargs; 189{ 190 args->version = NFS_ARGSVERSION; 191 args->addr = oargs->addr; 192 args->addrlen = oargs->addrlen; 193 args->sotype = oargs->sotype; 194 args->proto = oargs->proto; 195 args->fh = oargs->fh; 196 args->fhsize = oargs->fhsize; 197 args->flags = oargs->flags; 198 args->wsize = oargs->wsize; 199 args->rsize = oargs->rsize; 200 args->readdirsize = oargs->readdirsize; 201 args->timeo = oargs->timeo; 202 args->retrans = oargs->retrans; 203 args->maxgrouplist = oargs->maxgrouplist; 204 args->readahead = oargs->readahead; 205 args->leaseterm = oargs->leaseterm; 206 args->deadthresh = oargs->deadthresh; 207 args->hostname = oargs->hostname; 208} 209 210static void 211nfs_convert_diskless() 212{ 213 bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif, 214 sizeof(struct ifaliasreq)); 215 bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway, 216 sizeof(struct sockaddr_in)); 217 nfs_convert_oargs(&nfsv3_diskless.swap_args,&nfs_diskless.swap_args); 218 nfsv3_diskless.swap_fhsize = NFSX_V2FH; 219 bcopy(nfs_diskless.swap_fh,nfsv3_diskless.swap_fh,NFSX_V2FH); 220 bcopy(&nfs_diskless.swap_saddr,&nfsv3_diskless.swap_saddr, 221 sizeof(struct sockaddr_in)); 222 bcopy(nfs_diskless.swap_hostnam,nfsv3_diskless.swap_hostnam, 223 MNAMELEN); 224 nfsv3_diskless.swap_nblks = nfs_diskless.swap_nblks; 225 bcopy(&nfs_diskless.swap_ucred, &nfsv3_diskless.swap_ucred, 226 sizeof(struct ucred)); 227 nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args); 228 nfsv3_diskless.root_fhsize = NFSX_V2FH; 229 bcopy(nfs_diskless.root_fh,nfsv3_diskless.root_fh,NFSX_V2FH); 230 bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr, 231 sizeof(struct sockaddr_in)); 232 bcopy(nfs_diskless.root_hostnam,nfsv3_diskless.root_hostnam, 233 MNAMELEN); 234 nfsv3_diskless.root_time = nfs_diskless.root_time; 235 bcopy(nfs_diskless.my_hostnam,nfsv3_diskless.my_hostnam, 236 MAXHOSTNAMELEN); 237 nfs_diskless_valid = 3; 238} 239 240/* 241 * nfs statfs call 242 */ 243int 244nfs_statfs(mp, sbp, p) 245 struct mount *mp; 246 register struct statfs *sbp; 247 struct proc *p; 248{ 249 register struct vnode *vp; 250 register struct nfs_statfs *sfp; 251 register caddr_t cp; 252 register u_long *tl; 253 register long t1, t2; 254 caddr_t bpos, dpos, cp2; 255 struct nfsmount *nmp = VFSTONFS(mp); 256 int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr; 257 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 258 struct ucred *cred; 259 struct nfsnode *np; 260 u_quad_t tquad; 261 262#ifndef nolint 263 sfp = (struct nfs_statfs *)0; 264#endif 265 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); 266 if (error) 267 return (error); 268 vp = NFSTOV(np); 269 cred = crget(); 270 cred->cr_ngroups = 1; 271 if (v3 && (nmp->nm_flag & NFSMNT_GOTFSINFO) == 0) 272 (void)nfs_fsinfo(nmp, vp, cred, p); 273 nfsstats.rpccnt[NFSPROC_FSSTAT]++; 274 nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3)); 275 nfsm_fhtom(vp, v3); 276 nfsm_request(vp, NFSPROC_FSSTAT, p, cred); 277 if (v3) 278 nfsm_postop_attr(vp, retattr); 279 if (!error) { 280 nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3)); 281 } else 282 goto nfsmout; 283 284 sbp->f_type = MOUNT_NFS; 285 sbp->f_flags = nmp->nm_flag; 286 sbp->f_iosize = nfs_iosize(nmp); 287 if (v3) { 288 sbp->f_bsize = NFS_FABLKSIZE; 289 fxdr_hyper(&sfp->sf_tbytes, &tquad); 290 sbp->f_blocks = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); 291 fxdr_hyper(&sfp->sf_fbytes, &tquad); 292 sbp->f_bfree = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); 293 fxdr_hyper(&sfp->sf_abytes, &tquad); 294 sbp->f_bavail = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); 295 sbp->f_files = (fxdr_unsigned(long, sfp->sf_tfiles.nfsuquad[1]) 296 & 0x7fffffff); 297 sbp->f_ffree = (fxdr_unsigned(long, sfp->sf_ffiles.nfsuquad[1]) 298 & 0x7fffffff); 299 } else { 300 sbp->f_bsize = fxdr_unsigned(long, sfp->sf_bsize); 301 sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks); 302 sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree); 303 sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail); 304 sbp->f_files = 0; 305 sbp->f_ffree = 0; 306 } 307 if (sbp != &mp->mnt_stat) { 308 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 309 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 310 } 311 nfsm_reqdone; 312 vput(vp); 313 crfree(cred); 314 return (error); 315} 316 317/* 318 * nfs version 3 fsinfo rpc call 319 */ 320int 321nfs_fsinfo(nmp, vp, cred, p) 322 register struct nfsmount *nmp; 323 register struct vnode *vp; 324 struct ucred *cred; 325 struct proc *p; 326{ 327 register struct nfsv3_fsinfo *fsp; 328 register caddr_t cp; 329 register long t1, t2; 330 register u_long *tl, pref, max; 331 caddr_t bpos, dpos, cp2; 332 int error = 0, retattr; 333 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 334 335 nfsstats.rpccnt[NFSPROC_FSINFO]++; 336 nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1)); 337 nfsm_fhtom(vp, 1); 338 nfsm_request(vp, NFSPROC_FSINFO, p, cred); 339 nfsm_postop_attr(vp, retattr); 340 if (!error) { 341 nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO); 342 pref = fxdr_unsigned(u_long, fsp->fs_wtpref); 343 if (pref < nmp->nm_wsize) 344 nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) & 345 ~(NFS_FABLKSIZE - 1); 346 max = fxdr_unsigned(u_long, fsp->fs_wtmax); 347 if (max < nmp->nm_wsize) { 348 nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1); 349 if (nmp->nm_wsize == 0) 350 nmp->nm_wsize = max; 351 } 352 pref = fxdr_unsigned(u_long, fsp->fs_rtpref); 353 if (pref < nmp->nm_rsize) 354 nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) & 355 ~(NFS_FABLKSIZE - 1); 356 max = fxdr_unsigned(u_long, fsp->fs_rtmax); 357 if (max < nmp->nm_rsize) { 358 nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1); 359 if (nmp->nm_rsize == 0) 360 nmp->nm_rsize = max; 361 } 362 pref = fxdr_unsigned(u_long, fsp->fs_dtpref); 363 if (pref < nmp->nm_readdirsize) 364 nmp->nm_readdirsize = pref; 365 if (max < nmp->nm_readdirsize) { 366 nmp->nm_readdirsize = max; 367 } 368 nmp->nm_flag |= NFSMNT_GOTFSINFO; 369 } 370 nfsm_reqdone; 371 return (error); 372} 373 374/* 375 * Mount a remote root fs via. nfs. This depends on the info in the 376 * nfs_diskless structure that has been filled in properly by some primary 377 * bootstrap. 378 * It goes something like this: 379 * - do enough of "ifconfig" by calling ifioctl() so that the system 380 * can talk to the server 381 * - If nfs_diskless.mygateway is filled in, use that address as 382 * a default gateway. 383 * - build the rootfs mount point and call mountnfs() to do the rest. 384 */ 385int 386nfs_mountroot(mp) 387 struct mount *mp; 388{ 389 struct mount *swap_mp; 390 struct nfsv3_diskless *nd = &nfsv3_diskless; 391 struct socket *so; 392 struct vnode *vp; 393 struct proc *p = curproc; /* XXX */ 394 int error, i; 395 u_long l; 396 char buf[128]; 397 398 /* 399 * XXX time must be non-zero when we init the interface or else 400 * the arp code will wedge... 401 */
|
402 while (time.tv_sec == 0) 403 tsleep(&time, PZERO+8, "arpkludge", 10);
| 402 while (time_second == 0) 403 tsleep(&time_second, PZERO+8, "arpkludge", 10);
|
404 405 if (nfs_diskless_valid==1) 406 nfs_convert_diskless(); 407 408 /* 409 * XXX splnet, so networks will receive... 410 */ 411 splnet(); 412 413#ifdef notyet 414 /* Set up swap credentials. */ 415 proc0.p_ucred->cr_uid = ntohl(nd->swap_ucred.cr_uid); 416 proc0.p_ucred->cr_gid = ntohl(nd->swap_ucred.cr_gid); 417 if ((proc0.p_ucred->cr_ngroups = ntohs(nd->swap_ucred.cr_ngroups)) > 418 NGROUPS) 419 proc0.p_ucred->cr_ngroups = NGROUPS; 420 for (i = 0; i < proc0.p_ucred->cr_ngroups; i++) 421 proc0.p_ucred->cr_groups[i] = ntohl(nd->swap_ucred.cr_groups[i]); 422#endif 423 424 /* 425 * Do enough of ifconfig(8) so that the critical net interface can 426 * talk to the server. 427 */ 428 error = socreate(nd->myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0, p); 429 if (error) 430 panic("nfs_mountroot: socreate(%04x): %d", 431 nd->myif.ifra_addr.sa_family, error); 432 433 /* 434 * We might not have been told the right interface, so we pass 435 * over the first ten interfaces of the same kind, until we get 436 * one of them configured. 437 */ 438 439 for (i = strlen(nd->myif.ifra_name) - 1; 440 nd->myif.ifra_name[i] >= '0' && 441 nd->myif.ifra_name[i] <= '9'; 442 nd->myif.ifra_name[i] ++) { 443 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, p); 444 if(!error) 445 break; 446 } 447 if (error) 448 panic("nfs_mountroot: SIOCAIFADDR: %d", error); 449 soclose(so); 450 451 /* 452 * If the gateway field is filled in, set it as the default route. 453 */ 454 if (nd->mygateway.sin_len != 0) { 455 struct sockaddr_in mask, sin; 456 457 bzero((caddr_t)&mask, sizeof(mask)); 458 sin = mask; 459 sin.sin_family = AF_INET; 460 sin.sin_len = sizeof(sin); 461 error = rtrequest(RTM_ADD, (struct sockaddr *)&sin, 462 (struct sockaddr *)&nd->mygateway, 463 (struct sockaddr *)&mask, 464 RTF_UP | RTF_GATEWAY, (struct rtentry **)0); 465 if (error) 466 panic("nfs_mountroot: RTM_ADD: %d", error); 467 } 468 469 /* 470 * Create the rootfs mount point. 471 */ 472 nd->root_args.fh = nd->root_fh; 473 nd->root_args.fhsize = nd->root_fhsize; 474 l = ntohl(nd->root_saddr.sin_addr.s_addr); 475 sprintf(buf,"%ld.%ld.%ld.%ld:%s", 476 (l >> 24) & 0xff, (l >> 16) & 0xff, 477 (l >> 8) & 0xff, (l >> 0) & 0xff,nd->root_hostnam); 478 printf("NFS ROOT: %s\n",buf); 479 if (error = nfs_mountdiskless(buf, "/", MNT_RDONLY, 480 &nd->root_saddr, &nd->root_args, p, &vp, &mp)) { 481 if (swap_mp) { 482 mp->mnt_vfc->vfc_refcount--; 483 free(swap_mp, M_MOUNT); 484 } 485 return (error); 486 } 487 488 swap_mp = NULL; 489 if (nd->swap_nblks) { 490 491 /* Convert to DEV_BSIZE instead of Kilobyte */ 492 nd->swap_nblks *= 2; 493 494 /* 495 * Create a fake mount point just for the swap vnode so that the 496 * swap file can be on a different server from the rootfs. 497 */ 498 nd->swap_args.fh = nd->swap_fh; 499 nd->swap_args.fhsize = nd->swap_fhsize; 500 l = ntohl(nd->swap_saddr.sin_addr.s_addr); 501 sprintf(buf,"%ld.%ld.%ld.%ld:%s", 502 (l >> 24) & 0xff, (l >> 16) & 0xff, 503 (l >> 8) & 0xff, (l >> 0) & 0xff,nd->swap_hostnam); 504 printf("NFS SWAP: %s\n",buf); 505 if (error = nfs_mountdiskless(buf, "/swap", 0, 506 &nd->swap_saddr, &nd->swap_args, p, &vp, &swap_mp)) 507 return (error); 508 vfs_unbusy(swap_mp, p); 509 510 VTONFS(vp)->n_size = VTONFS(vp)->n_vattr.va_size = 511 nd->swap_nblks * DEV_BSIZE ; 512 513 /* 514 * Since the swap file is not the root dir of a file system, 515 * hack it to a regular file. 516 */ 517 vp->v_type = VREG; 518 vp->v_flag = 0; 519 VREF(vp); 520 swaponvp(p, vp, NODEV, nd->swap_nblks); 521 } 522 523 mp->mnt_flag |= MNT_ROOTFS; 524 mp->mnt_vnodecovered = NULLVP; 525 rootvp = vp; 526 vfs_unbusy(mp, p); 527 528 /* 529 * This is not really an nfs issue, but it is much easier to 530 * set hostname here and then let the "/etc/rc.xxx" files 531 * mount the right /var based upon its preset value. 532 */ 533 bcopy(nd->my_hostnam, hostname, MAXHOSTNAMELEN); 534 hostname[MAXHOSTNAMELEN - 1] = '\0'; 535 for (i = 0; i < MAXHOSTNAMELEN; i++) 536 if (hostname[i] == '\0') 537 break; 538 inittodr(ntohl(nd->root_time)); 539 return (0); 540} 541 542/* 543 * Internal version of mount system call for diskless setup. 544 */ 545static int 546nfs_mountdiskless(path, which, mountflag, sin, args, p, vpp, mpp) 547 char *path; 548 char *which; 549 int mountflag; 550 struct sockaddr_in *sin; 551 struct nfs_args *args; 552 struct proc *p; 553 struct vnode **vpp; 554 struct mount **mpp; 555{ 556 struct mount *mp; 557 struct sockaddr *nam; 558 int error; 559 560 mp = *mpp; 561 562 if (!mp && (error = vfs_rootmountalloc("nfs", path, &mp))) { 563 printf("nfs_mountroot: NFS not configured"); 564 return (error); 565 } 566 567 mp->mnt_kern_flag = 0; 568 mp->mnt_flag = mountflag; 569 nam = dup_sockaddr((struct sockaddr *)sin, 1); 570 if (error = mountnfs(args, mp, nam, which, path, vpp)) { 571 printf("nfs_mountroot: mount %s on %s: %d", path, which, error); 572 mp->mnt_vfc->vfc_refcount--; 573 vfs_unbusy(mp, p); 574 free(mp, M_MOUNT); 575 FREE(nam, M_SONAME); 576 return (error); 577 } 578 (void) copystr(which, mp->mnt_stat.f_mntonname, MNAMELEN - 1, 0); 579 *mpp = mp; 580 return (0); 581} 582 583/* 584 * VFS Operations. 585 * 586 * mount system call 587 * It seems a bit dumb to copyinstr() the host and path here and then 588 * bcopy() them in mountnfs(), but I wanted to detect errors before 589 * doing the sockargs() call because sockargs() allocates an mbuf and 590 * an error after that means that I have to release the mbuf. 591 */ 592/* ARGSUSED */ 593static int 594nfs_mount(mp, path, data, ndp, p) 595 struct mount *mp; 596 char *path; 597 caddr_t data; 598 struct nameidata *ndp; 599 struct proc *p; 600{ 601 int error; 602 struct nfs_args args; 603 struct sockaddr *nam; 604 struct vnode *vp; 605 char pth[MNAMELEN], hst[MNAMELEN]; 606 u_int len; 607 u_char nfh[NFSX_V3FHMAX]; 608 609 if (path == NULL) { 610 nfs_mountroot(mp); 611 return (0); 612 } 613 error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args)); 614 if (error) 615 return (error); 616 if (args.version != NFS_ARGSVERSION) { 617#ifndef NO_COMPAT_PRELITE2 618 /* 619 * If the argument version is unknown, then assume the 620 * caller is a pre-lite2 4.4BSD client and convert its 621 * arguments. 622 */ 623 struct onfs_args oargs; 624 error = copyin(data, (caddr_t)&oargs, sizeof (struct onfs_args)); 625 if (error) 626 return (error); 627 nfs_convert_oargs(&args,&oargs); 628#else /* NO_COMPAT_PRELITE2 */ 629 return (EPROGMISMATCH); 630#endif /* !NO_COMPAT_PRELITE2 */ 631 } 632 error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize); 633 if (error) 634 return (error); 635 error = copyinstr(path, pth, MNAMELEN-1, &len); 636 if (error) 637 return (error); 638 bzero(&pth[len], MNAMELEN - len); 639 error = copyinstr(args.hostname, hst, MNAMELEN-1, &len); 640 if (error) 641 return (error); 642 bzero(&hst[len], MNAMELEN - len); 643 /* sockargs() call must be after above copyin() calls */ 644 error = getsockaddr(&nam, (caddr_t)args.addr, args.addrlen); 645 if (error) 646 return (error); 647 args.fh = nfh; 648 error = mountnfs(&args, mp, nam, pth, hst, &vp); 649 return (error); 650} 651 652/* 653 * Common code for mount and mountroot 654 */ 655static int 656mountnfs(argp, mp, nam, pth, hst, vpp) 657 register struct nfs_args *argp; 658 register struct mount *mp; 659 struct sockaddr *nam; 660 char *pth, *hst; 661 struct vnode **vpp; 662{ 663 register struct nfsmount *nmp; 664 struct nfsnode *np; 665 int error, maxio; 666 struct vattr attrs; 667 668 if (mp->mnt_flag & MNT_UPDATE) { 669 nmp = VFSTONFS(mp); 670 /* update paths, file handles, etc, here XXX */ 671 FREE(nam, M_SONAME); 672 return (0); 673 } else { 674 MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount), 675 M_NFSMNT, M_WAITOK); 676 bzero((caddr_t)nmp, sizeof (struct nfsmount)); 677 TAILQ_INIT(&nmp->nm_uidlruhead); 678 TAILQ_INIT(&nmp->nm_bufq); 679 mp->mnt_data = (qaddr_t)nmp; 680 } 681 vfs_getnewfsid(mp); 682 nmp->nm_mountp = mp; 683 nmp->nm_flag = argp->flags; 684 if (nmp->nm_flag & NFSMNT_NQNFS) 685 /* 686 * We have to set mnt_maxsymlink to a non-zero value so 687 * that COMPAT_43 routines will know that we are setting 688 * the d_type field in directories (and can zero it for 689 * unsuspecting binaries). 690 */ 691 mp->mnt_maxsymlinklen = 1; 692 nmp->nm_timeo = NFS_TIMEO; 693 nmp->nm_retry = NFS_RETRANS; 694 nmp->nm_wsize = NFS_WSIZE; 695 nmp->nm_rsize = NFS_RSIZE; 696 nmp->nm_readdirsize = NFS_READDIRSIZE; 697 nmp->nm_numgrps = NFS_MAXGRPS; 698 nmp->nm_readahead = NFS_DEFRAHEAD; 699 nmp->nm_leaseterm = NQ_DEFLEASE; 700 nmp->nm_deadthresh = NQ_DEADTHRESH; 701 CIRCLEQ_INIT(&nmp->nm_timerhead); 702 nmp->nm_inprog = NULLVP; 703 nmp->nm_fhsize = argp->fhsize; 704 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize); 705 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN); 706 bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN); 707 nmp->nm_nam = nam; 708 709 /* 710 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes 711 * no sense in that context. 712 */ 713 if (argp->sotype == SOCK_STREAM) 714 argp->flags &= ~NFSMNT_NOCONN; 715 716 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) { 717 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10; 718 if (nmp->nm_timeo < NFS_MINTIMEO) 719 nmp->nm_timeo = NFS_MINTIMEO; 720 else if (nmp->nm_timeo > NFS_MAXTIMEO) 721 nmp->nm_timeo = NFS_MAXTIMEO; 722 } 723 724 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) { 725 nmp->nm_retry = argp->retrans; 726 if (nmp->nm_retry > NFS_MAXREXMIT) 727 nmp->nm_retry = NFS_MAXREXMIT; 728 } 729 730 if (argp->flags & NFSMNT_NFSV3) { 731 if (argp->sotype == SOCK_DGRAM) 732 maxio = NFS_MAXDGRAMDATA; 733 else 734 maxio = NFS_MAXDATA; 735 } else 736 maxio = NFS_V2MAXDATA; 737 738 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) { 739 nmp->nm_wsize = argp->wsize; 740 /* Round down to multiple of blocksize */ 741 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1); 742 if (nmp->nm_wsize <= 0) 743 nmp->nm_wsize = NFS_FABLKSIZE; 744 } 745 if (nmp->nm_wsize > maxio) 746 nmp->nm_wsize = maxio; 747 if (nmp->nm_wsize > MAXBSIZE) 748 nmp->nm_wsize = MAXBSIZE; 749 750 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) { 751 nmp->nm_rsize = argp->rsize; 752 /* Round down to multiple of blocksize */ 753 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1); 754 if (nmp->nm_rsize <= 0) 755 nmp->nm_rsize = NFS_FABLKSIZE; 756 } 757 if (nmp->nm_rsize > maxio) 758 nmp->nm_rsize = maxio; 759 if (nmp->nm_rsize > MAXBSIZE) 760 nmp->nm_rsize = MAXBSIZE; 761 762 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) { 763 nmp->nm_readdirsize = argp->readdirsize; 764 } 765 if (nmp->nm_readdirsize > maxio) 766 nmp->nm_readdirsize = maxio; 767 if (nmp->nm_readdirsize > nmp->nm_rsize) 768 nmp->nm_readdirsize = nmp->nm_rsize; 769 770 if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0 && 771 argp->maxgrouplist <= NFS_MAXGRPS) 772 nmp->nm_numgrps = argp->maxgrouplist; 773 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0 && 774 argp->readahead <= NFS_MAXRAHEAD) 775 nmp->nm_readahead = argp->readahead; 776 if ((argp->flags & NFSMNT_LEASETERM) && argp->leaseterm >= 2 && 777 argp->leaseterm <= NQ_MAXLEASE) 778 nmp->nm_leaseterm = argp->leaseterm; 779 if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 1 && 780 argp->deadthresh <= NQ_NEVERDEAD) 781 nmp->nm_deadthresh = argp->deadthresh; 782 /* Set up the sockets and per-host congestion */ 783 nmp->nm_sotype = argp->sotype; 784 nmp->nm_soproto = argp->proto; 785 786 /* 787 * For Connection based sockets (TCP,...) defer the connect until 788 * the first request, in case the server is not responding. 789 */ 790 if (nmp->nm_sotype == SOCK_DGRAM && 791 (error = nfs_connect(nmp, (struct nfsreq *)0))) 792 goto bad; 793 794 /* 795 * This is silly, but it has to be set so that vinifod() works. 796 * We do not want to do an nfs_statfs() here since we can get 797 * stuck on a dead server and we are holding a lock on the mount 798 * point. 799 */ 800 mp->mnt_stat.f_iosize = nfs_iosize(nmp); 801 /* 802 * A reference count is needed on the nfsnode representing the 803 * remote root. If this object is not persistent, then backward 804 * traversals of the mount point (i.e. "..") will not work if 805 * the nfsnode gets flushed out of the cache. Ufs does not have 806 * this problem, because one can identify root inodes by their 807 * number == ROOTINO (2). 808 */ 809 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); 810 if (error) 811 goto bad; 812 *vpp = NFSTOV(np); 813 814 /* 815 * Get file attributes for the mountpoint. This has the side 816 * effect of filling in (*vpp)->v_type with the correct value. 817 */ 818 VOP_GETATTR(*vpp, &attrs, curproc->p_ucred, curproc); 819 820 /* 821 * Lose the lock but keep the ref. 822 */ 823 VOP_UNLOCK(*vpp, 0, curproc); 824 825 return (0); 826bad: 827 nfs_disconnect(nmp); 828 free((caddr_t)nmp, M_NFSMNT); 829 FREE(nam, M_SONAME); 830 return (error); 831} 832 833/* 834 * unmount system call 835 */ 836static int 837nfs_unmount(mp, mntflags, p) 838 struct mount *mp; 839 int mntflags; 840 struct proc *p; 841{ 842 register struct nfsmount *nmp; 843 struct nfsnode *np; 844 struct vnode *vp; 845 int error, flags = 0; 846 847 if (mntflags & MNT_FORCE) 848 flags |= FORCECLOSE; 849 nmp = VFSTONFS(mp); 850 /* 851 * Goes something like this.. 852 * - Check for activity on the root vnode (other than ourselves). 853 * - Call vflush() to clear out vnodes for this file system, 854 * except for the root vnode. 855 * - Decrement reference on the vnode representing remote root. 856 * - Close the socket 857 * - Free up the data structures 858 */ 859 /* 860 * We need to decrement the ref. count on the nfsnode representing 861 * the remote root. See comment in mountnfs(). The VFS unmount() 862 * has done vput on this vnode, otherwise we would get deadlock! 863 */ 864 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); 865 if (error) 866 return(error); 867 vp = NFSTOV(np); 868 if (vp->v_usecount > 2) { 869 vput(vp); 870 return (EBUSY); 871 } 872 873 /* 874 * Must handshake with nqnfs_clientd() if it is active. 875 */ 876 nmp->nm_flag |= NFSMNT_DISMINPROG; 877 while (nmp->nm_inprog != NULLVP) 878 (void) tsleep((caddr_t)&lbolt, PSOCK, "nfsdism", 0); 879 error = vflush(mp, vp, flags); 880 if (error) { 881 vput(vp); 882 nmp->nm_flag &= ~NFSMNT_DISMINPROG; 883 return (error); 884 } 885 886 /* 887 * We are now committed to the unmount. 888 * For NQNFS, let the server daemon free the nfsmount structure. 889 */ 890 if (nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB)) 891 nmp->nm_flag |= NFSMNT_DISMNT; 892 893 /* 894 * There are two reference counts and one lock to get rid of here. 895 */ 896 vput(vp); 897 vrele(vp); 898 vgone(vp); 899 nfs_disconnect(nmp); 900 FREE(nmp->nm_nam, M_SONAME); 901 902 if ((nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB)) == 0) 903 free((caddr_t)nmp, M_NFSMNT); 904 return (0); 905} 906 907/* 908 * Return root of a filesystem 909 */ 910static int 911nfs_root(mp, vpp) 912 struct mount *mp; 913 struct vnode **vpp; 914{ 915 register struct vnode *vp; 916 struct nfsmount *nmp; 917 struct nfsnode *np; 918 int error; 919 920 nmp = VFSTONFS(mp); 921 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); 922 if (error) 923 return (error); 924 vp = NFSTOV(np); 925 if (vp->v_type == VNON) 926 vp->v_type = VDIR; 927 vp->v_flag = VROOT; 928 *vpp = vp; 929 return (0); 930} 931 932extern int syncprt; 933 934/* 935 * Flush out the buffer cache 936 */ 937/* ARGSUSED */ 938static int 939nfs_sync(mp, waitfor, cred, p) 940 struct mount *mp; 941 int waitfor; 942 struct ucred *cred; 943 struct proc *p; 944{ 945 register struct vnode *vp; 946 int error, allerror = 0; 947 948 /* 949 * Force stale buffer cache information to be flushed. 950 */ 951loop: 952 for (vp = mp->mnt_vnodelist.lh_first; 953 vp != NULL; 954 vp = vp->v_mntvnodes.le_next) { 955 /* 956 * If the vnode that we are about to sync is no longer 957 * associated with this mount point, start over. 958 */ 959 if (vp->v_mount != mp) 960 goto loop; 961 if (VOP_ISLOCKED(vp) || vp->v_dirtyblkhd.lh_first == NULL || 962 waitfor == MNT_LAZY) 963 continue; 964 if (vget(vp, LK_EXCLUSIVE, p)) 965 goto loop; 966 error = VOP_FSYNC(vp, cred, waitfor, p); 967 if (error) 968 allerror = error; 969 vput(vp); 970 } 971 return (allerror); 972} 973 974/* 975 * NFS flat namespace lookup. 976 * Currently unsupported. 977 */ 978/* ARGSUSED */ 979static int 980nfs_vget(mp, ino, vpp) 981 struct mount *mp; 982 ino_t ino; 983 struct vnode **vpp; 984{ 985 986 return (EOPNOTSUPP); 987} 988 989/* 990 * At this point, this should never happen 991 */ 992/* ARGSUSED */ 993static int 994nfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) 995 register struct mount *mp; 996 struct fid *fhp; 997 struct sockaddr *nam; 998 struct vnode **vpp; 999 int *exflagsp; 1000 struct ucred **credanonp; 1001{ 1002 1003 return (EINVAL); 1004} 1005 1006/* 1007 * Vnode pointer to File handle, should never happen either 1008 */ 1009/* ARGSUSED */ 1010static int 1011nfs_vptofh(vp, fhp) 1012 struct vnode *vp; 1013 struct fid *fhp; 1014{ 1015 1016 return (EINVAL); 1017} 1018 1019/* 1020 * Vfs start routine, a no-op. 1021 */ 1022/* ARGSUSED */ 1023static int 1024nfs_start(mp, flags, p) 1025 struct mount *mp; 1026 int flags; 1027 struct proc *p; 1028{ 1029 1030 return (0); 1031} 1032 1033/* 1034 * Do operations associated with quotas, not supported 1035 */ 1036/* ARGSUSED */ 1037static int 1038nfs_quotactl(mp, cmd, uid, arg, p) 1039 struct mount *mp; 1040 int cmd; 1041 uid_t uid; 1042 caddr_t arg; 1043 struct proc *p; 1044{ 1045 1046 return (EOPNOTSUPP); 1047}
| 404 405 if (nfs_diskless_valid==1) 406 nfs_convert_diskless(); 407 408 /* 409 * XXX splnet, so networks will receive... 410 */ 411 splnet(); 412 413#ifdef notyet 414 /* Set up swap credentials. */ 415 proc0.p_ucred->cr_uid = ntohl(nd->swap_ucred.cr_uid); 416 proc0.p_ucred->cr_gid = ntohl(nd->swap_ucred.cr_gid); 417 if ((proc0.p_ucred->cr_ngroups = ntohs(nd->swap_ucred.cr_ngroups)) > 418 NGROUPS) 419 proc0.p_ucred->cr_ngroups = NGROUPS; 420 for (i = 0; i < proc0.p_ucred->cr_ngroups; i++) 421 proc0.p_ucred->cr_groups[i] = ntohl(nd->swap_ucred.cr_groups[i]); 422#endif 423 424 /* 425 * Do enough of ifconfig(8) so that the critical net interface can 426 * talk to the server. 427 */ 428 error = socreate(nd->myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0, p); 429 if (error) 430 panic("nfs_mountroot: socreate(%04x): %d", 431 nd->myif.ifra_addr.sa_family, error); 432 433 /* 434 * We might not have been told the right interface, so we pass 435 * over the first ten interfaces of the same kind, until we get 436 * one of them configured. 437 */ 438 439 for (i = strlen(nd->myif.ifra_name) - 1; 440 nd->myif.ifra_name[i] >= '0' && 441 nd->myif.ifra_name[i] <= '9'; 442 nd->myif.ifra_name[i] ++) { 443 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, p); 444 if(!error) 445 break; 446 } 447 if (error) 448 panic("nfs_mountroot: SIOCAIFADDR: %d", error); 449 soclose(so); 450 451 /* 452 * If the gateway field is filled in, set it as the default route. 453 */ 454 if (nd->mygateway.sin_len != 0) { 455 struct sockaddr_in mask, sin; 456 457 bzero((caddr_t)&mask, sizeof(mask)); 458 sin = mask; 459 sin.sin_family = AF_INET; 460 sin.sin_len = sizeof(sin); 461 error = rtrequest(RTM_ADD, (struct sockaddr *)&sin, 462 (struct sockaddr *)&nd->mygateway, 463 (struct sockaddr *)&mask, 464 RTF_UP | RTF_GATEWAY, (struct rtentry **)0); 465 if (error) 466 panic("nfs_mountroot: RTM_ADD: %d", error); 467 } 468 469 /* 470 * Create the rootfs mount point. 471 */ 472 nd->root_args.fh = nd->root_fh; 473 nd->root_args.fhsize = nd->root_fhsize; 474 l = ntohl(nd->root_saddr.sin_addr.s_addr); 475 sprintf(buf,"%ld.%ld.%ld.%ld:%s", 476 (l >> 24) & 0xff, (l >> 16) & 0xff, 477 (l >> 8) & 0xff, (l >> 0) & 0xff,nd->root_hostnam); 478 printf("NFS ROOT: %s\n",buf); 479 if (error = nfs_mountdiskless(buf, "/", MNT_RDONLY, 480 &nd->root_saddr, &nd->root_args, p, &vp, &mp)) { 481 if (swap_mp) { 482 mp->mnt_vfc->vfc_refcount--; 483 free(swap_mp, M_MOUNT); 484 } 485 return (error); 486 } 487 488 swap_mp = NULL; 489 if (nd->swap_nblks) { 490 491 /* Convert to DEV_BSIZE instead of Kilobyte */ 492 nd->swap_nblks *= 2; 493 494 /* 495 * Create a fake mount point just for the swap vnode so that the 496 * swap file can be on a different server from the rootfs. 497 */ 498 nd->swap_args.fh = nd->swap_fh; 499 nd->swap_args.fhsize = nd->swap_fhsize; 500 l = ntohl(nd->swap_saddr.sin_addr.s_addr); 501 sprintf(buf,"%ld.%ld.%ld.%ld:%s", 502 (l >> 24) & 0xff, (l >> 16) & 0xff, 503 (l >> 8) & 0xff, (l >> 0) & 0xff,nd->swap_hostnam); 504 printf("NFS SWAP: %s\n",buf); 505 if (error = nfs_mountdiskless(buf, "/swap", 0, 506 &nd->swap_saddr, &nd->swap_args, p, &vp, &swap_mp)) 507 return (error); 508 vfs_unbusy(swap_mp, p); 509 510 VTONFS(vp)->n_size = VTONFS(vp)->n_vattr.va_size = 511 nd->swap_nblks * DEV_BSIZE ; 512 513 /* 514 * Since the swap file is not the root dir of a file system, 515 * hack it to a regular file. 516 */ 517 vp->v_type = VREG; 518 vp->v_flag = 0; 519 VREF(vp); 520 swaponvp(p, vp, NODEV, nd->swap_nblks); 521 } 522 523 mp->mnt_flag |= MNT_ROOTFS; 524 mp->mnt_vnodecovered = NULLVP; 525 rootvp = vp; 526 vfs_unbusy(mp, p); 527 528 /* 529 * This is not really an nfs issue, but it is much easier to 530 * set hostname here and then let the "/etc/rc.xxx" files 531 * mount the right /var based upon its preset value. 532 */ 533 bcopy(nd->my_hostnam, hostname, MAXHOSTNAMELEN); 534 hostname[MAXHOSTNAMELEN - 1] = '\0'; 535 for (i = 0; i < MAXHOSTNAMELEN; i++) 536 if (hostname[i] == '\0') 537 break; 538 inittodr(ntohl(nd->root_time)); 539 return (0); 540} 541 542/* 543 * Internal version of mount system call for diskless setup. 544 */ 545static int 546nfs_mountdiskless(path, which, mountflag, sin, args, p, vpp, mpp) 547 char *path; 548 char *which; 549 int mountflag; 550 struct sockaddr_in *sin; 551 struct nfs_args *args; 552 struct proc *p; 553 struct vnode **vpp; 554 struct mount **mpp; 555{ 556 struct mount *mp; 557 struct sockaddr *nam; 558 int error; 559 560 mp = *mpp; 561 562 if (!mp && (error = vfs_rootmountalloc("nfs", path, &mp))) { 563 printf("nfs_mountroot: NFS not configured"); 564 return (error); 565 } 566 567 mp->mnt_kern_flag = 0; 568 mp->mnt_flag = mountflag; 569 nam = dup_sockaddr((struct sockaddr *)sin, 1); 570 if (error = mountnfs(args, mp, nam, which, path, vpp)) { 571 printf("nfs_mountroot: mount %s on %s: %d", path, which, error); 572 mp->mnt_vfc->vfc_refcount--; 573 vfs_unbusy(mp, p); 574 free(mp, M_MOUNT); 575 FREE(nam, M_SONAME); 576 return (error); 577 } 578 (void) copystr(which, mp->mnt_stat.f_mntonname, MNAMELEN - 1, 0); 579 *mpp = mp; 580 return (0); 581} 582 583/* 584 * VFS Operations. 585 * 586 * mount system call 587 * It seems a bit dumb to copyinstr() the host and path here and then 588 * bcopy() them in mountnfs(), but I wanted to detect errors before 589 * doing the sockargs() call because sockargs() allocates an mbuf and 590 * an error after that means that I have to release the mbuf. 591 */ 592/* ARGSUSED */ 593static int 594nfs_mount(mp, path, data, ndp, p) 595 struct mount *mp; 596 char *path; 597 caddr_t data; 598 struct nameidata *ndp; 599 struct proc *p; 600{ 601 int error; 602 struct nfs_args args; 603 struct sockaddr *nam; 604 struct vnode *vp; 605 char pth[MNAMELEN], hst[MNAMELEN]; 606 u_int len; 607 u_char nfh[NFSX_V3FHMAX]; 608 609 if (path == NULL) { 610 nfs_mountroot(mp); 611 return (0); 612 } 613 error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args)); 614 if (error) 615 return (error); 616 if (args.version != NFS_ARGSVERSION) { 617#ifndef NO_COMPAT_PRELITE2 618 /* 619 * If the argument version is unknown, then assume the 620 * caller is a pre-lite2 4.4BSD client and convert its 621 * arguments. 622 */ 623 struct onfs_args oargs; 624 error = copyin(data, (caddr_t)&oargs, sizeof (struct onfs_args)); 625 if (error) 626 return (error); 627 nfs_convert_oargs(&args,&oargs); 628#else /* NO_COMPAT_PRELITE2 */ 629 return (EPROGMISMATCH); 630#endif /* !NO_COMPAT_PRELITE2 */ 631 } 632 error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize); 633 if (error) 634 return (error); 635 error = copyinstr(path, pth, MNAMELEN-1, &len); 636 if (error) 637 return (error); 638 bzero(&pth[len], MNAMELEN - len); 639 error = copyinstr(args.hostname, hst, MNAMELEN-1, &len); 640 if (error) 641 return (error); 642 bzero(&hst[len], MNAMELEN - len); 643 /* sockargs() call must be after above copyin() calls */ 644 error = getsockaddr(&nam, (caddr_t)args.addr, args.addrlen); 645 if (error) 646 return (error); 647 args.fh = nfh; 648 error = mountnfs(&args, mp, nam, pth, hst, &vp); 649 return (error); 650} 651 652/* 653 * Common code for mount and mountroot 654 */ 655static int 656mountnfs(argp, mp, nam, pth, hst, vpp) 657 register struct nfs_args *argp; 658 register struct mount *mp; 659 struct sockaddr *nam; 660 char *pth, *hst; 661 struct vnode **vpp; 662{ 663 register struct nfsmount *nmp; 664 struct nfsnode *np; 665 int error, maxio; 666 struct vattr attrs; 667 668 if (mp->mnt_flag & MNT_UPDATE) { 669 nmp = VFSTONFS(mp); 670 /* update paths, file handles, etc, here XXX */ 671 FREE(nam, M_SONAME); 672 return (0); 673 } else { 674 MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount), 675 M_NFSMNT, M_WAITOK); 676 bzero((caddr_t)nmp, sizeof (struct nfsmount)); 677 TAILQ_INIT(&nmp->nm_uidlruhead); 678 TAILQ_INIT(&nmp->nm_bufq); 679 mp->mnt_data = (qaddr_t)nmp; 680 } 681 vfs_getnewfsid(mp); 682 nmp->nm_mountp = mp; 683 nmp->nm_flag = argp->flags; 684 if (nmp->nm_flag & NFSMNT_NQNFS) 685 /* 686 * We have to set mnt_maxsymlink to a non-zero value so 687 * that COMPAT_43 routines will know that we are setting 688 * the d_type field in directories (and can zero it for 689 * unsuspecting binaries). 690 */ 691 mp->mnt_maxsymlinklen = 1; 692 nmp->nm_timeo = NFS_TIMEO; 693 nmp->nm_retry = NFS_RETRANS; 694 nmp->nm_wsize = NFS_WSIZE; 695 nmp->nm_rsize = NFS_RSIZE; 696 nmp->nm_readdirsize = NFS_READDIRSIZE; 697 nmp->nm_numgrps = NFS_MAXGRPS; 698 nmp->nm_readahead = NFS_DEFRAHEAD; 699 nmp->nm_leaseterm = NQ_DEFLEASE; 700 nmp->nm_deadthresh = NQ_DEADTHRESH; 701 CIRCLEQ_INIT(&nmp->nm_timerhead); 702 nmp->nm_inprog = NULLVP; 703 nmp->nm_fhsize = argp->fhsize; 704 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize); 705 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN); 706 bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN); 707 nmp->nm_nam = nam; 708 709 /* 710 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes 711 * no sense in that context. 712 */ 713 if (argp->sotype == SOCK_STREAM) 714 argp->flags &= ~NFSMNT_NOCONN; 715 716 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) { 717 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10; 718 if (nmp->nm_timeo < NFS_MINTIMEO) 719 nmp->nm_timeo = NFS_MINTIMEO; 720 else if (nmp->nm_timeo > NFS_MAXTIMEO) 721 nmp->nm_timeo = NFS_MAXTIMEO; 722 } 723 724 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) { 725 nmp->nm_retry = argp->retrans; 726 if (nmp->nm_retry > NFS_MAXREXMIT) 727 nmp->nm_retry = NFS_MAXREXMIT; 728 } 729 730 if (argp->flags & NFSMNT_NFSV3) { 731 if (argp->sotype == SOCK_DGRAM) 732 maxio = NFS_MAXDGRAMDATA; 733 else 734 maxio = NFS_MAXDATA; 735 } else 736 maxio = NFS_V2MAXDATA; 737 738 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) { 739 nmp->nm_wsize = argp->wsize; 740 /* Round down to multiple of blocksize */ 741 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1); 742 if (nmp->nm_wsize <= 0) 743 nmp->nm_wsize = NFS_FABLKSIZE; 744 } 745 if (nmp->nm_wsize > maxio) 746 nmp->nm_wsize = maxio; 747 if (nmp->nm_wsize > MAXBSIZE) 748 nmp->nm_wsize = MAXBSIZE; 749 750 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) { 751 nmp->nm_rsize = argp->rsize; 752 /* Round down to multiple of blocksize */ 753 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1); 754 if (nmp->nm_rsize <= 0) 755 nmp->nm_rsize = NFS_FABLKSIZE; 756 } 757 if (nmp->nm_rsize > maxio) 758 nmp->nm_rsize = maxio; 759 if (nmp->nm_rsize > MAXBSIZE) 760 nmp->nm_rsize = MAXBSIZE; 761 762 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) { 763 nmp->nm_readdirsize = argp->readdirsize; 764 } 765 if (nmp->nm_readdirsize > maxio) 766 nmp->nm_readdirsize = maxio; 767 if (nmp->nm_readdirsize > nmp->nm_rsize) 768 nmp->nm_readdirsize = nmp->nm_rsize; 769 770 if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0 && 771 argp->maxgrouplist <= NFS_MAXGRPS) 772 nmp->nm_numgrps = argp->maxgrouplist; 773 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0 && 774 argp->readahead <= NFS_MAXRAHEAD) 775 nmp->nm_readahead = argp->readahead; 776 if ((argp->flags & NFSMNT_LEASETERM) && argp->leaseterm >= 2 && 777 argp->leaseterm <= NQ_MAXLEASE) 778 nmp->nm_leaseterm = argp->leaseterm; 779 if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 1 && 780 argp->deadthresh <= NQ_NEVERDEAD) 781 nmp->nm_deadthresh = argp->deadthresh; 782 /* Set up the sockets and per-host congestion */ 783 nmp->nm_sotype = argp->sotype; 784 nmp->nm_soproto = argp->proto; 785 786 /* 787 * For Connection based sockets (TCP,...) defer the connect until 788 * the first request, in case the server is not responding. 789 */ 790 if (nmp->nm_sotype == SOCK_DGRAM && 791 (error = nfs_connect(nmp, (struct nfsreq *)0))) 792 goto bad; 793 794 /* 795 * This is silly, but it has to be set so that vinifod() works. 796 * We do not want to do an nfs_statfs() here since we can get 797 * stuck on a dead server and we are holding a lock on the mount 798 * point. 799 */ 800 mp->mnt_stat.f_iosize = nfs_iosize(nmp); 801 /* 802 * A reference count is needed on the nfsnode representing the 803 * remote root. If this object is not persistent, then backward 804 * traversals of the mount point (i.e. "..") will not work if 805 * the nfsnode gets flushed out of the cache. Ufs does not have 806 * this problem, because one can identify root inodes by their 807 * number == ROOTINO (2). 808 */ 809 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); 810 if (error) 811 goto bad; 812 *vpp = NFSTOV(np); 813 814 /* 815 * Get file attributes for the mountpoint. This has the side 816 * effect of filling in (*vpp)->v_type with the correct value. 817 */ 818 VOP_GETATTR(*vpp, &attrs, curproc->p_ucred, curproc); 819 820 /* 821 * Lose the lock but keep the ref. 822 */ 823 VOP_UNLOCK(*vpp, 0, curproc); 824 825 return (0); 826bad: 827 nfs_disconnect(nmp); 828 free((caddr_t)nmp, M_NFSMNT); 829 FREE(nam, M_SONAME); 830 return (error); 831} 832 833/* 834 * unmount system call 835 */ 836static int 837nfs_unmount(mp, mntflags, p) 838 struct mount *mp; 839 int mntflags; 840 struct proc *p; 841{ 842 register struct nfsmount *nmp; 843 struct nfsnode *np; 844 struct vnode *vp; 845 int error, flags = 0; 846 847 if (mntflags & MNT_FORCE) 848 flags |= FORCECLOSE; 849 nmp = VFSTONFS(mp); 850 /* 851 * Goes something like this.. 852 * - Check for activity on the root vnode (other than ourselves). 853 * - Call vflush() to clear out vnodes for this file system, 854 * except for the root vnode. 855 * - Decrement reference on the vnode representing remote root. 856 * - Close the socket 857 * - Free up the data structures 858 */ 859 /* 860 * We need to decrement the ref. count on the nfsnode representing 861 * the remote root. See comment in mountnfs(). The VFS unmount() 862 * has done vput on this vnode, otherwise we would get deadlock! 863 */ 864 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); 865 if (error) 866 return(error); 867 vp = NFSTOV(np); 868 if (vp->v_usecount > 2) { 869 vput(vp); 870 return (EBUSY); 871 } 872 873 /* 874 * Must handshake with nqnfs_clientd() if it is active. 875 */ 876 nmp->nm_flag |= NFSMNT_DISMINPROG; 877 while (nmp->nm_inprog != NULLVP) 878 (void) tsleep((caddr_t)&lbolt, PSOCK, "nfsdism", 0); 879 error = vflush(mp, vp, flags); 880 if (error) { 881 vput(vp); 882 nmp->nm_flag &= ~NFSMNT_DISMINPROG; 883 return (error); 884 } 885 886 /* 887 * We are now committed to the unmount. 888 * For NQNFS, let the server daemon free the nfsmount structure. 889 */ 890 if (nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB)) 891 nmp->nm_flag |= NFSMNT_DISMNT; 892 893 /* 894 * There are two reference counts and one lock to get rid of here. 895 */ 896 vput(vp); 897 vrele(vp); 898 vgone(vp); 899 nfs_disconnect(nmp); 900 FREE(nmp->nm_nam, M_SONAME); 901 902 if ((nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB)) == 0) 903 free((caddr_t)nmp, M_NFSMNT); 904 return (0); 905} 906 907/* 908 * Return root of a filesystem 909 */ 910static int 911nfs_root(mp, vpp) 912 struct mount *mp; 913 struct vnode **vpp; 914{ 915 register struct vnode *vp; 916 struct nfsmount *nmp; 917 struct nfsnode *np; 918 int error; 919 920 nmp = VFSTONFS(mp); 921 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); 922 if (error) 923 return (error); 924 vp = NFSTOV(np); 925 if (vp->v_type == VNON) 926 vp->v_type = VDIR; 927 vp->v_flag = VROOT; 928 *vpp = vp; 929 return (0); 930} 931 932extern int syncprt; 933 934/* 935 * Flush out the buffer cache 936 */ 937/* ARGSUSED */ 938static int 939nfs_sync(mp, waitfor, cred, p) 940 struct mount *mp; 941 int waitfor; 942 struct ucred *cred; 943 struct proc *p; 944{ 945 register struct vnode *vp; 946 int error, allerror = 0; 947 948 /* 949 * Force stale buffer cache information to be flushed. 950 */ 951loop: 952 for (vp = mp->mnt_vnodelist.lh_first; 953 vp != NULL; 954 vp = vp->v_mntvnodes.le_next) { 955 /* 956 * If the vnode that we are about to sync is no longer 957 * associated with this mount point, start over. 958 */ 959 if (vp->v_mount != mp) 960 goto loop; 961 if (VOP_ISLOCKED(vp) || vp->v_dirtyblkhd.lh_first == NULL || 962 waitfor == MNT_LAZY) 963 continue; 964 if (vget(vp, LK_EXCLUSIVE, p)) 965 goto loop; 966 error = VOP_FSYNC(vp, cred, waitfor, p); 967 if (error) 968 allerror = error; 969 vput(vp); 970 } 971 return (allerror); 972} 973 974/* 975 * NFS flat namespace lookup. 976 * Currently unsupported. 977 */ 978/* ARGSUSED */ 979static int 980nfs_vget(mp, ino, vpp) 981 struct mount *mp; 982 ino_t ino; 983 struct vnode **vpp; 984{ 985 986 return (EOPNOTSUPP); 987} 988 989/* 990 * At this point, this should never happen 991 */ 992/* ARGSUSED */ 993static int 994nfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) 995 register struct mount *mp; 996 struct fid *fhp; 997 struct sockaddr *nam; 998 struct vnode **vpp; 999 int *exflagsp; 1000 struct ucred **credanonp; 1001{ 1002 1003 return (EINVAL); 1004} 1005 1006/* 1007 * Vnode pointer to File handle, should never happen either 1008 */ 1009/* ARGSUSED */ 1010static int 1011nfs_vptofh(vp, fhp) 1012 struct vnode *vp; 1013 struct fid *fhp; 1014{ 1015 1016 return (EINVAL); 1017} 1018 1019/* 1020 * Vfs start routine, a no-op. 1021 */ 1022/* ARGSUSED */ 1023static int 1024nfs_start(mp, flags, p) 1025 struct mount *mp; 1026 int flags; 1027 struct proc *p; 1028{ 1029 1030 return (0); 1031} 1032 1033/* 1034 * Do operations associated with quotas, not supported 1035 */ 1036/* ARGSUSED */ 1037static int 1038nfs_quotactl(mp, cmd, uid, arg, p) 1039 struct mount *mp; 1040 int cmd; 1041 uid_t uid; 1042 caddr_t arg; 1043 struct proc *p; 1044{ 1045 1046 return (EOPNOTSUPP); 1047}
|