Еще информация к размышлению. strace кроме EFBIG выдает еще и SIGXFSZ:
Code:
_llseek(11, 1108992000, [1108992000], SEEK_SET) = 0
write(11, "d\363\303\32\355\263x\261\327\2447\271\350\336\332\302"..., 10240) = -1 EFBIG (File too large)
--- SIGXFSZ (File size limit exceeded) @ 0 (0) ---
с одной стороны подозрение вызывает lseek. Единственное место где он вызывается --- файл CFile.cpp, причем в форме lseek, которая может оказаться 32 и 64 битной. Однако, в Makefile определяется -D_FILE_OFFSET_BITS=64 в результате чего lseek превращается в корректный уже 64-битный _llseek , к тому же он возвращает успех. Так что похоже lseek не виноват.
Далее цитата из man 2 write:
Code:
EFBIG An attempt was made to write a file that exceeds the implementation-defined maximum file size or the process' file size limit,
or to write at a position past the maximum allowed offset.
Итак EFBIG могут вызвать 3 причины, а именно, попытки:
1) write a file that exceeds the implementation-defined maximum file size;
2) write a file that exceeds the process' file size limit;
3) write at a position past the maximum allowed offset.
Причем SIGXFSZ (File size limit exceeded), похоже, указывает на вариант №2.
Далее, существует такое понятие как лимиты ресурсов или RLIMIT, причем они используются в файле amule.cpp
, правда их там пытаются выставить в максимум.
Цитата из man 2 getrlimits , касаемо лимита размера файла, который может создать процесс:
Code:
RLIMIT_FSIZE
The maximum size of files that the process may create. Attempts to extend a file beyond this limit result in delivery of a
SIGXFSZ signal. By default, this signal terminates a process, but a process can catch this signal instead, in which case the
relevant system call (e.g., write() truncate()) fails with the error EFBIG.
Очень похоже на нашу ситуацию, по крайней мере оба ключевых слова (SIGXFSZ и EFBIG) присутствуют.
Чему же равен RLIMIT_FSIZE
Code:
#include <sys/time.h>
#include <sys/resource.h>
#include <stdio.h>
int main()
{
struct rlimit rl;
int res = getrlimit(RLIMIT_FSIZE, &rl);
printf("%ld %ld %d %ld\n", rl.rlim_cur, rl.rlim_max, sizeof(rlim_t), RLIM_INFINITY);
}
возвращает 2147483647 2147483647 4 2147483647
Это величина в байтах. Первое число т.н. soft rlimit , второе hard rlimit . Соответственно, при желании можем их установить, причем soft <= hard . Величины эти имеют тим rlim_t и являются 32-битными. Необходимо отметить, что у свежей suse они тоже четырехбитные (-1 -1 4 -1, что по сути есть то же самое). В результате непонятно как вообще в линухе можно работать с файлами более 2 Гб если лимит размера файла четырехбайтный.
Дополнение. А вот, кстати, где сидит 1 Гигабайт. Если запустить strace amuled -f, т.е. прописать его с самого начала, а не атачить к pid-у, то как раз и наблюдается то о чем я писал выше. Этот код выполняется в файле amule.cpp . А вот изменить то эти цифры что-то ни хрена не получается.
Code:
getrlimit(RLIMIT_DATA, {rlim_cur=RLIM_INFINITY, rlim_max=RLIM_INFINITY}) = 0
setrlimit(RLIMIT_DATA, {rlim_cur=1073741823, rlim_max=1073741823}) = 0
getrlimit(RLIMIT_FSIZE, {rlim_cur=RLIM_INFINITY, rlim_max=RLIM_INFINITY}) = 0
setrlimit(RLIMIT_FSIZE, {rlim_cur=1073741823, rlim_max=1073741823}) = 0
getrlimit(RLIMIT_NOFILE, {rlim_cur=1024, rlim_max=1024}) = 0
setrlimit(RLIMIT_NOFILE, {rlim_cur=1024, rlim_max=1024}) = 0
getrlimit(RLIMIT_RSS, {rlim_cur=7401488, rlim_max=4735824}) = 0
setrlimit(RLIMIT_RSS, {rlim_cur=720283552, rlim_max=2147449912}) = 0
Дополнение 2. Короче дело в следующем. Как и предполагалось в начале виноваты искривления uclibc . Максимальное значение RLIMIT_FSIZE равное RLIM_INFINITY определяется в ней для части архитектур как (~0UL), а для второй части, в т.ч. mipsel как (~0UL>>1) . А setrlimit для перестраховки делает еще раз >>1 Отсюда и берется 1Гб. Если закомментировать одну строчку (избавиться от setrlimit, который в общем то на хрен не нужен), то проблема исчезает:
strace после операции (getrlimit оставлен чисто для контроля):
Code:
getrlimit(RLIMIT_DATA, {rlim_cur=RLIM_INFINITY, rlim_max=RLIM_INFINITY}) = 0
getrlimit(RLIMIT_FSIZE, {rlim_cur=RLIM_INFINITY, rlim_max=RLIM_INFINITY}) = 0
getrlimit(RLIMIT_NOFILE, {rlim_cur=1024, rlim_max=1024}) = 0
getrlimit(RLIMIT_RSS, {rlim_cur=RLIM_INFINITY, rlim_max=RLIM_INFINITY}) = 0
Причем, как ни странно, вместо ожидаемого увеличения объема от 1 до 2 Гб, похоже проблема снялась совсем и, наконец, заработал LFS (aMule, кстати, не дает поставить на загрузку ссылку больше 4Гб ни под mipsel ни под виндой):
Code:
_llseek(13, 4205578240, [4205578240], SEEK_SET) = 0
write(13, "\210\302\2568\10\25\322\16\225\350!\372\200OQ\6x\326\362"..., 10240) = 10240
_llseek(13, 4205598720, [4205578240], SEEK_SET) = 0
write(13, "\216\35{\312\347\305\271\247\243{\206\202\357\254\311`"..., 10240) = 10240
_llseek(13, 4205608960, [4205608960], SEEK_SET) = 0
write(13, "\36\250\2732;\354C!\356\232\376\352\365\202\177,~h\233"..., 10240) = 10240