Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/nfsclient/nfs_clvnops.c
Show First 20 Lines • Show All 657 Lines • ▼ Show 20 Lines | if (error == EINTR || error == EIO) { | ||||
return (error); | return (error); | ||||
} | } | ||||
NFSLOCKNODE(np); | NFSLOCKNODE(np); | ||||
np->n_attrstamp = 0; | np->n_attrstamp = 0; | ||||
KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); | KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); | ||||
if (vp->v_type == VDIR) | if (vp->v_type == VDIR) | ||||
np->n_direofoffset = 0; | np->n_direofoffset = 0; | ||||
NFSUNLOCKNODE(np); | NFSUNLOCKNODE(np); | ||||
error = VOP_GETATTR(vp, &vattr, ap->a_cred); | error = VOP_GETATTR(vp, 0, &vattr, ap->a_cred); | ||||
if (error) { | if (error) { | ||||
if (NFS_ISV4(vp)) | if (NFS_ISV4(vp)) | ||||
(void) nfsrpc_close(vp, 0, ap->a_td); | (void) nfsrpc_close(vp, 0, ap->a_td); | ||||
return (error); | return (error); | ||||
} | } | ||||
NFSLOCKNODE(np); | NFSLOCKNODE(np); | ||||
np->n_mtime = vattr.va_mtime; | np->n_mtime = vattr.va_mtime; | ||||
if (NFS_ISV4(vp)) | if (NFS_ISV4(vp)) | ||||
np->n_change = vattr.va_filerev; | np->n_change = vattr.va_filerev; | ||||
} else { | } else { | ||||
NFSUNLOCKNODE(np); | NFSUNLOCKNODE(np); | ||||
error = VOP_GETATTR(vp, &vattr, ap->a_cred); | error = VOP_GETATTR(vp, 0, &vattr, ap->a_cred); | ||||
if (error) { | if (error) { | ||||
if (NFS_ISV4(vp)) | if (NFS_ISV4(vp)) | ||||
(void) nfsrpc_close(vp, 0, ap->a_td); | (void) nfsrpc_close(vp, 0, ap->a_td); | ||||
return (error); | return (error); | ||||
} | } | ||||
NFSLOCKNODE(np); | NFSLOCKNODE(np); | ||||
if ((NFS_ISV4(vp) && np->n_change != vattr.va_filerev) || | if ((NFS_ISV4(vp) && np->n_change != vattr.va_filerev) || | ||||
NFS_TIMESPEC_COMPARE(&np->n_mtime, &vattr.va_mtime)) { | NFS_TIMESPEC_COMPARE(&np->n_mtime, &vattr.va_mtime)) { | ||||
▲ Show 20 Lines • Show All 584 Lines • ▼ Show 20 Lines | if (!(nmp->nm_flag & NFSMNT_NOCTO) && | ||||
!(newnp->n_flag & NMODIFIED)) { | !(newnp->n_flag & NMODIFIED)) { | ||||
NFSLOCKNODE(newnp); | NFSLOCKNODE(newnp); | ||||
newnp->n_attrstamp = 0; | newnp->n_attrstamp = 0; | ||||
KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(newvp); | KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(newvp); | ||||
NFSUNLOCKNODE(newnp); | NFSUNLOCKNODE(newnp); | ||||
} | } | ||||
if (nfscl_nodeleg(newvp, 0) == 0 || | if (nfscl_nodeleg(newvp, 0) == 0 || | ||||
((u_int)(ticks - ncticks) < (nmp->nm_nametimeo * hz) && | ((u_int)(ticks - ncticks) < (nmp->nm_nametimeo * hz) && | ||||
VOP_GETATTR(newvp, &vattr, cnp->cn_cred) == 0 && | VOP_GETATTR(newvp, 0, &vattr, cnp->cn_cred) == 0 && | ||||
timespeccmp(&vattr.va_ctime, &nctime, ==))) { | timespeccmp(&vattr.va_ctime, &nctime, ==))) { | ||||
NFSINCRGLOBAL(nfsstatsv1.lookupcache_hits); | NFSINCRGLOBAL(nfsstatsv1.lookupcache_hits); | ||||
return (0); | return (0); | ||||
} | } | ||||
cache_purge(newvp); | cache_purge(newvp); | ||||
if (dvp != newvp) | if (dvp != newvp) | ||||
vput(newvp); | vput(newvp); | ||||
else | else | ||||
vrele(newvp); | vrele(newvp); | ||||
*vpp = NULLVP; | *vpp = NULLVP; | ||||
} else if (error == ENOENT) { | } else if (error == ENOENT) { | ||||
if (VN_IS_DOOMED(dvp)) | if (VN_IS_DOOMED(dvp)) | ||||
return (ENOENT); | return (ENOENT); | ||||
/* | /* | ||||
* We only accept a negative hit in the cache if the | * We only accept a negative hit in the cache if the | ||||
* modification time of the parent directory matches | * modification time of the parent directory matches | ||||
* the cached copy in the name cache entry. | * the cached copy in the name cache entry. | ||||
* Otherwise, we discard all of the negative cache | * Otherwise, we discard all of the negative cache | ||||
* entries for this directory. We also only trust | * entries for this directory. We also only trust | ||||
* negative cache entries for up to nm_negnametimeo | * negative cache entries for up to nm_negnametimeo | ||||
* seconds. | * seconds. | ||||
*/ | */ | ||||
if ((u_int)(ticks - ncticks) < (nmp->nm_negnametimeo * hz) && | if ((u_int)(ticks - ncticks) < (nmp->nm_negnametimeo * hz) && | ||||
VOP_GETATTR(dvp, &vattr, cnp->cn_cred) == 0 && | VOP_GETATTR(dvp, 0, &vattr, cnp->cn_cred) == 0 && | ||||
timespeccmp(&vattr.va_mtime, &nctime, ==)) { | timespeccmp(&vattr.va_mtime, &nctime, ==)) { | ||||
NFSINCRGLOBAL(nfsstatsv1.lookupcache_hits); | NFSINCRGLOBAL(nfsstatsv1.lookupcache_hits); | ||||
return (ENOENT); | return (ENOENT); | ||||
} | } | ||||
cache_purge_negative(dvp); | cache_purge_negative(dvp); | ||||
} | } | ||||
openmode = 0; | openmode = 0; | ||||
▲ Show 20 Lines • Show All 336 Lines • ▼ Show 20 Lines | nfs_mknodrpc(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, | ||||
u_int32_t rdev; | u_int32_t rdev; | ||||
if (vap->va_type == VCHR || vap->va_type == VBLK) | if (vap->va_type == VCHR || vap->va_type == VBLK) | ||||
rdev = vap->va_rdev; | rdev = vap->va_rdev; | ||||
else if (vap->va_type == VFIFO || vap->va_type == VSOCK) | else if (vap->va_type == VFIFO || vap->va_type == VSOCK) | ||||
rdev = 0xffffffff; | rdev = 0xffffffff; | ||||
else | else | ||||
return (EOPNOTSUPP); | return (EOPNOTSUPP); | ||||
if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred))) | if ((error = VOP_GETATTR(dvp, 0, &vattr, cnp->cn_cred))) | ||||
return (error); | return (error); | ||||
error = nfsrpc_mknod(dvp, cnp->cn_nameptr, cnp->cn_namelen, vap, | error = nfsrpc_mknod(dvp, cnp->cn_nameptr, cnp->cn_namelen, vap, | ||||
rdev, vap->va_type, cnp->cn_cred, curthread, &dnfsva, | rdev, vap->va_type, cnp->cn_cred, curthread, &dnfsva, | ||||
&nfsva, &nfhp, &attrflag, &dattrflag); | &nfsva, &nfhp, &attrflag, &dattrflag); | ||||
if (!error) { | if (!error) { | ||||
if (!nfhp) | if (!nfhp) | ||||
(void) nfsrpc_lookup(dvp, cnp->cn_nameptr, | (void) nfsrpc_lookup(dvp, cnp->cn_nameptr, | ||||
cnp->cn_namelen, cnp->cn_cred, curthread, | cnp->cn_namelen, cnp->cn_cred, curthread, | ||||
▲ Show 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | nfs_create(struct vop_create_args *ap) | ||||
struct vattr vattr; | struct vattr vattr; | ||||
/* | /* | ||||
* Oops, not for me.. | * Oops, not for me.. | ||||
*/ | */ | ||||
if (vap->va_type == VSOCK) | if (vap->va_type == VSOCK) | ||||
return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap)); | return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap)); | ||||
if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred))) | if ((error = VOP_GETATTR(dvp, 0, &vattr, cnp->cn_cred))) | ||||
return (error); | return (error); | ||||
if (vap->va_vaflags & VA_EXCLUSIVE) | if (vap->va_vaflags & VA_EXCLUSIVE) | ||||
fmode |= O_EXCL; | fmode |= O_EXCL; | ||||
dnp = VTONFS(dvp); | dnp = VTONFS(dvp); | ||||
nmp = VFSTONFS(dvp->v_mount); | nmp = VFSTONFS(dvp->v_mount); | ||||
again: | again: | ||||
/* For NFSv4, wait until any remove is done. */ | /* For NFSv4, wait until any remove is done. */ | ||||
NFSLOCKNODE(dnp); | NFSLOCKNODE(dnp); | ||||
▲ Show 20 Lines • Show All 99 Lines • ▼ Show 20 Lines | nfs_remove(struct vop_remove_args *ap) | ||||
struct nfsnode *np = VTONFS(vp); | struct nfsnode *np = VTONFS(vp); | ||||
int error = 0; | int error = 0; | ||||
struct vattr vattr; | struct vattr vattr; | ||||
KASSERT(vrefcnt(vp) > 0, ("nfs_remove: bad v_usecount")); | KASSERT(vrefcnt(vp) > 0, ("nfs_remove: bad v_usecount")); | ||||
if (vp->v_type == VDIR) | if (vp->v_type == VDIR) | ||||
error = EPERM; | error = EPERM; | ||||
else if (vrefcnt(vp) == 1 || (np->n_sillyrename && | else if (vrefcnt(vp) == 1 || (np->n_sillyrename && | ||||
VOP_GETATTR(vp, &vattr, cnp->cn_cred) == 0 && | VOP_GETATTR(vp, 0, &vattr, cnp->cn_cred) == 0 && | ||||
vattr.va_nlink > 1)) { | vattr.va_nlink > 1)) { | ||||
/* | /* | ||||
* Purge the name cache so that the chance of a lookup for | * Purge the name cache so that the chance of a lookup for | ||||
* the name succeeding while the remove is in progress is | * the name succeeding while the remove is in progress is | ||||
* minimized. Without node locking it can still happen, such | * minimized. Without node locking it can still happen, such | ||||
* that an I/O op returns ESTALE, but since you get this if | * that an I/O op returns ESTALE, but since you get this if | ||||
* another host removes the file.. | * another host removes the file.. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 410 Lines • ▼ Show 20 Lines | nfs_mkdir(struct vop_mkdir_args *ap) | ||||
struct componentname *cnp = ap->a_cnp; | struct componentname *cnp = ap->a_cnp; | ||||
struct nfsnode *np = NULL, *dnp; | struct nfsnode *np = NULL, *dnp; | ||||
struct vnode *newvp = NULL; | struct vnode *newvp = NULL; | ||||
struct vattr vattr; | struct vattr vattr; | ||||
struct nfsfh *nfhp; | struct nfsfh *nfhp; | ||||
struct nfsvattr nfsva, dnfsva; | struct nfsvattr nfsva, dnfsva; | ||||
int error = 0, attrflag, dattrflag, ret; | int error = 0, attrflag, dattrflag, ret; | ||||
if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred)) != 0) | if ((error = VOP_GETATTR(dvp, 0, &vattr, cnp->cn_cred)) != 0) | ||||
return (error); | return (error); | ||||
vap->va_type = VDIR; | vap->va_type = VDIR; | ||||
error = nfsrpc_mkdir(dvp, cnp->cn_nameptr, cnp->cn_namelen, | error = nfsrpc_mkdir(dvp, cnp->cn_nameptr, cnp->cn_namelen, | ||||
vap, cnp->cn_cred, curthread, &dnfsva, &nfsva, &nfhp, | vap, cnp->cn_cred, curthread, &dnfsva, &nfsva, &nfhp, | ||||
&attrflag, &dattrflag); | &attrflag, &dattrflag); | ||||
dnp = VTONFS(dvp); | dnp = VTONFS(dvp); | ||||
NFSLOCKNODE(dnp); | NFSLOCKNODE(dnp); | ||||
dnp->n_flag |= NMODIFIED; | dnp->n_flag |= NMODIFIED; | ||||
▲ Show 20 Lines • Show All 116 Lines • ▼ Show 20 Lines | nfs_readdir(struct vop_readdir_args *ap) | ||||
/* | /* | ||||
* First, check for hit on the EOF offset cache | * First, check for hit on the EOF offset cache | ||||
*/ | */ | ||||
NFSLOCKNODE(np); | NFSLOCKNODE(np); | ||||
if (np->n_direofoffset > 0 && uio->uio_offset >= np->n_direofoffset && | if (np->n_direofoffset > 0 && uio->uio_offset >= np->n_direofoffset && | ||||
(np->n_flag & NMODIFIED) == 0) { | (np->n_flag & NMODIFIED) == 0) { | ||||
NFSUNLOCKNODE(np); | NFSUNLOCKNODE(np); | ||||
if (VOP_GETATTR(vp, &vattr, ap->a_cred) == 0) { | if (VOP_GETATTR(vp, 0, &vattr, ap->a_cred) == 0) { | ||||
NFSLOCKNODE(np); | NFSLOCKNODE(np); | ||||
if ((NFS_ISV4(vp) && np->n_change == vattr.va_filerev) || | if ((NFS_ISV4(vp) && np->n_change == vattr.va_filerev) || | ||||
!NFS_TIMESPEC_COMPARE(&np->n_mtime, &vattr.va_mtime)) { | !NFS_TIMESPEC_COMPARE(&np->n_mtime, &vattr.va_mtime)) { | ||||
NFSUNLOCKNODE(np); | NFSUNLOCKNODE(np); | ||||
NFSINCRGLOBAL(nfsstatsv1.direofcache_hits); | NFSINCRGLOBAL(nfsstatsv1.direofcache_hits); | ||||
if (ap->a_eofflag != NULL) | if (ap->a_eofflag != NULL) | ||||
*ap->a_eofflag = 1; | *ap->a_eofflag = 1; | ||||
return (0); | return (0); | ||||
▲ Show 20 Lines • Show All 909 Lines • ▼ Show 20 Lines | if (!NFS_ISV4(vp) || (nmp->nm_flag & NFSMNT_NOLOCKD) != 0) { | ||||
* Now, if we just got a lock, invalidate data in the buffer | * Now, if we just got a lock, invalidate data in the buffer | ||||
* cache, as required, so that the coherency conforms with | * cache, as required, so that the coherency conforms with | ||||
* RFC3530 Sec. 9.3.2. | * RFC3530 Sec. 9.3.2. | ||||
*/ | */ | ||||
if (ap->a_op == F_SETLK) { | if (ap->a_op == F_SETLK) { | ||||
if ((np->n_flag & NMODIFIED) == 0) { | if ((np->n_flag & NMODIFIED) == 0) { | ||||
np->n_attrstamp = 0; | np->n_attrstamp = 0; | ||||
KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); | KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); | ||||
ret = VOP_GETATTR(vp, &va, cred); | ret = VOP_GETATTR(vp, 0, &va, cred); | ||||
} | } | ||||
if ((np->n_flag & NMODIFIED) || ret || | if ((np->n_flag & NMODIFIED) || ret || | ||||
np->n_change != va.va_filerev) { | np->n_change != va.va_filerev) { | ||||
(void) ncl_vinvalbuf(vp, V_SAVE, td, 1); | (void) ncl_vinvalbuf(vp, V_SAVE, td, 1); | ||||
np->n_attrstamp = 0; | np->n_attrstamp = 0; | ||||
KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); | KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); | ||||
ret = VOP_GETATTR(vp, &va, cred); | ret = VOP_GETATTR(vp, 0, &va, cred); | ||||
if (!ret) { | if (!ret) { | ||||
np->n_mtime = va.va_mtime; | np->n_mtime = va.va_mtime; | ||||
np->n_change = va.va_filerev; | np->n_change = va.va_filerev; | ||||
} | } | ||||
} | } | ||||
/* Mark that a file lock has been acquired. */ | /* Mark that a file lock has been acquired. */ | ||||
NFSLOCKNODE(np); | NFSLOCKNODE(np); | ||||
np->n_flag |= NHASBEENLOCKED; | np->n_flag |= NHASBEENLOCKED; | ||||
▲ Show 20 Lines • Show All 77 Lines • ▼ Show 20 Lines | if ((accmode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { | ||||
case VDIR: | case VDIR: | ||||
case VLNK: | case VLNK: | ||||
return (EROFS); | return (EROFS); | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
vap = &vattr; | vap = &vattr; | ||||
error = VOP_GETATTR(vp, vap, cred); | error = VOP_GETATTR(vp, 0, vap, cred); | ||||
if (error) | if (error) | ||||
goto out; | goto out; | ||||
error = vaccess(vp->v_type, vap->va_mode, vap->va_uid, vap->va_gid, | error = vaccess(vp->v_type, vap->va_mode, vap->va_uid, vap->va_gid, | ||||
accmode, cred); | accmode, cred); | ||||
out: | out: | ||||
return error; | return error; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 438 Lines • ▼ Show 20 Lines | else | ||||
consecutive = false; | consecutive = false; | ||||
mtx_unlock(&nmp->nm_mtx); | mtx_unlock(&nmp->nm_mtx); | ||||
inoff = *ap->a_inoffp; | inoff = *ap->a_inoffp; | ||||
outoff = *ap->a_outoffp; | outoff = *ap->a_outoffp; | ||||
tryoutcred = true; | tryoutcred = true; | ||||
must_commit = false; | must_commit = false; | ||||
if (error == 0) { | if (error == 0) { | ||||
vap = &VTONFS(invp)->n_vattr.na_vattr; | vap = &VTONFS(invp)->n_vattr.na_vattr; | ||||
error = VOP_GETATTR(invp, vap, ap->a_incred); | error = VOP_GETATTR(invp, 0, vap, ap->a_incred); | ||||
if (error == 0) { | if (error == 0) { | ||||
/* | /* | ||||
* Clip "len" at va_size so that RFC compliant servers | * Clip "len" at va_size so that RFC compliant servers | ||||
* will not reply NFSERR_INVAL. | * will not reply NFSERR_INVAL. | ||||
* Setting "len == 0" for the RPC would be preferred, | * Setting "len == 0" for the RPC would be preferred, | ||||
* but some Linux servers do not support that. | * but some Linux servers do not support that. | ||||
* If the len is being set to 0, do a Setattr RPC to | * If the len is being set to 0, do a Setattr RPC to | ||||
* set the server's atime. This behaviour was the | * set the server's atime. This behaviour was the | ||||
▲ Show 20 Lines • Show All 586 Lines • Show Last 20 Lines |