Bug 209251
Summary: | Blocking splice() does not allow to read all the available data from pipe | ||
---|---|---|---|
Product: | File System | Reporter: | Dmitry Izbitsky (izbitsky) |
Component: | Other | Assignee: | fs_other |
Status: | NEW --- | ||
Severity: | normal | CC: | izbitsky, regressions, sam |
Priority: | P1 | ||
Hardware: | All | ||
OS: | Linux | ||
Kernel Version: | 5.9.0-rc4 | Subsystem: | |
Regression: | No | Bisected commit-id: | |
Attachments: | Reproducer for the bug |
Created attachment 292493 [details] Reproducer for the bug If I do the following (I checked mainline kernel 5.9.0-rc4, 4.19.0-10-amd64 on Debian, 4.15.0-106-generic on Ubuntu): 1. Overfill pipe_write_end with data; 2. Call splice(socket, 0, pipe_write_end, 0, 100, 0) from another thread which will block because there is nothing to read from the socket; 3. Try to read from pipe_read_fd all the data written in (1); then read() will block after reading only part of the data – even though poll() reports POLLIN for pipe_read_fd. read() will block even if O_NONBLOCK is set for pipe_read_fd. The reproducer program test_splice.c is in attachment. It can be used like gcc test_splice.c -o test_splice -lpthread ./test_splice 127.0.0.1 11111 Output: 61441 bytes were written to pipe Connection was accepted Calling splice() in a thread to move data from the socket to the pipe which should block Trying to read all the data written to pipe before read() on pipe blocks for 4998 ms by now, after reading 4096 bytes Sending data from peer to unblock splice() splice() returned 10 61451 bytes was read from pipe Joining a thread which calls splice()... Joining a thread which unblocks splice()... If I run this program on 3.10.0-1062.1.2.el7.x86_64 (CentOS Linux release 7.7.1908), it works fine: ./test_splice 127.0.0.1 11111 61441 bytes were written to pipe Connection was accepted Calling splice() in a thread to move data from the socket to the pipe which should block Trying to read all the data written to pipe before 61441 bytes was read from pipe Joining a thread which calls splice()... Sending data from peer to unblock splice() splice() returned 10 Joining a thread which unblocks splice()...