| 1 |
|
| 2 | #ifndef _LINUX_SWAP_H
|
| 3 | #define _LINUX_SWAP_H
|
| 4 |
|
| 5 | #include <linux/spinlock.h>
|
| 6 | #include <linux/linkage.h>
|
| 7 | #include <linux/mmzone.h>
|
| 8 | #include <linux/list.h>
|
| 9 | #include <linux/memcontrol.h>
|
| 10 | #include <linux/sched.h>
|
| 11 | #include <linux/node.h>
|
| 12 | #include <linux/fs.h>
|
| 13 | #include <linux/pagemap.h>
|
| 14 | #include <linux/atomic.h>
|
| 15 | #include <linux/page-flags.h>
|
| 16 | #include <uapi/linux/mempolicy.h>
|
| 17 | #include <asm/page.h>
|
| 18 |
|
| 19 | #define SWAP_FLAG_PREFER 0x8000
|
| 20 | #define SWAP_FLAG_PRIO_MASK 0x7fff
|
| 21 | #define SWAP_FLAG_DISCARD 0x10000
|
| 22 | #define SWAP_FLAG_DISCARD_ONCE 0x20000
|
| 23 | #define SWAP_FLAG_DISCARD_PAGES 0x40000
|
| 24 |
|
| 25 | #define SWAP_FLAGS_VALID (SWAP_FLAG_PRIO_MASK | SWAP_FLAG_PREFER | \
|
| 26 | SWAP_FLAG_DISCARD | SWAP_FLAG_DISCARD_ONCE | \
|
| 27 | SWAP_FLAG_DISCARD_PAGES)
|
| 28 |
|
| 29 | static inline int current_is_kswapd(void)
|
| 30 | {
|
| 31 | return current->flags & PF_KSWAPD;
|
| 32 | }
|
| 33 |
|
| 34 | |
| 35 | * MAX_SWAPFILES defines the maximum number of swaptypes: things which can
|
| 36 | * be swapped to. The swap type and the offset into that swap type are
|
| 37 | * encoded into pte's and into pgoff_t's in the swapcache. Using five bits
|
| 38 | * for the type means that the maximum number of swapcache pages is 27 bits
|
| 39 | * on 32-bit-pgoff_t architectures. And that assumes that the architecture packs
|
| 40 | * the type/offset into the pte as 5/27 as well.
|
| 41 |
|
| 42 | #define MAX_SWAPFILES_SHIFT 5
|
| 43 |
|
| 44 | |
| 45 | * Use some of the swap files numbers for other purposes. This
|
| 46 | * is a convenient way to hook into the VM to trigger special
|
| 47 | * actions on faults.
|
| 48 |
|
| 49 |
|
| 50 | |
| 51 | * PTE markers are used to persist information onto PTEs that otherwise
|
| 52 | * should be a none pte. As its name "PTE" hints, it should only be
|
| 53 | * applied to the leaves of pgtables.
|
| 54 |
|
| 55 | #define SWP_PTE_MARKER_NUM 1
|
| 56 | #define SWP_PTE_MARKER (MAX_SWAPFILES + SWP_HWPOISON_NUM + \
|
| 57 | SWP_MIGRATION_NUM + SWP_DEVICE_NUM)
|
| 58 |
|
| 59 | |
| 60 | * Unaddressable device memory support. See include/linux/hmm.h and
|
| 61 | * Documentation/mm/hmm.rst. Short description is we need struct pages for
|
| 62 | * device memory that is unaddressable (inaccessible) by CPU, so that we can
|
| 63 | * migrate part of a process memory to device memory.
|
| 64 | *
|
| 65 | * When a page is migrated from CPU to device, we set the CPU page table entry
|
| 66 | * to a special SWP_DEVICE_{READ|WRITE} entry.
|
| 67 | *
|
| 68 | * When a page is mapped by the device for exclusive access we set the CPU page
|
| 69 | * table entries to a special SWP_DEVICE_EXCLUSIVE entry.
|
| 70 |
|
| 71 | #ifdef CONFIG_DEVICE_PRIVATE
|
| 72 | #define SWP_DEVICE_NUM 3
|
| 73 | #define SWP_DEVICE_WRITE (MAX_SWAPFILES+SWP_HWPOISON_NUM+SWP_MIGRATION_NUM)
|
| 74 | #define SWP_DEVICE_READ (MAX_SWAPFILES+SWP_HWPOISON_NUM+SWP_MIGRATION_NUM+1)
|
| 75 | #define SWP_DEVICE_EXCLUSIVE (MAX_SWAPFILES+SWP_HWPOISON_NUM+SWP_MIGRATION_NUM+2)
|
| 76 | #else
|
| 77 | #define SWP_DEVICE_NUM 0
|
| 78 | #endif
|
| 79 |
|
| 80 | |
| 81 | * Page migration support.
|
| 82 | *
|
| 83 | * SWP_MIGRATION_READ_EXCLUSIVE is only applicable to anonymous pages and
|
| 84 | * indicates that the referenced (part of) an anonymous page is exclusive to
|
| 85 | * a single process. For SWP_MIGRATION_WRITE, that information is implicit:
|
| 86 | * (part of) an anonymous page that are mapped writable are exclusive to a
|
| 87 | * single process.
|
| 88 |
|
| 89 | #ifdef CONFIG_MIGRATION
|
| 90 | #define SWP_MIGRATION_NUM 3
|
| 91 | #define SWP_MIGRATION_READ (MAX_SWAPFILES + SWP_HWPOISON_NUM)
|
| 92 | #define SWP_MIGRATION_READ_EXCLUSIVE (MAX_SWAPFILES + SWP_HWPOISON_NUM + 1)
|
| 93 | #define SWP_MIGRATION_WRITE (MAX_SWAPFILES + SWP_HWPOISON_NUM + 2)
|
| 94 | #else
|
| 95 | #define SWP_MIGRATION_NUM 0
|
| 96 | #endif
|
| 97 |
|
| 98 | |
| 99 | * Handling of hardware poisoned pages with memory corruption.
|
| 100 |
|
| 101 | #ifdef CONFIG_MEMORY_FAILURE
|
| 102 | #define SWP_HWPOISON_NUM 1
|
| 103 | #define SWP_HWPOISON MAX_SWAPFILES
|
| 104 | #else
|
| 105 | #define SWP_HWPOISON_NUM 0
|
| 106 | #endif
|
| 107 |
|
| 108 | #define MAX_SWAPFILES \
|
| 109 | ((1 << MAX_SWAPFILES_SHIFT) - SWP_DEVICE_NUM - \
|
| 110 | SWP_MIGRATION_NUM - SWP_HWPOISON_NUM - \
|
| 111 | SWP_PTE_MARKER_NUM)
|
| 112 |
|
| 113 | |
| 114 | * Magic header for a swap area. The first part of the union is
|
| 115 | * what the swap magic looks like for the old (limited to 128MB)
|
| 116 | * swap area format, the second part of the union adds - in the
|
| 117 | * old reserved area - some extra information. Note that the first
|
| 118 | * kilobyte is reserved for boot loader or disk label stuff...
|
| 119 | *
|
| 120 | * Having the magic at the end of the PAGE_SIZE makes detecting swap
|
| 121 | * areas somewhat tricky on machines that support multiple page sizes.
|
| 122 | * For 2.5 we'll probably want to move the magic to just beyond the
|
| 123 | * bootbits...
|
| 124 |
|
| 125 | union swap_header {
|
| 126 | struct {
|
| 127 | char reserved[PAGE_SIZE - 10];
|
| 128 | char magic[10];
|
| 129 | } magic;
|
| 130 | struct {
|
| 131 | char bootbits[1024];
|
| 132 | __u32 version;
|
| 133 | __u32 last_page;
|
| 134 | __u32 nr_badpages;
|
| 135 | unsigned char sws_uuid[16];
|
| 136 | unsigned char sws_volume[16];
|
| 137 | __u32 padding[117];
|
| 138 | __u32 badpages[1];
|
| 139 | } info;
|
| 140 | };
|
| 141 |
|
| 142 | |
| 143 | * current->reclaim_state points to one of these when a task is running
|
| 144 | * memory reclaim
|
| 145 |
|
| 146 | struct reclaim_state {
|
| 147 |
|
| 148 | unsigned long reclaimed;
|
| 149 | #ifdef CONFIG_LRU_GEN
|
| 150 |
|
| 151 | struct lru_gen_mm_walk *mm_walk;
|
| 152 | #endif
|
| 153 | };
|
| 154 |
|
| 155 | |
| 156 | * mm_account_reclaimed_pages(): account reclaimed pages outside of LRU-based
|
| 157 | * reclaim
|
| 158 | * @pages: number of pages reclaimed
|
| 159 | *
|
| 160 | * If the current process is undergoing a reclaim operation, increment the
|
| 161 | * number of reclaimed pages by @pages.
|
| 162 |
|
| 163 | static inline void mm_account_reclaimed_pages(unsigned long pages)
|
| 164 | {
|
| 165 | if (current->reclaim_state)
|
| 166 | current->reclaim_state->reclaimed += pages;
|
| 167 | }
|
| 168 |
|
| 169 | #ifdef __KERNEL__
|
| 170 |
|
| 171 | struct address_space;
|
| 172 | struct sysinfo;
|
| 173 | struct zone;
|
| 174 |
|
| 175 | |
| 176 | * A swap extent maps a range of a swapfile's PAGE_SIZE pages onto a range of
|
| 177 | * disk blocks. A rbtree of swap extents maps the entire swapfile (Where the
|
| 178 | * term `swapfile' refers to either a blockdevice or an IS_REG file). Apart
|
| 179 | * from setup, they're handled identically.
|
| 180 | *
|
| 181 | * We always assume that blocks are of size PAGE_SIZE.
|
| 182 |
|
| 183 | struct swap_extent {
|
| 184 | struct rb_node rb_node;
|
| 185 | pgoff_t start_page;
|
| 186 | pgoff_t nr_pages;
|
| 187 | sector_t start_block;
|
| 188 | };
|
| 189 |
|
| 190 | |
| 191 | * Max bad pages in the new format..
|
| 192 |
|
| 193 | #define MAX_SWAP_BADPAGES \
|
| 194 | ((offsetof(union swap_header, magic.magic) - \
|
| 195 | offsetof(union swap_header, info.badpages)) / sizeof(int))
|
| 196 |
|
| 197 | enum {
|
| 198 | SWP_USED = (1 << 0),
|
| 199 | SWP_WRITEOK = (1 << 1),
|
| 200 | SWP_DISCARDABLE = (1 << 2),
|
| 201 | SWP_DISCARDING = (1 << 3),
|
| 202 | SWP_SOLIDSTATE = (1 << 4),
|
| 203 | SWP_BLKDEV = (1 << 6),
|
| 204 | SWP_ACTIVATED = (1 << 7),
|
| 205 | SWP_AREA_DISCARD = (1 << 9),
|
| 206 | SWP_PAGE_DISCARD = (1 << 10),
|
| 207 | SWP_STABLE_WRITES = (1 << 11),
|
| 208 | SWP_SYNCHRONOUS_IO = (1 << 12),
|
| 209 | SWP_HIBERNATION = (1 << 13),
|
| 210 |
|
| 211 | };
|
| 212 |
|
| 213 | #define SWAP_CLUSTER_MAX 32UL
|
| 214 | #define SWAP_CLUSTER_MAX_SKIPPED (SWAP_CLUSTER_MAX << 10)
|
| 215 | #define COMPACT_CLUSTER_MAX SWAP_CLUSTER_MAX
|
| 216 |
|
| 217 | |
| 218 | * The first page in the swap file is the swap header, which is always marked
|
| 219 | * bad to prevent it from being allocated as an entry. This also prevents the
|
| 220 | * cluster to which it belongs being marked free. Therefore 0 is safe to use as
|
| 221 | * a sentinel to indicate an entry is not valid.
|
| 222 |
|
| 223 | #define SWAP_ENTRY_INVALID 0
|
| 224 |
|
| 225 | #ifdef CONFIG_THP_SWAP
|
| 226 | #define SWAP_NR_ORDERS (PMD_ORDER + 1)
|
| 227 | #else
|
| 228 | #define SWAP_NR_ORDERS 1
|
| 229 | #endif
|
| 230 |
|
| 231 | |
| 232 | * We keep using same cluster for rotational device so IO will be sequential.
|
| 233 | * The purpose is to optimize SWAP throughput on these device.
|
| 234 |
|
| 235 | struct swap_sequential_cluster {
|
| 236 | unsigned int next[SWAP_NR_ORDERS];
|
| 237 | };
|
| 238 |
|
| 239 | |
| 240 | * The in-memory structure used to track swap areas.
|
| 241 |
|
| 242 | struct swap_info_struct {
|
| 243 | struct percpu_ref users;
|
| 244 | unsigned long flags;
|
| 245 | signed short prio;
|
| 246 | struct plist_node list;
|
| 247 | signed char type;
|
| 248 | unsigned int max;
|
| 249 | struct swap_cluster_info *cluster_info;
|
| 250 | struct list_head free_clusters;
|
| 251 | struct list_head full_clusters;
|
| 252 | struct list_head nonfull_clusters[SWAP_NR_ORDERS];
|
| 253 |
|
| 254 | struct list_head frag_clusters[SWAP_NR_ORDERS];
|
| 255 |
|
| 256 | unsigned int pages;
|
| 257 | atomic_long_t inuse_pages;
|
| 258 | struct swap_sequential_cluster *global_cluster;
|
| 259 | spinlock_t global_cluster_lock;
|
| 260 | struct rb_root swap_extent_root;
|
| 261 | struct block_device *bdev;
|
| 262 | struct file *swap_file;
|
| 263 | struct completion comp;
|
| 264 | spinlock_t lock; |
| 265 | * protect map scan related fields like
|
| 266 | * inuse_pages and all cluster lists.
|
| 267 | * Other fields are only changed
|
| 268 | * at swapon/swapoff, so are protected
|
| 269 | * by swap_lock. changing flags need
|
| 270 | * hold this lock and swap_lock. If
|
| 271 | * both locks need hold, hold swap_lock
|
| 272 | * first.
|
| 273 |
|
| 274 | struct work_struct discard_work;
|
| 275 | struct work_struct reclaim_work;
|
| 276 | struct list_head discard_clusters;
|
| 277 | struct plist_node avail_list;
|
| 278 | const struct swap_ops *ops;
|
| 279 | };
|
| 280 |
|
| 281 | static inline swp_entry_t page_swap_entry(struct page *page)
|
| 282 | {
|
| 283 | struct folio *folio = page_folio(page);
|
| 284 | swp_entry_t entry = folio->swap;
|
| 285 |
|
| 286 | entry.val += folio_page_idx(folio, page);
|
| 287 | return entry;
|
| 288 | }
|
| 289 |
|
| 290 |
|
| 291 | extern unsigned long totalreserve_pages;
|
| 292 |
|
| 293 |
|
| 294 | #define nr_free_pages() global_zone_page_state(NR_FREE_PAGES)
|
| 295 |
|
| 296 |
|
| 297 | void folio_add_lru(struct folio *folio);
|
| 298 | void folio_mark_accessed(struct folio *folio);
|
| 299 | void lru_add_drain_all(void);
|
| 300 |
|
| 301 | enum lru_cache_drained {
|
| 302 | LRU_CACHE_NOT_DRAINED,
|
| 303 | LRU_CACHE_DRAINED,
|
| 304 | LRU_CACHE_DRAINED_ALL,
|
| 305 | };
|
| 306 | void lru_cache_drain_for_folio(const struct folio *folio,
|
| 307 | unsigned int extra_refs, enum lru_cache_drained *drained);
|
| 308 |
|
| 309 |
|
| 310 | void mark_page_accessed(struct page *page);
|
| 311 |
|
| 312 | extern atomic_t lru_disable_count;
|
| 313 |
|
| 314 | static inline bool lru_cache_disabled(void)
|
| 315 | {
|
| 316 | return atomic_read(&lru_disable_count);
|
| 317 | }
|
| 318 |
|
| 319 | extern unsigned long shrink_all_memory(unsigned long nr_pages);
|
| 320 | long remove_mapping(struct address_space *mapping, struct folio *folio);
|
| 321 |
|
| 322 | #if defined(CONFIG_SYSFS) && defined(CONFIG_NUMA)
|
| 323 | extern int reclaim_register_node(struct node *node);
|
| 324 | extern void reclaim_unregister_node(struct node *node);
|
| 325 |
|
| 326 | #else
|
| 327 |
|
| 328 | static inline int reclaim_register_node(struct node *node)
|
| 329 | {
|
| 330 | return 0;
|
| 331 | }
|
| 332 |
|
| 333 | static inline void reclaim_unregister_node(struct node *node)
|
| 334 | {
|
| 335 | }
|
| 336 | #endif
|
| 337 |
|
| 338 | void check_move_unevictable_folios(struct folio_batch *fbatch);
|
| 339 |
|
| 340 | extern void __meminit kswapd_run(int nid);
|
| 341 | extern void __meminit kswapd_stop(int nid);
|
| 342 |
|
| 343 | #ifdef CONFIG_SWAP
|
| 344 | int add_swap_extent(struct swap_info_struct *sis, unsigned long start_page,
|
| 345 | unsigned long nr_pages, sector_t start_block);
|
| 346 | int generic_swapfile_activate(struct swap_info_struct *, struct file *,
|
| 347 | sector_t *);
|
| 348 |
|
| 349 | static inline unsigned long total_swapcache_pages(void)
|
| 350 | {
|
| 351 | return global_node_page_state(NR_SWAPCACHE);
|
| 352 | }
|
| 353 |
|
| 354 | void free_swap_cache(struct folio *folio);
|
| 355 | void free_folio_and_swap_cache(struct folio *folio);
|
| 356 | void free_pages_and_swap_cache(struct encoded_page **, int);
|
| 357 |
|
| 358 | extern atomic_long_t nr_swap_pages;
|
| 359 | extern long total_swap_pages;
|
| 360 | extern atomic_t nr_rotate_swap;
|
| 361 |
|
| 362 |
|
| 363 | static inline bool vm_swap_full(void)
|
| 364 | {
|
| 365 | return atomic_long_read(&nr_swap_pages) * 2 < total_swap_pages;
|
| 366 | }
|
| 367 |
|
| 368 | static inline long get_nr_swap_pages(void)
|
| 369 | {
|
| 370 | return atomic_long_read(&nr_swap_pages);
|
| 371 | }
|
| 372 |
|
| 373 | extern void si_swapinfo(struct sysinfo *);
|
| 374 | extern int pin_hibernation_swap_type(dev_t device, sector_t offset);
|
| 375 | extern void unpin_hibernation_swap_type(int type);
|
| 376 | extern int find_hibernation_swap_type(dev_t device, sector_t offset);
|
| 377 | int find_first_swap(dev_t *device);
|
| 378 | extern unsigned int count_swap_pages(int, int);
|
| 379 | extern sector_t swapdev_block(int, pgoff_t);
|
| 380 | extern int __swap_count(swp_entry_t entry);
|
| 381 | extern bool swap_entry_swapped(struct swap_info_struct *si, swp_entry_t entry);
|
| 382 | extern int swp_swapcount(swp_entry_t entry);
|
| 383 | extern struct swap_info_struct *get_swap_device(swp_entry_t entry);
|
| 384 | sector_t swap_folio_sector(struct folio *folio);
|
| 385 |
|
| 386 | |
| 387 | * If there is an existing swap slot reference (swap entry) and the caller
|
| 388 | * guarantees that there is no race modification of it (e.g., PTL
|
| 389 | * protecting the swap entry in page table; shmem's cmpxchg protects t
|
| 390 | * he swap entry in shmem mapping), these two helpers below can be used
|
| 391 | * to put/dup the entries directly.
|
| 392 | *
|
| 393 | * All entries must be allocated by folio_alloc_swap(). And they must have
|
| 394 | * a swap count > 1. See comments of folio_*_swap helpers for more info.
|
| 395 |
|
| 396 | int swap_dup_entry_direct(swp_entry_t entry);
|
| 397 | void swap_put_entries_direct(swp_entry_t entry, int nr);
|
| 398 |
|
| 399 | |
| 400 | * folio_free_swap tries to free the swap entries pinned by a swap cache
|
| 401 | * folio, it has to be here to be called by other components.
|
| 402 |
|
| 403 | bool folio_free_swap(struct folio *folio);
|
| 404 |
|
| 405 |
|
| 406 | swp_entry_t swap_alloc_hibernation_slot(int type);
|
| 407 | void swap_free_hibernation_slot(swp_entry_t entry);
|
| 408 |
|
| 409 | static inline void put_swap_device(struct swap_info_struct *si)
|
| 410 | {
|
| 411 | percpu_ref_put(&si->users);
|
| 412 | }
|
| 413 |
|
| 414 | #else
|
| 415 | static inline struct swap_info_struct *get_swap_device(swp_entry_t entry)
|
| 416 | {
|
| 417 | return NULL;
|
| 418 | }
|
| 419 |
|
| 420 | static inline void put_swap_device(struct swap_info_struct *si)
|
| 421 | {
|
| 422 | }
|
| 423 |
|
| 424 | #define get_nr_swap_pages() 0L
|
| 425 | #define total_swap_pages 0L
|
| 426 | #define total_swapcache_pages() 0UL
|
| 427 | #define vm_swap_full() 0
|
| 428 |
|
| 429 | #define si_swapinfo(val) \
|
| 430 | do { (val)->freeswap = (val)->totalswap = 0; } while (0)
|
| 431 | #define free_folio_and_swap_cache(folio) \
|
| 432 | folio_put(folio)
|
| 433 | #define free_pages_and_swap_cache(pages, nr) \
|
| 434 | release_pages((pages), (nr));
|
| 435 |
|
| 436 | static inline void free_swap_cache(struct folio *folio)
|
| 437 | {
|
| 438 | }
|
| 439 |
|
| 440 | static inline int swap_dup_entry_direct(swp_entry_t ent)
|
| 441 | {
|
| 442 | return 0;
|
| 443 | }
|
| 444 |
|
| 445 | static inline void swap_put_entries_direct(swp_entry_t ent, int nr)
|
| 446 | {
|
| 447 | }
|
| 448 |
|
| 449 | static inline int __swap_count(swp_entry_t entry)
|
| 450 | {
|
| 451 | return 0;
|
| 452 | }
|
| 453 |
|
| 454 | static inline bool swap_entry_swapped(struct swap_info_struct *si, swp_entry_t entry)
|
| 455 | {
|
| 456 | return false;
|
| 457 | }
|
| 458 |
|
| 459 | static inline int swp_swapcount(swp_entry_t entry)
|
| 460 | {
|
| 461 | return 0;
|
| 462 | }
|
| 463 |
|
| 464 | static inline bool folio_free_swap(struct folio *folio)
|
| 465 | {
|
| 466 | return false;
|
| 467 | }
|
| 468 |
|
| 469 | static inline int add_swap_extent(struct swap_info_struct *sis,
|
| 470 | unsigned long start_page,
|
| 471 | unsigned long nr_pages, sector_t start_block)
|
| 472 | {
|
| 473 | return -EINVAL;
|
| 474 | }
|
| 475 | #endif
|
| 476 | #ifdef CONFIG_MEMCG
|
| 477 | void lru_reparent_memcg(struct mem_cgroup *memcg, struct mem_cgroup *parent, int nid);
|
| 478 | #endif
|
| 479 |
|
| 480 | #if defined(CONFIG_SWAP) && defined(CONFIG_MEMCG) && defined(CONFIG_BLK_CGROUP)
|
| 481 | void __folio_throttle_swaprate(struct folio *folio, gfp_t gfp);
|
| 482 | static inline void folio_throttle_swaprate(struct folio *folio, gfp_t gfp)
|
| 483 | {
|
| 484 | if (mem_cgroup_disabled())
|
| 485 | return;
|
| 486 | __folio_throttle_swaprate(folio, gfp);
|
| 487 | }
|
| 488 | #else
|
| 489 | static inline void folio_throttle_swaprate(struct folio *folio, gfp_t gfp)
|
| 490 | {
|
| 491 | }
|
| 492 | #endif
|
| 493 |
|
| 494 | #if defined(CONFIG_MEMCG) && defined(CONFIG_SWAP)
|
| 495 | int __mem_cgroup_try_charge_swap(struct folio *folio);
|
| 496 | static inline int mem_cgroup_try_charge_swap(struct folio *folio)
|
| 497 | {
|
| 498 | if (mem_cgroup_disabled())
|
| 499 | return 0;
|
| 500 | return __mem_cgroup_try_charge_swap(folio);
|
| 501 | }
|
| 502 |
|
| 503 | extern void __mem_cgroup_uncharge_swap(unsigned short id, unsigned int nr_pages);
|
| 504 | static inline void mem_cgroup_uncharge_swap(unsigned short id, unsigned int nr_pages)
|
| 505 | {
|
| 506 | if (mem_cgroup_disabled())
|
| 507 | return;
|
| 508 | __mem_cgroup_uncharge_swap(id, nr_pages);
|
| 509 | }
|
| 510 |
|
| 511 | extern long mem_cgroup_get_nr_swap_pages(struct mem_cgroup *memcg);
|
| 512 | extern bool mem_cgroup_swap_full(struct folio *folio);
|
| 513 | #else
|
| 514 | static inline int mem_cgroup_try_charge_swap(struct folio *folio)
|
| 515 | {
|
| 516 | return 0;
|
| 517 | }
|
| 518 |
|
| 519 | static inline void mem_cgroup_uncharge_swap(unsigned short id,
|
| 520 | unsigned int nr_pages)
|
| 521 | {
|
| 522 | }
|
| 523 |
|
| 524 | static inline long mem_cgroup_get_nr_swap_pages(struct mem_cgroup *memcg)
|
| 525 | {
|
| 526 | return get_nr_swap_pages();
|
| 527 | }
|
| 528 |
|
| 529 | static inline bool mem_cgroup_swap_full(struct folio *folio)
|
| 530 | {
|
| 531 | return vm_swap_full();
|
| 532 | }
|
| 533 | #endif
|
| 534 |
|
| 535 | |
| 536 | * and including the specified highidx
|
| 537 | * @zone: The current zone in the iterator
|
| 538 | * @pgdat: The pgdat which node_zones are being iterated
|
| 539 | * @idx: The index variable
|
| 540 | * @highidx: The index of the highest zone to return
|
| 541 | *
|
| 542 | * This macro iterates through all managed zones up to and including the specified highidx.
|
| 543 | * The zone iterator enters an invalid state after macro call and must be reinitialized
|
| 544 | * before it can be used again.
|
| 545 |
|
| 546 | #define for_each_managed_zone_pgdat(zone, pgdat, idx, highidx) \
|
| 547 | for ((idx) = 0, (zone) = (pgdat)->node_zones; \
|
| 548 | (idx) <= (highidx); \
|
| 549 | (idx)++, (zone)++) \
|
| 550 | if (!managed_zone(zone)) \
|
| 551 | continue; \
|
| 552 | else
|
| 553 |
|
| 554 | #endif
|
| 555 | #endif
|