mm/swapfile.c
Source file repositories/reference/linux-study-clean/mm/swapfile.c
File Facts
- System
- Linux kernel
- Corpus path
mm/swapfile.c- Extension
.c- Size
- 106039 bytes
- Lines
- 3933
- 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/mm.hlinux/sched/mm.hlinux/sched/task.hlinux/hugetlb.hlinux/mman.hlinux/slab.hlinux/kernel_stat.hlinux/swap.hlinux/vmalloc.hlinux/pagemap.hlinux/namei.hlinux/shmem_fs.hlinux/blk-cgroup.hlinux/random.hlinux/writeback.hlinux/proc_fs.hlinux/seq_file.hlinux/init.hlinux/ksm.hlinux/rmap.hlinux/security.hlinux/backing-dev.hlinux/mutex.hlinux/capability.hlinux/syscalls.hlinux/memcontrol.hlinux/poll.hlinux/oom.hlinux/swapfile.hlinux/export.hlinux/sort.h
Detected Declarations
syscall swapoffsyscall swaponstruct percpu_swap_clusterfunction notfunction swap_only_has_cachefunction __try_to_reclaim_swapfunction discard_swapfunction offset_to_swap_extentfunction swap_folio_sectorfunction discard_swap_clusterfunction cluster_is_emptyfunction cluster_is_discardfunction cluster_table_is_allocedfunction cluster_is_usablefunction cluster_indexfunction cluster_offsetfunction swap_cluster_free_table_folio_rcu_cbfunction swap_cluster_free_tablefunction swap_cluster_alloc_tablefunction swap_cluster_assert_emptyfunction swap_cluster_populatefunction move_clusterfunction swap_cluster_schedule_discardfunction __free_clusterfunction swap_do_scheduled_discardfunction swap_discard_workfunction swap_users_ref_freefunction free_clusterfunction partial_free_clusterfunction relocate_clusterfunction swap_cluster_setup_bad_slotfunction cluster_reclaim_rangefunction cluster_scan_rangefunction __swap_cluster_alloc_entriesfunction foliofunction alloc_swap_scan_clusterfunction alloc_swap_scan_listfunction swap_reclaim_full_clustersfunction swap_reclaim_workfunction cluster_alloc_swap_entryfunction del_from_avail_listfunction add_to_avail_listfunction swap_usage_addfunction swap_usage_subfunction swap_range_allocfunction swap_range_freefunction get_swap_device_infofunction swap_alloc_fast
Annotated Snippet
SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
{
struct swap_info_struct *p = NULL;
struct swap_cluster_info *cluster_info;
struct file *swap_file, *victim;
struct address_space *mapping;
struct inode *inode;
unsigned int maxpages;
int err, found = 0;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
BUG_ON(!current->mm);
CLASS(filename, pathname)(specialfile);
victim = file_open_name(pathname, O_RDWR|O_LARGEFILE, 0);
if (IS_ERR(victim))
return PTR_ERR(victim);
mapping = victim->f_mapping;
spin_lock(&swap_lock);
plist_for_each_entry(p, &swap_active_head, list) {
if (p->flags & SWP_WRITEOK) {
if (p->swap_file->f_mapping == mapping) {
found = 1;
break;
}
}
}
if (!found) {
err = -EINVAL;
spin_unlock(&swap_lock);
goto out_dput;
}
/* Refuse swapoff while the device is pinned for hibernation */
if (p->flags & SWP_HIBERNATION) {
err = -EBUSY;
spin_unlock(&swap_lock);
goto out_dput;
}
if (!security_vm_enough_memory_mm(current->mm, p->pages))
vm_unacct_memory(p->pages);
else {
err = -ENOMEM;
spin_unlock(&swap_lock);
goto out_dput;
}
spin_lock(&p->lock);
del_from_avail_list(p, true);
plist_del(&p->list, &swap_active_head);
atomic_long_sub(p->pages, &nr_swap_pages);
total_swap_pages -= p->pages;
spin_unlock(&p->lock);
spin_unlock(&swap_lock);
wait_for_allocation(p);
set_current_oom_origin();
err = try_to_unuse(p->type);
clear_current_oom_origin();
if (err) {
/* re-insert swap space back into swap_list */
reinsert_swap_info(p);
goto out_dput;
}
/*
* Wait for swap operations protected by get/put_swap_device()
* to complete. Because of synchronize_rcu() here, all swap
* operations protected by RCU reader side lock (including any
* spinlock) will be waited too. This makes it easy to
* prevent folio_test_swapcache() and the following swap cache
* operations from racing with swapoff.
*/
percpu_ref_kill(&p->users);
synchronize_rcu();
wait_for_completion(&p->comp);
flush_work(&p->discard_work);
flush_work(&p->reclaim_work);
flush_percpu_swap_cluster(p);
destroy_swap_extents(p, p->swap_file);
if (!(p->flags & SWP_SOLIDSTATE))
atomic_dec(&nr_rotate_swap);
Annotation
- Immediate include surface: `linux/blkdev.h`, `linux/mm.h`, `linux/sched/mm.h`, `linux/sched/task.h`, `linux/hugetlb.h`, `linux/mman.h`, `linux/slab.h`, `linux/kernel_stat.h`.
- Detected declarations: `syscall swapoff`, `syscall swapon`, `struct percpu_swap_cluster`, `function not`, `function swap_only_has_cache`, `function __try_to_reclaim_swap`, `function discard_swap`, `function offset_to_swap_extent`, `function swap_folio_sector`, `function discard_swap_cluster`.
- 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.