138414Smckusick /* 238414Smckusick * Copyright (c) 1989 The Regents of the University of California. 338414Smckusick * All rights reserved. 438414Smckusick * 538414Smckusick * This code is derived from software contributed to Berkeley by 638414Smckusick * Rick Macklem at The University of Guelph. 738414Smckusick * 838414Smckusick * Redistribution and use in source and binary forms are permitted 938414Smckusick * provided that the above copyright notice and this paragraph are 1038414Smckusick * duplicated in all such forms and that any documentation, 1138414Smckusick * advertising materials, and other materials related to such 1238414Smckusick * distribution and use acknowledge that the software was developed 1338414Smckusick * by the University of California, Berkeley. The name of the 1438414Smckusick * University may not be used to endorse or promote products derived 1538414Smckusick * from this software without specific prior written permission. 1638414Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1738414Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1838414Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1938414Smckusick * 20*39669Smckusick * @(#)nfs_vfsops.c 7.10 (Berkeley) 11/30/89 2138414Smckusick */ 2238414Smckusick 2338414Smckusick #include "param.h" 2438414Smckusick #include "signal.h" 2538414Smckusick #include "user.h" 2638414Smckusick #include "proc.h" 2738414Smckusick #include "uio.h" 2838414Smckusick #include "ucred.h" 2938425Smckusick #include "../ufs/dir.h" 3038414Smckusick #include "namei.h" 3138414Smckusick #include "vnode.h" 3238414Smckusick #include "mount.h" 3338414Smckusick #include "errno.h" 3438414Smckusick #include "malloc.h" 3538414Smckusick #include "mbuf.h" 3638414Smckusick #undef m_data 3738414Smckusick #include "socket.h" 3838414Smckusick #include "socketvar.h" 3938414Smckusick #include "../netinet/in.h" 4038414Smckusick #include "nfsv2.h" 4138414Smckusick #include "nfsnode.h" 4238414Smckusick #include "nfsmount.h" 4338414Smckusick #include "nfs.h" 4438414Smckusick 4538414Smckusick #ifndef shouldbe 4638414Smckusick #include "conf.h" 4738414Smckusick #endif 4838414Smckusick 4938414Smckusick /* 5038414Smckusick * nfs vfs operations. 5138414Smckusick */ 5238414Smckusick int nfs_mount(); 5338874Smckusick int nfs_start(); 5438414Smckusick int nfs_unmount(); 5538414Smckusick int nfs_root(); 5639443Smckusick int nfs_statfs(); 5738414Smckusick int nfs_sync(); 5838414Smckusick int nfs_fhtovp(); 5938414Smckusick int nfs_vptofh(); 6039443Smckusick int nfs_init(); 6138414Smckusick 6238414Smckusick struct vfsops nfs_vfsops = { 6338414Smckusick nfs_mount, 6438874Smckusick nfs_start, 6538414Smckusick nfs_unmount, 6638414Smckusick nfs_root, 6738414Smckusick nfs_statfs, 6838414Smckusick nfs_sync, 6938414Smckusick nfs_fhtovp, 7038414Smckusick nfs_vptofh, 7139443Smckusick nfs_init, 7238414Smckusick }; 7338414Smckusick 7438414Smckusick extern struct nfsreq nfsreqh; 7538414Smckusick static long nfs_mntid; 7638414Smckusick 7738414Smckusick /* 7838414Smckusick * Called by vfs_mountroot when nfs is going to be mounted as root 7938414Smckusick * Not Yet (By a LONG shot) 8038414Smckusick */ 8138414Smckusick nfs_mountroot() 8238414Smckusick { 8338414Smckusick return (ENODEV); 8438414Smckusick } 8538414Smckusick 8638414Smckusick /* 8738414Smckusick * VFS Operations. 8838414Smckusick * 8938414Smckusick * mount system call 9038414Smckusick * It seems a bit dumb to copyinstr() the host and path here and then 9138414Smckusick * bcopy() them in mountnfs(), but I wanted to detect errors before 9238414Smckusick * doing the sockargs() call because sockargs() allocates an mbuf and 9338414Smckusick * an error after that means that I have to release the mbuf. 9438414Smckusick */ 9539494Smckusick /* ARGSUSED */ 9638414Smckusick nfs_mount(mp, path, data, ndp) 9738414Smckusick struct mount *mp; 9838414Smckusick char *path; 9938414Smckusick caddr_t data; 10038414Smckusick struct nameidata *ndp; 10138414Smckusick { 10238414Smckusick int error; 10338414Smckusick struct nfs_args args; 10438414Smckusick struct mbuf *saddr; 10538414Smckusick char pth[MNAMELEN], hst[MNAMELEN]; 10638414Smckusick int len; 10738414Smckusick nfsv2fh_t nfh; 10838414Smckusick 10939460Smckusick if (mp->m_flag & M_UPDATE) 11039460Smckusick return (0); 11138414Smckusick if (error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args))) 11238414Smckusick return (error); 11338414Smckusick if (error=copyin((caddr_t)args.fh, (caddr_t)&nfh, sizeof (nfsv2fh_t))) 11438414Smckusick return (error); 11538414Smckusick if (error = copyinstr(path, pth, MNAMELEN-1, &len)) 11638414Smckusick return (error); 11738414Smckusick bzero(&pth[len], MNAMELEN-len); 11838414Smckusick if (error = copyinstr(args.hostname, hst, MNAMELEN-1, &len)) 11938414Smckusick return (error); 12038414Smckusick bzero(&hst[len], MNAMELEN-len); 12138414Smckusick /* sockargs() call must be after above copyin() calls */ 12238414Smckusick if (error = sockargs(&saddr, (caddr_t)args.addr, 12338414Smckusick sizeof (struct sockaddr_in), MT_SONAME)) 12438414Smckusick return (error); 12538414Smckusick args.fh = &nfh; 12638414Smckusick error = mountnfs(&args, mp, saddr, pth, hst); 12738414Smckusick return (error); 12838414Smckusick } 12938414Smckusick 13038414Smckusick /* 13138414Smckusick * Common code for mount and mountroot 13238414Smckusick */ 13338414Smckusick mountnfs(argp, mp, saddr, pth, hst) 13438414Smckusick register struct nfs_args *argp; 13538414Smckusick register struct mount *mp; 13638414Smckusick register struct mbuf *saddr; 13738414Smckusick char *pth, *hst; 13838414Smckusick { 13938414Smckusick register struct nfsmount *nmp; 14038425Smckusick #ifdef notdef 14138414Smckusick struct statfs statf, *sbp; 14238425Smckusick #endif 14338414Smckusick int error; 14438414Smckusick 14538414Smckusick nmp = (struct nfsmount *)malloc(sizeof (struct nfsmount), M_NFSMNT, 14638414Smckusick M_WAITOK); 14738414Smckusick mp->m_data = (qaddr_t)nmp; 14838414Smckusick mp->m_fsid.val[0] = ++nfs_mntid; 14938414Smckusick mp->m_fsid.val[1] = MOUNT_NFS; 15038414Smckusick nmp->nm_mountp = mp; 15138414Smckusick nmp->nm_flag = argp->flags; 15238414Smckusick nmp->nm_sockaddr = saddr; 15338414Smckusick /* Set up the sockets */ 15438414Smckusick if (error = socreate(AF_INET, &nmp->nm_so, SOCK_DGRAM, 0)) 15538414Smckusick goto bad; 15638414Smckusick if (error = soconnect(nmp->nm_so, saddr)) 15738414Smckusick goto bad; 15838414Smckusick if ((argp->flags & NFSMNT_TIMEO) && argp->timeo >= 1) 15938414Smckusick nmp->nm_timeo = argp->timeo; 16038414Smckusick else 16138414Smckusick nmp->nm_timeo = NFS_TIMEO; 16238414Smckusick if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 0) 16338414Smckusick nmp->nm_retrans = argp->retrans; 16438414Smckusick else 16538414Smckusick nmp->nm_retrans = NFS_RETRANS; 16638414Smckusick if ((argp->flags & NFSMNT_WSIZE) && 16738414Smckusick argp->wsize <= NFS_MAXDATA && argp->wsize > 0 && 16838414Smckusick (argp->wsize & 0x1ff) == 0) 16938414Smckusick nmp->nm_wsize = argp->wsize; 17038414Smckusick else 17138414Smckusick nmp->nm_wsize = NFS_WSIZE; 17238414Smckusick if ((argp->flags & NFSMNT_RSIZE) && 17338414Smckusick argp->rsize <= NFS_MAXDATA && argp->rsize > 0 && 17438414Smckusick (argp->rsize & 0x1ff) == 0) 17538414Smckusick nmp->nm_rsize = argp->rsize; 17638414Smckusick else 17738414Smckusick nmp->nm_rsize = NFS_RSIZE; 17838414Smckusick bcopy((caddr_t)argp->fh, (caddr_t)&nmp->nm_fh, sizeof(nfsv2fh_t)); 17938414Smckusick bcopy(pth, nmp->nm_path, MNAMELEN); 18038414Smckusick bcopy(hst, nmp->nm_host, MNAMELEN); 18138425Smckusick #ifdef notdef 18238414Smckusick sbp = &statf; 18338414Smckusick /* 18438414Smckusick * Kludge City... 18538414Smckusick * To do an interruptable hard mount, turn it into a soft mount 18638414Smckusick * with a retry limit of one and then repeat it so long as it 18738414Smckusick * times out and there is no pending signal for the process. 18838414Smckusick * It is tempting to just let nfs_statfs() sleep at positive 18938414Smckusick * prio, but then you would long jump out without taking the 19038414Smckusick * mount structure back out of the list. 19138414Smckusick * NB: NFSMNT_INT must NEVER be set for nfs_mountroot(), since 19238414Smckusick * the process context is not yet built!! 19338414Smckusick */ 19438414Smckusick if ((argp->flags && NFSMNT_INT) && (argp->flags & NFSMNT_SOFT) == 0) { 19538414Smckusick int savretrans; 19638414Smckusick 19738414Smckusick nmp->nm_flag |= NFSMNT_SOFT; 19838414Smckusick savretrans = nmp->nm_retrans; 19938414Smckusick nmp->nm_retrans = 1; 20038414Smckusick do { 20138414Smckusick error = nfs_statfs(mp, sbp); 20238414Smckusick } while (error == ETIMEDOUT && (u.u_procp->p_sig & 20338414Smckusick (sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM)| 20438414Smckusick sigmask(SIGKILL))) == 0); 20538414Smckusick nmp->nm_retrans = savretrans; 20638414Smckusick nmp->nm_flag &= ~NFSMNT_SOFT; 20738414Smckusick if (error) 20838414Smckusick goto bad; 20938414Smckusick } else if (error = nfs_statfs(mp, sbp)) 21038414Smckusick goto bad; 21138414Smckusick mp->m_fsize = sbp->f_fsize; 21238414Smckusick 21338414Smckusick /* 21438414Smckusick * If the block size is not an exact multiple of CLBYTES 21538414Smckusick * use CLBYTES so that paging in ZMAGIC executables doesn't 21638414Smckusick * get sick. (It is used by vinitfod()) 21738414Smckusick */ 21838414Smckusick if (sbp->f_bsize >= CLBYTES && claligned(sbp->f_bsize)) 21938414Smckusick mp->m_bsize = sbp->f_bsize; 22038414Smckusick else 22138414Smckusick mp->m_bsize = CLBYTES; 22238425Smckusick #else 22338425Smckusick /* 22438425Smckusick * Set to CLBYTES so that vinifod() doesn't get confused. 22538425Smckusick * Actually any exact multiple of CLBYTES will do 22638425Smckusick */ 22738425Smckusick mp->m_bsize = mp->m_fsize = CLBYTES; 22838425Smckusick #endif 22938414Smckusick return (0); 23038414Smckusick bad: 23138414Smckusick m_freem(saddr); 23238414Smckusick free((caddr_t)nmp, M_NFSMNT); 23338414Smckusick return (error); 23438414Smckusick } 23538414Smckusick 23638414Smckusick /* 23738414Smckusick * unmount system call 23838414Smckusick */ 23938414Smckusick nfs_unmount(mp, flags) 24038414Smckusick struct mount *mp; 24138414Smckusick int flags; 24238414Smckusick { 24338414Smckusick register struct nfsmount *nmp; 24438414Smckusick register struct nfsreq *rep; 24538414Smckusick struct nfsreq *rep2; 24638414Smckusick int error; 24738414Smckusick int s; 24838414Smckusick 24938414Smckusick if (flags & MNT_FORCE) 25038414Smckusick return (EINVAL); 25138414Smckusick nmp = vfs_to_nfs(mp); 25238414Smckusick /* 25338884Smacklem * Clear out the buffer cache 25438884Smacklem */ 255*39669Smckusick mntflushbuf(mp, 0); 256*39669Smckusick if (mntinvalbuf(mp)) 25738884Smacklem return (EBUSY); 25838884Smacklem /* 25938414Smckusick * Goes something like this.. 26039510Smckusick * - Call vflush() to clear out vnodes for this file system 26138414Smckusick * - Flush out lookup cache 26238414Smckusick * - Close the socket 26338414Smckusick * - Free up the data structures 26438414Smckusick */ 26539510Smckusick if (error = vflush(mp, (struct vnode *)0, flags)) 26638414Smckusick return (error); 26738414Smckusick /* 26838414Smckusick * Scan the request list for any requests left hanging about 26938414Smckusick */ 27038414Smckusick s = splnet(); 27138414Smckusick rep = nfsreqh.r_next; 27239347Smckusick while (rep && rep != &nfsreqh) { 27338414Smckusick if (rep->r_mntp == nmp) { 27438414Smckusick rep->r_prev->r_next = rep2 = rep->r_next; 27539347Smckusick rep->r_next->r_prev = rep->r_prev; 27638414Smckusick m_freem(rep->r_mreq); 27738414Smckusick if (rep->r_mrep != NULL) 27838414Smckusick m_freem(rep->r_mrep); 27938414Smckusick free((caddr_t)rep, M_NFSREQ); 28038414Smckusick rep = rep2; 28138414Smckusick } else 28238414Smckusick rep = rep->r_next; 28338414Smckusick } 28438414Smckusick splx(s); 28538414Smckusick soclose(nmp->nm_so); 28638414Smckusick m_freem(nmp->nm_sockaddr); 28738414Smckusick free((caddr_t)nmp, M_NFSMNT); 28838414Smckusick return (0); 28938414Smckusick } 29038414Smckusick 29138414Smckusick /* 29238414Smckusick * Return root of a filesystem 29338414Smckusick */ 29438414Smckusick nfs_root(mp, vpp) 29538414Smckusick struct mount *mp; 29638414Smckusick struct vnode **vpp; 29738414Smckusick { 29838414Smckusick register struct vnode *vp; 29938414Smckusick struct nfsmount *nmp; 30038414Smckusick struct nfsnode *np; 30138414Smckusick int error; 30238414Smckusick 30338414Smckusick nmp = vfs_to_nfs(mp); 30438414Smckusick if (error = nfs_nget(mp, &nmp->nm_fh, &np)) 30538414Smckusick return (error); 30638414Smckusick vp = NFSTOV(np); 30738414Smckusick vp->v_type = VDIR; 30838414Smckusick vp->v_flag = VROOT; 30938414Smckusick *vpp = vp; 31038414Smckusick return (0); 31138414Smckusick } 31238414Smckusick 31338884Smacklem extern int syncprt; 31438884Smacklem 31538414Smckusick /* 31638884Smacklem * Flush out the buffer cache 31738414Smckusick */ 31839494Smckusick /* ARGSUSED */ 31938414Smckusick nfs_sync(mp, waitfor) 32038414Smckusick struct mount *mp; 32138414Smckusick int waitfor; 32238414Smckusick { 32338884Smacklem if (syncprt) 32438884Smacklem bufstats(); 32538884Smacklem /* 32638884Smacklem * Force stale buffer cache information to be flushed. 32738884Smacklem */ 328*39669Smckusick mntflushbuf(mp); 32938414Smckusick return (0); 33038414Smckusick } 33138414Smckusick 33238414Smckusick /* 33338414Smckusick * At this point, this should never happen 33438414Smckusick */ 33539494Smckusick /* ARGSUSED */ 33638414Smckusick nfs_fhtovp(mp, fhp, vpp) 33738414Smckusick struct mount *mp; 33838414Smckusick struct fid *fhp; 33938414Smckusick struct vnode **vpp; 34038414Smckusick { 34139494Smckusick 34238414Smckusick return (EINVAL); 34338414Smckusick } 34438414Smckusick 34538414Smckusick /* 34638414Smckusick * Vnode pointer to File handle, should never happen either 34738414Smckusick */ 34839494Smckusick /* ARGSUSED */ 34938414Smckusick nfs_vptofh(mp, fhp, vpp) 35038414Smckusick struct mount *mp; 35138414Smckusick struct fid *fhp; 35238414Smckusick struct vnode **vpp; 35338414Smckusick { 35439494Smckusick 35538414Smckusick return (EINVAL); 35638414Smckusick } 35738884Smacklem 35838884Smacklem /* 35938884Smacklem * Vfs start routine, a no-op. 36038884Smacklem */ 36139494Smckusick /* ARGSUSED */ 36238884Smacklem nfs_start(mp, flags) 36338884Smacklem struct mount *mp; 36438884Smacklem int flags; 36538884Smacklem { 36639494Smckusick 36738884Smacklem return (0); 36838884Smacklem } 369