1*38414Smckusick /* 2*38414Smckusick * Copyright (c) 1989 The Regents of the University of California. 3*38414Smckusick * All rights reserved. 4*38414Smckusick * 5*38414Smckusick * This code is derived from software contributed to Berkeley by 6*38414Smckusick * Rick Macklem at The University of Guelph. 7*38414Smckusick * 8*38414Smckusick * Redistribution and use in source and binary forms are permitted 9*38414Smckusick * provided that the above copyright notice and this paragraph are 10*38414Smckusick * duplicated in all such forms and that any documentation, 11*38414Smckusick * advertising materials, and other materials related to such 12*38414Smckusick * distribution and use acknowledge that the software was developed 13*38414Smckusick * by the University of California, Berkeley. The name of the 14*38414Smckusick * University may not be used to endorse or promote products derived 15*38414Smckusick * from this software without specific prior written permission. 16*38414Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17*38414Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18*38414Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19*38414Smckusick * 20*38414Smckusick * @(#)nfs_vfsops.c 7.1 (Berkeley) 07/05/89 21*38414Smckusick */ 22*38414Smckusick 23*38414Smckusick #include "param.h" 24*38414Smckusick #include "signal.h" 25*38414Smckusick #include "user.h" 26*38414Smckusick #include "proc.h" 27*38414Smckusick #include "uio.h" 28*38414Smckusick #include "ucred.h" 29*38414Smckusick #include "dir.h" 30*38414Smckusick #include "namei.h" 31*38414Smckusick #include "vnode.h" 32*38414Smckusick #include "mount.h" 33*38414Smckusick #include "errno.h" 34*38414Smckusick #include "malloc.h" 35*38414Smckusick #include "mbuf.h" 36*38414Smckusick #undef m_data 37*38414Smckusick #include "socket.h" 38*38414Smckusick #include "socketvar.h" 39*38414Smckusick #include "../netinet/in.h" 40*38414Smckusick #include "nfsv2.h" 41*38414Smckusick #include "nfsnode.h" 42*38414Smckusick #include "nfsmount.h" 43*38414Smckusick #include "nfs.h" 44*38414Smckusick 45*38414Smckusick #ifndef shouldbe 46*38414Smckusick #include "conf.h" 47*38414Smckusick #endif 48*38414Smckusick 49*38414Smckusick /* 50*38414Smckusick * nfs vfs operations. 51*38414Smckusick */ 52*38414Smckusick int nfs_mount(); 53*38414Smckusick int nfs_unmount(); 54*38414Smckusick int nfs_root(); 55*38414Smckusick extern int nfs_statfs(); 56*38414Smckusick int nfs_sync(); 57*38414Smckusick int nfs_fhtovp(); 58*38414Smckusick int nfs_vptofh(); 59*38414Smckusick 60*38414Smckusick struct vfsops nfs_vfsops = { 61*38414Smckusick nfs_mount, 62*38414Smckusick nfs_unmount, 63*38414Smckusick nfs_root, 64*38414Smckusick nfs_statfs, 65*38414Smckusick nfs_sync, 66*38414Smckusick nfs_fhtovp, 67*38414Smckusick nfs_vptofh, 68*38414Smckusick }; 69*38414Smckusick 70*38414Smckusick extern struct nfsreq nfsreqh; 71*38414Smckusick static long nfs_mntid; 72*38414Smckusick 73*38414Smckusick /* 74*38414Smckusick * Called by vfs_mountroot when nfs is going to be mounted as root 75*38414Smckusick * Not Yet (By a LONG shot) 76*38414Smckusick */ 77*38414Smckusick nfs_mountroot() 78*38414Smckusick { 79*38414Smckusick return (ENODEV); 80*38414Smckusick } 81*38414Smckusick 82*38414Smckusick /* 83*38414Smckusick * VFS Operations. 84*38414Smckusick * 85*38414Smckusick * mount system call 86*38414Smckusick * It seems a bit dumb to copyinstr() the host and path here and then 87*38414Smckusick * bcopy() them in mountnfs(), but I wanted to detect errors before 88*38414Smckusick * doing the sockargs() call because sockargs() allocates an mbuf and 89*38414Smckusick * an error after that means that I have to release the mbuf. 90*38414Smckusick */ 91*38414Smckusick nfs_mount(mp, path, data, ndp) 92*38414Smckusick struct mount *mp; 93*38414Smckusick char *path; 94*38414Smckusick caddr_t data; 95*38414Smckusick struct nameidata *ndp; 96*38414Smckusick { 97*38414Smckusick int error; 98*38414Smckusick struct nfs_args args; 99*38414Smckusick struct mbuf *saddr; 100*38414Smckusick char pth[MNAMELEN], hst[MNAMELEN]; 101*38414Smckusick int len; 102*38414Smckusick nfsv2fh_t nfh; 103*38414Smckusick 104*38414Smckusick if (error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args))) 105*38414Smckusick return (error); 106*38414Smckusick if (error=copyin((caddr_t)args.fh, (caddr_t)&nfh, sizeof (nfsv2fh_t))) 107*38414Smckusick return (error); 108*38414Smckusick if (error = copyinstr(path, pth, MNAMELEN-1, &len)) 109*38414Smckusick return (error); 110*38414Smckusick bzero(&pth[len], MNAMELEN-len); 111*38414Smckusick if (error = copyinstr(args.hostname, hst, MNAMELEN-1, &len)) 112*38414Smckusick return (error); 113*38414Smckusick bzero(&hst[len], MNAMELEN-len); 114*38414Smckusick /* sockargs() call must be after above copyin() calls */ 115*38414Smckusick if (error = sockargs(&saddr, (caddr_t)args.addr, 116*38414Smckusick sizeof (struct sockaddr_in), MT_SONAME)) 117*38414Smckusick return (error); 118*38414Smckusick args.fh = &nfh; 119*38414Smckusick error = mountnfs(&args, mp, saddr, pth, hst); 120*38414Smckusick return (error); 121*38414Smckusick } 122*38414Smckusick 123*38414Smckusick /* 124*38414Smckusick * Common code for mount and mountroot 125*38414Smckusick */ 126*38414Smckusick mountnfs(argp, mp, saddr, pth, hst) 127*38414Smckusick register struct nfs_args *argp; 128*38414Smckusick register struct mount *mp; 129*38414Smckusick register struct mbuf *saddr; 130*38414Smckusick char *pth, *hst; 131*38414Smckusick { 132*38414Smckusick register struct nfsmount *nmp; 133*38414Smckusick struct nfsnode *np; 134*38414Smckusick struct statfs statf, *sbp; 135*38414Smckusick int error; 136*38414Smckusick 137*38414Smckusick nmp = (struct nfsmount *)malloc(sizeof (struct nfsmount), M_NFSMNT, 138*38414Smckusick M_WAITOK); 139*38414Smckusick mp->m_data = (qaddr_t)nmp; 140*38414Smckusick mp->m_fsid.val[0] = ++nfs_mntid; 141*38414Smckusick mp->m_fsid.val[1] = MOUNT_NFS; 142*38414Smckusick nmp->nm_mountp = mp; 143*38414Smckusick nmp->nm_flag = argp->flags; 144*38414Smckusick nmp->nm_sockaddr = saddr; 145*38414Smckusick /* Set up the sockets */ 146*38414Smckusick if (error = socreate(AF_INET, &nmp->nm_so, SOCK_DGRAM, 0)) 147*38414Smckusick goto bad; 148*38414Smckusick if (error = soconnect(nmp->nm_so, saddr)) 149*38414Smckusick goto bad; 150*38414Smckusick if ((argp->flags & NFSMNT_TIMEO) && argp->timeo >= 1) 151*38414Smckusick nmp->nm_timeo = argp->timeo; 152*38414Smckusick else 153*38414Smckusick nmp->nm_timeo = NFS_TIMEO; 154*38414Smckusick if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 0) 155*38414Smckusick nmp->nm_retrans = argp->retrans; 156*38414Smckusick else 157*38414Smckusick nmp->nm_retrans = NFS_RETRANS; 158*38414Smckusick if ((argp->flags & NFSMNT_WSIZE) && 159*38414Smckusick argp->wsize <= NFS_MAXDATA && argp->wsize > 0 && 160*38414Smckusick (argp->wsize & 0x1ff) == 0) 161*38414Smckusick nmp->nm_wsize = argp->wsize; 162*38414Smckusick else 163*38414Smckusick nmp->nm_wsize = NFS_WSIZE; 164*38414Smckusick if ((argp->flags & NFSMNT_RSIZE) && 165*38414Smckusick argp->rsize <= NFS_MAXDATA && argp->rsize > 0 && 166*38414Smckusick (argp->rsize & 0x1ff) == 0) 167*38414Smckusick nmp->nm_rsize = argp->rsize; 168*38414Smckusick else 169*38414Smckusick nmp->nm_rsize = NFS_RSIZE; 170*38414Smckusick bcopy((caddr_t)argp->fh, (caddr_t)&nmp->nm_fh, sizeof(nfsv2fh_t)); 171*38414Smckusick bcopy(pth, nmp->nm_path, MNAMELEN); 172*38414Smckusick bcopy(hst, nmp->nm_host, MNAMELEN); 173*38414Smckusick sbp = &statf; 174*38414Smckusick /* 175*38414Smckusick * Kludge City... 176*38414Smckusick * To do an interruptable hard mount, turn it into a soft mount 177*38414Smckusick * with a retry limit of one and then repeat it so long as it 178*38414Smckusick * times out and there is no pending signal for the process. 179*38414Smckusick * It is tempting to just let nfs_statfs() sleep at positive 180*38414Smckusick * prio, but then you would long jump out without taking the 181*38414Smckusick * mount structure back out of the list. 182*38414Smckusick * NB: NFSMNT_INT must NEVER be set for nfs_mountroot(), since 183*38414Smckusick * the process context is not yet built!! 184*38414Smckusick */ 185*38414Smckusick if ((argp->flags && NFSMNT_INT) && (argp->flags & NFSMNT_SOFT) == 0) { 186*38414Smckusick int savretrans; 187*38414Smckusick 188*38414Smckusick nmp->nm_flag |= NFSMNT_SOFT; 189*38414Smckusick savretrans = nmp->nm_retrans; 190*38414Smckusick nmp->nm_retrans = 1; 191*38414Smckusick do { 192*38414Smckusick error = nfs_statfs(mp, sbp); 193*38414Smckusick } while (error == ETIMEDOUT && (u.u_procp->p_sig & 194*38414Smckusick (sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM)| 195*38414Smckusick sigmask(SIGKILL))) == 0); 196*38414Smckusick nmp->nm_retrans = savretrans; 197*38414Smckusick nmp->nm_flag &= ~NFSMNT_SOFT; 198*38414Smckusick if (error) 199*38414Smckusick goto bad; 200*38414Smckusick } else if (error = nfs_statfs(mp, sbp)) 201*38414Smckusick goto bad; 202*38414Smckusick mp->m_fsize = sbp->f_fsize; 203*38414Smckusick 204*38414Smckusick /* 205*38414Smckusick * If the block size is not an exact multiple of CLBYTES 206*38414Smckusick * use CLBYTES so that paging in ZMAGIC executables doesn't 207*38414Smckusick * get sick. (It is used by vinitfod()) 208*38414Smckusick */ 209*38414Smckusick if (sbp->f_bsize >= CLBYTES && claligned(sbp->f_bsize)) 210*38414Smckusick mp->m_bsize = sbp->f_bsize; 211*38414Smckusick else 212*38414Smckusick mp->m_bsize = CLBYTES; 213*38414Smckusick return (0); 214*38414Smckusick bad: 215*38414Smckusick m_freem(saddr); 216*38414Smckusick free((caddr_t)nmp, M_NFSMNT); 217*38414Smckusick return (error); 218*38414Smckusick } 219*38414Smckusick 220*38414Smckusick /* 221*38414Smckusick * unmount system call 222*38414Smckusick */ 223*38414Smckusick nfs_unmount(mp, flags) 224*38414Smckusick struct mount *mp; 225*38414Smckusick int flags; 226*38414Smckusick { 227*38414Smckusick register struct nfsmount *nmp; 228*38414Smckusick register struct nfsreq *rep; 229*38414Smckusick struct nfsreq *rep2; 230*38414Smckusick int error; 231*38414Smckusick int s; 232*38414Smckusick 233*38414Smckusick if (flags & MNT_FORCE) 234*38414Smckusick return (EINVAL); 235*38414Smckusick nmp = vfs_to_nfs(mp); 236*38414Smckusick /* 237*38414Smckusick * Goes something like this.. 238*38414Smckusick * - Call nfs_nflush() to clear out the nfsnode table 239*38414Smckusick * - Flush out lookup cache 240*38414Smckusick * - Close the socket 241*38414Smckusick * - Free up the data structures 242*38414Smckusick */ 243*38414Smckusick if (error = nfs_nflush(mp)) { 244*38414Smckusick return (error); 245*38414Smckusick } 246*38414Smckusick /* 247*38414Smckusick * Scan the request list for any requests left hanging about 248*38414Smckusick */ 249*38414Smckusick s = splnet(); 250*38414Smckusick rep = nfsreqh.r_next; 251*38414Smckusick while (rep) { 252*38414Smckusick if (rep->r_mntp == nmp) { 253*38414Smckusick rep->r_prev->r_next = rep2 = rep->r_next; 254*38414Smckusick if (rep->r_next != NULL) 255*38414Smckusick rep->r_next->r_prev = rep->r_prev; 256*38414Smckusick m_freem(rep->r_mreq); 257*38414Smckusick if (rep->r_mrep != NULL) 258*38414Smckusick m_freem(rep->r_mrep); 259*38414Smckusick free((caddr_t)rep, M_NFSREQ); 260*38414Smckusick rep = rep2; 261*38414Smckusick } else 262*38414Smckusick rep = rep->r_next; 263*38414Smckusick } 264*38414Smckusick splx(s); 265*38414Smckusick soclose(nmp->nm_so); 266*38414Smckusick m_freem(nmp->nm_sockaddr); 267*38414Smckusick free((caddr_t)nmp, M_NFSMNT); 268*38414Smckusick return (0); 269*38414Smckusick } 270*38414Smckusick 271*38414Smckusick /* 272*38414Smckusick * Return root of a filesystem 273*38414Smckusick */ 274*38414Smckusick nfs_root(mp, vpp) 275*38414Smckusick struct mount *mp; 276*38414Smckusick struct vnode **vpp; 277*38414Smckusick { 278*38414Smckusick register struct vnode *vp; 279*38414Smckusick struct nfsmount *nmp; 280*38414Smckusick struct nfsnode *np; 281*38414Smckusick int error; 282*38414Smckusick 283*38414Smckusick nmp = vfs_to_nfs(mp); 284*38414Smckusick if (error = nfs_nget(mp, &nmp->nm_fh, &np)) 285*38414Smckusick return (error); 286*38414Smckusick vp = NFSTOV(np); 287*38414Smckusick vp->v_type = VDIR; 288*38414Smckusick vp->v_flag = VROOT; 289*38414Smckusick *vpp = vp; 290*38414Smckusick return (0); 291*38414Smckusick } 292*38414Smckusick 293*38414Smckusick /* 294*38414Smckusick * Since writes are synchronous, I think this is a no-op 295*38414Smckusick * Maybe write cache on nfs version 3 will require something ?? 296*38414Smckusick */ 297*38414Smckusick nfs_sync(mp, waitfor) 298*38414Smckusick struct mount *mp; 299*38414Smckusick int waitfor; 300*38414Smckusick { 301*38414Smckusick return (0); 302*38414Smckusick } 303*38414Smckusick 304*38414Smckusick /* 305*38414Smckusick * At this point, this should never happen 306*38414Smckusick */ 307*38414Smckusick nfs_fhtovp(mp, fhp, vpp) 308*38414Smckusick struct mount *mp; 309*38414Smckusick struct fid *fhp; 310*38414Smckusick struct vnode **vpp; 311*38414Smckusick { 312*38414Smckusick return (EINVAL); 313*38414Smckusick } 314*38414Smckusick 315*38414Smckusick /* 316*38414Smckusick * Vnode pointer to File handle, should never happen either 317*38414Smckusick */ 318*38414Smckusick nfs_vptofh(mp, fhp, vpp) 319*38414Smckusick struct mount *mp; 320*38414Smckusick struct fid *fhp; 321*38414Smckusick struct vnode **vpp; 322*38414Smckusick { 323*38414Smckusick return (EINVAL); 324*38414Smckusick } 325