📄 nfs_vnodeops.c
字号:
/* @(#)nfs_vnodeops.c 1.1 92/07/30 SMI *//* * Copyright (c) 1986 by Sun Microsystems, Inc. */#include <sys/param.h>#include "boot/systm.h"#include <sys/user.h>#include "boot/vnode.h"#include <sys/vfs.h>#include <sys/file.h>#include <sys/uio.h>#include <sys/buf.h>#include <sys/kernel.h>#include "boot/cmap.h"#include <netinet/in.h>#include <sys/proc.h>#include <rpc/types.h>#include <rpc/auth.h>#include <rpc/clnt.h>#include <rpc/xdr.h>#include "boot/nfs.h"#include <nfs/nfs_clnt.h>#include <nfs/rnode.h>#ifdef NFSDEBUGstatic int nfsdebug = 10;#endif /* NFSDEBUG */struct vnode *makenfsnode();char *newname();#define RNOCACHE 0x20 /* don't cache read and write blocks */#define check_stale_fh(errno, vp) if ((errno) == ESTALE) { dnlc_purge_vp(vp); }#define nfsattr_inval(vp) (vtor(vp)->r_attrtime.tv_sec = 0)#define ISVDEV(t) ((t == VBLK) || (t == VCHR) || (t == VFIFO))#define rlock(rp) { \ while ((rp)->r_flags & RLOCKED) { \ (rp)->r_flags |= RWANT; \ (void) sleep((caddr_t)(rp), PINOD); \ } \ (rp)->r_flags |= RLOCKED; \}#define runlock(rp) { \ (rp)->r_flags &= ~RLOCKED; \ if ((rp)->r_flags&RWANT) { \ (rp)->r_flags &= ~RWANT; \ wakeup((caddr_t)(rp)); \ } \}#undef uextern struct user u;/* * These are the vnode ops routines which implement the vnode interface to * the networked file system. These routines just take their parameters, * make them look networkish by putting the right info into interface structs, * and then calling the appropriate remote routine(s) to do the work. * * Note on directory name lookup cacheing: we desire that all operations * on a given client machine come out the same with or without the cache. * This is the same property we have with the disk buffer cache. In order * to guarantee this, we serialize all operations on a given directory, * by using rlock and runlock around rfscalls to the server. This way, * we cannot get into races with ourself that would cause invalid information * in the cache. Other clients (or the server itself) can cause our * cached information to become invalid, the same as with data buffers. * Also, if we do detect a stale fhandle, we purge the directory cache * relative to that vnode. This way, the user won't get burned by the * cache repeatedly. */int nfs_open();int nfs_close();int nfs_rdwr();int nfs_ioctl();int nfs_select();int nfs_getattr();int nfs_access();int nfs_lookup();int nfs_readdir();int nfs_readlink();int nfs_inactive();int nfs_bmap();int nfs_strategy();int nfs_badop();int nfs_noop();struct vnodeops nfs_vnodeops = { nfs_open, nfs_close, nfs_rdwr, nfs_ioctl, nfs_select, nfs_getattr, nfs_badop, /* nfs_setattr */ nfs_access, nfs_lookup, nfs_badop, /* nfs_create */ nfs_badop, /* nfs_remove */ nfs_badop, /* nfs_link */ nfs_badop, /* nfs_rename */ nfs_badop, /* nfs_mkdir */ nfs_badop, /* nfs_rmdir */ nfs_readdir, nfs_badop, /* nfs_symlink */ nfs_readlink, nfs_badop, /* nfs_fsync */ nfs_inactive, nfs_bmap, nfs_strategy, nfs_badop, nfs_badop, nfs_badop, /* nfs_locktl */ nfs_noop,};/*ARGSUSED*/intnfs_open(vpp, flag, cred) register struct vnode **vpp; int flag; struct ucred *cred;{ struct vattr va; int error;#ifdef NFSDEBUG dprint(nfsdebug, 6, "nfs_open %s %x flag %d\n", vtomi(*vpp)->mi_hostname, *vpp, flag);#endif /* * validate cached data by getting the attributes from the server */ nfsattr_inval(*vpp); error = nfs_getattr(*vpp, &va, cred); return (error);}/*ARGSUSED*/intnfs_close(vp, flag, cred) struct vnode *vp; int flag; struct ucred *cred;{#ifdef NFSDEBUG dprint(nfsdebug, 6, "nfs_close %s %x flag %d\n", vtomi(vp)->mi_hostname, vp, flag);#endif return(EACCES);}intnfs_rdwr(vp, uiop, rw, ioflag, cred) register struct vnode *vp; struct uio *uiop; enum uio_rw rw; int ioflag; struct ucred *cred;{ int error = 0; struct rnode *rp;#ifdef NFSDEBUG1 dprint(nfsdebug, 6, "nfs_rdwr: %s %x rw %s offset %x len %d\n", vtomi(vp)->mi_hostname, vp, rw == UIO_READ ? "READ" : "WRITE", uiop->uio_offset, uiop->uio_iov->iov_len);#endif if (vp->v_type != VREG) { return (EISDIR); } if (rw == UIO_WRITE || (rw == UIO_READ && vtor(vp)->r_cred == NULL)) { crhold(cred); if (vtor(vp)->r_cred) { crfree(vtor(vp)->r_cred); } vtor(vp)->r_cred = cred; } if ((ioflag & IO_APPEND) && rw == UIO_WRITE) { struct vattr va; rp = vtor(vp); rlock(rp); error = VOP_GETATTR(vp, &va, cred); if (!error) { uiop->uio_offset = rp->r_size; } } if (!error) { error = rwvp(vp, uiop, rw, cred); } if ((ioflag & IO_APPEND) && rw == UIO_WRITE) { runlock(rp); }#ifdef NFSDEBUG1 dprint(nfsdebug, 6, "nfs_rdwr returning %d\n", error);#endif /* NFSDEBUG */ return (error);}intrwvp(vp, uio, rw, cred) register struct vnode *vp; register struct uio *uio; enum uio_rw rw; struct ucred *cred;{ struct buf *bp; struct rnode *rp; daddr_t bn; register int n, on; int size; int error = 0; struct vnode *mapped_vp; daddr_t mapped_bn; int eof = 0;#ifdef NFSDEBUG1 dprint(nfsdebug, 6, "rwvp(vp 0x%x uio 0x%x rw 0x%x cred 0x%x)\n", vp, uio, rw, cred);#endif /* NFSDEBUG */ if (uio->uio_resid == 0) { return (0); } if (uio->uio_offset < 0 || (uio->uio_offset + uio->uio_resid) < 0) { return (EINVAL); }#ifdef notdef /* * Soooo, why wasn't this just removed */ if (rw == UIO_WRITE && vp->v_type == VREG && uio->uio_offset + uio->uio_resid > u.u_rlimit[RLIMIT_FSIZE].rlim_cur) { psignal(u.u_procp, SIGXFSZ); return (EFBIG); }#endif notdef rp = vtor(vp); /* * For now, ensure no cache. */ rp->r_flags |= RNOCACHE; size = vtoblksz(vp); size &= ~(DEV_BSIZE - 1); if (size <= 0) { panic("rwvp: zero size"); } do { bn = uio->uio_offset / size; on = uio->uio_offset % size; n = MIN((unsigned)(size - on), uio->uio_resid); VOP_BMAP(vp, bn, &mapped_vp, &mapped_bn); if (rp->r_flags & RNOCACHE) { bp = geteblk(size); if (rw == UIO_READ) { error = nfsread(vp, bp->b_un.b_addr+on, (int)uio->uio_offset, n, (int *)&bp->b_resid, cred); if (error) { brelse(bp); goto bad; } } } if (bp->b_flags & B_ERROR) { error = geterror(bp); brelse(bp); goto bad; } u.u_error = uiomove(bp->b_un.b_addr+on, n, rw, uio); if (rw == UIO_READ) { brelse(bp); } else { } } while (u.u_error == 0 && uio->uio_resid > 0 && !eof); if (error == 0) /* XXX */ error = u.u_error; /* XXX */ bad: return (error);}/* * Write to file. * Writes to remote server in largest size chunks that the server can * handle. Write is synchronous. *//*ARGSUSED*/nfswrite(vp, base, offset, count, cred) struct vnode *vp; caddr_t base; int offset; int count; struct ucred *cred;{ int error;#ifdef NFSDEBUG dprint(nfsdebug, 4, "nfswrite %s %x offset = %d, count = %d\n", vtomi(vp)->mi_hostname, vp, offset, count);#endif error = EACCES;#ifdef NFSDEBUG dprint(nfsdebug, 5, "nfswrite: returning %d\n", error);#endif return (error);}/* * Read from a file. * Reads data in largest chunks our interface can handle */nfsread(vp, base, offset, count, residp, cred) struct vnode *vp; caddr_t base; int offset; int count; int *residp; struct ucred *cred;{ int error; struct nfsreadargs ra; struct nfsrdresult rr; register int tsize;#ifdef NFSDEBUG1 dprint(nfsdebug, 4, "nfsread %s %x offset = %d, totcount = %d\n", vtomi(vp)->mi_hostname, vp, offset, count);#endif /* NFSDEBUG */ do { tsize = MIN(vtomi(vp)->mi_tsize, count); rr.rr_data = base; ra.ra_fhandle = *vtofh(vp); ra.ra_offset = offset; ra.ra_totcount = tsize; ra.ra_count = tsize; error = rfscall(vtomi(vp), RFS_READ, xdr_readargs, (caddr_t)&ra, xdr_rdresult, (caddr_t)&rr, cred); if (!error) { error = geterrno(rr.rr_status); check_stale_fh(error, vp); } if (!error) { count -= rr.rr_count; base += rr.rr_count; offset += rr.rr_count; } } while (!error && count && rr.rr_count == tsize); *residp = count; if (!error) { nfs_attrcache(vp, &rr.rr_attr); }#ifdef NFSDEBUG1 dprint(nfsdebug, 5, "nfsread: returning %d, resid %d\n", error, *residp);#endif return (error);}/*ARGSUSED*/intnfs_ioctl(vp, com, data, flag, cred) struct vnode *vp; int com; caddr_t data; int flag; struct ucred *cred;{ return (EOPNOTSUPP);}/*ARGSUSED*/intnfs_select(vp, which, cred) struct vnode *vp; int which; struct ucred *cred;{ return (EOPNOTSUPP);}/* * Timeout values for attributes for * regular files, and for directories. */int nfsac_regtimeo_min = 3;int nfsac_regtimeo_max = 60;int nfsac_dirtimeo_min = 30;int nfsac_dirtimeo_max = 60;/*ARGSUSED*/nfs_attrcache(vp, na) struct vnode *vp; struct nfsfattr *na;{#ifdef NFSDEBUG1 dprint(nfsdebug, 6, "nfs_attrcache(vp 0x%x na 0x%x)\n", vp, na);#endif /* NFSDEBUG */}intnfs_getattr(vp, vap, cred) struct vnode *vp; struct vattr *vap; struct ucred *cred;{ int error;#ifdef NFSDEBUG dprint(nfsdebug, 4, "nfs_getattr %s %x\n", vtomi(vp)->mi_hostname, vp);#endif sync_vp(vp); /* sync blocks so mod time is right */ error = nfsgetattr(vp, vap, cred);#ifdef NFSDEBUG dprint(nfsdebug, 5, "nfs_getattr: returns %d\n", error);#endif return (error);}intnfsgetattr(vp, vap, cred)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -