Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/nfsclient/nfs_clvnops.c.write
Show First 20 Lines • Show All 1,008 Lines • ▼ Show 20 Lines | |||||
nfs_setattr(struct vop_setattr_args *ap) | nfs_setattr(struct vop_setattr_args *ap) | ||||
{ | { | ||||
struct vnode *vp = ap->a_vp; | struct vnode *vp = ap->a_vp; | ||||
struct nfsnode *np = VTONFS(vp); | struct nfsnode *np = VTONFS(vp); | ||||
struct thread *td = curthread; /* XXX */ | struct thread *td = curthread; /* XXX */ | ||||
struct vattr *vap = ap->a_vap; | struct vattr *vap = ap->a_vap; | ||||
int error = 0; | int error = 0; | ||||
u_quad_t tsize; | u_quad_t tsize; | ||||
struct timespec ts; | |||||
#ifndef nolint | #ifndef nolint | ||||
tsize = (u_quad_t)0; | tsize = (u_quad_t)0; | ||||
#endif | #endif | ||||
/* | /* | ||||
* Setting of flags and marking of atimes are not supported. | * Setting of flags and marking of atimes are not supported. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | if ((vap->va_mtime.tv_sec != VNOVAL || vap->va_atime.tv_sec != VNOVAL) && | ||||
NFSUNLOCKNODE(np); | NFSUNLOCKNODE(np); | ||||
error = ncl_vinvalbuf(vp, V_SAVE, td, 1); | error = ncl_vinvalbuf(vp, V_SAVE, td, 1); | ||||
if (error == EINTR || error == EIO) | if (error == EINTR || error == EIO) | ||||
return (error); | return (error); | ||||
} else | } else | ||||
NFSUNLOCKNODE(np); | NFSUNLOCKNODE(np); | ||||
} | } | ||||
error = nfs_setattrrpc(vp, vap, ap->a_cred, td); | error = nfs_setattrrpc(vp, vap, ap->a_cred, td); | ||||
if (error && vap->va_size != VNOVAL) { | if (vap->va_size != VNOVAL) { | ||||
if (error == 0) { | |||||
nanouptime(&ts); | |||||
NFSLOCKNODE(np); | NFSLOCKNODE(np); | ||||
np->n_localmodtime = ts; | |||||
NFSUNLOCKNODE(np); | |||||
} else { | |||||
NFSLOCKNODE(np); | |||||
np->n_size = np->n_vattr.na_size = tsize; | np->n_size = np->n_vattr.na_size = tsize; | ||||
vnode_pager_setsize(vp, tsize); | vnode_pager_setsize(vp, tsize); | ||||
NFSUNLOCKNODE(np); | NFSUNLOCKNODE(np); | ||||
} | } | ||||
} | |||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Do an nfs setattr rpc. | * Do an nfs setattr rpc. | ||||
*/ | */ | ||||
static int | static int | ||||
nfs_setattrrpc(struct vnode *vp, struct vattr *vap, struct ucred *cred, | nfs_setattrrpc(struct vnode *vp, struct vattr *vap, struct ucred *cred, | ||||
Show All 39 Lines | nfs_lookup(struct vop_lookup_args *ap) | ||||
struct vnode *newvp; | struct vnode *newvp; | ||||
struct nfsmount *nmp; | struct nfsmount *nmp; | ||||
struct nfsnode *np, *newnp; | struct nfsnode *np, *newnp; | ||||
int error = 0, attrflag, dattrflag, ltype, ncticks; | int error = 0, attrflag, dattrflag, ltype, ncticks; | ||||
struct thread *td = cnp->cn_thread; | struct thread *td = cnp->cn_thread; | ||||
struct nfsfh *nfhp; | struct nfsfh *nfhp; | ||||
struct nfsvattr dnfsva, nfsva; | struct nfsvattr dnfsva, nfsva; | ||||
struct vattr vattr; | struct vattr vattr; | ||||
struct timespec nctime; | struct timespec nctime, ts; | ||||
uint32_t openmode; | uint32_t openmode; | ||||
*vpp = NULLVP; | *vpp = NULLVP; | ||||
if ((flags & ISLASTCN) && (mp->mnt_flag & MNT_RDONLY) && | if ((flags & ISLASTCN) && (mp->mnt_flag & MNT_RDONLY) && | ||||
(cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) | (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) | ||||
return (EROFS); | return (EROFS); | ||||
if (dvp->v_type != VDIR) | if (dvp->v_type != VDIR) | ||||
return (ENOTDIR); | return (ENOTDIR); | ||||
▲ Show 20 Lines • Show All 107 Lines • ▼ Show 20 Lines | if ((flags & OPENREAD) != 0) | ||||
openmode |= NFSV4OPEN_ACCESSREAD; | openmode |= NFSV4OPEN_ACCESSREAD; | ||||
if ((flags & OPENWRITE) != 0) | if ((flags & OPENWRITE) != 0) | ||||
openmode |= NFSV4OPEN_ACCESSWRITE; | openmode |= NFSV4OPEN_ACCESSWRITE; | ||||
} | } | ||||
NFSUNLOCKMNT(nmp); | NFSUNLOCKMNT(nmp); | ||||
newvp = NULLVP; | newvp = NULLVP; | ||||
NFSINCRGLOBAL(nfsstatsv1.lookupcache_misses); | NFSINCRGLOBAL(nfsstatsv1.lookupcache_misses); | ||||
nanouptime(&ts); | |||||
error = nfsrpc_lookup(dvp, cnp->cn_nameptr, cnp->cn_namelen, | error = nfsrpc_lookup(dvp, cnp->cn_nameptr, cnp->cn_namelen, | ||||
cnp->cn_cred, td, &dnfsva, &nfsva, &nfhp, &attrflag, &dattrflag, | cnp->cn_cred, td, &dnfsva, &nfsva, &nfhp, &attrflag, &dattrflag, | ||||
NULL, openmode); | NULL, openmode); | ||||
if (dattrflag) | if (dattrflag) | ||||
(void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1); | (void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1); | ||||
if (error) { | if (error) { | ||||
if (newvp != NULLVP) { | if (newvp != NULLVP) { | ||||
vput(newvp); | vput(newvp); | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | if (NFS_CMPFH(np, nfhp->nfh_fh, nfhp->nfh_len)) { | ||||
free(nfhp, M_NFSFH); | free(nfhp, M_NFSFH); | ||||
return (EISDIR); | return (EISDIR); | ||||
} | } | ||||
error = nfscl_nget(mp, dvp, nfhp, cnp, td, &np, NULL, | error = nfscl_nget(mp, dvp, nfhp, cnp, td, &np, NULL, | ||||
LK_EXCLUSIVE); | LK_EXCLUSIVE); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
newvp = NFSTOV(np); | newvp = NFSTOV(np); | ||||
/* | |||||
* If n_localmodtime >= time before RPC, then | |||||
* a file modification operation, such as | |||||
* VOP_SETATTR() of size, has occurred while | |||||
* the Lookup RPC and acquisition of the vnode | |||||
* happened. As such, the attributes might | |||||
* be stale, with possibly an incorrect size. | |||||
*/ | |||||
NFSLOCKNODE(np); | |||||
if (timespecisset(&np->n_localmodtime) && | |||||
timespeccmp(&np->n_localmodtime, &ts, >=)) { | |||||
NFSCL_DEBUG(4, "nfs_lookup: rename localmod " | |||||
"stale attributes\n"); | |||||
attrflag = 0; | |||||
} | |||||
NFSUNLOCKNODE(np); | |||||
if (attrflag) | if (attrflag) | ||||
(void) nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL, | (void) nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL, | ||||
0, 1); | 0, 1); | ||||
*vpp = newvp; | *vpp = newvp; | ||||
cnp->cn_flags |= SAVENAME; | cnp->cn_flags |= SAVENAME; | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | if (attrflag) | ||||
(void) nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL, | (void) nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL, | ||||
0, 1); | 0, 1); | ||||
} else { | } else { | ||||
error = nfscl_nget(mp, dvp, nfhp, cnp, td, &np, NULL, | error = nfscl_nget(mp, dvp, nfhp, cnp, td, &np, NULL, | ||||
cnp->cn_lkflags); | cnp->cn_lkflags); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
newvp = NFSTOV(np); | newvp = NFSTOV(np); | ||||
/* | |||||
* If n_localmodtime >= time before RPC, then | |||||
* a file modification operation, such as | |||||
* VOP_SETATTR() of size, has occurred while | |||||
* the Lookup RPC and acquisition of the vnode | |||||
* happened. As such, the attributes might | |||||
* be stale, with possibly an incorrect size. | |||||
*/ | |||||
NFSLOCKNODE(np); | |||||
if (timespecisset(&np->n_localmodtime) && | |||||
timespeccmp(&np->n_localmodtime, &ts, >=)) { | |||||
NFSCL_DEBUG(4, "nfs_lookup: localmod " | |||||
"stale attributes\n"); | |||||
attrflag = 0; | |||||
} | |||||
NFSUNLOCKNODE(np); | |||||
if (attrflag) | if (attrflag) | ||||
(void) nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL, | (void) nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL, | ||||
0, 1); | 0, 1); | ||||
else if ((flags & (ISLASTCN | ISOPEN)) == (ISLASTCN | ISOPEN) && | else if ((flags & (ISLASTCN | ISOPEN)) == (ISLASTCN | ISOPEN) && | ||||
!(np->n_flag & NMODIFIED)) { | !(np->n_flag & NMODIFIED)) { | ||||
/* | /* | ||||
* Flush the attribute cache when opening a | * Flush the attribute cache when opening a | ||||
* leaf node to ensure that fresh attributes | * leaf node to ensure that fresh attributes | ||||
▲ Show 20 Lines • Show All 1,201 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
struct vnode *newvp = NULL, *vp; | struct vnode *newvp = NULL, *vp; | ||||
struct nfsnode *np, *dnp = VTONFS(dvp); | struct nfsnode *np, *dnp = VTONFS(dvp); | ||||
struct nfsfh *nfhp, *onfhp; | struct nfsfh *nfhp, *onfhp; | ||||
struct nfsvattr nfsva, dnfsva; | struct nfsvattr nfsva, dnfsva; | ||||
struct componentname cn; | struct componentname cn; | ||||
int error = 0, attrflag, dattrflag; | int error = 0, attrflag, dattrflag; | ||||
u_int hash; | u_int hash; | ||||
struct timespec ts; | |||||
nanouptime(&ts); | |||||
error = nfsrpc_lookup(dvp, name, len, cred, td, &dnfsva, &nfsva, | error = nfsrpc_lookup(dvp, name, len, cred, td, &dnfsva, &nfsva, | ||||
&nfhp, &attrflag, &dattrflag, NULL, 0); | &nfhp, &attrflag, &dattrflag, NULL, 0); | ||||
if (dattrflag) | if (dattrflag) | ||||
(void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1); | (void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1); | ||||
if (npp && !error) { | if (npp && !error) { | ||||
if (*npp != NULL) { | if (*npp != NULL) { | ||||
np = *npp; | np = *npp; | ||||
vp = NFSTOV(np); | vp = NFSTOV(np); | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | #endif | ||||
} else { | } else { | ||||
cn.cn_nameptr = name; | cn.cn_nameptr = name; | ||||
cn.cn_namelen = len; | cn.cn_namelen = len; | ||||
error = nfscl_nget(dvp->v_mount, dvp, nfhp, &cn, td, | error = nfscl_nget(dvp->v_mount, dvp, nfhp, &cn, td, | ||||
&np, NULL, LK_EXCLUSIVE); | &np, NULL, LK_EXCLUSIVE); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
newvp = NFSTOV(np); | newvp = NFSTOV(np); | ||||
/* | |||||
* If n_localmodtime >= time before RPC, then | |||||
* a file modification operation, such as | |||||
* VOP_SETATTR() of size, has occurred while | |||||
* the Lookup RPC and acquisition of the vnode | |||||
* happened. As such, the attributes might | |||||
* be stale, with possibly an incorrect size. | |||||
*/ | |||||
NFSLOCKNODE(np); | |||||
if (timespecisset(&np->n_localmodtime) && | |||||
timespeccmp(&np->n_localmodtime, &ts, >=)) { | |||||
NFSCL_DEBUG(4, "nfs_lookitup: localmod " | |||||
"stale attributes\n"); | |||||
attrflag = 0; | |||||
} | } | ||||
NFSUNLOCKNODE(np); | |||||
} | |||||
if (!attrflag && *npp == NULL) { | if (!attrflag && *npp == NULL) { | ||||
if (newvp == dvp) | if (newvp == dvp) | ||||
vrele(newvp); | vrele(newvp); | ||||
else | else | ||||
vput(newvp); | vput(newvp); | ||||
return (ENOENT); | return (ENOENT); | ||||
} | } | ||||
if (attrflag) | if (attrflag) | ||||
▲ Show 20 Lines • Show All 930 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static int | static int | ||||
nfs_allocate(struct vop_allocate_args *ap) | nfs_allocate(struct vop_allocate_args *ap) | ||||
{ | { | ||||
struct vnode *vp = ap->a_vp; | struct vnode *vp = ap->a_vp; | ||||
struct thread *td = curthread; | struct thread *td = curthread; | ||||
struct nfsvattr nfsva; | struct nfsvattr nfsva; | ||||
struct nfsmount *nmp; | struct nfsmount *nmp; | ||||
struct nfsnode *np; | |||||
off_t alen; | off_t alen; | ||||
int attrflag, error, ret; | int attrflag, error, ret; | ||||
struct timespec ts; | |||||
attrflag = 0; | attrflag = 0; | ||||
nmp = VFSTONFS(vp->v_mount); | nmp = VFSTONFS(vp->v_mount); | ||||
np = VTONFS(vp); | |||||
mtx_lock(&nmp->nm_mtx); | mtx_lock(&nmp->nm_mtx); | ||||
if (NFSHASNFSV4(nmp) && nmp->nm_minorvers >= NFSV42_MINORVERSION && | if (NFSHASNFSV4(nmp) && nmp->nm_minorvers >= NFSV42_MINORVERSION && | ||||
(nmp->nm_privflag & NFSMNTP_NOALLOCATE) == 0) { | (nmp->nm_privflag & NFSMNTP_NOALLOCATE) == 0) { | ||||
mtx_unlock(&nmp->nm_mtx); | mtx_unlock(&nmp->nm_mtx); | ||||
/* | /* | ||||
* Flush first to ensure that the allocate adds to the | * Flush first to ensure that the allocate adds to the | ||||
* file's allocation on the server. | * file's allocation on the server. | ||||
*/ | */ | ||||
error = ncl_flush(vp, MNT_WAIT, td, 1, 0); | error = ncl_flush(vp, MNT_WAIT, td, 1, 0); | ||||
if (error == 0) { | if (error == 0) { | ||||
alen = *ap->a_len; | alen = *ap->a_len; | ||||
if ((uint64_t)alen > nfs_maxalloclen) | if ((uint64_t)alen > nfs_maxalloclen) | ||||
alen = nfs_maxalloclen; | alen = nfs_maxalloclen; | ||||
error = nfsrpc_allocate(vp, *ap->a_offset, alen, | error = nfsrpc_allocate(vp, *ap->a_offset, alen, | ||||
&nfsva, &attrflag, td->td_ucred, td, NULL); | &nfsva, &attrflag, td->td_ucred, td, NULL); | ||||
} | } | ||||
if (error == 0) { | if (error == 0) { | ||||
*ap->a_offset += alen; | *ap->a_offset += alen; | ||||
*ap->a_len -= alen; | *ap->a_len -= alen; | ||||
nanouptime(&ts); | |||||
NFSLOCKNODE(np); | |||||
np->n_localmodtime = ts; | |||||
NFSUNLOCKNODE(np); | |||||
} else if (error == NFSERR_NOTSUPP) { | } else if (error == NFSERR_NOTSUPP) { | ||||
mtx_lock(&nmp->nm_mtx); | mtx_lock(&nmp->nm_mtx); | ||||
nmp->nm_privflag |= NFSMNTP_NOALLOCATE; | nmp->nm_privflag |= NFSMNTP_NOALLOCATE; | ||||
mtx_unlock(&nmp->nm_mtx); | mtx_unlock(&nmp->nm_mtx); | ||||
error = EINVAL; | error = EINVAL; | ||||
} | } | ||||
} else { | } else { | ||||
mtx_unlock(&nmp->nm_mtx); | mtx_unlock(&nmp->nm_mtx); | ||||
Show All 18 Lines | nfs_deallocate(struct vop_deallocate_args *ap) | ||||
struct vnode *vp = ap->a_vp; | struct vnode *vp = ap->a_vp; | ||||
struct thread *td = curthread; | struct thread *td = curthread; | ||||
struct nfsvattr nfsva; | struct nfsvattr nfsva; | ||||
struct nfsmount *nmp; | struct nfsmount *nmp; | ||||
struct nfsnode *np; | struct nfsnode *np; | ||||
off_t tlen, mlen; | off_t tlen, mlen; | ||||
int attrflag, error, ret; | int attrflag, error, ret; | ||||
bool clipped; | bool clipped; | ||||
struct timespec ts; | |||||
error = 0; | error = 0; | ||||
attrflag = 0; | attrflag = 0; | ||||
nmp = VFSTONFS(vp->v_mount); | nmp = VFSTONFS(vp->v_mount); | ||||
np = VTONFS(vp); | np = VTONFS(vp); | ||||
mtx_lock(&nmp->nm_mtx); | mtx_lock(&nmp->nm_mtx); | ||||
if (NFSHASNFSV4(nmp) && nmp->nm_minorvers >= NFSV42_MINORVERSION && | if (NFSHASNFSV4(nmp) && nmp->nm_minorvers >= NFSV42_MINORVERSION && | ||||
(nmp->nm_privflag & NFSMNTP_NODEALLOCATE) == 0) { | (nmp->nm_privflag & NFSMNTP_NODEALLOCATE) == 0) { | ||||
Show All 26 Lines | if (error == 0) { | ||||
*ap->a_offset + tlen); | *ap->a_offset + tlen); | ||||
error = nfsrpc_deallocate(vp, *ap->a_offset, tlen, | error = nfsrpc_deallocate(vp, *ap->a_offset, tlen, | ||||
&nfsva, &attrflag, ap->a_cred, td, NULL); | &nfsva, &attrflag, ap->a_cred, td, NULL); | ||||
NFSCL_DEBUG(4, "dealloc: rpc=%d\n", error); | NFSCL_DEBUG(4, "dealloc: rpc=%d\n", error); | ||||
} | } | ||||
if (error == 0) { | if (error == 0) { | ||||
NFSCL_DEBUG(4, "dealloc: attrflag=%d na_size=%ju\n", | NFSCL_DEBUG(4, "dealloc: attrflag=%d na_size=%ju\n", | ||||
attrflag, (uintmax_t)nfsva.na_size); | attrflag, (uintmax_t)nfsva.na_size); | ||||
nanouptime(&ts); | |||||
NFSLOCKNODE(np); | |||||
np->n_localmodtime = ts; | |||||
NFSUNLOCKNODE(np); | |||||
if (attrflag != 0) { | if (attrflag != 0) { | ||||
if ((uint64_t)*ap->a_offset < nfsva.na_size) | if ((uint64_t)*ap->a_offset < nfsva.na_size) | ||||
*ap->a_offset += omin((off_t) | *ap->a_offset += omin((off_t) | ||||
nfsva.na_size - *ap->a_offset, | nfsva.na_size - *ap->a_offset, | ||||
tlen); | tlen); | ||||
} | } | ||||
if (clipped && tlen < *ap->a_len) | if (clipped && tlen < *ap->a_len) | ||||
*ap->a_len -= tlen; | *ap->a_len -= tlen; | ||||
▲ Show 20 Lines • Show All 693 Lines • Show Last 20 Lines |