Do not set B_NOCACHE on buffers when releasing them in flushbuflist().

If B_NOCACHE is set the pages of vm backed buffers will be invalidated.
However clean buffers can be backed by dirty VM pages so invalidating them
can lead to data loss.
Add support for flush dirty page in the data invalidation function
of some network file systems.

This fixes data losses during vnode recycling (and other code paths
using invalbuf(*,V_SAVE,*,*)) for data written using an mmaped file.

Collaborative effort by: jhb@,mohans@,peter@,ps@,ups@
Reviewed by:	tegge@
MFC after:	7 days
This commit is contained in:
Stephan Uphoff 2006-05-25 01:00:35 +00:00
parent 5bbfbd1422
commit dcf67e65d2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=158906
4 changed files with 20 additions and 1 deletions

View File

@ -611,6 +611,10 @@ nwfs_vinvalbuf(vp, td)
return EINTR;
}
np->n_flag |= NFLUSHINPROG;
if (vp->v_bufobj.bo_object != NULL)
vm_object_page_clean(vp->v_bufobj.bo_object, 0, 0, OBJPC_SYNC);
error = vinvalbuf(vp, V_SAVE, td, PCATCH, 0);
while (error) {
if (error == ERESTART || error == EINTR) {

View File

@ -683,6 +683,10 @@ smbfs_vinvalbuf(struct vnode *vp, struct thread *td)
return EINTR;
}
np->n_flag |= NFLUSHINPROG;
if (vp->v_bufobj.bo_object != NULL)
vm_object_page_clean(vp->v_bufobj.bo_object, 0, 0, OBJPC_SYNC);
error = vinvalbuf(vp, V_SAVE, td, PCATCH, 0);
while (error) {
if (error == ERESTART || error == EINTR) {

View File

@ -1134,7 +1134,7 @@ flushbuflist( struct bufv *bufv, int flags, struct bufobj *bo, int slpflag,
return (EAGAIN); /* XXX: why not loop ? */
}
bremfree(bp);
bp->b_flags |= (B_INVAL | B_NOCACHE | B_RELBUF);
bp->b_flags |= (B_INVAL | B_RELBUF);
bp->b_flags &= ~B_ASYNC;
brelse(bp);
BO_LOCK(bo);

View File

@ -1312,6 +1312,17 @@ nfs_vinvalbuf(struct vnode *vp, int flags, struct thread *td, int intrflg)
/*
* Now, flush as required.
*/
if ((flags & V_SAVE) && (vp->v_bufobj.bo_object != NULL)) {
vm_object_page_clean(vp->v_bufobj.bo_object, 0, 0, OBJPC_SYNC);
/*
* If the page clean was interrupted, fail the invalidation.
* Not doing so, we run the risk of losing dirty pages in the
* vinvalbuf() call below.
*/
if (intrflg && (error = nfs_sigintr(nmp, NULL, td)))
goto out;
}
error = vinvalbuf(vp, flags, td, slpflag, 0);
while (error) {
if (intrflg && (error = nfs_sigintr(nmp, NULL, td)))