Нашел странность в поведении splice на ядрах новее, чем 3.6. Берем такой файл:
#define _GNU_SOURCE
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<errno.h>
#include<stdio.h>
int main(void) {
int fdi = STDIN_FILENO;
int fdo = STDOUT_FILENO;
size_t r;
fprintf(stderr, "Seeking to %zd\n", lseek(fdo, 0, SEEK_END));
r = splice(fdi, NULL, fdo, NULL, BYTES_TO_SPLICE, 0);
fprintf(stderr, "Result: %zd %d\n", r, errno);
perror("Splice");
return 0;
}
Он пытается вызвать splice для записи за конец файла в stdout. Создаем блочное устройство:
dd if=/dev/zero of=myfile bs=1M count=100 losetup /dev/loop7 myfile
Пытаемся записать после его конца при разных значениях объема сплайса (BYTES_TO_SPLICE) на ядре 3.6:
# gcc -Wall -DBYTES_TO_SPLICE=4096 tspl.c # cat /dev/zero | ./a.out > /dev/loop7 Seeking to 104857600 Result: -1 5 Splice: Input/output error # gcc -Wall -DBYTES_TO_SPLICE=4095 tspl.c # cat /dev/zero | ./a.out > /dev/loop7 Seeking to 104857600 Result: -1 5 Splice: Input/output error
Казалось бы, все логично. Писать за конец блочного устройства нельзя. Однако возьмем ядро 3.10....
# gcc -Wall -DBYTES_TO_SPLICE=4095 tspl.c # cat /dev/zero | ./a.out > /dev/loop7 Seeking to 104857600 Result: -1 5 Splice: Input/output error # gcc -Wall -DBYTES_TO_SPLICE=4096 tspl.c # cat /dev/zero | ./a.out > /dev/loop7 Seeking to 104857600 Result: 4096 0 Splice: Success
При размере 4096 и больше об ошибке не сообщается. Куда уходят данные, тоже непонятно.
Есть у меня подозрение, что изменение поведения связано вот с этим коммитом.
Хотелось бы, чтобы какой-нибудь грамотный kernel hacker провел этот тест у себя на ядре поновее и привел свои соображения. Если это баг в ядре, то лучше о нем сообщить.