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().
This commit is contained in:
Mohan Srinivasan 2006-04-06 01:20:30 +00:00
parent 37b791151f
commit 5ef7d50da5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=157557
3 changed files with 36 additions and 5 deletions

View File

@ -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 @@ nfs_asyncio(struct nfsmount *nmp, struct buf *bp, struct ucred *cred, struct thr
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);

View File

@ -2880,6 +2880,21 @@ nfs_flush(struct vnode *vp, int waitfor, struct thread *td,
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 @@ nfs_flush(struct vnode *vp, int waitfor, struct thread *td,
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)

View File

@ -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