Bug 147829 - O_DIRECT read() returns 0 byte under ext3
O_DIRECT read() returns 0 byte under ext3
Product: Red Hat Enterprise Linux 3
Classification: Red Hat
Component: kernel (Show other bugs)
i686 Linux
medium Severity medium
: ---
: ---
Assigned To: Stephen Tweedie
Brian Brock
Depends On:
  Show dependency treegraph
Reported: 2005-02-11 14:11 EST by Xiaojun Wang
Modified: 2007-11-30 17:07 EST (History)
5 users (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Last Closed: 2005-03-21 16:36:31 EST
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---

Attachments (Terms of Use)

  None (edit)
Description Xiaojun Wang 2005-02-11 14:11:46 EST
Description of problem:


I am using O_DIRECT to read regular files under ext3, with no special
mount options.  It works fine except for the final read when the
remaining file size is less than pagesize.  In this case 0 byte is
returned instead of the actual number of bytes.

The program I used is diotest.c:

#include <stdio.h>
#include <fcntl.h>
#include <errno.h>

    char *message; 
    int fd = open("/work/xiaojun/oxx", O_RDONLY|O_DIRECT); 
    int len, pagesize = getpagesize(); 

    printf("pagesize = %d.\n", pagesize);

    posix_memalign((void **)&message, pagesize, pagesize); 

    if(fd < 0)
        printf("Unable to open file, errno is %d.\n", errno); 

        while((len = read(fd, message, pagesize)) > 0)
            printf("%d bytes read from file.\n", len); 

        if(len < 0)
            printf("%d bytes read from file.\n", len); 

The file /work/xiaojun/oxx is 5587 bytes. 

Version-Release number of selected component (if applicable):

How reproducible:
Every time

Steps to Reproduce:
1. Modify diotest.c to change file name to an existing file with size
bigger than 4K but less than 8K.
2. gcc -D_GNU_SOURCE diotest.c
3. ./a.out
4. For comparison, remove the O_DIRECT flag from open() and repeat 
steps 2 and 3 above.

Actual results:
pagesize = 4096.
4096 bytes read from file.
0 bytes read from file.

Expected results:
pagesize = 4096.
4096 bytes read from file.
1491 bytes read from file.
0 bytes read from file.

Additional info:
Comment 1 Terry Jones 2005-03-21 15:17:53 EST
Any movement on this?
Comment 3 Rik van Riel 2005-03-21 16:36:31 EST
O_DIRECT can only do block aligned reads in multiples of the block size.  Since
the last portion of the file is not a multiple of the block size (or, in the 2.6
kernel, a multiple of 512 bytes), O_DIRECT cannot do that read.

To quote the man page for read(2):

              Try to minimize cache effects of the I/O to and from this  file.
              In  general  this  will degrade performance, but it is useful in
              special situations, such  as  when  applications  do  their  own
              caching.   File I/O is done directly to/from user space buffers.
              The I/O is synchronous, i.e., at the completion of  the  read(2)
              or  write(2) system call, data is guaranteed to have been trans-
              ferred.  Under Linux 2.4 transfer sizes, and  the  alignment  of
              user buffer and file offset must all be multiples of the logical
              block size of the file system.  Under  Linux  2.6  alignment  to
              512-byte boundaries suffices.
              A  semantically similar interface for block devices is described
              in raw(8).

Since there are programs that depend on exactly this behaviour, I suspect this
cannot be changed.

Note You need to log in before you can comment on or make changes to this bug.