diff --git a/include/linux/fs.h b/include/linux/fs.h index 45689621a85160af0d367eae8689737cc4629a7f..be87edcaba06be6c368c056524601ea26361f4bf 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -87,6 +87,9 @@ struct inodes_stat_t { */ #define FMODE_NOCMTIME ((__force fmode_t)2048) +/* Expect random access pattern */ +#define FMODE_RANDOM ((__force fmode_t)4096) + /* * The below are the various read and write types that we support. Some of * them include behavioral modifiers that send information down to the diff --git a/mm/fadvise.c b/mm/fadvise.c index e43359214f6ff15020b6f05cc07aa5e6ddcb4162..8d723c9e8b75b316041ea564f5e243b79a94e2b7 100644 --- a/mm/fadvise.c +++ b/mm/fadvise.c @@ -77,12 +77,20 @@ SYSCALL_DEFINE(fadvise64_64)(int fd, loff_t offset, loff_t len, int advice) switch (advice) { case POSIX_FADV_NORMAL: file->f_ra.ra_pages = bdi->ra_pages; + spin_lock(&file->f_lock); + file->f_mode &= ~FMODE_RANDOM; + spin_unlock(&file->f_lock); break; case POSIX_FADV_RANDOM: - file->f_ra.ra_pages = 0; + spin_lock(&file->f_lock); + file->f_mode |= FMODE_RANDOM; + spin_unlock(&file->f_lock); break; case POSIX_FADV_SEQUENTIAL: file->f_ra.ra_pages = bdi->ra_pages * 2; + spin_lock(&file->f_lock); + file->f_mode &= ~FMODE_RANDOM; + spin_unlock(&file->f_lock); break; case POSIX_FADV_WILLNEED: if (!mapping->a_ops->readpage) { diff --git a/mm/readahead.c b/mm/readahead.c index 033bc135a41f3885cae863ca0c9f5185d6c5d665..337b20e946f6891ed9ae322d22c8e24a1b27f40e 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -501,6 +501,12 @@ void page_cache_sync_readahead(struct address_space *mapping, if (!ra->ra_pages) return; + /* be dumb */ + if (filp->f_mode & FMODE_RANDOM) { + force_page_cache_readahead(mapping, filp, offset, req_size); + return; + } + /* do read-ahead */ ondemand_readahead(mapping, ra, filp, false, offset, req_size); }