Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 22 Apr 2004 20:26:11 -0700 (PDT)
From:      Matthew Dillon <dillon@apollo.backplane.com>
To:        Stephan Uphoff <ups@tree.com>, Julian Elischer <julian@elischer.org>, hackers@freebsd.org
Subject:   Re99: how to flush out cache.? 
Message-ID:  <200404230326.i3N3QBAp004589@apollo.backplane.com>
References:  <200404230103.VAA18066@stups.com> <200404230253.i3N2rZ0t004401@apollo.backplane.com>

next in thread | previous in thread | raw e-mail | index | archive | help

:    (taking hackers off to reduce noise)

   oops.  I guess I didn't take it off hackers.  Sorry about that.

   Yah yah, I know, 'Matt's making a billion postings again'.

   In anycase, I sent a patch set to Stephan and julian, and since I didn't
   take it off the list like I said I would I guess I might as well post the
   patch set and the revised test program too for anyone following along.

   Note that the patch set is against DragonFly, but should easily patch into
   4.x.  Stephan and Julian will deal with 4.xisms and 5.xisms.

   The idea with the fix is as follows:

   * It's hard to make the VM system invalidate buffers, so don't try.
     Instead, make UFS recognize the IO_INVAL ioflag and mark the buffer
     appropriately in the putpages -> generic put pages -> VOP_WRITE() path.

     This only occurs if the msync'd map was writable.  If the msync'd map was
     only readable, then the data is not flushed through the vnode system and
     the pages will not be removed if there happens to be a buffer associated
     with them, even if the buffer is clean.

     I think this is reasonable.  Not perfect, but reasonable.

   * Set clean_only to TRUE when calling vm_object_page_remove(), which
     causes vm_object_page_remove() to ignore wired or dirty pages.  This
     code is called for both readable and writable maps so we can't just 
     remove the page unconditionallty, hence clean_only should be
     set to TRUE.

     This means that any pages associated with the buffer cache will NOT
     be removed if the map was read-only.  If the map was writable, then
     the IO_INVAL fix above will destroy the buffer and the page should
     wind up not being wired any more, and thus will be properly removed.

    That's it!

						-Matt
/*
 * y.c
 */
#include <sys/types.h>
#include <sys/mman.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int
main(int ac, char **av)
{
    int fd;
    char *ptr1;
    char *ptr2;
    char buf[4096];

    fd = open("test.dat", O_RDWR|O_CREAT|O_TRUNC, 0666);
    ftruncate(fd, 4096);
    ptr1 = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    *ptr1 = 'A';
    read(fd, buf, 4096);
    ptr2 = mmap(NULL, 4096, PROT_READ, MAP_SHARED, fd, 0);
    if (msync(ptr1, 4096, MS_INVALIDATE | MS_SYNC) < 0)
	perror("msync");
    sleep(4);
    printf("contents of *ptr1 is %d\n", *ptr1);
    printf("contents of *ptr2 is %d\n", *ptr2);
    return(0);
}

Index: vm/vm_map.c
===================================================================
RCS file: /cvs/src/sys/vm/vm_map.c,v
retrieving revision 1.24
diff -u -r1.24 vm_map.c
--- vm/vm_map.c	23 Mar 2004 22:54:32 -0000	1.24
+++ vm/vm_map.c	23 Apr 2004 02:56:17 -0000
@@ -2212,7 +2212,7 @@
 			vm_object_page_remove(object,
 			    OFF_TO_IDX(offset),
 			    OFF_TO_IDX(offset + size + PAGE_MASK),
-			    FALSE);
+			    TRUE);
 			vm_object_deallocate(object);
 		}
 		start += size;
Index: vfs/ufs/ufs_readwrite.c
===================================================================
RCS file: /cvs/src/sys/vfs/ufs/ufs_readwrite.c,v
retrieving revision 1.9
diff -u -r1.9 ufs_readwrite.c
--- vfs/ufs/ufs_readwrite.c	26 Jul 2003 22:04:27 -0000	1.9
+++ vfs/ufs/ufs_readwrite.c	23 Apr 2004 03:05:50 -0000
@@ -531,6 +531,8 @@
 			bp->b_flags |= B_DIRECT;
 		if (ioflag & IO_NOWDRAIN)
 			bp->b_flags |= B_NOWDRAIN;
+		if ((ioflag & (IO_SYNC|IO_INVAL)) == (IO_SYNC|IO_INVAL))
+			bp->b_flags |= B_NOCACHE;
 
 		if (uio->uio_offset + xfersize > ip->i_size) {
 			ip->i_size = uio->uio_offset + xfersize;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200404230326.i3N3QBAp004589>