summaryrefslogtreecommitdiffstats
path: root/sys/nfsclient
diff options
context:
space:
mode:
authormohans <mohans@FreeBSD.org>2006-04-06 01:20:30 +0000
committermohans <mohans@FreeBSD.org>2006-04-06 01:20:30 +0000
commit8a6c02da7df4358036aa25e6bfdff3041be47c60 (patch)
treeaf911ea1d219da3c9fd65d8c880efbd0492f2c3c /sys/nfsclient
parent4170173ab06311a95b74ad80577722e0588e097e (diff)
downloadFreeBSD-src-8a6c02da7df4358036aa25e6bfdff3041be47c60.zip
FreeBSD-src-8a6c02da7df4358036aa25e6bfdff3041be47c60.tar.gz
Keep track of the number of in-progress async direct IO writes in the nfsnode.
Make fsync/close wait until all of these drain. Add a check to nfs_getpage() and nfs_putpage().
Diffstat (limited to 'sys/nfsclient')
-rw-r--r--sys/nfsclient/nfs_bio.c21
-rw-r--r--sys/nfsclient/nfs_vnops.c17
-rw-r--r--sys/nfsclient/nfsnode.h3
3 files changed, 36 insertions, 5 deletions
diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c
index 896bb17..fca722f 100644
--- a/sys/nfsclient/nfs_bio.c
+++ b/sys/nfsclient/nfs_bio.c
@@ -105,7 +105,8 @@ nfs_getpages(struct vop_getpages_args *ap)
return VM_PAGER_ERROR;
}
- if (!nfs_directio_allow_mmap && (np->n_flag & NNONCACHE) &&
+ if (nfs_directio_enable && !nfs_directio_allow_mmap &&
+ (np->n_flag & NNONCACHE) &&
(vp->v_type == VREG)) {
printf("nfs_getpages: called on non-cacheable vnode??\n");
return VM_PAGER_ERROR;
@@ -287,8 +288,8 @@ nfs_putpages(struct vop_putpages_args *ap)
(void)nfs_fsinfo(nmp, vp, cred, td);
}
- if (!nfs_directio_allow_mmap && (np->n_flag & NNONCACHE) &&
- (vp->v_type == VREG))
+ if (nfs_directio_enable && !nfs_directio_allow_mmap &&
+ (np->n_flag & NNONCACHE) && (vp->v_type == VREG))
printf("nfs_putpages: called on noncache-able vnode??\n");
for (i = 0; i < npages; i++)
@@ -1246,7 +1247,8 @@ nfs_vinvalbuf(struct vnode *vp, int flags, struct thread *td, int intrflg)
goto out;
error = vinvalbuf(vp, flags, td, 0, slptimeo);
}
- np->n_flag &= ~NMODIFIED;
+ if (np->n_directio_asyncwr == 0)
+ np->n_flag &= ~NMODIFIED;
out:
if (old_lock != LK_EXCLUSIVE) {
if (old_lock == LK_SHARED) {
@@ -1383,6 +1385,8 @@ again:
BUF_KERNPROC(bp);
TAILQ_INSERT_TAIL(&nmp->nm_bufq, bp, b_freelist);
nmp->nm_bufqlen++;
+ if ((bp->b_flags & B_DIRECT) && bp->b_iocmd == BIO_WRITE)
+ VTONFS(bp->b_vp)->n_directio_asyncwr++;
return (0);
}
@@ -1409,6 +1413,15 @@ nfs_doio_directwrite(struct buf *bp)
free(iov_base, M_NFSDIRECTIO);
free(uiop->uio_iov, M_NFSDIRECTIO);
free(uiop, M_NFSDIRECTIO);
+ if ((bp->b_flags & B_DIRECT) && bp->b_iocmd == BIO_WRITE) {
+ struct nfsnode *np = VTONFS(bp->b_vp);
+
+ np->n_directio_asyncwr--;
+ if ((np->n_flag & NFSYNCWAIT) && np->n_directio_asyncwr == 0) {
+ np->n_flag &= ~NFSYNCWAIT;
+ wakeup((caddr_t)&np->n_directio_asyncwr);
+ }
+ }
vdrop(bp->b_vp);
bp->b_vp = NULL;
relpbuf(bp, &nfs_pbuf_freecnt);
diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c
index 7028836..ccaa150 100644
--- a/sys/nfsclient/nfs_vnops.c
+++ b/sys/nfsclient/nfs_vnops.c
@@ -2880,6 +2880,21 @@ loop:
VI_UNLOCK(vp);
goto loop;
}
+ /*
+ * Wait for all the async IO requests to drain
+ */
+ while (np->n_directio_asyncwr > 0) {
+ np->n_flag |= NFSYNCWAIT;
+ error = nfs_tsleep(td, (caddr_t)&np->n_directio_asyncwr,
+ slpflag | (PRIBIO + 1), "nfsfsync", 0);
+ if (error) {
+ if (nfs_sigintr(nmp, (struct nfsreq *)0, td)) {
+ error = EINTR;
+ goto done;
+ }
+ }
+ }
+
}
VI_UNLOCK(vp);
if (np->n_flag & NWRITEERR) {
@@ -2887,7 +2902,7 @@ loop:
np->n_flag &= ~NWRITEERR;
}
if (commit && vp->v_bufobj.bo_dirty.bv_cnt == 0 &&
- vp->v_bufobj.bo_numoutput == 0)
+ vp->v_bufobj.bo_numoutput == 0 && np->n_directio_asyncwr == 0)
np->n_flag &= ~NMODIFIED;
done:
if (bvec != NULL && bvec != bvec_on_stack)
diff --git a/sys/nfsclient/nfsnode.h b/sys/nfsclient/nfsnode.h
index 0c5817f..a0a2a88 100644
--- a/sys/nfsclient/nfsnode.h
+++ b/sys/nfsclient/nfsnode.h
@@ -126,6 +126,7 @@ struct nfsnode {
uint32_t n_namelen;
daddr_t ra_expect_lbn;
int n_directio_opens;
+ int n_directio_asyncwr;
};
#define n_atim n_un1.nf_atim
@@ -149,6 +150,8 @@ struct nfsnode {
#define NTRUNCATE 0x1000 /* Opened by nfs_setattr() */
#define NSIZECHANGED 0x2000 /* File size has changed: need cache inval */
#define NNONCACHE 0x4000 /* Node marked as noncacheable */
+#define NFSYNCWAIT 0x8000 /* fsync waiting for all directio async writes
+ to drain */
/*
* Convert between nfsnode pointers and vnode pointers
OpenPOWER on IntegriCloud