📄 nfs_server.c
字号:
* is always allowed to read it. */ if (u.u_uid != vp->g_uid) { error = VOP_ACCESS(vp, VREAD, u.u_cred); if (error) { /* * Exec is the same as read over the net because * of demand loading. */ error = VOP_ACCESS(vp, VEXEC, u.u_cred); } if (error) { goto bad; } } /* * Check whether we can do this with bread, which would * save the copy through the uio. */ fsbsize = ((struct gnode *)vp)->g_mp->m_fs_data->fd_otsize; offset = ra->ra_offset % fsbsize; /* * Don't call VOP_BREAD unless UFS file system. * VOP_BREAD is tailored to UFS. */ if ((((struct gnode *)vp)->g_mp->m_fstype == GT_ULTRIX) && (offset + ra->ra_count <= fsbsize) && (offset % 4 == 0)) { if (ra->ra_offset >= vp->g_size) { rr->rr_count = 0; gattr_to_nattr(vp, &rr->rr_attr); rr->rr_attr.na_blocksize = fsbsize; error = 0; goto done; } error = VOP_BREAD(vp, ra->ra_offset / fsbsize, &bp); if (error == 0) { rr->rr_data = bp->b_un.b_addr + offset; rr->rr_count = min( (u_int)(vp->g_size - ra->ra_offset), (u_int)ra->ra_count); rr->rr_bp = bp; rr->rr_vp = vp; gref(vp); gattr_to_nattr(vp, &rr->rr_attr); rr->rr_attr.na_blocksize = fsbsize; goto done; } else { printf("nfs read: failed, errno %d\n", error); } } rr->rr_bp = (struct buf *) 0; /* * Allocate space for data. This will be freed by xdr_rdresult * when it is called with x_op = XDR_FREE. */ kmem_alloc(rr->rr_data, char *, ra->ra_count, KM_NFS); rr->rr_bufallocaddr = rr->rr_data; rr->rr_bufallocsize = ra->ra_count; /* * Set up io vector */ iov.iov_base = rr->rr_data; iov.iov_len = ra->ra_count; uio.uio_iov = &iov; uio.uio_iovcnt = 1; uio.uio_segflg = UIO_SYSSPACE; uio.uio_offset = ra->ra_offset; uio.uio_resid = ra->ra_count; /* * for now we assume no append mode and ignore * totcount (read ahead) */ error = VOP_RDWR(vp, &uio, UIO_READ, IO_SYNC, u.u_cred); if (error) { goto bad; } gattr_to_nattr(vp, &rr->rr_attr); rr->rr_attr.na_blocksize = fsbsize; rr->rr_count = ra->ra_count - uio.uio_resid;bad: if (error && rr->rr_data != NULL) { kmem_free(rr->rr_bufallocaddr, KM_NFS); rr->rr_data = NULL; rr->rr_count = 0; }done: rr->rr_status = puterrno(error); gput(vp); return(0);}/* * Free data allocated by rfs_read. */rfs_rdfree(rr) struct nfsrdresult *rr;{ if (rr->rr_bp == 0 && rr->rr_data) { kmem_free(rr->rr_bufallocaddr, KM_NFS); }}/* * Write data to file. * Returns attributes of a file after writing some data to it. */intrfs_write(wa, ns, req, xprt, xpd) struct nfswriteargs *wa; struct nfsattrstat *ns; struct svc_req *req; SVCXPRT *xprt; struct exportdata *xpd;{ register int error = 0; register struct vnode *vp; struct vattr va; struct iovec iov; struct uio uio; struct timeval duptime; int dupmark; vp = fhtovp(&wa->wa_fhandle, xprt, RFS_WRITE, xpd); if (vp == NULL) { ns->ns_status = NFSERR_STALE; return(ESTALE); } if (rdonly(vp, xpd)) { error = EROFS; } else { if (svckudp_dup(req, &duptime, &dupmark) && duptime.tv_sec == vp->g_mtime.tv_sec && duptime.tv_usec == vp->g_mtime.tv_usec) { ++nfs_dupstats.writes; } else { if (u.u_uid != vp->g_uid) { /* * This is a kludge to allow writes of * files created with read only permission. * The owner of the file * is always allowed to write it. */ error = VOP_ACCESS(vp, VWRITE, u.u_cred); } if (!error) { iov.iov_base = wa->wa_data; iov.iov_len = wa->wa_count; uio.uio_iov = &iov; uio.uio_iovcnt = 1; uio.uio_segflg = UIO_SYSSPACE; uio.uio_offset = wa->wa_offset; uio.uio_resid = wa->wa_count; /* * for now we assume no append mode */ error = VOP_RDWR(vp, &uio, UIO_WRITE, IO_SYNC, u.u_cred); } } if (!error) { /* * Get attributes again so we send the latest mod * time to the client side for his cache. */ error = VOP_GETATTR(vp, &va, u.u_cred); } if (error) { svckudp_dupsave(req, *timepick, DUP_FAIL); } else { vattr_to_nattr(&va, &ns->ns_attr); svckudp_dupsave(req, vp->g_mtime, DUP_DONE); } } ns->ns_status = puterrno(error); gput(vp); return(0);}/* * Create a file. * Creates a file with given attributes and returns those attributes * and an fhandle for the new file. */intrfs_create(args, dr, req, xprt, xpd) struct nfscreatargs *args; struct nfsdiropres *dr; struct svc_req *req; SVCXPRT *xprt; struct exportdata *xpd;{ register int error = 0; struct vattr va; struct vnode *vp; register struct vnode *dvp; struct timeval duptime; int dupmark; sattr_to_vattr(&args->ca_sa, &va); /* * This is a completely gross hack to make mknod * work over the wire until we can wack the protocol */#define IFMT 0170000 /* type of file */#define IFCHR 0020000 /* character special */#define IFBLK 0060000 /* block special */#define IFSOCK 0140000 /* socket */ if ((va.va_mode & IFMT) == IFCHR) { va.va_type = VCHR; if (va.va_size == (u_long)NFS_FIFO_DEV) { va.va_type = VFIFO; /* xtra kludge for namedpipe */ va.va_mode = (va.va_mode & ~GFMT) | GFPORT; } else va.va_rdev = (dev_t)va.va_size; va.va_size = 0; } else if ((va.va_mode & IFMT) == IFBLK) { va.va_type = VBLK; va.va_rdev = (dev_t)va.va_size; va.va_size = 0; } else if ((va.va_mode & IFMT) == IFSOCK) { va.va_type = VSOCK; } else { va.va_type = VREG; va.va_mode = (va.va_mode & ~GFMT) | GFREG; } /* * XXX Should get exclusive flag and use it. */ dvp = fhtovp(&args->ca_da.da_fhandle, xprt, RFS_CREATE, xpd); if (dvp == NULL) { dr->dr_status = NFSERR_STALE; return(ESTALE); } if (rdonly(dvp, xpd)) { gfs_unlock(dvp); error = EROFS; } else { if (svckudp_dup(req, &duptime, &dupmark) && duptime.tv_sec == dvp->g_ctime.tv_sec && duptime.tv_usec == dvp->g_ctime.tv_usec) { ++nfs_dupstats.creates; error = VOP_LOOKUP(dvp, args->ca_da.da_name, &vp, u.u_cred); if (!error) { gfs_lock(vp); } gfs_unlock(dvp); } else { error = VOP_CREATE(dvp, args->ca_da.da_name, &va, NONEXCL, VWRITE, &vp, u.u_cred); } if (!error) { error = VOP_GETATTR(vp, &va, u.u_cred); if (!error) { vattr_to_nattr(&va, &dr->dr_attr); error = makefh(&dr->dr_fhandle, vp, args->ca_da.da_fhandle.fh_eno, args->ca_da.da_fhandle.fh_egen); } gput(vp); } if (error) { svckudp_dupsave(req, *timepick, DUP_FAIL); } else { svckudp_dupsave(req, dvp->g_ctime, DUP_DONE); } } dr->dr_status = puterrno(error); grele(dvp); return(0);}/* * Remove a file. * Remove named file from parent directory. */intrfs_remove(da, status, req, xprt, xpd) struct nfsdiropargs *da; enum nfsstat *status; struct svc_req *req; SVCXPRT *xprt; struct exportdata *xpd;{ register int error = 0; register struct vnode *vp; struct timeval duptime; int dupmark; vp = fhtovp(&da->da_fhandle, xprt, RFS_REMOVE, xpd); if (vp == NULL) { *status = NFSERR_STALE; return(ESTALE); } if (rdonly(vp, xpd)) { gfs_unlock(vp); error = EROFS; } else { if (svckudp_dup(req, &duptime, &dupmark) && duptime.tv_sec == vp->g_ctime.tv_sec && duptime.tv_usec == vp->g_ctime.tv_usec) { ++nfs_dupstats.removes; gfs_unlock(vp); } else error = VOP_REMOVE(vp, da->da_name, u.u_cred); if (error) { svckudp_dupsave(req, *timepick, DUP_FAIL); } else { svckudp_dupsave(req, vp->g_ctime, DUP_DONE); } } *status = puterrno(error); grele(vp); return(0);}/* * rename a file * Give a file (from) a new name (to). */intrfs_rename(args, status, req, xprt, xpd) struct nfsrnmargs *args; enum nfsstat *status; struct svc_req *req; SVCXPRT *xprt; struct exportdata *xpd;{ register int error = 0; register struct vnode *fromvp; register struct vnode *tovp; struct timeval duptime; int dupmark; fromvp = fhtovp(&args->rna_from.da_fhandle, xprt, RFS_RENAME, xpd); if (fromvp == NULL) { *status = NFSERR_STALE; return(ESTALE); } if (rdonly(fromvp, xpd)) { error = EROFS; gfs_unlock(fromvp); goto fromerr; } if ((args->rna_from.da_fhandle.fh_fsid == args->rna_to.da_fhandle.fh_fsid) && (args->rna_from.da_fhandle.fh_fno == args->rna_to.da_fhandle.fh_fno) && (args->rna_from.da_fhandle.fh_fgen == args->rna_to.da_fhandle.fh_fgen)) tovp=fromvp; else tovp = fhtovp(&args->rna_to.da_fhandle, xprt, RFS_RENAME, xpd); if (tovp == NULL) { *status = NFSERR_STALE; gput(fromvp); return(ESTALE); } if (rdonly(tovp, xpd)) { gfs_unlock(fromvp); gfs_unlock(tovp); error = EROFS; } else { if (svckudp_dup(req, &duptime, &dupmark) && duptime.tv_sec == fromvp->g_ctime.tv_sec && duptime.tv_usec == fromvp->g_ctime.tv_usec) { ++nfs_dupstats.renames; if (tovp != fromvp) gfs_unlock(tovp); gfs_unlock(fromvp); } else error = VOP_RENAME(fromvp, args->rna_from.da_name, tovp, args->rna_to.da_name, u.u_cred); if (error) { svckudp_dupsave(req, *timepick, DUP_FAIL); } else { svckudp_dupsave(req, fromvp->g_ctime, DUP_DONE); } } if (tovp != fromvp) grele(tovp);fromerr: grele(fromvp); *status = puterrno(error); return(0);} /* * Link to a file. * Create a file (to) which is a hard link to the given file (from). */intrfs_link(args, status, req, xprt, xpd) struct nfslinkargs *args; enum nfsstat *status; struct svc_req *req; SVCXPRT *xprt; struct exportdata *xpd;{ register int error = 0; register struct vnode *fromvp; register struct vnode *tovp; struct timeval duptime, savectime; int dupmark; tovp = fhtovp(&args->la_to.da_fhandle, xprt, RFS_LINK, xpd); if (tovp == NULL) { *status = NFSERR_STALE; return(ESTALE); } gfs_unlock(tovp); fromvp = fhtovp(&args->la_from, xprt, RFS_LINK, xpd); if (fromvp == NULL) { grele(tovp); *status = NFSERR_STALE; return(ESTALE); } if (rdonly(tovp, xpd)) { gput(fromvp); grele(tovp); error = EROFS; } else { if (svckudp_dup(req, &duptime, &dupmark) && duptime.tv_sec == fromvp->g_ctime.tv_sec && duptime.tv_usec == fromvp->g_ctime.tv_usec) { ++nfs_dupstats.links; savectime = fromvp->g_ctime; gput(fromvp); grele(tovp); } else error = vop_link(fromvp, tovp, args->la_to.da_name, &savectime, u.u_cred); if (error) { svckudp_dupsave(req, *timepick, DUP_FAIL); } else { svckudp_dupsave(req, savectime, DUP_DONE); } } *status = puterrno(error); return(0);} /* * Symbolicly link to a file. * Create a file (to) with the given attributes which is a symbolic link * to the given path name (to). */intrfs_symlink(args, status, req, xprt, xpd) struct nfsslargs *args; enum nfsstat *status; struct svc_req *req; SVCXPRT *xprt; struct exportdata *xpd;{ register int error = 0; struct vattr va; register struct vnode *vp; struct timeval duptime; int dupmark; sattr_to_vattr(&args->sla_sa, &va); va.va_type = VLNK; vp = fhtovp(&args->sla_from.da_fhandle, xprt, RFS_SYMLINK, xpd); if (vp == NULL) { *status = NFSERR_STALE; return(ESTALE); } if (rdonly(vp, xpd)) { gfs_unlock(vp); error = EROFS; } else { if (svckudp_dup(req, &duptime, &dupmark) && duptime.tv_sec == vp->g_ctime.tv_sec && duptime.tv_usec == vp->g_ctime.tv_usec) { ++nfs_dupstats.symlinks; gfs_unlock(vp); } else error = VOP_SYMLINK(vp, args->sla_from.da_name, &va, args->sla_tnm, u.u_cred); if (error) { svckudp_dupsave(req, *timepick, DUP_FAIL); } else { svckudp_dupsave(req, vp->g_ctime, DUP_DONE); } } *status = puterrno(error); grele(vp); return(0);} /* * Make a directory. * Create a directory with the given name, parent directory, and attributes. * Returns a file handle and attributes for the new directory. */intrfs_mkdir(args, dr, req, xprt, xpd) struct nfscreatargs *args; struct nfsdiropres *dr; struct svc_req *req; SVCXPRT *xprt; struct exportdata *xpd;{ register int error = 0; struct vattr va; struct vnode *dvp; register struct vnode *vp; struct timeval duptime; int dupmark; sattr_to_vattr(&args->ca_sa, &va); va.va_type = VDIR; /* * Should get exclusive flag and pass it on here */ vp = fhtovp(&args->ca_da.da_fhandle, xprt, RFS_MKDIR, xpd); if (vp == NULL) { dr->dr_status = NFSERR_STALE; return(ESTALE); } if (rdonly(vp, xpd)) { gfs_unlock(vp); error = EROFS; } else { if (svckudp_dup(req, &duptime, &dupmark) && duptime.tv_sec == vp->g_ctime.tv_sec && duptime.tv_usec == vp->g_ctime.tv_usec) { ++nfs_dupstats.mkdirs; error = VOP_LOOKUP(vp, args->ca_da.da_name, &dvp, u.u_cred); if (!error) { error = VOP_GETATTR(dvp, &va, u.u_cred); } gfs_unlock(vp); } else { error = VOP_MKDIR(vp, args->ca_da.da_name, &va, &dvp, u.u_cred); } if (!error) { vattr_to_nattr(&va, &dr->dr_attr); gfs_lock(dvp); error = makefh(&dr->dr_fhandle, dvp, args->ca_da.da_fhandle.fh_eno, args->ca_da.da_fhandle.fh_egen); gput(dvp); } if (error) { svckudp_dupsave(req, *timepick, DUP_FAIL); } else { svckudp_dupsave(req, vp->g_ctime, DUP_DONE); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -