Bug 1303001 - read() return -1 ENOMEM (Cannot allocate memory) when open() with O_DIRECT parameter
Summary: read() return -1 ENOMEM (Cannot allocate memory) when open() with O_DIRECT p...
Keywords:
Status: CLOSED CURRENTRELEASE
Alias: None
Product: Red Hat Enterprise Linux 7
Classification: Red Hat
Component: kernel-aarch64
Version: 7.2
Hardware: aarch64
OS: Linux
unspecified
unspecified
Target Milestone: rc
: ---
Assignee: Dave Anderson
QA Contact: Red Hat Kernel QE team
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2016-01-29 09:22 UTC by Li Wang
Modified: 2016-02-11 20:38 UTC (History)
3 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2016-02-11 20:38:35 UTC
Target Upstream Version:


Attachments (Terms of Use)

Description Li Wang 2016-01-29 09:22:23 UTC
Description of problem:

ltp/diotest4 failed on 4.4.0-0.rc4.21.el7.aarch64 as:
------
<<<test_start>>>
tag=dio04 stime=1454038921
cmdline="diotest4"
contacts=""
analysis=exit
<<<test_output>>>
diotest4    1  TPASS  :  Negative Offset
diotest4    2  TPASS  :  removed
diotest4    3  TPASS  :  Odd count of read and write
diotest4    4  TFAIL  :  diotest4.c:294: allows read beyond file size. returns -1: Cannot allocate memory
diotest4    5  TPASS  :  Invalid file descriptor
diotest4    6  TPASS  :  Out of range file descriptor
diotest4    7  TPASS  :  Closed file descriptor
diotest4    8  TPASS  :  removed
diotest4    9  TCONF  :  diotest4.c:344: Direct I/O on /dev/null is not supported
diotest4   10  TFAIL  :  diotest4.c:150: read failed for mmapped file. returns -1: Cannot allocate memory
diotest4   11  TFAIL  :  diotest4.c:182: read, write to a mmaped file
diotest4   12  TPASS  :  read, write to an unmapped file
diotest4   13  TPASS  :  read from file not open for reading
diotest4   14  TPASS  :  write to file not open for writing
diotest4   15  TPASS  :  read, write with non-aligned buffer
diotest4   16  TPASS  :  read, write buffer in read-only space
diotest4   17  TPASS  :  read, write in non-existant space
diotest4   18  TPASS  :  read, write for file with O_SYNC
diotest4    0  TINFO  :  2/15 test blocks failed

Version-Release number of selected component (if applicable):
4.4.0-0.rc4.21.el7.aarch64

How reproducible:
100%

Steps to Reproduce:
https://github.com/linux-test-project/ltp/blob/master/testcases/kernel/io/direct_io/diotest4.c

Actual results:
fail

Expected results:
pass

Additional info:
https://beaker.engineering.redhat.com/jobs/1206304

Comment 3 Larry Woodman 2016-02-04 13:11:03 UTC
This is most likely a side effect of the 64KB pages used in PPC64.

Larry

Comment 4 Dave Anderson 2016-02-11 20:38:35 UTC
This bug was recently introduced into the upstream kernel by this commit:

  commit 74cedf9b6c603f2278a05bc91b140b32b434d0b5
  Author: Jan Kara <jack>
  Date:   Mon Nov 30 10:15:42 2015 -0700

    direct-io: Fix negative return from dio read beyond eof
    
    Assume a filesystem with 4KB blocks. When a file has size 1000 bytes and
    we issue direct IO read at offset 1024, blockdev_direct_IO() reads the
    tail of the last block and the logic for handling short DIO reads in
    dio_complete() results in a return value -24 (1000 - 1024) which
    obviously confuses userspace.
    
    Fix the problem by bailing out early once we sample i_size and can
    reliably check that direct IO read starts beyond i_size.
    
    Reported-by: Avi Kivity <avi>
    Fixes: 9fe55eea7e4b444bafc42fa0000cc2d1d2847275
    CC: stable.org
    CC: Steven Whitehouse <swhiteho>
    Signed-off-by: Jan Kara <jack>
    Signed-off-by: Jens Axboe <axboe>

which was in 4.4-rc4: 

  # git describe --contains 74cedf9b6c603f2278a05bc91b140b32b434d0b5
  v4.4-rc4~14^2~5
  #

It was subsequently fixed by this commit:

  commit 2d4594acbf6d8f75a27f3578476b6a27d8b13ebb
  Author: Al Viro <viro.org.uk>
  Date:   Tue Dec 8 12:22:47 2015 -0500

    fix the regression from "direct-io: Fix negative return from dio read beyond eof"
    
    Sure, it's better to bail out of past-the-eof read and return 0 than return
    a bogus negative value on such.  Only we'd better make sure we are bailing out
    with 0 and not -ENOMEM...
    
    Cc: stable.org
    Signed-off-by: Al Viro <viro.org.uk>

which was in 4.4-rc5:

  git describe --contains 2d4594acbf6d8f75a27f3578476b6a27d8b13ebb
  v4.4-rc5~24^2

The 4.4.0-0.rc4.21.el7 kernel-aarch64 snapshot just happened to 
be taken in between the two commits above:

  %define rpmversion 4.4.0
  %define pkgrelease 0.rc4.21.el7

The current kernel-aarch64 kernel is version 4.5.0-0.rc3.27.el7, which
has Al Viro's fix, and which passes the test as expected:
  
  # uname -r
  4.5.0-0.rc3.27.el7.aarch64
  # ./diotest4
  PASS! Read beyond the file size
  #


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