aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/fs/nfsclient/nfs_clbio.c51
-rw-r--r--sys/fs/nfsclient/nfs_clport.c3
-rw-r--r--sys/sys/proc.h2
3 files changed, 39 insertions, 17 deletions
diff --git a/sys/fs/nfsclient/nfs_clbio.c b/sys/fs/nfsclient/nfs_clbio.c
index d8d4600c3ff9..a2cfcada2218 100644
--- a/sys/fs/nfsclient/nfs_clbio.c
+++ b/sys/fs/nfsclient/nfs_clbio.c
@@ -425,14 +425,11 @@ int
ncl_bioread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
{
struct nfsnode *np = VTONFS(vp);
- int biosize, i;
struct buf *bp, *rabp;
struct thread *td;
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
daddr_t lbn, rabn;
- int bcount;
- int seqcount;
- int nra, error = 0, n = 0, on = 0;
+ int biosize, bcount, error, i, n, nra, on, save2, seqcount;
off_t tmp_off;
KASSERT(uio->uio_rw == UIO_READ, ("ncl_read mode"));
@@ -464,6 +461,8 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
/* No caching/ no readaheads. Just read data into the user buffer */
return ncl_readrpc(vp, uio, cred);
+ n = 0;
+ on = 0;
biosize = vp->v_bufobj.bo_bsize;
seqcount = (int)((off_t)(ioflag >> IO_SEQSHIFT) * biosize / BKVASIZE);
@@ -471,6 +470,7 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
if (error)
return error;
+ save2 = curthread_pflags2_set(TDP2_SBPAGES);
do {
u_quad_t nsize;
@@ -495,7 +495,9 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
rabp = nfs_getcacheblk(vp, rabn, biosize, td);
if (!rabp) {
error = newnfs_sigintr(nmp, td);
- return (error ? error : EINTR);
+ if (error == 0)
+ error = EINTR;
+ goto out;
}
if ((rabp->b_flags & (B_CACHE|B_DELWRI)) == 0) {
rabp->b_flags |= B_ASYNC;
@@ -526,7 +528,9 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
if (!bp) {
error = newnfs_sigintr(nmp, td);
- return (error ? error : EINTR);
+ if (error == 0)
+ error = EINTR;
+ goto out;
}
/*
@@ -540,7 +544,7 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
error = ncl_doio(vp, bp, cred, td, 0);
if (error) {
brelse(bp);
- return (error);
+ goto out;
}
}
@@ -561,7 +565,9 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
bp = nfs_getcacheblk(vp, (daddr_t)0, NFS_MAXPATHLEN, td);
if (!bp) {
error = newnfs_sigintr(nmp, td);
- return (error ? error : EINTR);
+ if (error == 0)
+ error = EINTR;
+ goto out;
}
if ((bp->b_flags & B_CACHE) == 0) {
bp->b_iocmd = BIO_READ;
@@ -570,7 +576,7 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
if (error) {
bp->b_ioflags |= BIO_ERROR;
brelse(bp);
- return (error);
+ goto out;
}
}
n = MIN(uio->uio_resid, NFS_MAXPATHLEN - bp->b_resid);
@@ -580,14 +586,17 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
NFSINCRGLOBAL(nfsstatsv1.biocache_readdirs);
if (np->n_direofoffset
&& uio->uio_offset >= np->n_direofoffset) {
- return (0);
+ error = 0;
+ goto out;
}
lbn = (uoff_t)uio->uio_offset / NFS_DIRBLKSIZ;
on = uio->uio_offset & (NFS_DIRBLKSIZ - 1);
bp = nfs_getcacheblk(vp, lbn, NFS_DIRBLKSIZ, td);
if (!bp) {
- error = newnfs_sigintr(nmp, td);
- return (error ? error : EINTR);
+ error = newnfs_sigintr(nmp, td);
+ if (error == 0)
+ error = EINTR;
+ goto out;
}
if ((bp->b_flags & B_CACHE) == 0) {
bp->b_iocmd = BIO_READ;
@@ -612,12 +621,16 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
*/
for (i = 0; i <= lbn && !error; i++) {
if (np->n_direofoffset
- && (i * NFS_DIRBLKSIZ) >= np->n_direofoffset)
- return (0);
+ && (i * NFS_DIRBLKSIZ) >= np->n_direofoffset) {
+ error = 0;
+ goto out;
+ }
bp = nfs_getcacheblk(vp, i, NFS_DIRBLKSIZ, td);
if (!bp) {
error = newnfs_sigintr(nmp, td);
- return (error ? error : EINTR);
+ if (error == 0)
+ error = EINTR;
+ goto out;
}
if ((bp->b_flags & B_CACHE) == 0) {
bp->b_iocmd = BIO_READ;
@@ -646,7 +659,7 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
* we give up.
*/
if (error)
- return (error);
+ goto out;
}
/*
@@ -706,6 +719,12 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
if (bp != NULL)
brelse(bp);
} while (error == 0 && uio->uio_resid > 0 && n > 0);
+out:
+ curthread_pflags2_restore(save2);
+ if ((curthread->td_pflags2 & TDP2_SBPAGES) == 0) {
+ NFSLOCKNODE(np);
+ ncl_pager_setsize(vp, NULL);
+ }
return (error);
}
diff --git a/sys/fs/nfsclient/nfs_clport.c b/sys/fs/nfsclient/nfs_clport.c
index 77ecdd255ea2..017b81776579 100644
--- a/sys/fs/nfsclient/nfs_clport.c
+++ b/sys/fs/nfsclient/nfs_clport.c
@@ -597,7 +597,8 @@ ncl_pager_setsize(struct vnode *vp, u_quad_t *nsizep)
setnsize = false;
if (object != NULL && nsize != object->un_pager.vnp.vnp_size) {
- if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE)
+ if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE &&
+ (curthread->td_pflags2 & TDP2_SBPAGES) == 0)
setnsize = true;
else
np->n_flag |= NVNSETSZSKIP;
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 2b574cb1c7b2..bbae5cf1caae 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -515,6 +515,8 @@ do { \
#define TDP_EXECVMSPC 0x40000000 /* Execve destroyed old vmspace */
#define TDP_SIGFASTPENDING 0x80000000 /* Pending signal due to sigfastblock */
+#define TDP2_SBPAGES 0x00000001 /* Owns sbusy on some pages */
+
/*
* Reasons that the current thread can not be run yet.
* More than one may apply.