Skip to contentSkip to conversation

[2.4] kiobuf flush dcache properly

PATCH New Jun Sun 1 participant 1 message Apr 2, 2003

Subsystems (2)
lore
Share & tools
lore

Jun Sun

author
#0 lore raw

PATCH 1/1 [2.4] kiobuf flush dcache properly

Some CPUs have cache aliasing problem, where the same physical memory could appear in more than one places in data cache (such as those found in MIPS and Sparc). For those CPUs, kiobuf is not flushing cache properly.

The symptom can be easily found if you open files with O_DIRECT flag and do file copies on those CPUs.

This patch fixes the problem.

Basically if it is a WRITE (from user to disk), we need to flush cache before the IO. If it is a READ, we need to flush cache after the IO.

Please apply.

Jun

mm/memory.c renamed from mm/memory.c.orig +9 -8
diff -Nru linux-2.4.20/mm/memory.c.orig linux-2.4.20/mm/memory.c
@@ -553,6 +553,7 @@
 	if (err)
 		return err;
 
+	iobuf->rw = rw;
 	iobuf->locked = 0;
 	iobuf->offset = va & (PAGE_SIZE-1);
 	iobuf->length = len;
@@ -569,11 +570,10 @@
 		return err;
 	}
 	iobuf->nr_pages = err;
-	while (pgcount--) {
-		/* FIXME: flush superflous for rw==READ,
-		 * probably wrong function for rw==WRITE
-		 */
-		flush_dcache_page(iobuf->maplist[pgcount]);
+	/* if rw==WRITE, get updated data before writing them to disk */
+	if (rw==WRITE) {
+		while (pgcount--) 
+			flush_dcache_page(iobuf->maplist[pgcount]);
 	}
 	dprintk ("map_user_kiobuf: end OK\n");
 	return 0;
@@ -628,9 +628,10 @@
 		if (map) {
 			if (iobuf->locked)
 				UnlockPage(map);
-			/* FIXME: cache flush missing for rw==READ
-			 * FIXME: call the correct reference counting function
-			 */
+			/* if rw==READ, flush dcache before user uses data */
+			if (iobuf->rw==READ) {
+				flush_dcache_page(iobuf->maplist[i]);
+			}
 			page_cache_release(map);
 		}
 	}
include/linux/iobuf.h renamed from include/linux/iobuf.h.orig +1 -0
diff -Nru linux-2.4.20/include/linux/iobuf.h.orig linux-2.4.20/include/linux/iobuf.h
@@ -32,6 +32,7 @@
 
 struct kiobuf 
 {
+	int		rw;		/* mapped for READ or WRITE */
 	int		nr_pages;	/* Pages actually referenced */
 	int		array_len;	/* Space in the allocated lists */
 	int		offset;		/* Offset to start of valid data */