mm/readahead.c
Source file repositories/reference/linux-study-clean/mm/readahead.c
File Facts
- System
- Linux kernel
- Corpus path
mm/readahead.c- Extension
.c- Size
- 28129 bytes
- Lines
- 866
- Domain
- Core OS
- Bucket
- Memory Management
- Inferred role
- Core OS: syscall or user/kernel boundary
- Status
- core implementation candidate
Why This File Exists
Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.
- Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.
- Defines or participates in a user/kernel boundary; inspect argument validation, copy_from_user/copy_to_user, credentials, and dispatch target.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/blkdev.hlinux/kernel.hlinux/dax.hlinux/gfp.hlinux/export.hlinux/backing-dev.hlinux/task_io_accounting_ops.hlinux/pagemap.hlinux/psi.hlinux/syscalls.hlinux/file.hlinux/mm_inline.hlinux/blk-cgroup.hlinux/fadvise.hlinux/sched/mm.htrace/events/readahead.hinternal.h
Detected Declarations
syscall readaheadfunction Copyrightfunction read_pagesfunction page_cache_sync_readaheadfunction do_page_cache_rafunction force_page_cache_rafunction get_init_ra_sizefunction get_next_ra_sizefunction atfunction page_cache_ra_orderfunction ractl_max_pagesfunction page_cache_sync_rafunction page_cache_async_rafunction ksys_readaheadfunction readahead_expandexport file_ra_state_initexport page_cache_ra_unboundedexport page_cache_sync_raexport page_cache_async_raexport readahead_expand
Annotated Snippet
SYSCALL_DEFINE3(readahead, int, fd, loff_t, offset, size_t, count)
{
return ksys_readahead(fd, offset, count);
}
#if defined(CONFIG_COMPAT) && defined(__ARCH_WANT_COMPAT_READAHEAD)
COMPAT_SYSCALL_DEFINE4(readahead, int, fd, compat_arg_u64_dual(offset), size_t, count)
{
return ksys_readahead(fd, compat_arg_u64_glue(offset), count);
}
#endif
/**
* readahead_expand - Expand a readahead request
* @ractl: The request to be expanded
* @new_start: The revised start
* @new_len: The revised size of the request
*
* Attempt to expand a readahead request outwards from the current size to the
* specified size by inserting locked pages before and after the current window
* to increase the size to the new window. This may involve the insertion of
* THPs, in which case the window may get expanded even beyond what was
* requested.
*
* The algorithm will stop if it encounters a conflicting page already in the
* pagecache and leave a smaller expansion than requested.
*
* The caller must check for this by examining the revised @ractl object for a
* different expansion than was requested.
*/
void readahead_expand(struct readahead_control *ractl,
loff_t new_start, size_t new_len)
{
struct address_space *mapping = ractl->mapping;
struct file_ra_state *ra = ractl->ra;
pgoff_t new_index, new_nr_pages;
gfp_t gfp_mask = readahead_gfp_mask(mapping);
unsigned long min_nrpages = mapping_min_folio_nrpages(mapping);
unsigned int min_order = mapping_min_folio_order(mapping);
new_index = new_start / PAGE_SIZE;
/*
* Readahead code should have aligned the ractl->_index to
* min_nrpages before calling readahead aops.
*/
VM_BUG_ON(!IS_ALIGNED(ractl->_index, min_nrpages));
/* Expand the leading edge downwards */
while (ractl->_index > new_index) {
unsigned long index = ractl->_index - 1;
struct folio *folio = xa_load(&mapping->i_pages, index);
if (folio && !xa_is_value(folio))
return; /* Folio apparently present */
folio = ractl_alloc_folio(ractl, gfp_mask, min_order);
if (!folio)
return;
index = mapping_align_index(mapping, index);
if (filemap_add_folio(mapping, folio, index, gfp_mask) < 0) {
folio_put(folio);
return;
}
if (unlikely(folio_test_workingset(folio)) &&
!ractl->_workingset) {
ractl->_workingset = true;
psi_memstall_enter(&ractl->_pflags);
}
ractl->_nr_pages += min_nrpages;
ractl->_index = folio->index;
}
new_len += new_start - readahead_pos(ractl);
new_nr_pages = DIV_ROUND_UP(new_len, PAGE_SIZE);
/* Expand the trailing edge upwards */
while (ractl->_nr_pages < new_nr_pages) {
unsigned long index = ractl->_index + ractl->_nr_pages;
struct folio *folio = xa_load(&mapping->i_pages, index);
if (folio && !xa_is_value(folio))
return; /* Folio apparently present */
folio = ractl_alloc_folio(ractl, gfp_mask, min_order);
if (!folio)
return;
index = mapping_align_index(mapping, index);
if (filemap_add_folio(mapping, folio, index, gfp_mask) < 0) {
Annotation
- Immediate include surface: `linux/blkdev.h`, `linux/kernel.h`, `linux/dax.h`, `linux/gfp.h`, `linux/export.h`, `linux/backing-dev.h`, `linux/task_io_accounting_ops.h`, `linux/pagemap.h`.
- Detected declarations: `syscall readahead`, `function Copyright`, `function read_pages`, `function page_cache_sync_readahead`, `function do_page_cache_ra`, `function force_page_cache_ra`, `function get_init_ra_size`, `function get_next_ra_size`, `function at`, `function page_cache_ra_order`.
- Atlas domain: Core OS / Memory Management.
- Implementation status: core implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.