Существует некоторая несовместимость между Linux версиями ядра 4.x и 5.x об обработке *pos
аргумента, переданного seq_file
функциям обратного вызова.
Linux ядру 5.x устанавливает только *pos
в 0 и оставляет другие модификации для обратных вызовов seq_file
(функции .start
и .next
в struct seq_operations
).
Однако в Linux в ядре 4. x *pos
может быть увеличен на 1 вне ваших обратных вызовов . Это делается, если последний .show
вызовет точно количество байтов, необходимых для выполнения запроса read
системного вызова.
Поскольку ваш код готов только к *pos
значениям, которые являются делится на BUFFER_STEP
, он работает некорректно, когда *pos
увеличивается вне ваших функций, поэтому он делится на BUFFER_STEP
больше.
Я не знаю, поведение Linux 4.x корректен, но если вы хотите, чтобы ваш код работал с таким поведением, вам нужно подготовиться ко всем значениям *pos
, а не только к значениям, созданным вашим кодом.
Простое исправление вашего код будет интерпретироваться *pos
как индекс чанка вместо байтовый индекс :
static void* seqf_ex_start (struct seq_file* m, loff_t* pos)
{
if (*pos >= (BUFFER_SIZE/BUFFER_STEP)) {
return NULL;
}
return buffer + (*pos * BUFFER_STEP);
}
static void* seqf_ex_next (struct seq_file* m, void* v, loff_t* pos)
{
*pos += 1;
if (*pos >= (BUFFER_SIZE/BUFFER_STEP)) {
return NULL;
}
return buffer + (*pos * BUFFER_STEP);
}
static int seqf_ex_show (struct seq_file* m, void* v)
{
seq_printf(m, "%.*s\n", BUFFER_STEP, (char*)v);
return 0;
}
Таким образом, ваш код будет работать с all значения из *pos
. (Те, которые слишком высоки, будут отсечены чеками if (*pos >= (BUFFER_SIZE/BUFFER_STEP))
). И приращение *pos
на 1, выполняемое вне вашего кода, эквивалентно вызову вашего .next
обратного вызова.