filemap.c (5c68005083d620b1499fc81926a514d39ae8b88c) filemap.c (cf264e1329fb0307e044f7675849f9f38b44c11a)
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * linux/mm/filemap.c
4 *
5 * Copyright (C) 1994-1999 Linus Torvalds
6 */
7
8/*

--- 8 unchanged lines hidden (view full) ---

17#include <linux/sched/signal.h>
18#include <linux/uaccess.h>
19#include <linux/capability.h>
20#include <linux/kernel_stat.h>
21#include <linux/gfp.h>
22#include <linux/mm.h>
23#include <linux/swap.h>
24#include <linux/swapops.h>
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * linux/mm/filemap.c
4 *
5 * Copyright (C) 1994-1999 Linus Torvalds
6 */
7
8/*

--- 8 unchanged lines hidden (view full) ---

17#include <linux/sched/signal.h>
18#include <linux/uaccess.h>
19#include <linux/capability.h>
20#include <linux/kernel_stat.h>
21#include <linux/gfp.h>
22#include <linux/mm.h>
23#include <linux/swap.h>
24#include <linux/swapops.h>
25#include <linux/syscalls.h>
25#include <linux/mman.h>
26#include <linux/pagemap.h>
27#include <linux/file.h>
28#include <linux/uio.h>
29#include <linux/error-injection.h>
30#include <linux/hash.h>
31#include <linux/writeback.h>
32#include <linux/backing-dev.h>

--- 20 unchanged lines hidden (view full) ---

53
54/*
55 * FIXME: remove all knowledge of the buffer layer from the core VM
56 */
57#include <linux/buffer_head.h> /* for try_to_free_buffers */
58
59#include <asm/mman.h>
60
26#include <linux/mman.h>
27#include <linux/pagemap.h>
28#include <linux/file.h>
29#include <linux/uio.h>
30#include <linux/error-injection.h>
31#include <linux/hash.h>
32#include <linux/writeback.h>
33#include <linux/backing-dev.h>

--- 20 unchanged lines hidden (view full) ---

54
55/*
56 * FIXME: remove all knowledge of the buffer layer from the core VM
57 */
58#include <linux/buffer_head.h> /* for try_to_free_buffers */
59
60#include <asm/mman.h>
61
62#include "swap.h"
63
61/*
62 * Shared mappings implemented 30.11.1994. It's not fully working yet,
63 * though.
64 *
65 * Shared mappings now work. 15.8.1995 Bruno.
66 *
67 * finished 'unifying' the page and buffer cache and SMP-threaded the
68 * page-cache, 21.05.1999, Ingo Molnar <mingo@redhat.com>

--- 4045 unchanged lines hidden (view full) ---

4114 if (folio_test_writeback(folio))
4115 return false;
4116
4117 if (mapping && mapping->a_ops->release_folio)
4118 return mapping->a_ops->release_folio(folio, gfp);
4119 return try_to_free_buffers(folio);
4120}
4121EXPORT_SYMBOL(filemap_release_folio);
64/*
65 * Shared mappings implemented 30.11.1994. It's not fully working yet,
66 * though.
67 *
68 * Shared mappings now work. 15.8.1995 Bruno.
69 *
70 * finished 'unifying' the page and buffer cache and SMP-threaded the
71 * page-cache, 21.05.1999, Ingo Molnar <mingo@redhat.com>

--- 4045 unchanged lines hidden (view full) ---

4117 if (folio_test_writeback(folio))
4118 return false;
4119
4120 if (mapping && mapping->a_ops->release_folio)
4121 return mapping->a_ops->release_folio(folio, gfp);
4122 return try_to_free_buffers(folio);
4123}
4124EXPORT_SYMBOL(filemap_release_folio);
4125
4126#ifdef CONFIG_CACHESTAT_SYSCALL
4127/**
4128 * filemap_cachestat() - compute the page cache statistics of a mapping
4129 * @mapping: The mapping to compute the statistics for.
4130 * @first_index: The starting page cache index.
4131 * @last_index: The final page index (inclusive).
4132 * @cs: the cachestat struct to write the result to.
4133 *
4134 * This will query the page cache statistics of a mapping in the
4135 * page range of [first_index, last_index] (inclusive). The statistics
4136 * queried include: number of dirty pages, number of pages marked for
4137 * writeback, and the number of (recently) evicted pages.
4138 */
4139static void filemap_cachestat(struct address_space *mapping,
4140 pgoff_t first_index, pgoff_t last_index, struct cachestat *cs)
4141{
4142 XA_STATE(xas, &mapping->i_pages, first_index);
4143 struct folio *folio;
4144
4145 rcu_read_lock();
4146 xas_for_each(&xas, folio, last_index) {
4147 unsigned long nr_pages;
4148 pgoff_t folio_first_index, folio_last_index;
4149
4150 if (xas_retry(&xas, folio))
4151 continue;
4152
4153 if (xa_is_value(folio)) {
4154 /* page is evicted */
4155 void *shadow = (void *)folio;
4156 bool workingset; /* not used */
4157 int order = xa_get_order(xas.xa, xas.xa_index);
4158
4159 nr_pages = 1 << order;
4160 folio_first_index = round_down(xas.xa_index, 1 << order);
4161 folio_last_index = folio_first_index + nr_pages - 1;
4162
4163 /* Folios might straddle the range boundaries, only count covered pages */
4164 if (folio_first_index < first_index)
4165 nr_pages -= first_index - folio_first_index;
4166
4167 if (folio_last_index > last_index)
4168 nr_pages -= folio_last_index - last_index;
4169
4170 cs->nr_evicted += nr_pages;
4171
4172#ifdef CONFIG_SWAP /* implies CONFIG_MMU */
4173 if (shmem_mapping(mapping)) {
4174 /* shmem file - in swap cache */
4175 swp_entry_t swp = radix_to_swp_entry(folio);
4176
4177 shadow = get_shadow_from_swap_cache(swp);
4178 }
4179#endif
4180 if (workingset_test_recent(shadow, true, &workingset))
4181 cs->nr_recently_evicted += nr_pages;
4182
4183 goto resched;
4184 }
4185
4186 nr_pages = folio_nr_pages(folio);
4187 folio_first_index = folio_pgoff(folio);
4188 folio_last_index = folio_first_index + nr_pages - 1;
4189
4190 /* Folios might straddle the range boundaries, only count covered pages */
4191 if (folio_first_index < first_index)
4192 nr_pages -= first_index - folio_first_index;
4193
4194 if (folio_last_index > last_index)
4195 nr_pages -= folio_last_index - last_index;
4196
4197 /* page is in cache */
4198 cs->nr_cache += nr_pages;
4199
4200 if (folio_test_dirty(folio))
4201 cs->nr_dirty += nr_pages;
4202
4203 if (folio_test_writeback(folio))
4204 cs->nr_writeback += nr_pages;
4205
4206resched:
4207 if (need_resched()) {
4208 xas_pause(&xas);
4209 cond_resched_rcu();
4210 }
4211 }
4212 rcu_read_unlock();
4213}
4214
4215/*
4216 * The cachestat(2) system call.
4217 *
4218 * cachestat() returns the page cache statistics of a file in the
4219 * bytes range specified by `off` and `len`: number of cached pages,
4220 * number of dirty pages, number of pages marked for writeback,
4221 * number of evicted pages, and number of recently evicted pages.
4222 *
4223 * An evicted page is a page that is previously in the page cache
4224 * but has been evicted since. A page is recently evicted if its last
4225 * eviction was recent enough that its reentry to the cache would
4226 * indicate that it is actively being used by the system, and that
4227 * there is memory pressure on the system.
4228 *
4229 * `off` and `len` must be non-negative integers. If `len` > 0,
4230 * the queried range is [`off`, `off` + `len`]. If `len` == 0,
4231 * we will query in the range from `off` to the end of the file.
4232 *
4233 * The `flags` argument is unused for now, but is included for future
4234 * extensibility. User should pass 0 (i.e no flag specified).
4235 *
4236 * Currently, hugetlbfs is not supported.
4237 *
4238 * Because the status of a page can change after cachestat() checks it
4239 * but before it returns to the application, the returned values may
4240 * contain stale information.
4241 *
4242 * return values:
4243 * zero - success
4244 * -EFAULT - cstat or cstat_range points to an illegal address
4245 * -EINVAL - invalid flags
4246 * -EBADF - invalid file descriptor
4247 * -EOPNOTSUPP - file descriptor is of a hugetlbfs file
4248 */
4249SYSCALL_DEFINE4(cachestat, unsigned int, fd,
4250 struct cachestat_range __user *, cstat_range,
4251 struct cachestat __user *, cstat, unsigned int, flags)
4252{
4253 struct fd f = fdget(fd);
4254 struct address_space *mapping;
4255 struct cachestat_range csr;
4256 struct cachestat cs;
4257 pgoff_t first_index, last_index;
4258
4259 if (!f.file)
4260 return -EBADF;
4261
4262 if (copy_from_user(&csr, cstat_range,
4263 sizeof(struct cachestat_range))) {
4264 fdput(f);
4265 return -EFAULT;
4266 }
4267
4268 /* hugetlbfs is not supported */
4269 if (is_file_hugepages(f.file)) {
4270 fdput(f);
4271 return -EOPNOTSUPP;
4272 }
4273
4274 if (flags != 0) {
4275 fdput(f);
4276 return -EINVAL;
4277 }
4278
4279 first_index = csr.off >> PAGE_SHIFT;
4280 last_index =
4281 csr.len == 0 ? ULONG_MAX : (csr.off + csr.len - 1) >> PAGE_SHIFT;
4282 memset(&cs, 0, sizeof(struct cachestat));
4283 mapping = f.file->f_mapping;
4284 filemap_cachestat(mapping, first_index, last_index, &cs);
4285 fdput(f);
4286
4287 if (copy_to_user(cstat, &cs, sizeof(struct cachestat)))
4288 return -EFAULT;
4289
4290 return 0;
4291}
4292#endif /* CONFIG_CACHESTAT_SYSCALL */