diff options
author | mohans <mohans@FreeBSD.org> | 2006-04-06 01:20:30 +0000 |
---|---|---|
committer | mohans <mohans@FreeBSD.org> | 2006-04-06 01:20:30 +0000 |
commit | 8a6c02da7df4358036aa25e6bfdff3041be47c60 (patch) | |
tree | af911ea1d219da3c9fd65d8c880efbd0492f2c3c /sys/nfsclient | |
parent | 4170173ab06311a95b74ad80577722e0588e097e (diff) | |
download | FreeBSD-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.c | 21 | ||||
-rw-r--r-- | sys/nfsclient/nfs_vnops.c | 17 | ||||
-rw-r--r-- | sys/nfsclient/nfsnode.h | 3 |
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 |