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*39488Smckusick * @(#)nfs_vnops.c 7.13 (Berkeley) 11/03/89 2138414Smckusick */ 2238414Smckusick 2338414Smckusick /* 2438414Smckusick * vnode op calls for sun nfs version 2 2538414Smckusick */ 2638414Smckusick 2738414Smckusick #include "machine/pte.h" 2838414Smckusick #include "machine/mtpr.h" 2938414Smckusick #include "strings.h" 3038414Smckusick #include "param.h" 3138414Smckusick #include "user.h" 3238414Smckusick #include "proc.h" 3338414Smckusick #include "mount.h" 3438414Smckusick #include "buf.h" 3538414Smckusick #include "vm.h" 3638425Smckusick #include "../ufs/dir.h" 3738414Smckusick #include "malloc.h" 3838414Smckusick #include "mbuf.h" 3938414Smckusick #include "uio.h" 4038414Smckusick #include "ucred.h" 4138414Smckusick #include "namei.h" 4238414Smckusick #include "errno.h" 4338414Smckusick #include "file.h" 4438414Smckusick #include "conf.h" 4538414Smckusick #include "vnode.h" 4638414Smckusick #include "../ufs/inode.h" 4738884Smacklem #include "map.h" 4838414Smckusick #include "nfsv2.h" 4938414Smckusick #include "nfs.h" 5038414Smckusick #include "nfsnode.h" 5138414Smckusick #include "nfsmount.h" 5238414Smckusick #include "xdr_subs.h" 5338414Smckusick #include "nfsm_subs.h" 5438884Smacklem #include "nfsiom.h" 5538414Smckusick 5638414Smckusick /* Defs */ 5738414Smckusick #define TRUE 1 5838414Smckusick #define FALSE 0 5938414Smckusick 6038414Smckusick /* Global vars */ 6138414Smckusick int nfs_lookup(), 6238414Smckusick nfs_create(), 6339459Smckusick nfs_mknod(), 6438414Smckusick nfs_open(), 6538414Smckusick nfs_close(), 6638414Smckusick nfs_access(), 6738414Smckusick nfs_getattr(), 6838414Smckusick nfs_setattr(), 6938414Smckusick nfs_read(), 7038414Smckusick nfs_write(), 7138414Smckusick vfs_noop(), 7238414Smckusick vfs_nullop(), 7338414Smckusick nfs_remove(), 7438414Smckusick nfs_link(), 7538414Smckusick nfs_rename(), 7638414Smckusick nfs_mkdir(), 7738414Smckusick nfs_rmdir(), 7838414Smckusick nfs_symlink(), 7938414Smckusick nfs_readdir(), 8038414Smckusick nfs_readlink(), 8138414Smckusick nfs_abortop(), 8238414Smckusick nfs_lock(), 8338414Smckusick nfs_unlock(), 8438414Smckusick nfs_bmap(), 8538414Smckusick nfs_strategy(), 8638884Smacklem nfs_fsync(), 8739394Smckusick nfs_inactive(), 8839394Smckusick nfs_reclaim(); 8938414Smckusick 9038414Smckusick struct vnodeops nfsv2_vnodeops = { 9138414Smckusick nfs_lookup, 9238414Smckusick nfs_create, 9339459Smckusick nfs_mknod, 9438414Smckusick nfs_open, 9538414Smckusick nfs_close, 9638414Smckusick nfs_access, 9738414Smckusick nfs_getattr, 9838414Smckusick nfs_setattr, 9938414Smckusick nfs_read, 10038414Smckusick nfs_write, 10138414Smckusick vfs_noop, 10238414Smckusick vfs_noop, 10338414Smckusick vfs_noop, 10438884Smacklem nfs_fsync, 10539459Smckusick vfs_nullop, 10638414Smckusick nfs_remove, 10738414Smckusick nfs_link, 10838414Smckusick nfs_rename, 10938414Smckusick nfs_mkdir, 11038414Smckusick nfs_rmdir, 11138414Smckusick nfs_symlink, 11238414Smckusick nfs_readdir, 11338414Smckusick nfs_readlink, 11438414Smckusick nfs_abortop, 11538414Smckusick nfs_inactive, 11639394Smckusick nfs_reclaim, 11738414Smckusick nfs_lock, 11838414Smckusick nfs_unlock, 11938414Smckusick nfs_bmap, 12038414Smckusick nfs_strategy, 12138414Smckusick }; 12238414Smckusick 12338414Smckusick /* Special device vnode ops */ 12439441Smckusick int spec_lookup(), 12539441Smckusick spec_open(), 12639441Smckusick spec_read(), 12739441Smckusick spec_write(), 12839441Smckusick spec_strategy(), 12939441Smckusick spec_ioctl(), 13039441Smckusick spec_select(), 13139441Smckusick spec_close(), 13239441Smckusick spec_badop(), 13339441Smckusick spec_nullop(); 13438414Smckusick 13539441Smckusick struct vnodeops spec_nfsv2nodeops = { 13639441Smckusick spec_lookup, 13739441Smckusick spec_badop, 13839441Smckusick spec_badop, 13939441Smckusick spec_open, 14039441Smckusick spec_close, 14138414Smckusick nfs_access, 14238414Smckusick nfs_getattr, 14338414Smckusick nfs_setattr, 14439441Smckusick spec_read, 14539441Smckusick spec_write, 14639441Smckusick spec_ioctl, 14739441Smckusick spec_select, 14839441Smckusick spec_badop, 14939441Smckusick spec_nullop, 15039441Smckusick spec_badop, 15139441Smckusick spec_badop, 15239441Smckusick spec_badop, 15339441Smckusick spec_badop, 15439441Smckusick spec_badop, 15539441Smckusick spec_badop, 15639441Smckusick spec_badop, 15739441Smckusick spec_badop, 15839441Smckusick spec_badop, 15939441Smckusick spec_badop, 16038414Smckusick nfs_inactive, 16139394Smckusick nfs_reclaim, 16238414Smckusick nfs_lock, 16338414Smckusick nfs_unlock, 16439441Smckusick spec_badop, 16539441Smckusick spec_strategy, 16638414Smckusick }; 16738414Smckusick 16838414Smckusick extern u_long nfs_procids[NFS_NPROCS]; 16938414Smckusick extern u_long nfs_prog, nfs_vers; 17038414Smckusick extern char nfsiobuf[MAXPHYS+NBPG]; 17138884Smacklem struct map nfsmap[NFS_MSIZ]; 17238414Smckusick enum vtype v_type[NFLNK+1]; 17338884Smacklem struct buf nfs_bqueue; /* Queue head for nfsiod's */ 17439341Smckusick int nfs_asyncdaemons = 0; 17539341Smckusick struct proc *nfs_iodwant[MAX_ASYNCDAEMON]; 17638884Smacklem static int nfsmap_want = 0; 17738414Smckusick 17838414Smckusick /* 17938414Smckusick * nfs null call from vfs. 18038414Smckusick */ 18138414Smckusick nfs_null(vp, cred) 18238414Smckusick struct vnode *vp; 18338414Smckusick struct ucred *cred; 18438414Smckusick { 185*39488Smckusick caddr_t bpos, dpos; 186*39488Smckusick u_long xid; 187*39488Smckusick int error = 0; 188*39488Smckusick struct mbuf *mreq, *mrep, *md, *mb; 18938414Smckusick 19038414Smckusick nfsm_reqhead(nfs_procids[NFSPROC_NULL], cred, 0); 19138414Smckusick nfsm_request(vp); 19238414Smckusick nfsm_reqdone; 19338414Smckusick return (error); 19438414Smckusick } 19538414Smckusick 19638414Smckusick /* 19738414Smckusick * nfs access vnode op. 19838414Smckusick * Essentially just get vattr and then imitate iaccess() 19938414Smckusick */ 20038414Smckusick nfs_access(vp, mode, cred) 20138414Smckusick struct vnode *vp; 20238414Smckusick int mode; 20338414Smckusick register struct ucred *cred; 20438414Smckusick { 20538414Smckusick register struct vattr *vap; 20638414Smckusick register gid_t *gp; 20738414Smckusick struct vattr vattr; 20838414Smckusick register int i; 20938414Smckusick int error; 21038414Smckusick 21138414Smckusick /* 21238414Smckusick * If you're the super-user, 21338414Smckusick * you always get access. 21438414Smckusick */ 21538414Smckusick if (cred->cr_uid == 0) 21638414Smckusick return (0); 21738414Smckusick vap = &vattr; 21838884Smacklem if (error = nfs_getattr(vp, vap, cred)) 21938884Smacklem return (error); 22038414Smckusick /* 22138414Smckusick * Access check is based on only one of owner, group, public. 22238414Smckusick * If not owner, then check group. If not a member of the 22338414Smckusick * group, then check public access. 22438414Smckusick */ 22538414Smckusick if (cred->cr_uid != vap->va_uid) { 22638414Smckusick mode >>= 3; 22738414Smckusick gp = cred->cr_groups; 22838414Smckusick for (i = 0; i < cred->cr_ngroups; i++, gp++) 22938414Smckusick if (vap->va_gid == *gp) 23038414Smckusick goto found; 23138414Smckusick mode >>= 3; 23238414Smckusick found: 23338414Smckusick ; 23438414Smckusick } 23538414Smckusick if ((vap->va_mode & mode) != 0) 23638414Smckusick return (0); 23738414Smckusick return (EACCES); 23838414Smckusick } 23938414Smckusick 24038414Smckusick /* 24138414Smckusick * nfs open vnode op 24238414Smckusick * Just check to see if the type is ok 24338414Smckusick */ 244*39488Smckusick /* ARGSUSED */ 24538414Smckusick nfs_open(vp, mode, cred) 24638414Smckusick struct vnode *vp; 24738414Smckusick int mode; 24838414Smckusick struct ucred *cred; 24938414Smckusick { 25038414Smckusick register enum vtype vtyp; 25138414Smckusick 25238414Smckusick vtyp = vp->v_type; 25338414Smckusick if (vtyp == VREG || vtyp == VDIR || vtyp == VLNK) 25438414Smckusick return (0); 25538414Smckusick else 25638414Smckusick return (EACCES); 25738414Smckusick } 25838414Smckusick 25938414Smckusick /* 26038414Smckusick * nfs close vnode op 26138884Smacklem * For reg files, invalidate any buffer cache entries. 26238414Smckusick */ 263*39488Smckusick /* ARGSUSED */ 26438414Smckusick nfs_close(vp, fflags, cred) 26538414Smckusick register struct vnode *vp; 26638414Smckusick int fflags; 26738414Smckusick struct ucred *cred; 26838414Smckusick { 269*39488Smckusick register struct nfsnode *np = VTONFS(vp); 27039341Smckusick int error = 0; 27138414Smckusick 27239341Smckusick if (vp->v_type == VREG && ((np->n_flag & NMODIFIED) || 27339341Smckusick ((np->n_flag & NBUFFERED) && np->n_sillyrename))) { 27439441Smckusick nfs_lock(vp); 27539341Smckusick np->n_flag &= ~(NMODIFIED|NBUFFERED); 27639341Smckusick error = nfs_blkflush(vp, (daddr_t)0, np->n_size, TRUE); 27739341Smckusick if (np->n_flag & NWRITEERR) { 27839341Smckusick np->n_flag &= ~NWRITEERR; 27939341Smckusick if (!error) 28039341Smckusick error = np->n_error ? np->n_error : EIO; 28139341Smckusick } 28239441Smckusick nfs_unlock(vp); 28338884Smacklem } 28438414Smckusick return (error); 28538414Smckusick } 28638414Smckusick 28738414Smckusick /* 28838414Smckusick * nfs getattr call from vfs. 28938414Smckusick */ 29038414Smckusick nfs_getattr(vp, vap, cred) 291*39488Smckusick register struct vnode *vp; 292*39488Smckusick struct vattr *vap; 29338414Smckusick struct ucred *cred; 29438414Smckusick { 295*39488Smckusick register caddr_t cp; 296*39488Smckusick register long t1; 297*39488Smckusick caddr_t bpos, dpos; 298*39488Smckusick u_long xid; 299*39488Smckusick int error = 0; 300*39488Smckusick struct mbuf *mreq, *mrep, *md, *mb, *mb2; 30138414Smckusick 30238414Smckusick /* First look in the cache.. */ 30338414Smckusick if (nfs_getattrcache(vp, vap) == 0) 30438414Smckusick return (0); 30538414Smckusick nfsstats.rpccnt[NFSPROC_GETATTR]++; 30638414Smckusick nfsm_reqhead(nfs_procids[NFSPROC_GETATTR], cred, NFSX_FH); 30738414Smckusick nfsm_fhtom(vp); 30838414Smckusick nfsm_request(vp); 30938414Smckusick nfsm_loadattr(vp, vap); 31038414Smckusick nfsm_reqdone; 31138414Smckusick return (error); 31238414Smckusick } 31338414Smckusick 31438414Smckusick /* 31538414Smckusick * nfs setattr call. 31638414Smckusick */ 31738414Smckusick nfs_setattr(vp, vap, cred) 318*39488Smckusick register struct vnode *vp; 31938414Smckusick register struct vattr *vap; 32038414Smckusick struct ucred *cred; 32138414Smckusick { 32238884Smacklem register struct nfsv2_sattr *sp; 323*39488Smckusick register caddr_t cp; 324*39488Smckusick register long t1; 325*39488Smckusick caddr_t bpos, dpos; 326*39488Smckusick u_long xid; 327*39488Smckusick int error = 0; 328*39488Smckusick struct mbuf *mreq, *mrep, *md, *mb, *mb2; 32939359Smckusick struct nfsnode *np; 33038414Smckusick 33138414Smckusick nfsstats.rpccnt[NFSPROC_SETATTR]++; 33238414Smckusick nfsm_reqhead(nfs_procids[NFSPROC_SETATTR], cred, NFSX_FH+NFSX_SATTR); 33338414Smckusick nfsm_fhtom(vp); 33438884Smacklem nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR); 33538414Smckusick if (vap->va_mode == 0xffff) 33638884Smacklem sp->sa_mode = VNOVAL; 33738414Smckusick else 33838884Smacklem sp->sa_mode = vtonfs_mode(vp->v_type, vap->va_mode); 33938414Smckusick if (vap->va_uid == 0xffff) 34038884Smacklem sp->sa_uid = VNOVAL; 34138414Smckusick else 34238884Smacklem sp->sa_uid = txdr_unsigned(vap->va_uid); 34338414Smckusick if (vap->va_gid == 0xffff) 34438884Smacklem sp->sa_gid = VNOVAL; 34538414Smckusick else 34638884Smacklem sp->sa_gid = txdr_unsigned(vap->va_gid); 34738884Smacklem sp->sa_size = txdr_unsigned(vap->va_size); 34839359Smckusick if (vap->va_size != VNOVAL) { 34939359Smckusick np = VTONFS(vp); 35039359Smckusick if (np->n_flag & NMODIFIED) { 35139359Smckusick np->n_flag &= ~NMODIFIED; 35239359Smckusick nfs_blkflush(vp, (daddr_t)0, np->n_size, TRUE); 35339359Smckusick } 35439359Smckusick } 35538884Smacklem txdr_time(&vap->va_atime, &sp->sa_atime); 35638884Smacklem txdr_time(&vap->va_mtime, &sp->sa_mtime); 35738414Smckusick nfsm_request(vp); 35838414Smckusick nfsm_loadattr(vp, (struct vattr *)0); 35938414Smckusick /* should we fill in any vap fields ?? */ 36038414Smckusick nfsm_reqdone; 36138414Smckusick return (error); 36238414Smckusick } 36338414Smckusick 36438414Smckusick /* 36538414Smckusick * nfs lookup call, one step at a time... 36638414Smckusick * First look in cache 36738414Smckusick * If not found, unlock the directory nfsnode and do the rpc 36838414Smckusick */ 36938414Smckusick nfs_lookup(vp, ndp) 37038414Smckusick register struct vnode *vp; 37138414Smckusick register struct nameidata *ndp; 37238414Smckusick { 37338414Smckusick register struct vnode *vdp; 374*39488Smckusick register u_long *p; 375*39488Smckusick register caddr_t cp; 376*39488Smckusick register long t1, t2; 377*39488Smckusick caddr_t bpos, dpos, cp2; 378*39488Smckusick u_long xid; 379*39488Smckusick struct mbuf *mreq, *mrep, *md, *mb, *mb2; 38038414Smckusick struct vnode *newvp; 38138414Smckusick long len; 38238414Smckusick nfsv2fh_t *fhp; 38338414Smckusick struct nfsnode *np; 384*39488Smckusick int lockparent, wantparent, flag, error = 0; 38538414Smckusick 38638414Smckusick ndp->ni_dvp = vp; 38738414Smckusick ndp->ni_vp = NULL; 38838414Smckusick if (vp->v_type != VDIR) 38938414Smckusick return (ENOTDIR); 39038414Smckusick lockparent = ndp->ni_nameiop & LOCKPARENT; 39138414Smckusick flag = ndp->ni_nameiop & OPFLAG; 39238414Smckusick wantparent = ndp->ni_nameiop & (LOCKPARENT|WANTPARENT); 39339341Smckusick if ((error = cache_lookup(ndp)) && error != ENOENT) { 39438884Smacklem struct vattr vattr; 39538884Smacklem int vpid; 39638884Smacklem 39739441Smckusick if (vp == ndp->ni_rdir && ndp->ni_isdotdot) 39839441Smckusick panic("nfs_lookup: .. through root"); 39939441Smckusick vdp = ndp->ni_vp; 40038884Smacklem vpid = vdp->v_id; 40138414Smckusick /* 40238884Smacklem * See the comment starting `Step through' in ufs/ufs_lookup.c 40338884Smacklem * for an explanation of the locking protocol 40438414Smckusick */ 40538414Smckusick if (vp == vdp) { 40638425Smckusick VREF(vdp); 40739441Smckusick error = 0; 40838414Smckusick } else if (ndp->ni_isdotdot) { 40938414Smckusick nfs_unlock(vp); 41039441Smckusick error = vget(vdp); 41138414Smckusick } else { 41239441Smckusick error = vget(vdp); 41338414Smckusick nfs_unlock(vp); 41438414Smckusick } 41539441Smckusick if (!error) { 41639441Smckusick if (vpid == vdp->v_id && 41739441Smckusick !nfs_getattr(vdp, &vattr, ndp->ni_cred)) { 41839441Smckusick nfsstats.lookupcache_hits++; 41939441Smckusick return (0); 42039441Smckusick } else { 42139441Smckusick nfs_nput(vdp); 42239441Smckusick } 42338884Smacklem } 42438884Smacklem nfs_lock(vp); 42538884Smacklem ndp->ni_vp = (struct vnode *)0; 42638414Smckusick } 42739341Smckusick error = 0; 42838414Smckusick nfsstats.lookupcache_misses++; 42938414Smckusick nfsstats.rpccnt[NFSPROC_LOOKUP]++; 43038414Smckusick len = ndp->ni_namelen; 43138414Smckusick nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], ndp->ni_cred, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)); 43238414Smckusick nfsm_fhtom(vp); 43338414Smckusick nfsm_strtom(ndp->ni_ptr, len, NFS_MAXNAMLEN); 43438414Smckusick nfsm_request(vp); 43538414Smckusick nfsmout: 43638414Smckusick if (error) { 43738414Smckusick if ((flag == CREATE || flag == RENAME) && 43838414Smckusick *ndp->ni_next == 0) { 43938414Smckusick if (!lockparent) 44038414Smckusick nfs_unlock(vp); 44138414Smckusick } 44238414Smckusick return (ENOENT); 44338414Smckusick } 44438414Smckusick nfsm_disect(fhp,nfsv2fh_t *,NFSX_FH); 44538414Smckusick 44638414Smckusick /* 44738414Smckusick * Handle DELETE and RENAME cases... 44838414Smckusick */ 44938414Smckusick if (flag == DELETE && *ndp->ni_next == 0) { 45038414Smckusick if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) { 45138425Smckusick VREF(vp); 45238414Smckusick newvp = vp; 45338414Smckusick np = VTONFS(vp); 45438414Smckusick } else { 45538414Smckusick if (error = nfs_nget(vp->v_mount, fhp, &np)) { 45638414Smckusick m_freem(mrep); 45738414Smckusick return (error); 45838414Smckusick } 45938414Smckusick newvp = NFSTOV(np); 46038414Smckusick } 46139459Smckusick if (error = 46239459Smckusick nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) { 46338414Smckusick if (newvp != vp) 46438414Smckusick nfs_nput(newvp); 46538414Smckusick else 46638425Smckusick vrele(vp); 46738414Smckusick m_freem(mrep); 46838414Smckusick return (error); 46938414Smckusick } 47038414Smckusick ndp->ni_vp = newvp; 47138414Smckusick if (!lockparent) 47238414Smckusick nfs_unlock(vp); 47338414Smckusick m_freem(mrep); 47438414Smckusick return (0); 47538414Smckusick } 47638414Smckusick 47738414Smckusick if (flag == RENAME && wantparent && *ndp->ni_next == 0) { 47838414Smckusick if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) { 47938414Smckusick m_freem(mrep); 48038414Smckusick return (EISDIR); 48138414Smckusick } 48238414Smckusick if (error = nfs_nget(vp->v_mount, fhp, &np)) { 48338414Smckusick m_freem(mrep); 48438414Smckusick return (error); 48538414Smckusick } 48638414Smckusick newvp = NFSTOV(np); 48739459Smckusick if (error = 48839459Smckusick nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) { 48938425Smckusick nfs_nput(newvp); 49038414Smckusick m_freem(mrep); 49138414Smckusick return (error); 49238414Smckusick } 49338414Smckusick ndp->ni_vp = newvp; 49438414Smckusick if (!lockparent) 49538414Smckusick nfs_unlock(vp); 49638414Smckusick return (0); 49738414Smckusick } 49838414Smckusick 49938414Smckusick if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) { 50038425Smckusick VREF(vp); 50138414Smckusick newvp = vp; 50238414Smckusick np = VTONFS(vp); 50338414Smckusick } else if (ndp->ni_isdotdot) { 50438414Smckusick nfs_unlock(vp); 50538414Smckusick if (error = nfs_nget(vp->v_mount, fhp, &np)) { 50638414Smckusick nfs_lock(vp); 50738414Smckusick m_freem(mrep); 50838414Smckusick return (error); 50938414Smckusick } 51038414Smckusick nfs_lock(vp); 51138414Smckusick newvp = NFSTOV(np); 51238414Smckusick } else { 51338414Smckusick if (error = nfs_nget(vp->v_mount, fhp, &np)) { 51438414Smckusick m_freem(mrep); 51538414Smckusick return (error); 51638414Smckusick } 51738414Smckusick newvp = NFSTOV(np); 51838414Smckusick } 51939459Smckusick if (error = nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) { 52038414Smckusick if (newvp != vp) 52138414Smckusick nfs_nput(newvp); 52238414Smckusick else 52338425Smckusick vrele(vp); 52438414Smckusick m_freem(mrep); 52538414Smckusick return (error); 52638414Smckusick } 52738414Smckusick m_freem(mrep); 52838414Smckusick 52938414Smckusick if (vp != newvp && (!lockparent || *ndp->ni_next != '\0')) 53038414Smckusick nfs_unlock(vp); 53138414Smckusick ndp->ni_vp = newvp; 53238414Smckusick if (error == 0 && ndp->ni_makeentry) 53338414Smckusick cache_enter(ndp); 53438414Smckusick return (error); 53538414Smckusick } 53638414Smckusick 53738414Smckusick /* 53838414Smckusick * nfs readlink call 53938414Smckusick */ 54038414Smckusick nfs_readlink(vp, uiop, cred) 541*39488Smckusick register struct vnode *vp; 54238414Smckusick struct uio *uiop; 54338414Smckusick struct ucred *cred; 54438414Smckusick { 545*39488Smckusick register u_long *p; 546*39488Smckusick register caddr_t cp; 547*39488Smckusick register long t1; 548*39488Smckusick caddr_t bpos, dpos, cp2; 549*39488Smckusick u_long xid; 550*39488Smckusick int error = 0; 551*39488Smckusick struct mbuf *mreq, *mrep, *md, *mb, *mb2; 55238414Smckusick long len; 55338414Smckusick 55438414Smckusick nfsstats.rpccnt[NFSPROC_READLINK]++; 55538414Smckusick nfsm_reqhead(nfs_procids[NFSPROC_READLINK], cred, NFSX_FH); 55638414Smckusick nfsm_fhtom(vp); 55738414Smckusick nfsm_request(vp); 55838414Smckusick nfsm_strsiz(len, NFS_MAXPATHLEN); 55938414Smckusick nfsm_mtouio(uiop, len); 56038414Smckusick nfsm_reqdone; 56138414Smckusick return (error); 56238414Smckusick } 56338414Smckusick 56438414Smckusick /* 56538414Smckusick * nfs read call 56638414Smckusick */ 56738884Smacklem nfs_readrpc(vp, uiop, offp, cred) 568*39488Smckusick register struct vnode *vp; 56938414Smckusick struct uio *uiop; 57038414Smckusick off_t *offp; 57138414Smckusick struct ucred *cred; 57238414Smckusick { 573*39488Smckusick register u_long *p; 574*39488Smckusick register caddr_t cp; 575*39488Smckusick register long t1; 576*39488Smckusick caddr_t bpos, dpos, cp2; 577*39488Smckusick u_long xid; 578*39488Smckusick int error = 0; 579*39488Smckusick struct mbuf *mreq, *mrep, *md, *mb, *mb2; 58038414Smckusick struct nfsmount *nmp; 58138414Smckusick long len, retlen, tsiz; 58238414Smckusick 58338414Smckusick nmp = vfs_to_nfs(vp->v_mount); 58438414Smckusick tsiz = uiop->uio_resid; 58538414Smckusick while (tsiz > 0) { 58638414Smckusick nfsstats.rpccnt[NFSPROC_READ]++; 58738414Smckusick len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz; 58838414Smckusick nfsm_reqhead(nfs_procids[NFSPROC_READ], cred, NFSX_FH+NFSX_UNSIGNED*3); 58938414Smckusick nfsm_fhtom(vp); 59038414Smckusick nfsm_build(p, u_long *, NFSX_UNSIGNED*3); 59138414Smckusick *p++ = txdr_unsigned(*offp); 59238414Smckusick *p++ = txdr_unsigned(len); 59338414Smckusick *p = 0; 59438414Smckusick nfsm_request(vp); 59538414Smckusick nfsm_loadattr(vp, (struct vattr *)0); 59638414Smckusick nfsm_strsiz(retlen, nmp->nm_rsize); 59738414Smckusick nfsm_mtouio(uiop, retlen); 59838414Smckusick m_freem(mrep); 59938414Smckusick *offp += retlen; 60038414Smckusick if (retlen < len) 60138414Smckusick tsiz = 0; 60238414Smckusick else 60338414Smckusick tsiz -= len; 60438414Smckusick } 60538414Smckusick nfsmout: 60638414Smckusick return (error); 60738414Smckusick } 60838414Smckusick 60938414Smckusick /* 61038414Smckusick * nfs write call 61138414Smckusick */ 61238884Smacklem nfs_writerpc(vp, uiop, offp, cred) 613*39488Smckusick register struct vnode *vp; 61438414Smckusick struct uio *uiop; 61538414Smckusick off_t *offp; 61638414Smckusick struct ucred *cred; 61738414Smckusick { 618*39488Smckusick register u_long *p; 619*39488Smckusick register caddr_t cp; 620*39488Smckusick register long t1; 621*39488Smckusick caddr_t bpos, dpos; 622*39488Smckusick u_long xid; 623*39488Smckusick int error = 0; 624*39488Smckusick struct mbuf *mreq, *mrep, *md, *mb, *mb2; 62538414Smckusick struct nfsmount *nmp; 62638414Smckusick long len, tsiz; 62738414Smckusick 62838414Smckusick nmp = vfs_to_nfs(vp->v_mount); 62938414Smckusick tsiz = uiop->uio_resid; 63038414Smckusick while (tsiz > 0) { 63138414Smckusick nfsstats.rpccnt[NFSPROC_WRITE]++; 63238414Smckusick len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz; 63338414Smckusick nfsm_reqhead(nfs_procids[NFSPROC_WRITE], cred, 63438414Smckusick NFSX_FH+NFSX_UNSIGNED*4); 63538414Smckusick nfsm_fhtom(vp); 63638414Smckusick nfsm_build(p, u_long *, NFSX_UNSIGNED*4); 63738414Smckusick *(p+1) = txdr_unsigned(*offp); 63838414Smckusick *(p+3) = txdr_unsigned(len); 63938414Smckusick nfsm_uiotom(uiop, len); 64038414Smckusick nfsm_request(vp); 64138414Smckusick nfsm_loadattr(vp, (struct vattr *)0); 64238414Smckusick m_freem(mrep); 64338414Smckusick tsiz -= len; 64438414Smckusick *offp += len; 64538414Smckusick } 64638414Smckusick nfsmout: 64738414Smckusick return (error); 64838414Smckusick } 64938414Smckusick 65038414Smckusick /* 65139459Smckusick * nfs mknod call 65239459Smckusick * This call is currently not supported. 65339459Smckusick */ 65439459Smckusick /* ARGSUSED */ 65539459Smckusick nfs_mknod(ndp, vap, cred) 65639459Smckusick struct nameidata *ndp; 65739459Smckusick struct ucred *cred; 65839459Smckusick struct vattr *vap; 65939459Smckusick { 66039459Smckusick 66139459Smckusick nfs_abortop(ndp); 66239459Smckusick return (EOPNOTSUPP); 66339459Smckusick } 66439459Smckusick 66539459Smckusick /* 66638414Smckusick * nfs file create call 66738414Smckusick */ 66838414Smckusick nfs_create(ndp, vap) 66938414Smckusick register struct nameidata *ndp; 67038414Smckusick register struct vattr *vap; 67138414Smckusick { 67238884Smacklem register struct nfsv2_sattr *sp; 673*39488Smckusick register u_long *p; 674*39488Smckusick register caddr_t cp; 675*39488Smckusick register long t1, t2; 676*39488Smckusick caddr_t bpos, dpos, cp2; 677*39488Smckusick u_long xid; 678*39488Smckusick int error = 0; 679*39488Smckusick struct mbuf *mreq, *mrep, *md, *mb, *mb2; 68038414Smckusick 68138414Smckusick nfsstats.rpccnt[NFSPROC_CREATE]++; 68238414Smckusick nfsm_reqhead(nfs_procids[NFSPROC_CREATE], ndp->ni_cred, 68338414Smckusick NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen)+NFSX_SATTR); 68438414Smckusick nfsm_fhtom(ndp->ni_dvp); 68538414Smckusick nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN); 68638884Smacklem nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR); 68738884Smacklem sp->sa_mode = vtonfs_mode(VREG, vap->va_mode); 68838884Smacklem sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid); 68938884Smacklem sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid); 69038884Smacklem sp->sa_size = txdr_unsigned(0); 69138414Smckusick /* or should these be VNOVAL ?? */ 69238884Smacklem txdr_time(&vap->va_atime, &sp->sa_atime); 69338884Smacklem txdr_time(&vap->va_mtime, &sp->sa_mtime); 69438414Smckusick nfsm_request(ndp->ni_dvp); 69538414Smckusick nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp); 69638414Smckusick nfsm_reqdone; 69738414Smckusick nfs_nput(ndp->ni_dvp); 69838414Smckusick return (error); 69938414Smckusick } 70038414Smckusick 70138414Smckusick /* 70238414Smckusick * nfs file remove call 70339341Smckusick * To try and make nfs semantics closer to vfs semantics, a file that has 70439341Smckusick * other references to the vnode is renamed instead of removed and then 70539341Smckusick * removed later on the last close. 70639341Smckusick * Unfortunately you must flush the buffer cache and cmap to get rid of 70739341Smckusick * all extraneous vnode references before you check the reference cnt. 70839341Smckusick * 1 - If the file could have blocks in the buffer cache 70939341Smckusick * flush them out and invalidate them 71039341Smckusick * mpurge the vnode to flush out cmap references 71139341Smckusick * (This is necessary to update the vnode ref cnt as well as sensible 71239341Smckusick * for actual removes, to free up the buffers) 71339341Smckusick * 2 - If v_count > 1 71439341Smckusick * If a rename is not already in the works 71539341Smckusick * call nfs_sillyrename() to set it up 71639341Smckusick * else 71739341Smckusick * do the remove rpc 71838414Smckusick */ 71938414Smckusick nfs_remove(ndp) 72038414Smckusick register struct nameidata *ndp; 72138414Smckusick { 72239341Smckusick register struct vnode *vp = ndp->ni_vp; 72339341Smckusick register struct nfsnode *np = VTONFS(ndp->ni_vp); 724*39488Smckusick register u_long *p; 725*39488Smckusick register caddr_t cp; 726*39488Smckusick register long t1, t2; 727*39488Smckusick caddr_t bpos, dpos; 728*39488Smckusick u_long xid; 729*39488Smckusick int error = 0; 730*39488Smckusick struct mbuf *mreq, *mrep, *md, *mb, *mb2; 73138414Smckusick 73239341Smckusick if (vp->v_type == VREG) { 73339341Smckusick if (np->n_flag & (NMODIFIED|NBUFFERED)) { 73439341Smckusick np->n_flag &= ~(NMODIFIED|NBUFFERED); 73539341Smckusick nfs_blkflush(vp, (daddr_t)0, np->n_size, TRUE); 73639341Smckusick } 73739341Smckusick if (np->n_flag & NPAGEDON) 73839341Smckusick mpurge(vp); /* In case cmap entries still ref it */ 73939341Smckusick } 74039341Smckusick if (vp->v_count > 1) { 74139341Smckusick if (!np->n_sillyrename) 74239341Smckusick error = nfs_sillyrename(ndp, REMOVE); 74339341Smckusick } else { 74438414Smckusick nfsstats.rpccnt[NFSPROC_REMOVE]++; 74538414Smckusick nfsm_reqhead(nfs_procids[NFSPROC_REMOVE], ndp->ni_cred, 74638414Smckusick NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen)); 74738414Smckusick nfsm_fhtom(ndp->ni_dvp); 74838414Smckusick nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN); 74938414Smckusick nfsm_request(ndp->ni_dvp); 75038414Smckusick nfsm_reqdone; 75138414Smckusick } 75238414Smckusick if (ndp->ni_dvp == ndp->ni_vp) 75338425Smckusick vrele(ndp->ni_vp); 75438414Smckusick else 75538425Smckusick nfs_nput(ndp->ni_vp); 75638425Smckusick nfs_nput(ndp->ni_dvp); 75738414Smckusick return (error); 75838414Smckusick } 75938414Smckusick 76038414Smckusick /* 76138414Smckusick * nfs file remove rpc called from nfs_inactive 76238414Smckusick */ 76338414Smckusick nfs_removeit(ndp) 76438414Smckusick register struct nameidata *ndp; 76538414Smckusick { 766*39488Smckusick register u_long *p; 767*39488Smckusick register caddr_t cp; 768*39488Smckusick register long t1, t2; 769*39488Smckusick caddr_t bpos, dpos; 770*39488Smckusick u_long xid; 771*39488Smckusick int error = 0; 772*39488Smckusick struct mbuf *mreq, *mrep, *md, *mb, *mb2; 77338414Smckusick 77438414Smckusick nfsstats.rpccnt[NFSPROC_REMOVE]++; 77538414Smckusick nfsm_reqhead(nfs_procids[NFSPROC_REMOVE], ndp->ni_cred, 77638414Smckusick NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen)); 77738414Smckusick nfsm_fhtom(ndp->ni_dvp); 77838414Smckusick nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN); 77938414Smckusick nfsm_request(ndp->ni_dvp); 78038414Smckusick nfsm_reqdone; 78138414Smckusick return (error); 78238414Smckusick } 78338414Smckusick 78438414Smckusick /* 78538414Smckusick * nfs file rename call 78638414Smckusick */ 78738414Smckusick nfs_rename(sndp, tndp) 78838414Smckusick register struct nameidata *sndp, *tndp; 78938414Smckusick { 790*39488Smckusick register u_long *p; 791*39488Smckusick register caddr_t cp; 792*39488Smckusick register long t1, t2; 793*39488Smckusick caddr_t bpos, dpos; 794*39488Smckusick u_long xid; 795*39488Smckusick int error = 0; 796*39488Smckusick struct mbuf *mreq, *mrep, *md, *mb, *mb2; 79738414Smckusick 79838414Smckusick nfsstats.rpccnt[NFSPROC_RENAME]++; 79938414Smckusick nfsm_reqhead(nfs_procids[NFSPROC_RENAME], tndp->ni_cred, 80038414Smckusick (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(sndp->ni_dent.d_namlen)+ 80138414Smckusick nfsm_rndup(tndp->ni_dent.d_namlen)); /* or sndp->ni_cred?*/ 80238414Smckusick nfsm_fhtom(sndp->ni_dvp); 80338414Smckusick nfsm_strtom(sndp->ni_dent.d_name,sndp->ni_dent.d_namlen,NFS_MAXNAMLEN); 80438414Smckusick nfsm_fhtom(tndp->ni_dvp); 80538414Smckusick nfsm_strtom(tndp->ni_dent.d_name,tndp->ni_dent.d_namlen,NFS_MAXNAMLEN); 80638414Smckusick nfsm_request(sndp->ni_dvp); 80738414Smckusick nfsm_reqdone; 80838414Smckusick if (sndp->ni_vp->v_type == VDIR) { 80938414Smckusick if (tndp->ni_vp != NULL && tndp->ni_vp->v_type == VDIR) 81038414Smckusick cache_purge(tndp->ni_dvp); 81138414Smckusick cache_purge(sndp->ni_dvp); 81238414Smckusick } 81338414Smckusick nfs_abortop(sndp); 81438414Smckusick nfs_abortop(tndp); 81538414Smckusick return (error); 81638414Smckusick } 81738414Smckusick 81838414Smckusick /* 81938414Smckusick * nfs file rename rpc called from above 82038414Smckusick */ 82138414Smckusick nfs_renameit(sndp, tndp) 82238414Smckusick register struct nameidata *sndp, *tndp; 82338414Smckusick { 824*39488Smckusick register u_long *p; 825*39488Smckusick register caddr_t cp; 826*39488Smckusick register long t1, t2; 827*39488Smckusick caddr_t bpos, dpos; 828*39488Smckusick u_long xid; 829*39488Smckusick int error = 0; 830*39488Smckusick struct mbuf *mreq, *mrep, *md, *mb, *mb2; 83138414Smckusick 83238414Smckusick nfsstats.rpccnt[NFSPROC_RENAME]++; 83338414Smckusick nfsm_reqhead(nfs_procids[NFSPROC_RENAME], tndp->ni_cred, 83438414Smckusick (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(sndp->ni_dent.d_namlen)+ 83538414Smckusick nfsm_rndup(tndp->ni_dent.d_namlen)); /* or sndp->ni_cred?*/ 83638414Smckusick nfsm_fhtom(sndp->ni_dvp); 83738414Smckusick nfsm_strtom(sndp->ni_dent.d_name,sndp->ni_dent.d_namlen,NFS_MAXNAMLEN); 83838414Smckusick nfsm_fhtom(tndp->ni_dvp); 83938414Smckusick nfsm_strtom(tndp->ni_dent.d_name,tndp->ni_dent.d_namlen,NFS_MAXNAMLEN); 84038414Smckusick nfsm_request(sndp->ni_dvp); 84138414Smckusick nfsm_reqdone; 84238414Smckusick return (error); 84338414Smckusick } 84438414Smckusick 84538414Smckusick /* 84638414Smckusick * nfs hard link create call 84738414Smckusick */ 84838414Smckusick nfs_link(vp, ndp) 849*39488Smckusick register struct vnode *vp; 85038414Smckusick register struct nameidata *ndp; 85138414Smckusick { 852*39488Smckusick register u_long *p; 853*39488Smckusick register caddr_t cp; 854*39488Smckusick register long t1, t2; 855*39488Smckusick caddr_t bpos, dpos; 856*39488Smckusick u_long xid; 857*39488Smckusick int error = 0; 858*39488Smckusick struct mbuf *mreq, *mrep, *md, *mb, *mb2; 85938414Smckusick 86038425Smckusick if (ndp->ni_dvp != vp) 86138425Smckusick nfs_lock(vp); 86238414Smckusick nfsstats.rpccnt[NFSPROC_LINK]++; 86338414Smckusick nfsm_reqhead(nfs_procids[NFSPROC_LINK], ndp->ni_cred, 86438414Smckusick NFSX_FH*2+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen)); 86538414Smckusick nfsm_fhtom(vp); 86638414Smckusick nfsm_fhtom(ndp->ni_dvp); 86738414Smckusick nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN); 86838414Smckusick nfsm_request(vp); 86938414Smckusick nfsm_reqdone; 87038425Smckusick if (ndp->ni_dvp != vp) 87138425Smckusick nfs_unlock(vp); 87238414Smckusick nfs_nput(ndp->ni_dvp); 87338414Smckusick return (error); 87438414Smckusick } 87538414Smckusick 87638414Smckusick /* 87738414Smckusick * nfs symbolic link create call 87838414Smckusick */ 87938414Smckusick nfs_symlink(ndp, vap, nm) 88038414Smckusick struct nameidata *ndp; 88138414Smckusick struct vattr *vap; 88238414Smckusick char *nm; /* is this the path ?? */ 88338414Smckusick { 88438884Smacklem register struct nfsv2_sattr *sp; 885*39488Smckusick register u_long *p; 886*39488Smckusick register caddr_t cp; 887*39488Smckusick register long t1, t2; 888*39488Smckusick caddr_t bpos, dpos; 889*39488Smckusick u_long xid; 890*39488Smckusick int error = 0; 891*39488Smckusick struct mbuf *mreq, *mrep, *md, *mb, *mb2; 89238414Smckusick 89338414Smckusick nfsstats.rpccnt[NFSPROC_SYMLINK]++; 89438414Smckusick nfsm_reqhead(nfs_procids[NFSPROC_SYMLINK], ndp->ni_cred, 89538414Smckusick NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen)+NFSX_UNSIGNED); 89638414Smckusick nfsm_fhtom(ndp->ni_dvp); 89738414Smckusick nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN); 89838414Smckusick nfsm_strtom(nm, strlen(nm), NFS_MAXPATHLEN); 89938884Smacklem nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR); 90038884Smacklem sp->sa_mode = vtonfs_mode(VLNK, vap->va_mode); 90138884Smacklem sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid); 90238884Smacklem sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid); 90338884Smacklem sp->sa_size = txdr_unsigned(VNOVAL); 90438884Smacklem txdr_time(&vap->va_atime, &sp->sa_atime); /* or VNOVAL ?? */ 90538884Smacklem txdr_time(&vap->va_mtime, &sp->sa_mtime); /* or VNOVAL ?? */ 90638414Smckusick nfsm_request(ndp->ni_dvp); 90738414Smckusick nfsm_reqdone; 90838414Smckusick nfs_nput(ndp->ni_dvp); 90938414Smckusick return (error); 91038414Smckusick } 91138414Smckusick 91238414Smckusick /* 91338414Smckusick * nfs make dir call 91438414Smckusick */ 91538414Smckusick nfs_mkdir(ndp, vap) 916*39488Smckusick register struct nameidata *ndp; 91738414Smckusick struct vattr *vap; 91838414Smckusick { 91938884Smacklem register struct nfsv2_sattr *sp; 920*39488Smckusick register u_long *p; 921*39488Smckusick register caddr_t cp; 922*39488Smckusick register long t1, t2; 923*39488Smckusick caddr_t bpos, dpos, cp2; 924*39488Smckusick u_long xid; 925*39488Smckusick int error = 0; 926*39488Smckusick struct mbuf *mreq, *mrep, *md, *mb, *mb2; 92738414Smckusick 92838414Smckusick nfsstats.rpccnt[NFSPROC_MKDIR]++; 92938414Smckusick nfsm_reqhead(nfs_procids[NFSPROC_MKDIR], ndp->ni_cred, 93038414Smckusick NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen)+NFSX_SATTR); 93138414Smckusick nfsm_fhtom(ndp->ni_dvp); 93238414Smckusick nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN); 93338884Smacklem nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR); 93438884Smacklem sp->sa_mode = vtonfs_mode(VDIR, vap->va_mode); 93538884Smacklem sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid); 93638884Smacklem sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid); 93738884Smacklem sp->sa_size = txdr_unsigned(VNOVAL); 93838884Smacklem txdr_time(&vap->va_atime, &sp->sa_atime); /* or VNOVAL ?? */ 93938884Smacklem txdr_time(&vap->va_mtime, &sp->sa_mtime); /* or VNOVAL ?? */ 94038414Smckusick nfsm_request(ndp->ni_dvp); 94138414Smckusick nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp); 94238414Smckusick nfsm_reqdone; 94338414Smckusick nfs_nput(ndp->ni_dvp); 94438414Smckusick return (error); 94538414Smckusick } 94638414Smckusick 94738414Smckusick /* 94838414Smckusick * nfs remove directory call 94938414Smckusick */ 95038414Smckusick nfs_rmdir(ndp) 95138414Smckusick register struct nameidata *ndp; 95238414Smckusick { 953*39488Smckusick register u_long *p; 954*39488Smckusick register caddr_t cp; 955*39488Smckusick register long t1, t2; 956*39488Smckusick caddr_t bpos, dpos; 957*39488Smckusick u_long xid; 958*39488Smckusick int error = 0; 959*39488Smckusick struct mbuf *mreq, *mrep, *md, *mb, *mb2; 96038414Smckusick 96138414Smckusick if (ndp->ni_dvp == ndp->ni_vp) { 96238414Smckusick vrele(ndp->ni_dvp); 96338414Smckusick nfs_nput(ndp->ni_dvp); 96438414Smckusick return (EINVAL); 96538414Smckusick } 96638414Smckusick nfsstats.rpccnt[NFSPROC_RMDIR]++; 96738414Smckusick nfsm_reqhead(nfs_procids[NFSPROC_RMDIR], ndp->ni_cred, 96838414Smckusick NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen)); 96938414Smckusick nfsm_fhtom(ndp->ni_dvp); 97038414Smckusick nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN); 97138414Smckusick nfsm_request(ndp->ni_dvp); 97238414Smckusick nfsm_reqdone; 97338884Smacklem cache_purge(ndp->ni_dvp); 97438884Smacklem cache_purge(ndp->ni_vp); 97538884Smacklem nfs_nput(ndp->ni_vp); 97638884Smacklem nfs_nput(ndp->ni_dvp); 97738414Smckusick return (error); 97838414Smckusick } 97938414Smckusick 98038414Smckusick /* 98138414Smckusick * nfs readdir call 98238414Smckusick * Although cookie is defined as opaque, I translate it to/from net byte 98338414Smckusick * order so that it looks more sensible. This appears consistent with the 98438414Smckusick * Ultrix implementation of NFS. 98538414Smckusick */ 98638414Smckusick nfs_readdir(vp, uiop, offp, cred) 987*39488Smckusick register struct vnode *vp; 98838414Smckusick struct uio *uiop; 98938414Smckusick off_t *offp; 99038414Smckusick struct ucred *cred; 99138414Smckusick { 99238414Smckusick register long len; 99338414Smckusick register struct direct *dp; 994*39488Smckusick register u_long *p; 995*39488Smckusick register caddr_t cp; 996*39488Smckusick register long t1; 997*39488Smckusick caddr_t bpos, dpos, cp2; 998*39488Smckusick u_long xid; 999*39488Smckusick int error = 0; 1000*39488Smckusick struct mbuf *mreq, *mrep, *md, *mb, *mb2; 100138414Smckusick struct mbuf *md2; 100238414Smckusick caddr_t dpos2; 100338414Smckusick int siz; 100438414Smckusick int more_dirs, eofflg; 100538414Smckusick off_t off, savoff; 100638414Smckusick struct direct *savdp; 100738414Smckusick 100838414Smckusick nfs_lock(vp); 100938414Smckusick nfsstats.rpccnt[NFSPROC_READDIR]++; 101038414Smckusick nfsm_reqhead(nfs_procids[NFSPROC_READDIR], cred, xid); 101138414Smckusick nfsm_fhtom(vp); 101238414Smckusick nfsm_build(p, u_long *, 2*NFSX_UNSIGNED); 101338414Smckusick off = *offp; 101438414Smckusick *p++ = txdr_unsigned(off); 101538414Smckusick *p = txdr_unsigned(uiop->uio_resid); 101638414Smckusick nfsm_request(vp); 101738414Smckusick siz = 0; 101838414Smckusick nfsm_disect(p, u_long *, NFSX_UNSIGNED); 101938414Smckusick more_dirs = fxdr_unsigned(int, *p); 102038414Smckusick 102138414Smckusick /* Save the position so that we can do nfsm_mtouio() later */ 102238414Smckusick dpos2 = dpos; 102338414Smckusick md2 = md; 102438414Smckusick 102538414Smckusick /* loop thru the dir entries, doctoring them to 4bsd form */ 1026*39488Smckusick savoff = off = 0; 1027*39488Smckusick savdp = dp = NULL; 102838414Smckusick while (more_dirs && siz < uiop->uio_resid) { 102938414Smckusick savoff = off; /* Hold onto offset and dp */ 103038414Smckusick savdp = dp; 103138414Smckusick nfsm_disecton(p, u_long *, 2*NFSX_UNSIGNED); 103238414Smckusick dp = (struct direct *)p; 103338414Smckusick dp->d_ino = fxdr_unsigned(u_long, *p++); 103438414Smckusick len = fxdr_unsigned(int, *p); 103538414Smckusick if (len <= 0 || len > NFS_MAXNAMLEN) { 103638414Smckusick error = EBADRPC; 103738414Smckusick m_freem(mrep); 103838414Smckusick goto nfsmout; 103938414Smckusick } 104038414Smckusick dp->d_namlen = (u_short)len; 104138414Smckusick len = nfsm_rndup(len); 104238414Smckusick nfsm_adv(len); 104338414Smckusick nfsm_disecton(p, u_long *, 2*NFSX_UNSIGNED); 104438414Smckusick off = fxdr_unsigned(off_t, *p); 104538414Smckusick *p++ = 0; /* Ensures null termination of name */ 104638414Smckusick more_dirs = fxdr_unsigned(int, *p); 104738414Smckusick dp->d_reclen = len+4*NFSX_UNSIGNED; 104838414Smckusick siz += dp->d_reclen; 104938414Smckusick } 105038414Smckusick /* 105138414Smckusick * If at end of rpc data, get the eof boolean 105238414Smckusick */ 105338414Smckusick if (!more_dirs) { 105438414Smckusick nfsm_disecton(p, u_long *, NFSX_UNSIGNED); 105538414Smckusick eofflg = fxdr_unsigned(long, *p); 105638414Smckusick } 105738414Smckusick /* 105838414Smckusick * If there is too much to fit in the data buffer, use savoff and 105938414Smckusick * savdp to trim off the last record. 106038414Smckusick * --> we are not at eof 106138414Smckusick */ 106238414Smckusick if (siz > uiop->uio_resid) { 106338414Smckusick eofflg = FALSE; 106438414Smckusick off = savoff; 106538414Smckusick siz -= dp->d_reclen; 106638414Smckusick dp = savdp; 106738414Smckusick } 106838414Smckusick if (siz > 0) { 106938414Smckusick #ifdef notdef 107038414Smckusick if (!eofflg) 107138414Smckusick dp->d_reclen += (uiop->uio_resid-siz); 107238414Smckusick #endif 107338414Smckusick md = md2; 107438414Smckusick dpos = dpos2; 107538414Smckusick nfsm_mtouio(uiop, siz); 107638414Smckusick #ifdef notdef 107738414Smckusick if (!eofflg) 107838414Smckusick uiop->uio_resid = 0; 107938414Smckusick #endif 108038414Smckusick *offp = off; 108138414Smckusick } 108238414Smckusick nfsm_reqdone; 108338414Smckusick nfs_unlock(vp); 108438414Smckusick return (error); 108538414Smckusick } 108638414Smckusick 108738414Smckusick /* 108838414Smckusick * nfs statfs call 108938414Smckusick * (Actually a vfsop, not a vnode op) 109038414Smckusick */ 109138414Smckusick nfs_statfs(mp, sbp) 109238414Smckusick struct mount *mp; 109338414Smckusick register struct statfs *sbp; 109438414Smckusick { 1095*39488Smckusick register struct vnode *vp; 109638884Smacklem register struct nfsv2_statfs *sfp; 1097*39488Smckusick register caddr_t cp; 1098*39488Smckusick register long t1; 1099*39488Smckusick caddr_t bpos, dpos, cp2; 1100*39488Smckusick u_long xid; 1101*39488Smckusick int error = 0; 1102*39488Smckusick struct mbuf *mreq, *mrep, *md, *mb, *mb2; 110338884Smacklem struct nfsmount *nmp; 110438414Smckusick struct ucred *cred; 110538414Smckusick struct nfsnode *np; 110638414Smckusick 110738414Smckusick nmp = vfs_to_nfs(mp); 110838414Smckusick if (error = nfs_nget(mp, &nmp->nm_fh, &np)) 110938414Smckusick return (error); 111038414Smckusick vp = NFSTOV(np); 111138414Smckusick nfsstats.rpccnt[NFSPROC_STATFS]++; 111238414Smckusick cred = crget(); 111338414Smckusick cred->cr_ngroups = 1; 111438414Smckusick nfsm_reqhead(nfs_procids[NFSPROC_STATFS], cred, NFSX_FH); 111538414Smckusick nfsm_fhtom(vp); 111638414Smckusick nfsm_request(vp); 111738884Smacklem nfsm_disect(sfp, struct nfsv2_statfs *, NFSX_STATFS); 111838414Smckusick sbp->f_type = MOUNT_NFS; 111938884Smacklem sbp->f_bsize = fxdr_unsigned(long, sfp->sf_tsize); 112038884Smacklem sbp->f_fsize = fxdr_unsigned(long, sfp->sf_bsize); 112138884Smacklem sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks); 112238884Smacklem sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree); 112338884Smacklem sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail); 112438739Smckusick sbp->f_files = 0; 112538739Smckusick sbp->f_ffree = 0; 112638414Smckusick bcopy(nmp->nm_path, sbp->f_mntonname, MNAMELEN); 112738414Smckusick bcopy(nmp->nm_host, sbp->f_mntfromname, MNAMELEN); 112838414Smckusick nfsm_reqdone; 112938414Smckusick nfs_nput(vp); 113038414Smckusick crfree(cred); 113138414Smckusick return (error); 113238414Smckusick } 113338414Smckusick 1134*39488Smckusick static char hextoasc[] = "0123456789abcdef"; 113538414Smckusick 113638414Smckusick /* 113738414Smckusick * Silly rename. To make the NFS filesystem that is stateless look a little 113838414Smckusick * more like the "ufs" a remove of an active vnode is translated to a rename 113938414Smckusick * to a funny looking filename that is removed by nfs_inactive on the 114038414Smckusick * nfsnode. There is the potential for another process on a different client 114138414Smckusick * to create the same funny name between the nfs_lookitup() fails and the 114238414Smckusick * nfs_rename() completes, but... 114338414Smckusick */ 114438414Smckusick nfs_sillyrename(ndp, flag) 1145*39488Smckusick register struct nameidata *ndp; 114638414Smckusick int flag; 114738414Smckusick { 114838414Smckusick register struct nfsnode *np; 114938414Smckusick register struct sillyrename *sp; 115038414Smckusick register struct nameidata *tndp; 115138414Smckusick int error; 115238414Smckusick short pid; 115338414Smckusick 115438414Smckusick np = VTONFS(ndp->ni_dvp); 115539341Smckusick cache_purge(ndp->ni_dvp); 115638414Smckusick MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename), 115738884Smacklem M_TEMP, M_WAITOK); 115838414Smckusick sp->s_flag = flag; 115938414Smckusick bcopy((caddr_t)&np->n_fh, (caddr_t)&sp->s_fh, NFSX_FH); 116038414Smckusick np = VTONFS(ndp->ni_vp); 116138414Smckusick tndp = &sp->s_namei; 116238414Smckusick tndp->ni_cred = crdup(ndp->ni_cred); 116338414Smckusick 116438414Smckusick /* Fudge together a funny name */ 116538414Smckusick pid = u.u_procp->p_pid; 116638414Smckusick bcopy(".nfsAxxxx4.4", tndp->ni_dent.d_name, 13); 116738414Smckusick tndp->ni_dent.d_namlen = 12; 1168*39488Smckusick tndp->ni_dent.d_name[8] = hextoasc[pid & 0xf]; 1169*39488Smckusick tndp->ni_dent.d_name[7] = hextoasc[(pid >> 4) & 0xf]; 1170*39488Smckusick tndp->ni_dent.d_name[6] = hextoasc[(pid >> 8) & 0xf]; 1171*39488Smckusick tndp->ni_dent.d_name[5] = hextoasc[(pid >> 12) & 0xf]; 117238414Smckusick 117338414Smckusick /* Try lookitups until we get one that isn't there */ 117438414Smckusick while (nfs_lookitup(ndp->ni_dvp, tndp, (nfsv2fh_t *)0) == 0) { 117538414Smckusick tndp->ni_dent.d_name[4]++; 117638414Smckusick if (tndp->ni_dent.d_name[4] > 'z') { 117738414Smckusick error = EINVAL; 117838414Smckusick goto bad; 117938414Smckusick } 118038414Smckusick } 118138414Smckusick if (error = nfs_renameit(ndp, tndp)) 118238414Smckusick goto bad; 118338414Smckusick nfs_lookitup(ndp->ni_dvp, tndp, &np->n_fh); 118438414Smckusick np->n_sillyrename = sp; 118538414Smckusick return (0); 118638414Smckusick bad: 118738884Smacklem crfree(tndp->ni_cred); 118838414Smckusick free((caddr_t)sp, M_TEMP); 118938414Smckusick return (error); 119038414Smckusick } 119138414Smckusick 119238414Smckusick /* 119338414Smckusick * Look up a file name for silly rename stuff. 119438414Smckusick * Just like nfs_lookup() except that it doesn't load returned values 119538414Smckusick * into the nfsnode table. 119638414Smckusick * If fhp != NULL it copies the returned file handle out 119738414Smckusick */ 119838414Smckusick nfs_lookitup(vp, ndp, fhp) 119938414Smckusick register struct vnode *vp; 120038414Smckusick register struct nameidata *ndp; 120138414Smckusick nfsv2fh_t *fhp; 120238414Smckusick { 1203*39488Smckusick register u_long *p; 1204*39488Smckusick register caddr_t cp; 1205*39488Smckusick register long t1, t2; 1206*39488Smckusick caddr_t bpos, dpos, cp2; 1207*39488Smckusick u_long xid; 1208*39488Smckusick int error = 0; 1209*39488Smckusick struct mbuf *mreq, *mrep, *md, *mb, *mb2; 121038414Smckusick long len; 121138414Smckusick 121238414Smckusick nfsstats.rpccnt[NFSPROC_LOOKUP]++; 121338414Smckusick ndp->ni_dvp = vp; 121438414Smckusick ndp->ni_vp = NULL; 121538414Smckusick len = ndp->ni_dent.d_namlen; 121638414Smckusick nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], ndp->ni_cred, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)); 121738414Smckusick nfsm_fhtom(vp); 121838414Smckusick nfsm_strtom(ndp->ni_dent.d_name, len, NFS_MAXNAMLEN); 121938414Smckusick nfsm_request(vp); 122038414Smckusick if (fhp != NULL) { 122138414Smckusick nfsm_disect(cp, caddr_t, NFSX_FH); 122238414Smckusick bcopy(cp, (caddr_t)fhp, NFSX_FH); 122338414Smckusick } 122438414Smckusick nfsm_reqdone; 122538414Smckusick return (error); 122638414Smckusick } 122738414Smckusick 122838414Smckusick /* 122938414Smckusick * Kludge City.. 123038414Smckusick * - make nfs_bmap() essentially a no-op that does no translation 123138414Smckusick * - do nfs_strategy() by faking physical I/O with nfs_readit/nfs_writeit 123238414Smckusick * after mapping the physical addresses into Kernel Virtual space in the 123338414Smckusick * nfsiobuf area. 123438414Smckusick * (Maybe I could use the process's page mapping, but I was concerned that 123538414Smckusick * Kernel Write might not be enabled and also figured copyout() would do 123638414Smckusick * a lot more work than bcopy() and also it currently happens in the 123738414Smckusick * context of the swapper process (2). 123838414Smckusick */ 123938414Smckusick nfs_bmap(vp, bn, vpp, bnp) 124038414Smckusick struct vnode *vp; 124138414Smckusick daddr_t bn; 124238414Smckusick struct vnode **vpp; 124338414Smckusick daddr_t *bnp; 124438414Smckusick { 124538414Smckusick if (vpp != NULL) 124638414Smckusick *vpp = vp; 124738414Smckusick if (bnp != NULL) 124838414Smckusick *bnp = bn * btodb(vp->v_mount->m_bsize); 124938414Smckusick return (0); 125038414Smckusick } 125138414Smckusick 125238414Smckusick /* 125338884Smacklem * Strategy routine for phys. i/o 125438884Smacklem * If the biod's are running, queue a request 125538884Smacklem * otherwise just call nfs_doio() to get it done 125638414Smckusick */ 125738414Smckusick nfs_strategy(bp) 125838414Smckusick register struct buf *bp; 125938414Smckusick { 126038884Smacklem register struct buf *dp; 126139341Smckusick register int i; 126238884Smacklem struct proc *rp; 126338884Smacklem int error = 0; 126439341Smckusick int fnd = 0; 126538884Smacklem 126638884Smacklem /* 126738884Smacklem * If an i/o daemon is waiting 126838884Smacklem * queue the request, wake it up and wait for completion 126938884Smacklem * otherwise just do it ourselves 127038884Smacklem */ 127139341Smckusick for (i = 0; i < nfs_asyncdaemons; i++) { 127239341Smckusick if (rp = nfs_iodwant[i]) { 127339341Smckusick /* 127439341Smckusick * Ensure that the async_daemon is still waiting here 127539341Smckusick */ 127639341Smckusick if (rp->p_stat != SSLEEP || 127739341Smckusick rp->p_wchan != ((caddr_t)&nfs_iodwant[i])) { 127839341Smckusick nfs_iodwant[i] = (struct proc *)0; 127939341Smckusick continue; 128039341Smckusick } 128139341Smckusick dp = &nfs_bqueue; 128239341Smckusick if (dp->b_actf == NULL) { 128339341Smckusick dp->b_actl = bp; 128439341Smckusick bp->b_actf = dp; 128539341Smckusick } else { 128639341Smckusick dp->b_actf->b_actl = bp; 128739341Smckusick bp->b_actf = dp->b_actf; 128839341Smckusick } 128939341Smckusick dp->b_actf = bp; 129039341Smckusick bp->b_actl = dp; 129139341Smckusick fnd++; 129239341Smckusick nfs_iodwant[i] = (struct proc *)0; 129339341Smckusick wakeup((caddr_t)&nfs_iodwant[i]); 129439341Smckusick break; 129538884Smacklem } 129639341Smckusick } 129739341Smckusick if (!fnd) 129838884Smacklem error = nfs_doio(bp); 129938884Smacklem return (error); 130038884Smacklem } 130138884Smacklem 130238884Smacklem /* 130338884Smacklem * Fun and games with i/o 130438884Smacklem * Essentially play ubasetup() and disk interrupt service routine by 130538884Smacklem * mapping the data buffer into kernel virtual space and doing the 130638884Smacklem * nfs read or write rpc's from it. 130738884Smacklem * If the biod's are not running, this is just called from nfs_strategy(), 130838884Smacklem * otherwise it is called by the biod's to do what would normally be 130938884Smacklem * partially disk interrupt driven. 131038884Smacklem */ 131138884Smacklem nfs_doio(bp) 131238884Smacklem register struct buf *bp; 131338884Smacklem { 131438414Smckusick register struct pte *pte, *ppte; 131538414Smckusick register caddr_t vaddr; 131638414Smckusick register struct uio *uiop; 131738414Smckusick register struct vnode *vp; 131839341Smckusick struct nfsnode *np; 131938884Smacklem struct ucred *cr; 132038884Smacklem int npf, npf2; 132138884Smacklem int reg; 132238884Smacklem caddr_t vbase; 132338884Smacklem caddr_t addr; 132438414Smckusick unsigned v; 132538414Smckusick struct proc *rp; 132638414Smckusick int o, error; 132738884Smacklem int bcnt; 132838414Smckusick off_t off; 132938414Smckusick struct uio uio; 133038414Smckusick struct iovec io; 133138414Smckusick 133238414Smckusick vp = bp->b_vp; 133338414Smckusick uiop = &uio; 133438414Smckusick uiop->uio_iov = &io; 133538414Smckusick uiop->uio_iovcnt = 1; 133638414Smckusick uiop->uio_segflg = UIO_SYSSPACE; 133738884Smacklem if (bp->b_flags & B_READ) { 133838884Smacklem io.iov_len = uiop->uio_resid = bp->b_bcount; 133938884Smacklem uiop->uio_offset = off = bp->b_blkno*DEV_BSIZE; 134038884Smacklem addr = bp->b_un.b_addr; 134138884Smacklem bcnt = bp->b_bcount; 134238884Smacklem } else { 134338884Smacklem io.iov_len = uiop->uio_resid = bp->b_dirtyend-bp->b_dirtyoff; 134438884Smacklem uiop->uio_offset = off = (bp->b_blkno*DEV_BSIZE)+bp->b_dirtyoff; 134538884Smacklem addr = bp->b_un.b_addr+bp->b_dirtyoff; 134638884Smacklem bcnt = bp->b_dirtyend-bp->b_dirtyoff; 134738414Smckusick } 134838414Smckusick /* 134938884Smacklem * For phys i/o, map the b_addr into kernel virtual space using 135038884Smacklem * the Nfsiomap pte's 135138884Smacklem * Also, add a temporary b_rcred for reading using the process's uid 135238884Smacklem * and a guess at a group 135338414Smckusick */ 135438884Smacklem if (bp->b_flags & B_PHYS) { 135539341Smckusick VTONFS(vp)->n_flag |= NPAGEDON; 135638884Smacklem bp->b_rcred = cr = crget(); 135738884Smacklem rp = (bp->b_flags & B_DIRTY) ? &proc[2] : bp->b_proc; 135838884Smacklem cr->cr_uid = rp->p_uid; 135938884Smacklem cr->cr_gid = 0; /* Anything ?? */ 136038884Smacklem cr->cr_ngroups = 1; 136138884Smacklem o = (int)addr & PGOFSET; 136238884Smacklem npf2 = npf = btoc(bcnt + o); 136338884Smacklem /* 136438884Smacklem * Get some mapping page table entries 136538884Smacklem */ 136638884Smacklem while ((reg = rmalloc(nfsmap, (long)npf)) == 0) { 136738884Smacklem nfsmap_want++; 136838884Smacklem sleep((caddr_t)&nfsmap_want, PZERO-1); 136938884Smacklem } 137038884Smacklem reg--; 137138884Smacklem /* I know it is always the else, but that may change someday */ 137238884Smacklem if ((bp->b_flags & B_PHYS) == 0) 137338884Smacklem pte = kvtopte(bp->b_un.b_addr); 137438884Smacklem else if (bp->b_flags & B_PAGET) 137538884Smacklem pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)]; 137638884Smacklem else { 137738884Smacklem v = btop(bp->b_un.b_addr); 137838884Smacklem if (bp->b_flags & B_UAREA) 137938884Smacklem pte = &rp->p_addr[v]; 138038884Smacklem else 138138884Smacklem pte = vtopte(rp, v); 138238884Smacklem } 138338884Smacklem /* 138438884Smacklem * Play vmaccess() but with the Nfsiomap page table 138538884Smacklem */ 138638884Smacklem ppte = &Nfsiomap[reg]; 138738884Smacklem vbase = vaddr = &nfsiobuf[reg*NBPG]; 138838884Smacklem while (npf != 0) { 138938884Smacklem mapin(ppte, (u_int)vaddr, pte->pg_pfnum, (int)(PG_V|PG_KW)); 139038414Smckusick #if defined(tahoe) 139138884Smacklem mtpr(P1DC, vaddr); 139238414Smckusick #endif 139338884Smacklem ppte++; 139438884Smacklem pte++; 139538884Smacklem vaddr += NBPG; 139638884Smacklem --npf; 139738884Smacklem } 139838884Smacklem io.iov_base = vbase+o; 139938884Smacklem } else { 140038884Smacklem io.iov_base = addr; 140138414Smckusick } 140238414Smckusick if (bp->b_flags & B_READ) { 140338414Smckusick uiop->uio_rw = UIO_READ; 140438884Smacklem bp->b_error = error = nfs_readrpc(vp, uiop, &off, bp->b_rcred); 140538414Smckusick } else { 140638414Smckusick uiop->uio_rw = UIO_WRITE; 140738884Smacklem bp->b_error = error = nfs_writerpc(vp, uiop, &off, bp->b_wcred); 140839341Smckusick if (error) { 140939341Smckusick np = VTONFS(vp); 141039341Smckusick np->n_error = error; 141139341Smckusick np->n_flag |= NWRITEERR; 141239341Smckusick } 141338884Smacklem bp->b_dirtyoff = bp->b_dirtyend = 0; 141438414Smckusick } 141538884Smacklem if (error) 141638884Smacklem bp->b_flags |= B_ERROR; 141738414Smckusick bp->b_resid = uiop->uio_resid; 141838884Smacklem /* 141938884Smacklem * Release pte's used by physical i/o 142038884Smacklem */ 142138884Smacklem if (bp->b_flags & B_PHYS) { 142238884Smacklem crfree(cr); 142338884Smacklem rmfree(nfsmap, (long)npf2, (long)++reg); 142438884Smacklem if (nfsmap_want) { 142538884Smacklem nfsmap_want = 0; 142638884Smacklem wakeup((caddr_t)&nfsmap_want); 142738884Smacklem } 142838884Smacklem } 142938414Smckusick biodone(bp); 143038414Smckusick return (error); 143138414Smckusick } 143238884Smacklem 143338884Smacklem /* 143438884Smacklem * Flush all the blocks associated with a vnode. 143538884Smacklem * Walk through the buffer pool and push any dirty pages 143638884Smacklem * associated with the vnode. 143738884Smacklem */ 1438*39488Smckusick /* ARGSUSED */ 143938884Smacklem nfs_fsync(vp, fflags, cred) 144038884Smacklem register struct vnode *vp; 144138884Smacklem int fflags; 144238884Smacklem struct ucred *cred; 144338884Smacklem { 144438884Smacklem register struct nfsnode *np = VTONFS(vp); 144538884Smacklem int error; 144638884Smacklem 144738884Smacklem nfs_lock(vp); 144838884Smacklem if (np->n_flag & NMODIFIED) { 144938884Smacklem np->n_flag &= ~NMODIFIED; 145039341Smckusick error = nfs_blkflush(vp, (daddr_t)0, np->n_size, FALSE); 145138884Smacklem } 145238884Smacklem nfs_unlock(vp); 145338884Smacklem return (error); 145438884Smacklem } 1455