readahead: fix sequential read cache miss detection
The kernel's readahead algorithm sometimes interprets random read accesses
as sequential and triggers unnecessary data prefecthing from storage
device (impacting random read average latency).
In order to identify sequential cache read misses, the readahead algorithm
intends to check whether offset - previous offset == 1 (trivial sequential
reads) or offset - previous offset == 0 (sequential reads not aligned on
page boundary):
if (offset - (ra->prev_pos >> PAGE_CACHE_SHIFT) <= 1UL)
The current offset is stored in the "offset" variable of type "pgoff_t"
(unsigned long), while previous offset is stored in "ra->prev_pos" of type
"loff_t" (long long). Therefore, operands of the if statement are
implicitly converted to type long long. Consequently, when previous
offset > current offset (which happens on random pattern), the if
condition is true and access is wrongly interpeted as sequential. An
unnecessary data prefetching is triggered, impacting the average random
read latency.
Storing the previous offset value in a "pgoff_t" variable (unsigned long)
fixes the sequential read detection logic.
Signed-off-by: Damien Ramonda <damien.ramonda@intel.com> Reviewed-by: Fengguang Wu <fengguang.wu@intel.com> Acked-by: Pierre Tardy <pierre.tardy@intel.com> Acked-by: David Cohen <david.a.cohen@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>