Re: O_DIRECT wierd behavior..

GOTO Masanori (gotom@debian.org)
Sun, 16 Dec 2001 15:29:40 +0900


Hi,

At Sat, 15 Dec 2001 19:47:46 -0500 (EST),
Suresh Gopalakrishnan wrote:
> I tried this small piece of code from an old post in the archive:
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <fcntl.h>
> #include <sys/stat.h>
> #include <sys/types.h>
> #include <unistd.h>
>
> #define O_DIRECT 040000 /* direct disk access hint */
>
> int main()
> {
> char buf[16384];
> int fd;
> char *p;
>
> p = (char *)((((unsigned long)buf) + 8191) & ~8191L);
> fd = open("/tmp/blah", O_CREAT | O_RDWR | O_DIRECT);
>
> printf("write returns %i\n", write(fd, buf, 8192));
> printf("write returns %i\n", write(fd, p, 1));
>
> return 0;
> }
>
> Output is:
>
> write returns -1
> Filesize limit exceeded (core dumped)
>
> $ ls -l /tmp/blah
> ---------- 1 gsuresh users 4294967274 Dec 15 19:15 /tmp/blah
>
> The kernel is 2.4.16 and /tmp is ext2. (It runs fine on 2.4.2).
>
> Any idea why this happens and how to fix this?

Hmm, kernel 2.4.17-rc1 also has this problem.

The reason of this problem is that written is defined as unsigned long
currently, so if generic_file_direct_IO returns -EINVAL, then written
is translated as (unsigned long)(-EINVAL) = (0x100000000-EINVAL). Thus
the file size changed such a big value!

This patch fixes it.

--- linux-2.4.17-rc1.vanilla/mm/filemap.c Sun Dec 16 14:57:42 2001
+++ linux-2.4.17-rc1/mm/filemap.c Sun Dec 16 15:02:10 2001
@@ -2854,7 +2854,7 @@
unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
loff_t pos;
struct page *page, *cached_page;
- unsigned long written;
+ ssize_t written;
long status = 0;
int err;
unsigned bytes;

This problem breaks file inode size with direct IO... we lost the
correct file inode size forever. It's serious. Linus and Marcelo,
please consider to apply this patch?

However, your program does not work yet. Try my test program. It
works well because valloc()/memalign() allocates aligned page
boundary.

But, my interest is that why we cannot access with stack memory or
malloc()-ed memory. I heard Suresh's program works fine on 2.4.2, but
it does not work on 2.4.17-rc1. Should we modify the kernel to work
well with user stack/heap memory when we use direct IO for the file ?
Or, this behavior is absolutely correct ?

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

#define O_DIRECT 040000 /* direct disk access hint */

int main()
{
char *buf;
int fd;

buf = valloc(16384);
fd = open("/tmp/blah", O_CREAT | O_RDWR | O_DIRECT, 0755 );

printf("write returns %i\n", write(fd, buf, 4096));

return 0;
}

-- gotom

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/