summaryrefslogtreecommitdiffstats
path: root/sys/nfs/nfs_bio.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/nfs/nfs_bio.c')
-rw-r--r--sys/nfs/nfs_bio.c36
1 files changed, 33 insertions, 3 deletions
diff --git a/sys/nfs/nfs_bio.c b/sys/nfs/nfs_bio.c
index 1dad3c4..9adaa14 100644
--- a/sys/nfs/nfs_bio.c
+++ b/sys/nfs/nfs_bio.c
@@ -339,6 +339,7 @@ nfs_bioread(vp, uio, ioflag, cred)
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
daddr_t lbn, rabn;
int bcount;
+ int seqcount;
int nra, error = 0, n = 0, on = 0;
#ifdef DIAGNOSTIC
@@ -350,6 +351,7 @@ nfs_bioread(vp, uio, ioflag, cred)
if (uio->uio_offset < 0) /* XXX VDIR cookies can be negative */
return (EINVAL);
p = uio->uio_procp;
+
if ((nmp->nm_flag & NFSMNT_NFSV3) != 0 &&
(nmp->nm_state & NFSSTA_GOTFSINFO) == 0)
(void)nfs_fsinfo(nmp, vp, cred, p);
@@ -357,6 +359,7 @@ nfs_bioread(vp, uio, ioflag, cred)
(uio->uio_offset + uio->uio_resid) > nmp->nm_maxfilesize)
return (EFBIG);
biosize = vp->v_mount->mnt_stat.f_iosize;
+ seqcount = (int)((off_t)(ioflag >> 16) * biosize / BKVASIZE);
/*
* For nfs, cache consistency can only be maintained approximately.
* Although RFC1094 does not specify the criteria, the following is
@@ -455,7 +458,7 @@ nfs_bioread(vp, uio, ioflag, cred)
* Start the read ahead(s), as required.
*/
if (nfs_numasync > 0 && nmp->nm_readahead > 0) {
- for (nra = 0; nra < nmp->nm_readahead &&
+ for (nra = 0; nra < nmp->nm_readahead && nra < seqcount &&
(off_t)(lbn + 1 + nra) * biosize < np->n_size; nra++) {
rabn = lbn + 1 + nra;
if (!incore(vp, rabn)) {
@@ -521,8 +524,6 @@ nfs_bioread(vp, uio, ioflag, cred)
n = 0;
if (on < bcount)
n = min((unsigned)(bcount - on), uio->uio_resid);
-
- vp->v_lastr = lbn;
break;
case VLNK:
nfsstats.biocache_readlinks++;
@@ -1344,6 +1345,35 @@ nfs_doio(bp, cr, p)
bp->b_error = error;
}
} else {
+ /*
+ * If we only need to commit, try to commit
+ */
+ if (bp->b_flags & B_NEEDCOMMIT) {
+ int retv;
+ off_t off;
+
+ off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff;
+ bp->b_flags |= B_WRITEINPROG;
+ retv = nfs_commit(
+ bp->b_vp, off, bp->b_dirtyend-bp->b_dirtyoff,
+ bp->b_wcred, p);
+ bp->b_flags &= ~B_WRITEINPROG;
+ if (retv == 0) {
+ bp->b_dirtyoff = bp->b_dirtyend = 0;
+ bp->b_flags &= ~B_NEEDCOMMIT;
+ bp->b_resid = 0;
+ biodone(bp);
+ return (0);
+ }
+ if (retv == NFSERR_STALEWRITEVERF) {
+ nfs_clearcommit(bp->b_vp->v_mount);
+ }
+ }
+
+ /*
+ * Setup for actual write
+ */
+
if ((off_t)bp->b_blkno * DEV_BSIZE + bp->b_dirtyend > np->n_size)
bp->b_dirtyend = np->n_size - (off_t)bp->b_blkno * DEV_BSIZE;
OpenPOWER on IntegriCloud