1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * 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 * from: @(#)nfs_vfsops.c 7.31 (Berkeley) 5/6/91 37 * $Id: nfs_vfsops.c,v 1.20 1994/05/18 00:35:17 cgd Exp $ 38 */ 39 40 #include <sys/param.h> 41 #include <sys/conf.h> 42 #include <sys/ioctl.h> 43 #include <sys/signal.h> 44 #include <sys/proc.h> 45 #include <sys/namei.h> 46 #include <sys/vnode.h> 47 #include <sys/mount.h> 48 #include <sys/buf.h> 49 #include <sys/mbuf.h> 50 #include <sys/socket.h> 51 #include <sys/systm.h> 52 53 #include <net/if.h> 54 #include <net/route.h> 55 56 #include <netinet/in.h> 57 58 #include <nfs/nfsv2.h> 59 #include <nfs/nfsnode.h> 60 #include <nfs/nfsmount.h> 61 #include <nfs/nfs.h> 62 #include <nfs/xdr_subs.h> 63 #include <nfs/nfsm_subs.h> 64 #include <nfs/nfsdiskless.h> 65 66 /* 67 * nfs vfs operations. 68 */ 69 struct vfsops nfs_vfsops = { 70 MOUNT_NFS, 71 nfs_mount, 72 nfs_start, 73 nfs_unmount, 74 nfs_root, 75 nfs_quotactl, 76 nfs_statfs, 77 nfs_sync, 78 nfs_fhtovp, 79 nfs_vptofh, 80 nfs_init, 81 }; 82 83 static u_char nfs_mntid; 84 extern u_long nfs_procids[NFS_NPROCS]; 85 extern u_long nfs_prog, nfs_vers; 86 void nfs_disconnect(); 87 88 #define TRUE 1 89 #define FALSE 0 90 91 /* 92 * nfs statfs call 93 */ 94 nfs_statfs(mp, sbp, p) 95 struct mount *mp; 96 register struct statfs *sbp; 97 struct proc *p; 98 { 99 register struct vnode *vp; 100 register struct nfsv2_statfs *sfp; 101 register caddr_t cp; 102 register long t1; 103 caddr_t bpos, dpos, cp2; 104 u_long xid; 105 int error = 0; 106 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 107 struct nfsmount *nmp; 108 struct ucred *cred; 109 struct nfsnode *np; 110 111 nmp = VFSTONFS(mp); 112 if (error = nfs_nget(mp, &nmp->nm_fh, &np)) 113 return (error); 114 vp = NFSTOV(np); 115 nfsstats.rpccnt[NFSPROC_STATFS]++; 116 cred = crget(); 117 cred->cr_ngroups = 1; 118 nfsm_reqhead(nfs_procids[NFSPROC_STATFS], cred, NFSX_FH); 119 nfsm_fhtom(vp); 120 nfsm_request(vp, NFSPROC_STATFS, p, 0); 121 nfsm_disect(sfp, struct nfsv2_statfs *, NFSX_STATFS); 122 #ifdef COMPAT_09 123 sbp->f_type = 2; 124 #else 125 sbp->f_type = 0; 126 #endif 127 sbp->f_flags = nmp->nm_flag; 128 sbp->f_iosize = fxdr_unsigned(long, sfp->sf_tsize); 129 sbp->f_bsize = fxdr_unsigned(long, sfp->sf_bsize); 130 sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks); 131 sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree); 132 sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail); 133 sbp->f_files = 0; 134 sbp->f_ffree = 0; 135 if (sbp != &mp->mnt_stat) { 136 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 137 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 138 } 139 strncpy(&sbp->f_fstypename[0], mp->mnt_op->vfs_name, MFSNAMELEN); 140 sbp->f_fstypename[MFSNAMELEN] = '\0'; 141 nfsm_reqdone; 142 nfs_nput(vp); 143 crfree(cred); 144 return (error); 145 } 146 147 /* 148 * Mount a remote root fs via. nfs. 149 * 150 * Configure up an interface 151 * Initialize a nfs_diskless struct with: 152 * ip addr 153 * broadcast addr 154 * netmask 155 * as acquired and implied by RARP. 156 * 157 * Then call nfs_boot() to fill in the rest of the structure with enough 158 * information to mount root and swap. 159 */ 160 nfs_mountroot() 161 { 162 register struct mount *mp; 163 register struct mbuf *m; 164 struct socket *so; 165 struct vnode *vp; 166 struct ifnet *ifp; 167 struct sockaddr_in *sin; 168 struct in_addr myip; 169 struct ifreq ireq; 170 struct nfs_diskless diskless; 171 int error, len; 172 173 /* 174 * Find an interface, rarp for its ip address, stuff it, the 175 * implied broadcast addr, and netmask into a nfs_diskless struct. 176 */ 177 178 for (ifp = ifnet; ifp; ifp = ifp->if_next) 179 if ((ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) == 0) 180 break; 181 if (ifp == NULL) 182 return ENETUNREACH; 183 strcpy(ireq.ifr_name, ifp->if_name); 184 len = strlen(ireq.ifr_name); 185 ireq.ifr_name[len] = '0' + ifp->if_unit; /* XXX */ 186 ireq.ifr_name[len+1] = '\0'; 187 ireq.ifr_flags = IFF_UP; 188 if (error = ifioctl(NULL, SIOCSIFFLAGS, (caddr_t)&ireq, curproc)) 189 panic("nfs_mountroot, bringing interface %s up", 190 ireq.ifr_name); 191 bzero((caddr_t) &diskless, sizeof(diskless)); 192 strcpy(diskless.myif.ifra_name, ireq.ifr_name); 193 if (revarpwhoami(&myip, ifp)) 194 panic("revarp failed"); 195 sin = (struct sockaddr_in *) &ireq.ifr_addr; 196 bzero((caddr_t) sin, sizeof(struct sockaddr_in)); 197 sin->sin_len = sizeof(struct sockaddr_in); 198 sin->sin_family = AF_INET; 199 sin->sin_addr = myip; 200 201 /* 202 * Do enough of ifconfig(8) so that the chosen interface can 203 * talk to the server(s). 204 */ 205 if (socreate(AF_INET, &so, SOCK_DGRAM, 0)) 206 panic("nfs ifconf"); 207 if (ifioctl(so, SIOCSIFADDR, (caddr_t)&ireq, curproc)) 208 panic("nfs_mountroot: setting interface address\n"); 209 bcopy((caddr_t) sin, (caddr_t) &diskless.myif.ifra_addr, 210 sizeof(struct sockaddr)); 211 if (ifioctl(so, SIOCGIFBRDADDR, (caddr_t)&ireq, curproc)) 212 panic("nfs baddr"); 213 bcopy((caddr_t) &ireq.ifr_broadaddr, 214 (caddr_t) &diskless.myif.ifra_broadaddr, 215 sizeof (ireq.ifr_broadaddr)); 216 if (ifioctl(so, SIOCGIFNETMASK, (caddr_t)&ireq, curproc)) 217 panic("nfs get netmask"); 218 soclose(so); 219 220 if (error = nfs_boot(&diskless)) 221 return error; 222 223 /* 224 * If the gateway field is filled in, set it as the default route. 225 */ 226 #ifdef COMPAT_43 227 if (diskless.mygateway.sa_family == AF_INET) { 228 struct ortentry rt; 229 struct sockaddr_in *sin; 230 231 sin = (struct sockaddr_in *) &rt.rt_dst; 232 sin->sin_len = sizeof (struct sockaddr_in); 233 sin->sin_family = AF_INET; 234 sin->sin_addr.s_addr = 0; /* default */ 235 bcopy((caddr_t)&diskless.mygateway, (caddr_t)&rt.rt_gateway, 236 sizeof (struct sockaddr_in)); 237 rt.rt_flags = (RTF_UP | RTF_GATEWAY); 238 if (rtioctl(SIOCADDRT, (caddr_t)&rt, curproc)) 239 panic("nfs root route"); 240 } 241 #endif /* COMPAT_43 */ 242 243 /* 244 * If swapping to an nfs node (indicated by swdevt[0].sw_dev == NODEV): 245 * Create a fake mount point just for the swap vnode so that the 246 * swap file can be on a different server from the rootfs. 247 */ 248 if (swdevt[0].sw_dev == NODEV) { 249 mp = (struct mount *)malloc((u_long)sizeof(struct mount), 250 M_MOUNT, M_NOWAIT); 251 if (mp == NULL) 252 panic("nfs root mount"); 253 mp->mnt_op = &nfs_vfsops; 254 mp->mnt_flag = 0; 255 mp->mnt_exroot = 0; 256 LIST_INIT(&mp->mnt_vnodelist); 257 258 /* 259 * Set up the diskless nfs_args for the swap mount point 260 * and then call mountnfs() to mount it. 261 * Since the swap file is not the root dir of a file system, 262 * hack it to a regular file. 263 */ 264 diskless.swap_args.fh = (nfsv2fh_t *)diskless.swap_fh; 265 MGET(m, MT_SONAME, M_DONTWAIT); 266 if (m == NULL) 267 panic("nfs root mbuf"); 268 bcopy((caddr_t)&diskless.swap_saddr, mtod(m, caddr_t), 269 diskless.swap_saddr.sa_len); 270 m->m_len = diskless.swap_saddr.sa_len; 271 if (mountnfs(&diskless.swap_args, mp, m, "/swap", 272 diskless.swap_hostnam, &vp)) 273 panic("nfs swap"); 274 vp->v_type = VREG; 275 vp->v_flag = 0; 276 swapdev_vp = vp; 277 VREF(vp); 278 swdevt[0].sw_vp = vp; 279 { 280 struct vattr attr; 281 282 if (nfs_dogetattr(vp,&attr,NOCRED,0,0)) { 283 panic("nfs swap getattr"); 284 } 285 swdevt[0].sw_nblks = attr.va_size / DEV_BSIZE; 286 } 287 } 288 289 /* 290 * Create the rootfs mount point. 291 */ 292 mp = (struct mount *)malloc((u_long)sizeof(struct mount), 293 M_MOUNT, M_NOWAIT); 294 if (mp == NULL) 295 panic("nfs root mount2"); 296 mp->mnt_op = &nfs_vfsops; 297 mp->mnt_flag = MNT_RDONLY; 298 mp->mnt_exroot = 0; 299 LIST_INIT(&mp->mnt_vnodelist); 300 301 /* 302 * Set up the root fs args and call mountnfs() to do the rest. 303 */ 304 diskless.root_args.fh = (nfsv2fh_t *)diskless.root_fh; 305 MGET(m, MT_SONAME, M_DONTWAIT); 306 if (m == NULL) 307 panic("nfs root mbuf2"); 308 bcopy((caddr_t)&diskless.root_saddr, mtod(m, caddr_t), 309 diskless.root_saddr.sa_len); 310 m->m_len = diskless.root_saddr.sa_len; 311 if (mountnfs(&diskless.root_args, mp, m, "/", 312 diskless.root_hostnam, &vp)) 313 panic("nfs root"); 314 if (vfs_lock(mp)) 315 panic("nfs root2"); 316 rootfs = mp; 317 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list); 318 mp->mnt_vnodecovered = NULLVP; 319 vfs_unlock(mp); 320 rootvp = vp; 321 inittodr((time_t)0); /* There is no time in the nfs fsstat so ?? */ 322 return (0); 323 } 324 325 static void 326 nfs_decode_flags(argp, nmp) 327 struct nfs_args *argp; 328 struct nfsmount *nmp; 329 { 330 int s = splnet(); 331 332 /* Don't touch the lock flags */ 333 nmp->nm_flag = (argp->flags & ~(NFSMNT_LOCKBITS)) | 334 (nmp->nm_flag & NFSMNT_LOCKBITS); 335 splx(s); 336 337 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) { 338 nmp->nm_rto = argp->timeo; 339 /* NFS timeouts are specified in 1/10 sec. */ 340 nmp->nm_rto = (nmp->nm_rto * 10) / NFS_HZ; 341 if (nmp->nm_rto < NFS_MINTIMEO) 342 nmp->nm_rto = NFS_MINTIMEO; 343 else if (nmp->nm_rto > NFS_MAXTIMEO) 344 nmp->nm_rto = NFS_MAXTIMEO; 345 nmp->nm_rttvar = nmp->nm_rto << 1; 346 } 347 348 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) { 349 nmp->nm_retry = argp->retrans; 350 if (nmp->nm_retry > NFS_MAXREXMIT) 351 nmp->nm_retry = NFS_MAXREXMIT; 352 } 353 354 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) { 355 nmp->nm_wsize = argp->wsize; 356 /* Round down to multiple of blocksize */ 357 nmp->nm_wsize &= ~0x1ff; 358 if (nmp->nm_wsize <= 0) 359 nmp->nm_wsize = 512; 360 else if (nmp->nm_wsize > NFS_MAXDATA) 361 nmp->nm_wsize = NFS_MAXDATA; 362 } 363 if (nmp->nm_wsize > MAXBSIZE) 364 nmp->nm_wsize = MAXBSIZE; 365 366 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) { 367 nmp->nm_rsize = argp->rsize; 368 /* Round down to multiple of blocksize */ 369 nmp->nm_rsize &= ~0x1ff; 370 if (nmp->nm_rsize <= 0) 371 nmp->nm_rsize = 512; 372 else if (nmp->nm_rsize > NFS_MAXDATA) 373 nmp->nm_rsize = NFS_MAXDATA; 374 } 375 if (nmp->nm_rsize > MAXBSIZE) 376 nmp->nm_rsize = MAXBSIZE; 377 } 378 379 /* 380 * VFS Operations. 381 * 382 * mount system call 383 * It seems a bit dumb to copyinstr() the host and path here and then 384 * bcopy() them in mountnfs(), but I wanted to detect errors before 385 * doing the sockargs() call because sockargs() allocates an mbuf and 386 * an error after that means that I have to release the mbuf. 387 */ 388 /* ARGSUSED */ 389 nfs_mount(mp, path, data, ndp, p) 390 struct mount *mp; 391 char *path; 392 caddr_t data; 393 struct nameidata *ndp; 394 struct proc *p; 395 { 396 int error; 397 struct nfs_args args; 398 struct mbuf *nam; 399 struct vnode *vp; 400 char pth[MNAMELEN], hst[MNAMELEN]; 401 u_int len; 402 nfsv2fh_t nfh; 403 404 if (error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args))) 405 return (error); 406 if (mp->mnt_flag & MNT_UPDATE) { 407 register struct nfsmount *nmp = VFSTONFS(mp); 408 409 if (nmp == NULL) 410 return EIO; 411 nfs_decode_flags(&args, nmp); 412 return (0); 413 } 414 if (error = copyin((caddr_t)args.fh, (caddr_t)&nfh, sizeof (nfsv2fh_t))) 415 return (error); 416 if (error = copyinstr(path, pth, MNAMELEN-1, &len)) 417 return (error); 418 bzero(&pth[len], MNAMELEN - len); 419 if (error = copyinstr(args.hostname, hst, MNAMELEN-1, &len)) 420 return (error); 421 bzero(&hst[len], MNAMELEN - len); 422 /* sockargs() call must be after above copyin() calls */ 423 if (error = sockargs(&nam, (caddr_t)args.addr, 424 sizeof (struct sockaddr), MT_SONAME)) 425 return (error); 426 args.fh = &nfh; 427 error = mountnfs(&args, mp, nam, pth, hst, &vp); 428 return (error); 429 } 430 431 /* 432 * Common code for mount and mountroot 433 */ 434 mountnfs(argp, mp, nam, pth, hst, vpp) 435 register struct nfs_args *argp; 436 register struct mount *mp; 437 struct mbuf *nam; 438 char *pth, *hst; 439 struct vnode **vpp; 440 { 441 register struct nfsmount *nmp; 442 struct proc *p = curproc; /* XXX */ 443 struct nfsnode *np; 444 int error; 445 fsid_t tfsid; 446 447 MALLOC(nmp, struct nfsmount *, sizeof *nmp, M_NFSMNT, M_WAITOK); 448 bzero((caddr_t)nmp, sizeof *nmp); 449 mp->mnt_data = (qaddr_t)nmp; 450 451 getnewfsid(mp, makefstype(MOUNT_NFS)); 452 nmp->nm_mountp = mp; 453 nmp->nm_rto = NFS_TIMEO; 454 nmp->nm_rtt = -1; 455 nmp->nm_rttvar = nmp->nm_rto << 1; 456 nmp->nm_retry = NFS_RETRANS; 457 nmp->nm_wsize = NFS_WSIZE; 458 nmp->nm_rsize = NFS_RSIZE; 459 bcopy((caddr_t)argp->fh, (caddr_t)&nmp->nm_fh, sizeof(nfsv2fh_t)); 460 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN); 461 bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN); 462 nmp->nm_nam = nam; 463 nfs_decode_flags(argp, nmp); 464 465 /* Set up the sockets and per-host congestion */ 466 nmp->nm_sotype = argp->sotype; 467 nmp->nm_soproto = argp->proto; 468 if (error = nfs_connect(nmp)) 469 goto bad; 470 471 if (error = nfs_statfs(mp, &mp->mnt_stat, p)) 472 goto bad; 473 /* 474 * A reference count is needed on the nfsnode representing the 475 * remote root. If this object is not persistent, then backward 476 * traversals of the mount point (i.e. "..") will not work if 477 * the nfsnode gets flushed out of the cache. Ufs does not have 478 * this problem, because one can identify root inodes by their 479 * number == ROOTINO (2). 480 */ 481 if (error = nfs_nget(mp, &nmp->nm_fh, &np)) 482 goto bad; 483 /* 484 * Unlock it, but keep the reference count. 485 */ 486 nfs_unlock(NFSTOV(np)); 487 *vpp = NFSTOV(np); 488 489 return (0); 490 bad: 491 nfs_disconnect(nmp); 492 FREE(nmp, M_NFSMNT); 493 m_freem(nam); 494 return (error); 495 } 496 497 /* 498 * unmount system call 499 */ 500 nfs_unmount(mp, mntflags, p) 501 struct mount *mp; 502 int mntflags; 503 struct proc *p; 504 { 505 register struct nfsmount *nmp; 506 struct nfsnode *np; 507 struct vnode *vp; 508 int error, flags = 0; 509 extern int doforce; 510 511 if (mntflags & MNT_FORCE) { 512 if (!doforce || mp == rootfs) 513 return (EINVAL); 514 flags |= FORCECLOSE; 515 } 516 nmp = VFSTONFS(mp); 517 /* 518 * Clear out the buffer cache 519 */ 520 mntflushbuf(mp, 0); 521 if (mntinvalbuf(mp)) 522 return (EBUSY); 523 /* 524 * Goes something like this.. 525 * - Check for activity on the root vnode (other than ourselves). 526 * - Call vflush() to clear out vnodes for this file system, 527 * except for the root vnode. 528 * - Decrement reference on the vnode representing remote root. 529 * - Close the socket 530 * - Free up the data structures 531 */ 532 /* 533 * We need to decrement the ref. count on the nfsnode representing 534 * the remote root. See comment in mountnfs(). The VFS unmount() 535 * has done vput on this vnode, otherwise we would get deadlock! 536 */ 537 if (error = nfs_nget(mp, &nmp->nm_fh, &np)) 538 return(error); 539 vp = NFSTOV(np); 540 if (vp->v_usecount > 2) { 541 vput(vp); 542 return (EBUSY); 543 } 544 if (error = vflush(mp, vp, flags)) { 545 vput(vp); 546 return (error); 547 } 548 /* 549 * Get rid of two reference counts, and unlock it on the second. 550 */ 551 vrele(vp); 552 vput(vp); 553 vgone(vp); 554 nfs_disconnect(nmp); 555 m_freem(nmp->nm_nam); 556 free((caddr_t)nmp, M_NFSMNT); 557 return (0); 558 } 559 560 /* 561 * Return root of a filesystem 562 */ 563 nfs_root(mp, vpp) 564 struct mount *mp; 565 struct vnode **vpp; 566 { 567 register struct vnode *vp; 568 struct nfsmount *nmp; 569 struct nfsnode *np; 570 int error; 571 struct vattr va; 572 struct proc *p = curproc /* XXX */; 573 574 nmp = VFSTONFS(mp); 575 if (error = nfs_nget(mp, &nmp->nm_fh, &np)) 576 return (error); 577 vp = NFSTOV(np); 578 if (error = nfs_getattr(vp, &va, p->p_ucred, p)) 579 return (error); 580 vp->v_type = va.va_type; 581 vp->v_flag = VROOT; 582 *vpp = vp; 583 return (0); 584 } 585 586 /* 587 * Flush out the buffer cache 588 */ 589 /* ARGSUSED */ 590 nfs_sync(mp, waitfor) 591 struct mount *mp; 592 int waitfor; 593 { 594 /* 595 * Force stale buffer cache information to be flushed. 596 */ 597 mntflushbuf(mp, waitfor == MNT_WAIT ? B_SYNC : 0); 598 return (0); 599 } 600 601 /* 602 * At this point, this should never happen 603 */ 604 /* ARGSUSED */ 605 nfs_fhtovp(mp, fhp, vpp) 606 struct mount *mp; 607 struct fid *fhp; 608 struct vnode **vpp; 609 { 610 611 return (EINVAL); 612 } 613 614 /* 615 * Vnode pointer to File handle, should never happen either 616 */ 617 /* ARGSUSED */ 618 nfs_vptofh(vp, fhp) 619 struct vnode *vp; 620 struct fid *fhp; 621 { 622 623 return (EINVAL); 624 } 625 626 /* 627 * Vfs start routine, a no-op. 628 */ 629 /* ARGSUSED */ 630 nfs_start(mp, flags, p) 631 struct mount *mp; 632 int flags; 633 struct proc *p; 634 { 635 636 return (0); 637 } 638 639 /* 640 * Do operations associated with quotas, not supported 641 */ 642 nfs_quotactl(mp, cmd, uid, arg, p) 643 struct mount *mp; 644 int cmd; 645 uid_t uid; 646 caddr_t arg; 647 struct proc *p; 648 { 649 #ifdef lint 650 mp = mp; cmd = cmd; uid = uid; arg = arg; 651 #endif /* lint */ 652 return (EOPNOTSUPP); 653 } 654