📄 nfs_vnodeops.c
字号:
struct vnode *vp; struct vattr *vap; struct ucred *cred;{ int error = 0; struct nfsattrstat *ns; struct rnode *rp;#ifdef NFSDEBUG dprint(nfsdebug, 6, "nfsgetattr(vp 0x%x vap 0x%x cred 0x%x)\n", vp, vap, cred);#endif /* NFSDEBUG */ rp = vtor(vp); if (timercmp(&time, &rp->r_attrtime, <)) { /* * Use cached attributes. */ rp = vtor(vp); nattr_to_vattr(&rp->r_attr, vap); vap->va_fsid = 0xff00 | vtomi(vp)->mi_mntno; if (rp->r_size < vap->va_size || ((rp->r_flags & RDIRTY) == 0)){ rp->r_size = vap->va_size; } else if (vap->va_size < rp->r_size && (rp->r_flags & RDIRTY)){ vap->va_size = rp->r_size; } } else { ns = (struct nfsattrstat *)kmem_alloc((u_int)sizeof(*ns)); error = rfscall(vtomi(vp), RFS_GETATTR, xdr_fhandle, (caddr_t)vtofh(vp), xdr_attrstat, (caddr_t)ns, cred); if (!error) { error = geterrno(ns->ns_status); if (!error) { nattr_to_vattr(&ns->ns_attr, vap); /* * this is a kludge to make programs that use * dev from stat to tell file systems apart * happy. we kludge up a dev from the mount * number and an arbitrary major number 255. */ vap->va_fsid = 0xff00 | vtomi(vp)->mi_mntno; if (rp->r_size < vap->va_size || ((rp->r_flags & RDIRTY) == 0)){ rp->r_size = vap->va_size; } else if ((vap->va_size < rp->r_size) && (rp->r_flags & RDIRTY)) { vap->va_size = rp->r_size; } nfs_attrcache(vp, &ns->ns_attr); } else { check_stale_fh(error, vp); } } kmem_free((caddr_t)ns, (u_int)sizeof(*ns)); }#ifdef NFSDEBUG dprint(nfsdebug, 6, "nfsgetattr: returning 0x%x\n", error);#endif /* NFSDEBUG */ return (error);}/*ARGSUSED*/intnfs_access(vp, mode, cred) struct vnode *vp; int mode; struct ucred *cred;{ struct vattr va;#ifdef NEVER int *gp;#endif NEVER#ifdef NFSDEBUG dprint(nfsdebug, 4, "nfs_access %s %x mode %d uid %d\n", vtomi(vp)->mi_hostname, vp, mode, cred->cr_uid);#endif u.u_error = nfsgetattr(vp, &va, cred); if (u.u_error) { return (u.u_error); } /* * If you're the super-user, * you always get access. */ if (cred->cr_uid == 0) return (0);#ifdef NEVER /* * Access check is based on only * one of owner, group, public. * If not owner, then check group. * If not a member of the group, then * check public access. */ if (cred->cr_uid != va.va_uid) { mode >>= 3; if (cred->cr_gid == va.va_gid) goto found; gp = cred->cr_groups; for (; gp < &cred->cr_groups[NGROUPS] && *gp != NOGROUP; gp++) if (va.va_gid == *gp) goto found; mode >>= 3; }found:#endif /* NEVER */ if ((va.va_mode & mode) == mode) {#ifdef NFSDEBUG dprint(nfsdebug, 5, "nfs_access: OK\n");#endif /* NFSDEBUG */ return (0); }#ifdef NFSDEBUG dprint(nfsdebug, 5, "nfs_access: returning %d\n", u.u_error);#endif /* NFSDEBUG */ u.u_error = EACCES; return (EACCES);}intnfs_readlink(vp, uiop, cred) struct vnode *vp; struct uio *uiop; struct ucred *cred;{ int error; struct nfsrdlnres rl;#ifdef NFSDEBUG dprint(nfsdebug, 6, "nfs_readlink %s %x\n", vtomi(vp)->mi_hostname, vp);#endif if(vp->v_type != VLNK) return (ENXIO); rl.rl_data = (char *)kmem_alloc((u_int)NFS_MAXPATHLEN); error = rfscall(vtomi(vp), RFS_READLINK, xdr_fhandle, (caddr_t)vtofh(vp), xdr_rdlnres, (caddr_t)&rl, cred); if (!error) { error = geterrno(rl.rl_status); if (!error) { error = uiomove(rl.rl_data, (int)rl.rl_count, UIO_READ, uiop); } else { check_stale_fh(error, vp); } } kmem_free((caddr_t)rl.rl_data, (u_int)NFS_MAXPATHLEN);#ifdef NFSDEBUG dprint(nfsdebug, 6, "nfs_readlink: returning %d\n", error);#endif return (error);}/*ARGSUSED*/staticsync_vp(vp) struct vnode *vp;{}/* * Weirdness: if the file was removed while it was open it got * renamed (by nfs_remove) instead. Here we remove the renamed * file. *//*ARGSUSED*/intnfs_inactive(vp, cred) struct vnode *vp; struct ucred *cred;{ int error; struct nfsdiropargs da; enum nfsstat status; register struct rnode *rp;#ifdef NFSDEBUG dprint(nfsdebug, 4, "nfs_inactive '%s' 0x%x\n", vtomi(vp)->mi_hostname, vp);#endif rp = vtor(vp); /* * Pull rnode off of the hash list so it won't be found */ runsave(rp); if (rp->r_unldvp != NULL) { rlock(vtor(rp->r_unldvp)); setdiropargs(&da, rp->r_unlname, rp->r_unldvp); error = rfscall( vtomi(rp->r_unldvp), RFS_REMOVE, xdr_diropargs, (caddr_t)&da, xdr_enum, (caddr_t)&status, rp->r_unlcred); if (!error) { error = geterrno(status); } runlock(vtor(rp->r_unldvp)); VN_RELE(rp->r_unldvp); rp->r_unldvp = NULL; kmem_free((caddr_t)rp->r_unlname, (u_int)NFS_MAXNAMLEN); rp->r_unlname = NULL; crfree(rp->r_unlcred); rp->r_unlcred = NULL; } ((struct mntinfo *)vp->v_vfsp->vfs_data)->mi_refct--; if (rp->r_cred) { crfree(rp->r_cred); rp->r_cred = NULL; } rfree(rp);#ifdef NFSDEBUG dprint(nfsdebug, 5, "nfs_inactive done\n");#endif return (0);}int nfs_dnlc = 1; /* use dnlc *//* * Remote file system operations having to do with directory manipulation. */nfs_lookup(dvp, nm, vpp, cred) struct vnode *dvp; char *nm; struct vnode **vpp; struct ucred *cred;{ int error; struct nfsdiropargs da; struct nfsdiropres *dr; struct vattr va;#ifdef NFSDEBUG dprint(nfsdebug, 4, "nfs_lookup %s %x '%s'\n", vtomi(dvp)->mi_hostname, dvp, nm);#endif /* * Before checking dnlc, call getattr to be * sure directory hasn't changed. getattr * will purge dnlc if a change has occurred. */ if (error = nfs_getattr(dvp, &va, cred)) { return (error); } rlock(vtor(dvp)); *vpp = (struct vnode *)0; if (*vpp) { VN_HOLD(*vpp); } else { dr = (struct nfsdiropres *)kmem_alloc((u_int)sizeof(*dr)); setdiropargs(&da, nm, dvp); error = rfscall(vtomi(dvp), RFS_LOOKUP, xdr_diropargs, (caddr_t)&da, xdr_diropres, (caddr_t)dr, cred); if (!error) { error = geterrno(dr->dr_status); check_stale_fh(error, dvp); } if (!error) { *vpp = makenfsnode(&dr->dr_fhandle, &dr->dr_attr, dvp->v_vfsp); } else { *vpp = (struct vnode *)0; } kmem_free((caddr_t)dr, (u_int)sizeof(*dr)); } runlock(vtor(dvp));#ifdef NFSDEBUG dprint(nfsdebug, 5, "nfs_lookup returning %d vp = %x\n", error, *vpp);#endif return (error);}/* * Read directory entries. * There are some weird things to look out for here. The uio_offset * field is either 0 or it is the offset returned from a previous * readdir. It is an opaque value used by the server to find the * correct directory block to read. The byte count must be at least * vtoblksz(vp) bytes. The count field is the number of blocks to * read on the server. This is advisory only, the server may return * only one block's worth of entries. Entries may be compressed on * the server. */nfs_readdir(vp, uiop, cred) struct vnode *vp; register struct uio *uiop; struct ucred *cred;{ int error = 0; struct iovec *iovp; unsigned count; struct nfsrddirargs rda; struct nfsrddirres rd; struct rnode *rp;#ifdef NFSDEBUG dprint(nfsdebug, 6, "nfs_readdir(vp 0x%x uiop 0x%x cred 0x%x)\n", vp, uiop, cred);#endif rp = vtor(vp); if ((rp->r_flags & REOF) && (rp->r_size == (u_long)uiop->uio_offset)) { return (0); } iovp = uiop->uio_iov; count = iovp->iov_len;#ifdef NFSDEBUG dprint(nfsdebug, 6, "nfs_readdir %s %x count %d offset %d\n", vtomi(vp)->mi_hostname, vp, count, uiop->uio_offset);#endif /* * XXX We should do some kind of test for count >= DEV_BSIZE */ if (uiop->uio_iovcnt != 1) { return (EINVAL); } count = MIN(count, vtomi(vp)->mi_tsize); rda.rda_count = count; rda.rda_offset = uiop->uio_offset; rda.rda_fh = *vtofh(vp); rd.rd_size = count; rd.rd_entries = (struct direct *)kmem_alloc((u_int)count); error = rfscall(vtomi(vp), RFS_READDIR, xdr_rddirargs, (caddr_t)&rda, xdr_getrddirres, (caddr_t)&rd, cred); if (!error) { error = geterrno(rd.rd_status); check_stale_fh(error, vp); } if (!error) { /* * move dir entries to user land */ if (rd.rd_size) { error = uiomove((caddr_t)rd.rd_entries, (int)rd.rd_size, UIO_READ, uiop); rda.rda_offset = rd.rd_offset; uiop->uio_offset = rd.rd_offset; } if (rd.rd_eof) { rp->r_flags |= REOF; rp->r_size = uiop->uio_offset; } } kmem_free((caddr_t)rd.rd_entries, (u_int)count);#ifdef NFSDEBUG dprint(nfsdebug, 6, "nfs_readdir: returning %d resid %d, offset %d\n", error, uiop->uio_resid, uiop->uio_offset);#endif return (error);}/* * Convert from file system blocks to device blocks */intnfs_bmap(vp, bn, vpp, bnp) struct vnode *vp; /* file's vnode */ daddr_t bn; /* fs block number */ struct vnode **vpp; /* RETURN vp of device */ daddr_t *bnp; /* RETURN device block number */{ int bsize; /* server's block size in bytes */#ifdef NFSDEBUG1 dprint(nfsdebug, 4, "nfs_bmap %s %x blk %d vpp 0x%x\n", vtomi(vp)->mi_hostname, vp, bn, vpp);#endif /* NFSDEBUG */ if (vpp) *vpp = vp; if (bnp) { bsize = vtoblksz(vp); *bnp = bn * (bsize / DEV_BSIZE); } return (0);}struct buf *async_bufhead;int async_daemon_count;intnfs_strategy(bp) register struct buf *bp;{#ifdef NFSDEBUG dprint(nfsdebug, 4, "nfs_strategy bp %x\n", bp);#endif}async_daemon(){}do_bio(bp) register struct buf *bp;{#ifdef NFSDEBUG dprint(nfsdebug, 4, "do_bio: addr %x, blk %d, offset %d, size %d, B_READ %d\n", bp->b_un.b_addr, bp->b_blkno, bp->b_blkno * DEV_BSIZE, bp->b_bcount, bp->b_flags & B_READ);#endif}intnfs_badop(){#ifdef notdef panic("nfs_badop");#endif return (0);}intnfs_noop(){ return (EREMOTE);}dnlc_purge_vp(vp) register struct vnode *vp;{#ifdef NFSDEBUG dprint(nfsdebug, 6, "dnlc_purge_vp(vp 0x%x)\n", vp);#endif /* NFSDEBUG */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -