public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Jun Sun <jsun@mvista.com>
To: linux-kernel@vger.kernel.org, linux-mips@linux-mips.org
Cc: jsun@mvista.com
Subject: Re: possible cache aliasing problem with O_DIRECT?
Date: Tue, 10 Dec 2002 18:32:54 -0800	[thread overview]
Message-ID: <20021210183254.Y8642@mvista.com> (raw)
In-Reply-To: <20021210182051.X8642@mvista.com>; from jsun@mvista.com on Tue, Dec 10, 2002 at 06:20:51PM -0800

[-- Attachment #1: Type: text/plain, Size: 1797 bytes --]


... forgot the attachment, possibly due to the same memory 
corruption problem. :-)

Also, the problem is discovered in 2.4.18.  I checked with 2.4.19
and it appears it should be there as well.

Jun

On Tue, Dec 10, 2002 at 06:20:51PM -0800, Jun Sun wrote:
> 
> I am chasing a problem which might be a cache aliasing problem
> when a disk file is opened with O_DIRECT flag.
> 
> I attached the source code of two programs.  One generates a binary file
> and the other opens the file with O_DIRECT and reads it.  It checks
> the content of the file while reading it.
> 
> I tested this on a MIPS board with NEC vr5432 CPU, which has a
> virtually indexed, two-way set associative d-cache, and can easily 
> re-produce the data corruption problem.
> 
> I attached a patch which apparently solves the problem.
> 
> I am not an expert in fs and mm, but my guess is:
> 
> 1) user process allocates a big buffer
> 2) the user buffer is mapped into kernel virtual space for doing direct IO 
>    through map_user_kiobuf()
> 3) since the virtual address for buffer area is different in user space
>    from that in kernel virtual, kernel should do a flush cache for those
>    pages after doing the IO.  That is why my attached patch makes it work.
> 
> Does this make sense?
> 
> However, I still have some puzzles.  For it to work completely, another
> cache flushing needs to be done for the address range of the buffer in user
> space.  I thought this should be done some where inside map_user_kiobuf()
> but could not find it anywhere.  Did I miss it?  Or it just happens to work
> even without it?
> 
> Another puzzling part is that I also tested the program on another couple
> of MIPS boards which *should* suffer from this problem, but failed to 
> re-produce it.
> 
> Any thoughts?
> 
> Jun
> 

[-- Attachment #2: gen-file.c --]
[-- Type: text/plain, Size: 565 bytes --]


/*
 * generate a binary file with 33554432/4 32-bit integers.  The
 * integers range from 0 to 33554432/4-1.
 *
 * This file is used by my-diotest.c.
 */

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define		TOTAL_SIZE		33554432

main()
{
	int intsize=TOTAL_SIZE/4;
	int f;
	int i;
	int ret;
	assert(sizeof(i) == 4);
	f=open("srcdata-ordered", O_RDWR | O_CREAT);
	assert(f > 0);
	for (i=0; i< intsize; i++) {
		ret=write(f, &i, sizeof(i));
		assert(ret == sizeof(i));
	}
	close(f);
}

[-- Attachment #3: my-diotest.c --]
[-- Type: text/plain, Size: 1402 bytes --]


/*
 * test program to demonstrate possible cache aliasing problem with O_DRECT
 * option on IDE files.
 *
 * Problem exists on NEC rochopper boards with vr5432/vr5500 CPUs.  However
 * it did not show up with vr4131 cpu and toshiba CPUs, which is unexpected.
 */

#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define IOSIZE  32768

void *aligned_alloc(int size, int align)
{
	void *p = malloc(size + align);
	return (void*) (((unsigned)p + align-1) / align * align);
}

void check_buffer(char *p, int round)
{
	int *q= (int*)p;
	int intsize = IOSIZE / 4;
	int i;
	int base=round*intsize;
	for (i=0; i< intsize; i++, q++)	
		if (*q != base+i) 
			printf("error at (%d, %d): got %d, expect %d\n",
				round, i, *q, base+i);
}

void dcp(int sfd)
{
	int zfd;
	int r, w;
	char *p;
	int round=0;

#if 0
	zfd = open("/dev/zero", O_RDWR);
	p = mmap(NULL, IOSIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE, zfd, 0);
	close(zfd);
#endif
	p = aligned_alloc(IOSIZE, 4096);
	printf("buffer alloced/mapped to memory area: %x\n", p);

	while (1) {
		memset(p, 0, IOSIZE);
		r = read(sfd, p, IOSIZE);
		if (r <= 0) break;
		check_buffer(p, round);
		round++;
	}
}

int
main(int argc, char *argv[])
{
	int sfd;
	int ret;

	sfd = open(argv[1], O_RDONLY | O_DIRECT);
	printf ("sfd ret = %d\n", sfd);
	dcp(sfd);
	return 0;
}

[-- Attachment #4: o_direct-cache-flush.patch --]
[-- Type: text/plain, Size: 534 bytes --]

diff -Nru mm/filemap.c.orig mm/filemap.c
--- mm/filemap.c.orig	Mon Dec  9 18:27:41 2002
+++ mm/filemap.c	Tue Dec 10 17:13:41 2002
@@ -1550,9 +1550,13 @@
 
 		retval = mapping->a_ops->direct_IO(rw, inode, iobuf, (offset+progress) >> blocksize_bits, blocksize);
 
-		if (rw == READ && retval > 0)
+		if (rw == READ && retval > 0) {
+			int i;
+			for (i=0; i< iobuf->nr_pages; i++)
+				flush_page_to_ram(iobuf->maplist[i]);
 			mark_dirty_kiobuf(iobuf, retval);
-		
+		}
+
 		if (retval >= 0) {
 			count -= retval;
 			buf += retval;

      reply	other threads:[~2002-12-11  2:25 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-12-11  2:20 possible cache aliasing problem with O_DIRECT? Jun Sun
2002-12-11  2:32 ` Jun Sun [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20021210183254.Y8642@mvista.com \
    --to=jsun@mvista.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mips@linux-mips.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox