📄 nfs_vnops.c
字号:
* - make nfs_bmap() essentially a no-op that does no translation * - do nfs_strategy() by faking physical I/O with nfs_readrpc/nfs_writerpc * after mapping the physical addresses into Kernel Virtual space in the * nfsiobuf area. * (Maybe I could use the process's page mapping, but I was concerned that * Kernel Write might not be enabled and also figured copyout() would do * a lot more work than bcopy() and also it currently happens in the * context of the swapper process (2). */intnfs_bmap(ap) struct vop_bmap_args /* { struct vnode *a_vp; daddr_t a_bn; struct vnode **a_vpp; daddr_t *a_bnp; int *a_runp; } */ *ap;{ register struct vnode *vp = ap->a_vp; if (ap->a_vpp != NULL) *ap->a_vpp = vp; if (ap->a_bnp != NULL) *ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize); return (0);}/* * Strategy routine. * For async requests when nfsiod(s) are running, queue the request by * calling nfs_asyncio(), otherwise just all nfs_doio() to do the * request. */intnfs_strategy(ap) struct vop_strategy_args *ap;{ register struct buf *bp = ap->a_bp; struct ucred *cr; struct proc *p; int error = 0; if (bp->b_flags & B_PHYS) panic("nfs physio"); if (bp->b_flags & B_ASYNC) p = (struct proc *)0; else p = curproc; /* XXX */ if (bp->b_flags & B_READ) cr = bp->b_rcred; else cr = bp->b_wcred; /* * If the op is asynchronous and an i/o daemon is waiting * queue the request, wake it up and wait for completion * otherwise just do it ourselves. */ if ((bp->b_flags & B_ASYNC) == 0 || nfs_asyncio(bp, NOCRED)) error = nfs_doio(bp, cr, p); return (error);}/* * Mmap a file * * NB Currently unsupported. *//* ARGSUSED */intnfs_mmap(ap) struct vop_mmap_args /* { struct vnode *a_vp; int a_fflags; struct ucred *a_cred; struct proc *a_p; } */ *ap;{ return (EINVAL);}/* * Flush all the blocks associated with a vnode. * Walk through the buffer pool and push any dirty pages * associated with the vnode. *//* ARGSUSED */intnfs_fsync(ap) struct vop_fsync_args /* { struct vnodeop_desc *a_desc; struct vnode * a_vp; struct ucred * a_cred; int a_waitfor; struct proc * a_p; } */ *ap;{ register struct vnode *vp = ap->a_vp; register struct nfsnode *np = VTONFS(vp); register struct buf *bp; struct buf *nbp; struct nfsmount *nmp; int s, error = 0, slptimeo = 0, slpflag = 0; nmp = VFSTONFS(vp->v_mount); if (nmp->nm_flag & NFSMNT_INT) slpflag = PCATCH;loop: s = splbio(); for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { nbp = bp->b_vnbufs.le_next; if (bp->b_flags & B_BUSY) { if (ap->a_waitfor != MNT_WAIT) continue; bp->b_flags |= B_WANTED; error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1), "nfsfsync", slptimeo); splx(s); if (error) { if (nfs_sigintr(nmp, (struct nfsreq *)0, ap->a_p)) return (EINTR); if (slpflag == PCATCH) { slpflag = 0; slptimeo = 2 * hz; } } goto loop; } if ((bp->b_flags & B_DELWRI) == 0) panic("nfs_fsync: not dirty"); bremfree(bp); bp->b_flags |= B_BUSY; splx(s); bp->b_flags |= B_ASYNC; VOP_BWRITE(bp); goto loop; } splx(s); if (ap->a_waitfor == MNT_WAIT) { while (vp->v_numoutput) { vp->v_flag |= VBWAIT; error = tsleep((caddr_t)&vp->v_numoutput, slpflag | (PRIBIO + 1), "nfsfsync", slptimeo); if (error) { if (nfs_sigintr(nmp, (struct nfsreq *)0, ap->a_p)) return (EINTR); if (slpflag == PCATCH) { slpflag = 0; slptimeo = 2 * hz; } } } if (vp->v_dirtyblkhd.lh_first) {#ifdef DIAGNOSTIC vprint("nfs_fsync: dirty", vp);#endif goto loop; } } if (np->n_flag & NWRITEERR) { error = np->n_error; np->n_flag &= ~NWRITEERR; } return (error);}/* * Return POSIX pathconf information applicable to nfs. * * Currently the NFS protocol does not support getting such * information from the remote server. *//* ARGSUSED */nfs_pathconf(ap) struct vop_pathconf_args /* { struct vnode *a_vp; int a_name; int *a_retval; } */ *ap;{ return (EINVAL);}/* * NFS advisory byte-level locks. * Currently unsupported. */intnfs_advlock(ap) struct vop_advlock_args /* { struct vnode *a_vp; caddr_t a_id; int a_op; struct flock *a_fl; int a_flags; } */ *ap;{ return (EOPNOTSUPP);}/* * Print out the contents of an nfsnode. */intnfs_print(ap) struct vop_print_args /* { struct vnode *a_vp; } */ *ap;{ register struct vnode *vp = ap->a_vp; register struct nfsnode *np = VTONFS(vp); printf("tag VT_NFS, fileid %d fsid 0x%x", np->n_vattr.va_fileid, np->n_vattr.va_fsid);#ifdef FIFO if (vp->v_type == VFIFO) fifo_printinfo(vp);#endif /* FIFO */ printf("\n");}/* * NFS directory offset lookup. * Currently unsupported. */intnfs_blkatoff(ap) struct vop_blkatoff_args /* { struct vnode *a_vp; off_t a_offset; char **a_res; struct buf **a_bpp; } */ *ap;{ return (EOPNOTSUPP);}/* * NFS flat namespace allocation. * Currently unsupported. */intnfs_valloc(ap) struct vop_valloc_args /* { struct vnode *a_pvp; int a_mode; struct ucred *a_cred; struct vnode **a_vpp; } */ *ap;{ return (EOPNOTSUPP);}/* * NFS flat namespace free. * Currently unsupported. */intnfs_vfree(ap) struct vop_vfree_args /* { struct vnode *a_pvp; ino_t a_ino; int a_mode; } */ *ap;{ return (EOPNOTSUPP);}/* * NFS file truncation. */intnfs_truncate(ap) struct vop_truncate_args /* { struct vnode *a_vp; off_t a_length; int a_flags; struct ucred *a_cred; struct proc *a_p; } */ *ap;{ /* Use nfs_setattr */ printf("nfs_truncate: need to implement!!"); return (EOPNOTSUPP);}/* * NFS update. */intnfs_update(ap) struct vop_update_args /* { struct vnode *a_vp; struct timeval *a_ta; struct timeval *a_tm; int a_waitfor; } */ *ap;{ /* Use nfs_setattr */ printf("nfs_update: need to implement!!"); return (EOPNOTSUPP);}/* * nfs special file access vnode op. * Essentially just get vattr and then imitate iaccess() since the device is * local to the client. */intnfsspec_access(ap) struct vop_access_args /* { struct vnode *a_vp; int a_mode; struct ucred *a_cred; struct proc *a_p; } */ *ap;{ register struct vattr *vap; register gid_t *gp; register struct ucred *cred = ap->a_cred; mode_t mode = ap->a_mode; struct vattr vattr; register int i; int error; /* * If you're the super-user, * you always get access. */ if (cred->cr_uid == 0) return (0); vap = &vattr; if (error = VOP_GETATTR(ap->a_vp, vap, cred, ap->a_p)) return (error); /* * 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 != vap->va_uid) { mode >>= 3; gp = cred->cr_groups; for (i = 0; i < cred->cr_ngroups; i++, gp++) if (vap->va_gid == *gp) goto found; mode >>= 3;found: ; } return ((vap->va_mode & mode) == mode ? 0 : EACCES);}/* * Read wrapper for special devices. */intnfsspec_read(ap) struct vop_read_args /* { struct vnode *a_vp; struct uio *a_uio; int a_ioflag; struct ucred *a_cred; } */ *ap;{ register struct nfsnode *np = VTONFS(ap->a_vp); /* * Set access flag. */ np->n_flag |= NACC; np->n_atim = time; return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap));}/* * Write wrapper for special devices. */intnfsspec_write(ap) struct vop_write_args /* { struct vnode *a_vp; struct uio *a_uio; int a_ioflag; struct ucred *a_cred; } */ *ap;{ register struct nfsnode *np = VTONFS(ap->a_vp); /* * Set update flag. */ np->n_flag |= NUPD; np->n_mtim = time; return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap));}/* * Close wrapper for special devices. * * Update the times on the nfsnode then do device close. */intnfsspec_close(ap) struct vop_close_args /* { struct vnode *a_vp; int a_fflag; struct ucred *a_cred; struct proc *a_p; } */ *ap;{ register struct vnode *vp = ap->a_vp; register struct nfsnode *np = VTONFS(vp); struct vattr vattr; if (np->n_flag & (NACC | NUPD)) { np->n_flag |= NCHG; if (vp->v_usecount == 1 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { VATTR_NULL(&vattr); if (np->n_flag & NACC) { vattr.va_atime.ts_sec = np->n_atim.tv_sec; vattr.va_atime.ts_nsec = np->n_atim.tv_usec * 1000; } if (np->n_flag & NUPD) { vattr.va_mtime.ts_sec = np->n_mtim.tv_sec; vattr.va_mtime.ts_nsec = np->n_mtim.tv_usec * 1000; } (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); } } return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap));}#ifdef FIFO/* * Read wrapper for fifos. */intnfsfifo_read(ap) struct vop_read_args /* { struct vnode *a_vp; struct uio *a_uio; int a_ioflag; struct ucred *a_cred; } */ *ap;{ extern int (**fifo_vnodeop_p)(); register struct nfsnode *np = VTONFS(ap->a_vp); /* * Set access flag. */ np->n_flag |= NACC; np->n_atim = time; return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap));}/* * Write wrapper for fifos. */intnfsfifo_write(ap) struct vop_write_args /* { struct vnode *a_vp; struct uio *a_uio; int a_ioflag; struct ucred *a_cred; } */ *ap;{ extern int (**fifo_vnodeop_p)(); register struct nfsnode *np = VTONFS(ap->a_vp); /* * Set update flag. */ np->n_flag |= NUPD; np->n_mtim = time; return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap));}/* * Close wrapper for fifos. * * Update the times on the nfsnode then do fifo close. */intnfsfifo_close(ap) struct vop_close_args /* { struct vnode *a_vp; int a_fflag;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -