mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-10-26 10:57:38 +08:00
Pull MM updates from Andrew Morton:
- "selftests/mm: improve khugepaged coverage" (Kiryl Shutsemau):
Give khugepaged a proper workout. Extend the tests to all supported
mTHP orders, check exactly which windows collapsed, and make scan
completion deterministic. Race collapse against faults, pinning, fork
and remap; verify that the contents survive.
Add coverage for whole-page-table zaps and memory pressure too.
- "selftests/mm: separate GUP microbenchmarking from functional testing"
(Sarthak Sharma):
Untangle GUP benchmarking from correctness testing. Move the
benchmark into tools/mm, add a standalone harness-based GUP selftest,
and move shared helpers into tools/lib/mm. Give each tool one job
instead of mixing timing measurements with correctness checks.
Cover the mapping, pinning and batch-size combinations explicitly.
- "mm: Switch device DAX to section-based vmemmap optimization" (Muchun
Song):
Apply section-based vmemmap optimization to device DAX. Rework the
backing metadata layout to save memory while preserving the handling
of device memory hotplug and its different alignment and lifetime
requirements.
- "mm: Introduce section-based vmemmap optimization for HugeTLB"
(Muchun Song):
Cut the memory consumed by HugeTLB's struct page array with
section-based vmemmap optimization. Arrange the metadata so large
huge pages need fewer backing pages, while keeping initialization,
teardown and the various hugepage configurations straight.
- "mm/huge_memory: clean up and decouple the anon and file split
helpers" (Kairui Song):
Separate anonymous and file-backed folio splitting, which have rather
different locking and bookkeeping requirements. Move the work into
separate helpers, drop dead checks and tidy swap-cache handling. Fix
error paths, including one that could leave a folio frozen.
Keep the swap cache cases separate from file-cache splitting.
- "mm: Unconditional per-VMA locks and cleanups" (Dave Hansen):
Make per-VMA locking unconditional and clean up the old conditional
code around it. This removes configuration-dependent plumbing and
lets callers depend on one locking model rather than carrying both
cases along.
- "memcg: remove the v1 soft limit" (Shakeel Butt):
Remove the old cgroup v1 memory soft-limit machinery. This has long
since been superseded by the newer memory-control interfaces; hauling
around a separate reclaim scheme for it no longer buys us much.
- "read proc/pid/smaps_rollup under per-vma lock" (Suren Baghdasaryan):
Read /proc/PID/smaps_rollup using per-VMA locks where possible,
rather than holding mmap_lock across the entire walk. Retain the
contention fallback and add tearing tests. This considerably reduces
latency when another thread is busy changing its mappings.
- "mm/damon: introduce data access-as-a-data attribute" (SJ Park):
Teach DAMON to expose memory access observations as data attributes,
making them available to the probe and filtering machinery. Extend
the interfaces, documentation and tests so the new information can be
used rather than merely collected.
- "Remove PG_private by using page/folio->private checks instead" (Zi
Yan):
Get rid of PG_private and use the folio's private pointer to say
whether private data is attached. Convert the filesystem users,
including erofs, f2fs and md, and clean up the old accessors and
flags. There are a few special cases, notably swapcache and hugetlb,
which need explicit care.
- "mm: make userland page table freeing RCU-safe" (Lorenzo Stoakes):
Make freeing userspace page tables safe against RCU readers. Sort out
the page-table lifetime and locking rules so walkers cannot stumble
over freed tables while mappings are being torn down.
- "make unused huge shrinker memcg aware" (Qi Zheng):
Make shmem's unused-huge-folio shrinker aware of memory cgroups, so
reclaim can find those folios under the right memcg. Wire up the
per-memcg tracking and its lifetime rules, and give the shrinklist
its own lockdep class to avoid spurious dependency reports.
- "mm: Drop pxd_ERROR()" (Anshuman Khandual):
Remove the old pxd_ERROR() page-table checks and their
architecture-specific baggage. Simplify the common page-table
interfaces and callers now that these checks no longer serve a
useful purpose.
- "memcg: group struct fields by access pattern" (Shakeel Butt):
Rearrange memcg's hot and cold fields according to how they're
actually accessed. Keep frequently updated counters and their
neighboring state from fighting over cachelines and reduce needless
cacheline traffic.
- "mm/damon/core: fix the size charged for a filter-trimmed region"
(Donggeun Yoo):
Fix DAMOS quota accounting when a filter trims a monitoring region.
Charge only the part left after filtering, not the original region,
and add KUnit coverage. Previously the excluded memory could eat into
the quota and make schemes run more slowly than requested.
- "mm/damon: add kunit and selftests for probes and probe weights" (SJ
Park):
Add more tests for DAMON probes and their weights, including
validation and the results reported to userspace. This is mostly
about catching regressions in the newer probe infrastructure before
they become harder to diagnose.
- "mm: memcontrol: constify the read side of the read side of the memcg
API" (Tal Zussman):
Mark the read-only parts of the memcg interface const, from folio and
lruvec accessors to counters and swap helpers. Most of this is
mechanical, but it makes the contracts clearer and lets the compiler
catch accidental writes.
- "mm/damon/vaddr: support {prep,apply}_probes" (SJ Park):
Support the new prepare/apply probe operations in DAMON's
virtual-address backend. This brings vaddr monitoring into line with
the probe infrastructure and makes the added probe types useful there
too.
- "mm/mglru: clean up folio counters and flag usage" (Kairui Song):
Simplify MGLRU's folio counters and flag handling. Remove redundant
accounting paths and make the state transitions easier to follow
without changing the intended reclaim policy.
- "arch, mm/execmem: resolve confusion about set_direct_map_valid_noflush()"
(Mike Rapoport (Microsoft)):
Clarify and straighten out the set_direct_map_valid_noflush()
interface across architectures and execmem. Make the requested
mapping changes and the callers' expectations agree, rather than
relying on subtly different architecture behavior.
- "mm: zswap: free cold writeback folios promptly" (Alexandre Ghiti):
Free zswap writeback folios as soon as their disk write completes.
They are cold temporary buffers, so putting them on the LRU only
makes reclaim rediscover them later. Extend swap-cache dropbehind and
let zswap keep these folios off the LRU altogether.
- "mm: gup: cleanup gup_fast call chain" (Aristeu Rozanski):
Clean up the GUP-fast call chain and simplify how the fast-path
helpers pass their arguments and results around. Keep the page-pin
behavior the same while making the call sequence easier to maintain.
- "mm: optimize zone-device memmap initialization" (Li Zhe):
Speed up initialization of zone-device struct pages. Avoid redundant
work when setting up large device-memory ranges, where touching every
descriptor can get expensive.
- "mm/zswap: shrink zswap_entry via a pool id" (Jianyue Wu):
Reduce the size of zswap_entry by storing a compact pool identifier
instead of a full pointer. Keep the pool lookup and lifetime handling
correct while saving per-entry metadata.
- "mm/damon: support access monitoring of hugetlb-backed memory"
(Krishna Iyer):
Let DAMON monitor hugetlb-backed memory too. Extend the relevant
access checks and add coverage so those mappings no longer fall
through a hole in the monitoring machinery.
- "mm/execmem: fixes and cleanups for the ROX cache" (Mike Rapoport):
Tidy execmem's read-only-executable cache and fix its handling of the
awkward allocation and release cases. The aim is to make the cache's
ownership and permission transitions more predictable.
- "zsmallc: remove old object read API" (Sergey Senozhatsky):
Drop zsmalloc's old object-read API and move its remaining users to
the supported access mechanism. This removes a duplicate interface
which we no longer need.
- "mm/mempolicy: stop copying state in the interleave paths" (Gregory
Price):
Stop copying mempolicy state in the interleave paths when a reference
to the existing policy will do. This avoids extra work and makes the
ownership rules less obscure.
- "mm/mglru: speed up inc_min_seq() and fix cold/hot inversions" (Barry
Song):
Make MGLRU's generation advancement cheaper and fix cases where cold
and hot folios end up in the wrong order. Adjust the counter and list
handling so reclaim doesn't keep passing over the better eviction
candidates.
- "mm: Fix MF_DELAYED handling on memory failure" (Lisa Wang):
Treat MF_DELAYED as a partially completed memory-failure operation,
not an outright failure. Propagate that result correctly through
shmem and the generic handler, fix the extra-reference accounting,
and add tests for the resulting SIGBUS behavior.
- "tools/mm/page_owner_sort: fix --sort, add module filter, improve
usage" (Ye Liu):
Fix page_owner_sort's --sort handling, add module-based filtering and
make the usage output more helpful. This makes the tool less
frustrating when tracking down who is holding on to pages.
- "mm/damon: move damos filter range arguments validation to core" (SJ
Park):
Move DAMOS filter range validation into the core, where all callers
can share it. Also close the sysfs read-twice races which could pass
inconsistent ranges, and add tests for invalid input.
- "mm/damon: misc cleanups" (Zenghui Yu):
Clean up a collection of small DAMON rough edges in the core,
interfaces and tests. No large behavior change here, just simpler
code and fewer opportunities for confusion.
- "mm/damon: cleanup code, add test cases, and update guidances in
docs" (SJ Park):
Clean up DAMON's core and interfaces, add missing test cases and
bring the documentation into line with the code. These changes should
make the newer facilities easier to understand and maintain.
- "mm/damon: introduce hugepage_size probe filter" (SJ Park):
Add a DAMON probe filter for hugepage size. Let users select a range
of folio sizes through sysfs, validate the range and document the new
interface, so monitoring can concentrate on memory backed by the
desired hugepage sizes.
- "selftests/mm: pagemap_ioctl test fixes and cleanups" (Zenghui Yu):
Fix some pagemap ioctl test assumptions and clean up their setup and
reporting. Make failures point to the operation that went wrong
rather than to test harness bookkeeping.
- "mm: avoid large folio splits when swap is unavailable" (Johannes
Weiner):
Avoid splitting large folios merely to attempt swap when no swap
space is available. There is little point paying for an expensive
split when reclaim cannot actually swap the resulting pages out.
- "mm: workingset: fix the shadow node budget under MGLRU" (Hui Zhu):
Fix the workingset shadow-node budget with MGLRU enabled. Keep the
shadow entries within the intended limits so refault tracking does
not quietly consume more metadata than it should.
- "selftests/mm: TAP output and global-state fixes" (Song Hu):
Fix selftests which produce misleading TAP output or fail to restore
global settings after a run. A test ought to leave the system as it
found it, particularly when a whole suite follows behind.
- "mm: remove page_swap_entry()" (Tal Zussman):
Remove page_swap_entry() and convert its remaining users to the folio
and swap-entry helpers. Lose an old page-level interface and make the
swap paths a little more consistent.
- "mm: refactor zonelist constructors and iterators" (Gregory Price):
Refactor the zonelist construction and walk helpers to reduce
duplicated logic. Keep the allocation ordering rules intact while
making it clearer how zones are selected.
- "mm: kmemleak: batch the struct page scan" (Breno Leitao):
Scan adjacent struct pages in batches instead of taking kmemleak_lock
once for every single page. This preserves scan coverage and the
lock-hold bound, while cutting overhead substantially on debug
kernels.
- "mm/damon: misc improvements in tests and documents" (Zenghui Yu):
Fix some DAMON selftests which leave kdamond running or fail under
Python safe-path mode, and improve the KUnit coverage and
documentation. Nothing especially glamorous, but these are worth
doing.
- "mm/damon: introduce probe_hits_wsum DAMOS core filter" (SJ Park):
Add a DAMOS core filter using weighted probe-hit counts. This gives
schemes another way to select regions based on what the monitoring
probes observed.
- "mm/mglru: fix ineffective memory protection for non-kswapd reclaim"
(Ridong Chen):
Fix MGLRU's memory protection handling for reclaim outside kswapd.
The protection settings weren't having the intended effect in these
paths, leaving protected memory more exposed than requested.
- "mm/damon: improve readability, clarity and test coverage" (SJ Park):
Simplify a handful of DAMON core helpers, clarify their behavior and
expand test coverage. There are no intended userspace-visible changes
in this batch.
- "mm: replace PF_KCOMPACTD/PF_KSWAPD with kthread_func()" (Kefeng
Wang):
Stop identifying reclaim and compaction workers through the PF_KSWAPD
and PF_KCOMPACTD task flags. Use their kthread functions instead and
remove the redundant flag plumbing.
- "mm/hugetlb: fix surplus accounting and availability checks during
demotion" (Longlong Xia):
Fix HugeTLB surplus accounting and availability checks when demoting
huge pages. Keep the counters and reservation decisions consistent as
one huge page turns into several smaller ones.
- "mm/damon: add kunit tests for probe_hits handling and probe params
validation" (Jason Angelov):
Add KUnit tests for DAMON probe-hit handling and invalid probe
parameters. These cover edge cases that were too easy to miss in
ordinary monitoring tests.
- "mm/damon: fix misc bugs in kunit, quota goals and sysfs refresh_ms"
(SJ Park):
Fix a few DAMON bugs in KUnit tests, quota-goal handling and the
sysfs refresh interval. Small fixes, but the incorrect results and
control behavior were real.
- "mm: zswap: optimize zswap invalidate and store" (Kefeng Wang):
Simplify zswap's invalidate and store paths to avoid avoidable
lookups and work. Keep the entry lifetime rules intact while making
those frequent operations cheaper.
- "mm: replace custom ratelimiting logic" (Pedro Falcato):
Replace hand-rolled MM rate limiting with the common kernel helpers.
There is no need to maintain another local version of the same
mechanism.
- "mm/vmalloc: minor cleanups" (Ye Liu):
Tidy some vmalloc initialization and reporting code, and pull
duplicated vmap-area insertion work into a helper. No functional
changes are intended.
- "mm/mglru: clean up isolate_folios for readability and clarity"
(Ridong Chen):
Clean up MGLRU's isolate_folios() so the decisions are easier to read
and verify. Keep reclaim behavior unchanged while removing
unnecessary twists in the control flow.
- "Catch automatic storage in IDA and Maple Tree definitions" (Yury
Norov):
Catch IDA and maple-tree definitions placed in automatic storage
where the lifetime rules are wrong or easy to get wrong. Add checks
so such mistakes are harder to slip through unnoticed.
- "mm, swap: some random fixes and cleanups" (Kemeng Shi):
Fix and simplify a few unrelated swap paths, removing redundant work
and tidying up error handling. A small collection of things which
were better fixed than left lying around.
- "mm/page_io: folio conversion cleanups" (Tal Zussman):
Finish some page-to-folio conversions in swap I/O, removing obsolete
wrappers and using folio operations consistently. The I/O behavior is
intended to remain the same.
- "mm/swap: skip empty clusters in the swapoff scan" (Youngjun Park):
Skip empty swap clusters during swapoff instead of walking slots
which have nothing to release. This avoids pointless work on sparsely
used swap devices.
- "mm: trace: decode architecture-specific VMA flags" (Meijing Zhao):
Teach the VMA trace output to decode architecture-specific flags,
rather than leaving them as unexplained bits. That should make
tracing a good deal more useful when debugging unusual mappings.
- "mm, swap: don't spin on a bad swap entry" (Breno Leitao):
Stop repeatedly retrying a swap entry which is already known to be
bad. Make the error path terminate cleanly instead of wasting CPU
chasing an entry that cannot be used.
- "mm/page_isolation: fix UBSAN shift-out-of-bounds in
isolate_single_pageblock" (Qi Xi):
Fix an out-of-range shift in isolate_single_pageblock() and tighten
its associated boundary handling. UBSAN found the issue; the result
should be more robust pageblock isolation.
- "mm: khugepaged: fix tracepoint UAF" (Vernon Yang):
Fix a use-after-free in khugepaged tracepoint handling. Make sure the
information recorded by tracing stays valid for as long as the trace
event needs it.
- "mm/damon: fix DAMOS bugs in core, paddr and vaddr" (SJ Park):
Fix several DAMOS problems across the core and physical- and
virtual-address backends. The changes close error cases and bring the
implementations back into agreement.
- "mm/hugetlb_cgroup: move the per-node usage along with the folio"
(Hongfu Li):
Move HugeTLB per-node usage accounting when folios migrate between
nodes or are reparented to another cgroup. Otherwise numa_stat can
retain stale charges and even underflow when the folio is freed.
- "docs/core-api: memory-allocation: add k[mz]alloc_obj() and clarify
kmalloc" (Mike Rapoport):
Document the typed k[mz]alloc_obj() allocation helpers and clear up
some kmalloc guidance. Make it easier for callers to choose the right
interface.
- "selftests/mm: Validate selections and scope memfd_secret setup"
(Tianyi Chen):
Check selftest selections before running and confine memfd_secret
setup to the cases that actually need it. Avoid confusing failures
caused by the test harness itself.
- "mm/damon: move zero damos quota target_value handling to the core
layer" (SJ Park):
Handle a zero DAMOS quota goal target in the core rather than making
each user of the interface invent its own rule. Keep quota decisions
consistent across callers.
- "mm/damon: Introduce a huge page collapsing mechanism using auto
tuning" (Asier Gutierrez):
Add an auto-tuned DAMON mechanism for collapsing huge pages. Use
monitoring feedback to decide when collapse is worthwhile rather than
forcing one fixed policy onto every workload.
- "kmemleak: fix stale documentation and raise the verbose default"
(Breno Leitao):
Bring the kmemleak documentation up to date and require a third
confirming scan before verbose kernels print a suspected leak. The
extra scan helps suppress transient false positives in noisy debug
builds.
- "mm/memory: improve insert_pages() error handling" (Avi Weiss):
Tighten insert_pages() error handling so partial failures are
reported and cleaned up consistently. The caller should not have to
guess how far the operation got.
- "mm/damon: allow NULL or unstarted damon_ctx parameter for
damon_call()" (SJ Park):
Make damon_call() handle NULL and not-yet-started contexts safely.
Simplify the rules for callers and avoid an indefinite wait on an
invalid state.
- "mm/damon: introduce pgidle_set probe filter type" (SJ Park):
Add a pgidle_set DAMON probe filter, giving monitoring users another
way to select pages by their idle-tracking state. Wire it through the
filter interfaces and tests.
- "mm/damon/core: remove unused helper functions" (Cheng-Han Wu):
Remove DAMON core helpers which no longer have callers. Keep the API
surface smaller rather than retaining dead code just in case.
- "mm: stop calling pmd_folio() on special PMDs" (Gregory Price):
Avoid calling pmd_folio() on special PMD mappings that have no struct
page. The old assumption could fault in procfs walkers; use the
normal-folio checks and handle those mappings properly.
- "mm: remove three unused helpers from mm.h" (Tal Zussman):
Remove three unused helpers from mm.h. Fewer obsolete interfaces for
the next person to stumble over.
- "mm/damon: improvements in efficiency, error handling, documents"
(Liew Rui Yan):
Skip needless DAMOS quota work once the quota is full, propagate a
missing sysfs error and tidy a couple of comments. The ignored error
could make a monitoring-start request appear successful when it
wasn't.
- "docs/mm/damon/design: add explanation of nr_snapshots" (Liew Rui
Yan):
Explain DAMON's nr_snapshots accounting in the design documentation
and straighten out the associated terminology. Make it clearer what
users should expect from that counter.
- "selftests/cgroup: fixes for test_zswap on single core VM" (Wilson
Felipe Pereira):
Fix two test_zswap failures on single-CPU VMs. Wait for the exiting
child's cgroup to become unpopulated before reconfiguring it, and
avoid another test assumption which breaks under constrained
scheduling.
- "docs/ksm: fix advisor documentation and comment" (Jinjiang Tu):
Correct the KSM advisor documentation and a misleading code comment.
Keep the description aligned with how the advisor actually works.
- "Fix bugs in HugeTLB allocation when mem_cgroup_charge_hugetlb()
fails" (Ackerley Tng):
Fix HugeTLB allocation cleanup when the memcg charge fails. Make sure
failure exits undo what was allocated rather than leaving stale
accounting or resources behind.
- "mm, memcg: fix memory.peak reset clobbering other fds' watermark"
(Ridong Chen):
Fix memory.peak reset handling so resetting one file descriptor
doesn't overwrite the watermark kept for another. Keep those per-open
measurements independent as intended.
- "mm: reject zone device folios in more folio walkers" (Gregory
Price):
Reject zone-device folios in page walkers that cannot safely handle
them. Extend the existing checks rather than assuming every folio has
ordinary system-memory backing.
- "percpu: remove code with no effect" (Sang-Heon Jeon):
Remove a few pieces of percpu code which no longer do anything. There
is no reason to keep maintaining dead paths.
* tag 'mm-stable-2026-10-19-21-33' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: (539 commits)
mm: shmem: assign a lock class to the unused huge shrinklist
mm: vmscan: put rotation-missed folios at the LRU tail
mm: kmemleak: scan the struct page array in MAX_SCAN_SIZE batches
mm: kmemleak: move the struct page scan into a helper
mm/damon: document that a zero sample_interval is accepted
mm/damon: fix typos in comments
mm/damon/sysfs: propagate damon_call() error in turn_damon_on
mm/damon/core: skip quota score setup when the quota is full
mm/damon/tests/core-kunit: test the size charged for a filter-trimmed region
mm/damon/core: charge only the part of a region the filter left
mm: disallow raw PFN mappings of huge/shared zeropage
selftests/mm: zap whole PTE tables in the khugepaged race harness
selftests/mm: add memory-pressure threads to the khugepaged race harness
selftests/mm: race the collapse of windows with holes
selftests/mm: add khugepaged race harness
selftests/mm: check that one khugepaged pass collapses one window
selftests/mm: run every supported collapse order by default
selftests/mm: cover a shared-source collapse write race
selftests/mm: parameterize the mixed-source collapse case by source order
selftests/mm: add order-parameterized khugepaged collapse cases
...
3007 lines
78 KiB
C
3007 lines
78 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* linux/fs/buffer.c
|
|
*
|
|
* Copyright (C) 1991, 1992, 2002 Linus Torvalds
|
|
*/
|
|
|
|
/*
|
|
* Start bdflush() with kernel_thread not syscall - Paul Gortmaker, 12/95
|
|
*
|
|
* Removed a lot of unnecessary code and simplified things now that
|
|
* the buffer cache isn't our primary cache - Andrew Tridgell 12/96
|
|
*
|
|
* Speed up hash, lru, and free list operations. Use gfp() for allocating
|
|
* hash table, use SLAB cache for buffer heads. SMP threading. -DaveM
|
|
*
|
|
* Added 32k buffer block sizes - these are required older ARM systems. - RMK
|
|
*
|
|
* async buffer flushing, 1999 Andrea Arcangeli <andrea@suse.de>
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/sched/signal.h>
|
|
#include <linux/syscalls.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/iomap.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/percpu.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/capability.h>
|
|
#include <linux/blkdev.h>
|
|
#include <linux/blk-crypto.h>
|
|
#include <linux/file.h>
|
|
#include <linux/quotaops.h>
|
|
#include <linux/highmem.h>
|
|
#include <linux/export.h>
|
|
#include <linux/backing-dev.h>
|
|
#include <linux/writeback.h>
|
|
#include <linux/hash.h>
|
|
#include <linux/suspend.h>
|
|
#include <linux/buffer_head.h>
|
|
#include <linux/task_io_accounting_ops.h>
|
|
#include <linux/bio.h>
|
|
#include <linux/cpu.h>
|
|
#include <linux/bitops.h>
|
|
#include <linux/mpage.h>
|
|
#include <linux/bit_spinlock.h>
|
|
#include <linux/folio_batch.h>
|
|
#include <linux/sched/mm.h>
|
|
#include <trace/events/block.h>
|
|
#include <linux/fscrypt.h>
|
|
#include <linux/fsverity.h>
|
|
#include <linux/sched/isolation.h>
|
|
|
|
#include "internal.h"
|
|
|
|
#define BH_ENTRY(list) list_entry((list), struct buffer_head, b_assoc_buffers)
|
|
|
|
inline void touch_buffer(struct buffer_head *bh)
|
|
{
|
|
trace_block_touch_buffer(bh);
|
|
folio_mark_accessed(bh->b_folio);
|
|
}
|
|
EXPORT_SYMBOL(touch_buffer);
|
|
|
|
void __lock_buffer(struct buffer_head *bh)
|
|
{
|
|
wait_on_bit_lock_io(&bh->b_state, BH_Lock, TASK_UNINTERRUPTIBLE);
|
|
}
|
|
EXPORT_SYMBOL(__lock_buffer);
|
|
|
|
void unlock_buffer(struct buffer_head *bh)
|
|
{
|
|
clear_and_wake_up_bit(BH_Lock, &bh->b_state);
|
|
}
|
|
EXPORT_SYMBOL(unlock_buffer);
|
|
|
|
/*
|
|
* Returns if the folio has dirty or writeback buffers. If all the buffers
|
|
* are unlocked and clean then the folio_test_dirty information is stale. If
|
|
* any of the buffers are locked, it is assumed they are locked for IO.
|
|
*/
|
|
void buffer_check_dirty_writeback(struct folio *folio,
|
|
bool *dirty, bool *writeback)
|
|
{
|
|
struct buffer_head *head, *bh;
|
|
*dirty = false;
|
|
*writeback = false;
|
|
|
|
BUG_ON(!folio_test_locked(folio));
|
|
|
|
head = folio_buffers(folio);
|
|
if (!head)
|
|
return;
|
|
|
|
if (folio_test_writeback(folio))
|
|
*writeback = true;
|
|
|
|
bh = head;
|
|
do {
|
|
if (buffer_locked(bh))
|
|
*writeback = true;
|
|
|
|
if (buffer_dirty(bh))
|
|
*dirty = true;
|
|
|
|
bh = bh->b_this_page;
|
|
} while (bh != head);
|
|
}
|
|
|
|
/*
|
|
* Block until a buffer comes unlocked. This doesn't stop it
|
|
* from becoming locked again - you have to lock it yourself
|
|
* if you want to preserve its state.
|
|
*/
|
|
void __wait_on_buffer(struct buffer_head * bh)
|
|
{
|
|
wait_on_bit_io(&bh->b_state, BH_Lock, TASK_UNINTERRUPTIBLE);
|
|
}
|
|
EXPORT_SYMBOL(__wait_on_buffer);
|
|
|
|
static void buffer_io_error(struct buffer_head *bh, char *msg)
|
|
{
|
|
if (!test_bit(BH_Quiet, &bh->b_state))
|
|
printk_ratelimited(KERN_ERR
|
|
"Buffer I/O error on dev %pg, logical block %llu%s\n",
|
|
bh->b_bdev, (unsigned long long)bh->b_blocknr, msg);
|
|
}
|
|
|
|
/**
|
|
* bio_endio_bh - Discard the bio used to submit a buffer.
|
|
* @bio: The bio.
|
|
* @bhp: Where to return the buffer_head.
|
|
*
|
|
* Call this in your bio_end_io handler to retrieve the buffer_head
|
|
* submitted in bh_submit(). If you did not call bh_submit(), do not
|
|
* call this function; it will return garbage.
|
|
*
|
|
* This function consumes the bio refcount which will probably free the
|
|
* bio.
|
|
*
|
|
* Return: True if the I/O succeeded.
|
|
*/
|
|
bool bio_endio_bh(struct bio *bio, struct buffer_head **bhp)
|
|
{
|
|
bool success = bio->bi_status == BLK_STS_OK;
|
|
struct buffer_head *bh = bio->bi_private;
|
|
|
|
if (unlikely(bio_flagged(bio, BIO_QUIET)))
|
|
set_bit(BH_Quiet, &bh->b_state);
|
|
bio_put(bio);
|
|
|
|
*bhp = bh;
|
|
return success;
|
|
}
|
|
EXPORT_SYMBOL(bio_endio_bh);
|
|
|
|
/**
|
|
* end_buffer_read_sync - Handle buffer reads finishing
|
|
* @bh: The buffer.
|
|
* @uptodate: True if the read was successful.
|
|
*
|
|
* If a buffer is read through a mechanism that isn't bh_submit(), you
|
|
* can call this function to finish the read.
|
|
*/
|
|
void end_buffer_read_sync(struct buffer_head *bh, int uptodate)
|
|
{
|
|
if (uptodate) {
|
|
set_buffer_uptodate(bh);
|
|
} else {
|
|
/* This happens, due to failed read-ahead attempts. */
|
|
clear_buffer_uptodate(bh);
|
|
}
|
|
unlock_buffer(bh);
|
|
}
|
|
EXPORT_SYMBOL(end_buffer_read_sync);
|
|
|
|
/**
|
|
* bh_end_read - I/O end handler for reads
|
|
* @bio: The bio being completed.
|
|
*
|
|
* Pass this function to bh_submit() if you're reading into the buffer,
|
|
* unless you need your own special I/O end handler.
|
|
*/
|
|
void bh_end_read(struct bio *bio)
|
|
{
|
|
struct buffer_head *bh;
|
|
bool uptodate = bio_endio_bh(bio, &bh);
|
|
end_buffer_read_sync(bh, uptodate);
|
|
}
|
|
EXPORT_SYMBOL(bh_end_read);
|
|
|
|
/**
|
|
* bh_end_write - I/O end handler for writes
|
|
* @bio: The bio being completed.
|
|
*
|
|
* Pass this function to bh_submit() if you're writing from the buffer,
|
|
* unless you need your own special I/O end handler.
|
|
*/
|
|
void bh_end_write(struct bio *bio)
|
|
{
|
|
struct buffer_head *bh;
|
|
bool success = bio_endio_bh(bio, &bh);
|
|
|
|
if (success) {
|
|
clear_buffer_write_io_error(bh);
|
|
} else {
|
|
buffer_io_error(bh, ", lost sync page write");
|
|
mark_buffer_write_io_error(bh);
|
|
}
|
|
unlock_buffer(bh);
|
|
}
|
|
EXPORT_SYMBOL(bh_end_write);
|
|
|
|
static struct buffer_head *
|
|
__find_get_block_slow(struct block_device *bdev, sector_t block, bool atomic)
|
|
{
|
|
struct address_space *bd_mapping = bdev->bd_mapping;
|
|
const int blkbits = bd_mapping->host->i_blkbits;
|
|
struct buffer_head *ret = NULL;
|
|
pgoff_t index;
|
|
struct buffer_head *bh;
|
|
struct buffer_head *head;
|
|
struct folio *folio;
|
|
int all_mapped = 1;
|
|
static DEFINE_RATELIMIT_STATE(last_warned, HZ, 1);
|
|
|
|
index = ((loff_t)block << blkbits) / PAGE_SIZE;
|
|
folio = __filemap_get_folio(bd_mapping, index, FGP_ACCESSED, 0);
|
|
if (IS_ERR(folio))
|
|
goto out;
|
|
|
|
/*
|
|
* Folio lock protects the buffers. Callers that cannot block
|
|
* will fallback to serializing vs try_to_free_buffers() via
|
|
* the i_private_lock.
|
|
*/
|
|
if (atomic)
|
|
spin_lock(&bd_mapping->i_private_lock);
|
|
else
|
|
folio_lock(folio);
|
|
|
|
head = folio_buffers(folio);
|
|
if (!head)
|
|
goto out_unlock;
|
|
/*
|
|
* Upon a noref migration, the folio lock serializes here;
|
|
* otherwise bail.
|
|
*/
|
|
if (test_bit_acquire(BH_Migrate, &head->b_state)) {
|
|
WARN_ON(!atomic);
|
|
goto out_unlock;
|
|
}
|
|
|
|
bh = head;
|
|
do {
|
|
if (!buffer_mapped(bh))
|
|
all_mapped = 0;
|
|
else if (bh->b_blocknr == block) {
|
|
ret = bh;
|
|
get_bh(bh);
|
|
goto out_unlock;
|
|
}
|
|
bh = bh->b_this_page;
|
|
} while (bh != head);
|
|
|
|
/* we might be here because some of the buffers on this folio are
|
|
* not mapped. This is due to various races between
|
|
* file io on the block device and getblk. It gets dealt with
|
|
* elsewhere, don't buffer_error if we had some unmapped buffers
|
|
*/
|
|
ratelimit_set_flags(&last_warned, RATELIMIT_MSG_ON_RELEASE);
|
|
if (all_mapped && __ratelimit(&last_warned)) {
|
|
printk("__find_get_block_slow() failed. block=%llu, "
|
|
"b_blocknr=%llu, b_state=0x%08lx, b_size=%zu, "
|
|
"device %pg blocksize: %d\n",
|
|
(unsigned long long)block,
|
|
(unsigned long long)bh->b_blocknr,
|
|
bh->b_state, bh->b_size, bdev,
|
|
1 << blkbits);
|
|
}
|
|
out_unlock:
|
|
if (atomic)
|
|
spin_unlock(&bd_mapping->i_private_lock);
|
|
else
|
|
folio_unlock(folio);
|
|
folio_put(folio);
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
|
|
{
|
|
unsigned long flags;
|
|
struct buffer_head *first;
|
|
struct buffer_head *tmp;
|
|
struct folio *folio;
|
|
int folio_uptodate = 1;
|
|
|
|
BUG_ON(!buffer_async_read(bh));
|
|
|
|
folio = bh->b_folio;
|
|
if (uptodate) {
|
|
set_buffer_uptodate(bh);
|
|
} else {
|
|
clear_buffer_uptodate(bh);
|
|
buffer_io_error(bh, ", async page read");
|
|
}
|
|
|
|
/*
|
|
* Be _very_ careful from here on. Bad things can happen if
|
|
* two buffer heads end IO at almost the same time and both
|
|
* decide that the folio is now completely done.
|
|
*/
|
|
first = folio_buffers(folio);
|
|
spin_lock_irqsave(&first->b_uptodate_lock, flags);
|
|
clear_buffer_async_read(bh);
|
|
unlock_buffer(bh);
|
|
tmp = bh;
|
|
do {
|
|
if (!buffer_uptodate(tmp))
|
|
folio_uptodate = 0;
|
|
if (buffer_async_read(tmp)) {
|
|
BUG_ON(!buffer_locked(tmp));
|
|
goto still_busy;
|
|
}
|
|
tmp = tmp->b_this_page;
|
|
} while (tmp != bh);
|
|
spin_unlock_irqrestore(&first->b_uptodate_lock, flags);
|
|
|
|
folio_end_read(folio, folio_uptodate);
|
|
return;
|
|
|
|
still_busy:
|
|
spin_unlock_irqrestore(&first->b_uptodate_lock, flags);
|
|
}
|
|
|
|
struct verify_bh_ctx {
|
|
struct work_struct work;
|
|
struct buffer_head *bh;
|
|
struct fsverity_info *vi;
|
|
};
|
|
|
|
static void verify_bh(struct work_struct *work)
|
|
{
|
|
struct verify_bh_ctx *ctx =
|
|
container_of(work, struct verify_bh_ctx, work);
|
|
struct buffer_head *bh = ctx->bh;
|
|
bool valid;
|
|
|
|
valid = fsverity_verify_blocks(ctx->vi, bh->b_folio, bh->b_size,
|
|
bh_offset(bh));
|
|
end_buffer_async_read(bh, valid);
|
|
kfree(ctx);
|
|
}
|
|
|
|
/*
|
|
* I/O completion handler for block_read_full_folio() - folios
|
|
* which come unlocked at the end of I/O.
|
|
*/
|
|
static void bh_end_async_read(struct bio *bio)
|
|
{
|
|
struct buffer_head *bh;
|
|
bool uptodate = bio_endio_bh(bio, &bh);
|
|
struct inode *inode = bh->b_folio->mapping->host;
|
|
struct fsverity_info *vi = NULL;
|
|
|
|
/* needed by ext4 */
|
|
if (bh->b_folio->index < DIV_ROUND_UP(inode->i_size, PAGE_SIZE))
|
|
vi = fsverity_get_info(inode);
|
|
|
|
/* Verify (with fsverity) if needed. */
|
|
if (vi && uptodate) {
|
|
struct verify_bh_ctx *ctx = kmalloc_obj(*ctx, GFP_ATOMIC);
|
|
|
|
if (ctx) {
|
|
ctx->bh = bh;
|
|
ctx->vi = vi;
|
|
INIT_WORK(&ctx->work, verify_bh);
|
|
fsverity_enqueue_verify_work(&ctx->work);
|
|
return;
|
|
}
|
|
uptodate = false;
|
|
}
|
|
end_buffer_async_read(bh, uptodate);
|
|
}
|
|
|
|
/**
|
|
* bh_end_async_write - I/O end handler for async folio writes
|
|
* @bio: The bio being completed.
|
|
*
|
|
* Pass this function to bh_submit() if you're doing the equivalent of
|
|
* block_write_full_folio(). That is, the folio is unlocked, and will
|
|
* have its writeback flag cleared once all async write buffers have
|
|
* completed.
|
|
*/
|
|
void bh_end_async_write(struct bio *bio)
|
|
{
|
|
struct buffer_head *bh;
|
|
bool success = bio_endio_bh(bio, &bh);
|
|
unsigned long flags;
|
|
struct buffer_head *first;
|
|
struct buffer_head *tmp;
|
|
struct folio *folio;
|
|
|
|
BUG_ON(!buffer_async_write(bh));
|
|
|
|
folio = bh->b_folio;
|
|
if (success) {
|
|
clear_buffer_write_io_error(bh);
|
|
} else {
|
|
buffer_io_error(bh, ", lost async page write");
|
|
mark_buffer_write_io_error(bh);
|
|
}
|
|
|
|
first = folio_buffers(folio);
|
|
spin_lock_irqsave(&first->b_uptodate_lock, flags);
|
|
|
|
clear_buffer_async_write(bh);
|
|
unlock_buffer(bh);
|
|
tmp = bh->b_this_page;
|
|
while (tmp != bh) {
|
|
if (buffer_async_write(tmp)) {
|
|
BUG_ON(!buffer_locked(tmp));
|
|
goto still_busy;
|
|
}
|
|
tmp = tmp->b_this_page;
|
|
}
|
|
spin_unlock_irqrestore(&first->b_uptodate_lock, flags);
|
|
folio_end_writeback(folio);
|
|
return;
|
|
|
|
still_busy:
|
|
spin_unlock_irqrestore(&first->b_uptodate_lock, flags);
|
|
}
|
|
EXPORT_SYMBOL(bh_end_async_write);
|
|
|
|
|
|
/*
|
|
* fs/buffer.c contains helper functions for buffer-backed address space's
|
|
* fsync functions. A common requirement for buffer-based filesystems is
|
|
* that certain data from the backing blockdev needs to be written out for
|
|
* a successful fsync(). For example, ext2 indirect blocks need to be
|
|
* written back and waited upon before fsync() returns.
|
|
*
|
|
* The functions mmb_mark_buffer_dirty(), mmb_sync(), mmb_has_buffers()
|
|
* and mmb_invalidate() are provided for the management of a list of dependent
|
|
* buffers in mapping_metadata_bhs struct.
|
|
*
|
|
* The locking is a little subtle: The list of buffer heads is protected by
|
|
* the lock in mapping_metadata_bhs so functions coming from bdev mapping
|
|
* (such as try_to_free_buffers()) need to safely get to mapping_metadata_bhs
|
|
* using RCU, grab the lock, verify we didn't race with somebody detaching the
|
|
* bh / moving it to different inode and only then proceeding.
|
|
*/
|
|
|
|
void mmb_init(struct mapping_metadata_bhs *mmb, struct address_space *mapping)
|
|
{
|
|
spin_lock_init(&mmb->lock);
|
|
INIT_LIST_HEAD(&mmb->list);
|
|
mmb->mapping = mapping;
|
|
}
|
|
EXPORT_SYMBOL(mmb_init);
|
|
|
|
static void __remove_assoc_queue(struct mapping_metadata_bhs *mmb,
|
|
struct buffer_head *bh)
|
|
{
|
|
lockdep_assert_held(&mmb->lock);
|
|
list_del_init(&bh->b_assoc_buffers);
|
|
WARN_ON(!bh->b_mmb);
|
|
bh->b_mmb = NULL;
|
|
}
|
|
|
|
static void remove_assoc_queue(struct buffer_head *bh)
|
|
{
|
|
struct mapping_metadata_bhs *mmb;
|
|
|
|
/*
|
|
* The locking dance is ugly here. We need to acquire the lock
|
|
* protecting the metadata bh list while possibly racing with bh
|
|
* being removed from the list or moved to a different one. We
|
|
* use RCU to pin mapping_metadata_bhs in memory to
|
|
* opportunistically acquire the lock and then recheck the bh
|
|
* didn't move under us.
|
|
*/
|
|
while (bh->b_mmb) {
|
|
rcu_read_lock();
|
|
mmb = READ_ONCE(bh->b_mmb);
|
|
if (mmb) {
|
|
spin_lock(&mmb->lock);
|
|
if (bh->b_mmb == mmb)
|
|
__remove_assoc_queue(mmb, bh);
|
|
spin_unlock(&mmb->lock);
|
|
}
|
|
rcu_read_unlock();
|
|
}
|
|
}
|
|
|
|
bool mmb_has_buffers(struct mapping_metadata_bhs *mmb)
|
|
{
|
|
return !list_empty(&mmb->list);
|
|
}
|
|
EXPORT_SYMBOL_GPL(mmb_has_buffers);
|
|
|
|
/**
|
|
* mmb_sync - write out & wait upon all buffers in a list
|
|
* @mmb: the list of buffers to write
|
|
*
|
|
* Starts I/O against the buffers in the given list and waits upon
|
|
* that I/O. Basically, this is a convenience function for fsync(). @mmb is
|
|
* for a file or directory which needs those buffers to be written for a
|
|
* successful fsync().
|
|
*
|
|
* We have conflicting pressures: we want to make sure that all
|
|
* initially dirty buffers get waited on, but that any subsequently
|
|
* dirtied buffers don't. After all, we don't want fsync to last
|
|
* forever if somebody is actively writing to the file.
|
|
*
|
|
* Do this in two main stages: first we copy dirty buffers to a
|
|
* temporary inode list, queueing the writes as we go. Then we clean
|
|
* up, waiting for those writes to complete. mmb_mark_buffer_dirty()
|
|
* doesn't touch b_assoc_buffers list if b_mmb is set so we are sure the
|
|
* buffer stays on our list until IO completes (at which point it can be
|
|
* reaped).
|
|
*/
|
|
int mmb_sync(struct mapping_metadata_bhs *mmb)
|
|
{
|
|
struct buffer_head *bh;
|
|
int err = 0;
|
|
struct blk_plug plug;
|
|
LIST_HEAD(tmp);
|
|
|
|
if (!mmb_has_buffers(mmb))
|
|
return 0;
|
|
|
|
blk_start_plug(&plug);
|
|
|
|
spin_lock(&mmb->lock);
|
|
while (!list_empty(&mmb->list)) {
|
|
bh = BH_ENTRY(mmb->list.next);
|
|
WARN_ON_ONCE(bh->b_mmb != mmb);
|
|
__remove_assoc_queue(mmb, bh);
|
|
/* Avoid race with mmb_mark_buffer_dirty() which does
|
|
* a lockless check and we rely on seeing the dirty bit */
|
|
smp_mb();
|
|
if (buffer_dirty(bh) || buffer_locked(bh)) {
|
|
list_add(&bh->b_assoc_buffers, &tmp);
|
|
bh->b_mmb = mmb;
|
|
if (buffer_dirty(bh)) {
|
|
get_bh(bh);
|
|
spin_unlock(&mmb->lock);
|
|
/*
|
|
* Ensure any pending I/O completes so that
|
|
* write_dirty_buffer() actually writes the
|
|
* current contents - it is a noop if I/O is
|
|
* still in flight on potentially older
|
|
* contents.
|
|
*/
|
|
write_dirty_buffer(bh, REQ_SYNC);
|
|
|
|
/*
|
|
* Kick off IO for the previous mapping. Note
|
|
* that we will not run the very last mapping,
|
|
* wait_on_buffer() will do that for us
|
|
* through sync_buffer().
|
|
*/
|
|
brelse(bh);
|
|
spin_lock(&mmb->lock);
|
|
}
|
|
}
|
|
}
|
|
|
|
spin_unlock(&mmb->lock);
|
|
blk_finish_plug(&plug);
|
|
spin_lock(&mmb->lock);
|
|
|
|
while (!list_empty(&tmp)) {
|
|
bh = BH_ENTRY(tmp.prev);
|
|
get_bh(bh);
|
|
__remove_assoc_queue(mmb, bh);
|
|
/* Avoid race with mmb_mark_buffer_dirty() which does
|
|
* a lockless check and we rely on seeing the dirty bit */
|
|
smp_mb();
|
|
if (buffer_dirty(bh)) {
|
|
list_add(&bh->b_assoc_buffers, &mmb->list);
|
|
bh->b_mmb = mmb;
|
|
}
|
|
spin_unlock(&mmb->lock);
|
|
wait_on_buffer(bh);
|
|
if (buffer_write_io_error(bh))
|
|
err = -EIO;
|
|
brelse(bh);
|
|
spin_lock(&mmb->lock);
|
|
}
|
|
spin_unlock(&mmb->lock);
|
|
return err;
|
|
}
|
|
EXPORT_SYMBOL(mmb_sync);
|
|
|
|
/*
|
|
* Called when we've recently written block `bblock', and it is known that
|
|
* `bblock' was for a buffer_boundary() buffer. This means that the block at
|
|
* `bblock + 1' is probably a dirty indirect block. Hunt it down and, if it's
|
|
* dirty, schedule it for IO. So that indirects merge nicely with their data.
|
|
*/
|
|
void write_boundary_block(struct block_device *bdev,
|
|
sector_t bblock, unsigned blocksize)
|
|
{
|
|
struct buffer_head *bh;
|
|
|
|
bh = __find_get_block_nonatomic(bdev, bblock + 1, blocksize);
|
|
if (bh) {
|
|
if (buffer_dirty(bh))
|
|
write_dirty_buffer(bh, 0);
|
|
put_bh(bh);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* mmb_mark_buffer_dirty - Mark a metadata buffer dirty.
|
|
* @bh: The buffer to mark dirty.
|
|
* @mmb: The list of buffers to add the buffer to.
|
|
*
|
|
* Mark the buffer dirty and add it to the list if it is not already on
|
|
* a list.
|
|
*/
|
|
void mmb_mark_buffer_dirty(struct buffer_head *bh,
|
|
struct mapping_metadata_bhs *mmb)
|
|
{
|
|
mark_buffer_dirty(bh);
|
|
if (!bh->b_mmb) {
|
|
spin_lock(&mmb->lock);
|
|
/*
|
|
* For a corrupted filesystem with multiply claimed blocks this
|
|
* can fail. Avoid corrupting the linked list in that case.
|
|
*/
|
|
if (cmpxchg(&bh->b_mmb, NULL, mmb) != NULL) {
|
|
spin_unlock(&mmb->lock);
|
|
return;
|
|
}
|
|
list_move_tail(&bh->b_assoc_buffers, &mmb->list);
|
|
spin_unlock(&mmb->lock);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(mmb_mark_buffer_dirty);
|
|
|
|
/**
|
|
* block_dirty_folio - Mark a folio as dirty.
|
|
* @mapping: The address space containing this folio.
|
|
* @folio: The folio to mark dirty.
|
|
*
|
|
* Filesystems which use buffer_heads can use this function as their
|
|
* ->dirty_folio implementation. Some filesystems need to do a little
|
|
* work before calling this function. Filesystems which do not use
|
|
* buffer_heads should call filemap_dirty_folio() instead.
|
|
*
|
|
* If the folio has buffers, the uptodate buffers are set dirty, to
|
|
* preserve dirty-state coherency between the folio and the buffers.
|
|
* Buffers added to a dirty folio are created dirty.
|
|
*
|
|
* The buffers are dirtied before the folio is dirtied. There's a small
|
|
* race window in which writeback may see the folio cleanness but not the
|
|
* buffer dirtiness. That's fine. If this code were to set the folio
|
|
* dirty before the buffers, writeback could clear the folio dirty flag,
|
|
* see a bunch of clean buffers and we'd end up with dirty buffers/clean
|
|
* folio on the dirty folio list.
|
|
*
|
|
* We use i_private_lock to lock against try_to_free_buffers() while
|
|
* using the folio's buffer list. This also prevents clean buffers
|
|
* being added to the folio after it was set dirty.
|
|
*
|
|
* Context: May only be called from process context. Does not sleep.
|
|
* Caller must ensure that @folio cannot be truncated during this call,
|
|
* typically by holding the folio lock or having a page in the folio
|
|
* mapped and holding the page table lock.
|
|
*
|
|
* Return: True if the folio was dirtied; false if it was already dirtied.
|
|
*/
|
|
bool block_dirty_folio(struct address_space *mapping, struct folio *folio)
|
|
{
|
|
struct buffer_head *head;
|
|
bool newly_dirty;
|
|
|
|
spin_lock(&mapping->i_private_lock);
|
|
head = folio_buffers(folio);
|
|
if (head) {
|
|
struct buffer_head *bh = head;
|
|
|
|
do {
|
|
set_buffer_dirty(bh);
|
|
bh = bh->b_this_page;
|
|
} while (bh != head);
|
|
}
|
|
/*
|
|
* Lock out folio's memcg migration to keep folio dirty flag
|
|
* synchronized with per-memcg dirty page counters.
|
|
*/
|
|
newly_dirty = !folio_test_set_dirty(folio);
|
|
spin_unlock(&mapping->i_private_lock);
|
|
|
|
if (newly_dirty)
|
|
__folio_mark_dirty(folio, mapping, 1);
|
|
|
|
if (newly_dirty)
|
|
__mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
|
|
|
|
return newly_dirty;
|
|
}
|
|
EXPORT_SYMBOL(block_dirty_folio);
|
|
|
|
/*
|
|
* Invalidate any and all dirty buffers on a given buffers list. We are
|
|
* probably unmounting the fs, but that doesn't mean we have already
|
|
* done a sync(). Just drop the buffers from the inode list.
|
|
*/
|
|
void mmb_invalidate(struct mapping_metadata_bhs *mmb)
|
|
{
|
|
if (mmb_has_buffers(mmb)) {
|
|
spin_lock(&mmb->lock);
|
|
while (!list_empty(&mmb->list))
|
|
__remove_assoc_queue(mmb, BH_ENTRY(mmb->list.next));
|
|
spin_unlock(&mmb->lock);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(mmb_invalidate);
|
|
|
|
/*
|
|
* Create the appropriate buffers when given a folio for data area and
|
|
* the size of each buffer.. Use the bh->b_this_page linked list to
|
|
* follow the buffers created. Return NULL if unable to create more
|
|
* buffers.
|
|
*
|
|
* The retry flag is used to differentiate async IO (paging, swapping)
|
|
* which may not fail from ordinary buffer allocations.
|
|
*/
|
|
struct buffer_head *folio_alloc_buffers(struct folio *folio, unsigned long size,
|
|
gfp_t gfp)
|
|
{
|
|
struct buffer_head *bh, *head;
|
|
long offset;
|
|
struct mem_cgroup *memcg, *old_memcg;
|
|
|
|
memcg = get_mem_cgroup_from_folio(folio);
|
|
old_memcg = set_active_memcg(memcg);
|
|
|
|
head = NULL;
|
|
offset = folio_size(folio);
|
|
while ((offset -= size) >= 0) {
|
|
bh = alloc_buffer_head(gfp);
|
|
if (!bh)
|
|
goto no_grow;
|
|
|
|
bh->b_this_page = head;
|
|
bh->b_blocknr = -1;
|
|
head = bh;
|
|
|
|
bh->b_size = size;
|
|
|
|
/* Link the buffer to its folio */
|
|
folio_set_bh(bh, folio, offset);
|
|
}
|
|
out:
|
|
set_active_memcg(old_memcg);
|
|
mem_cgroup_put(memcg);
|
|
return head;
|
|
/*
|
|
* In case anything failed, we just free everything we got.
|
|
*/
|
|
no_grow:
|
|
if (head) {
|
|
do {
|
|
bh = head;
|
|
head = head->b_this_page;
|
|
free_buffer_head(bh);
|
|
} while (head);
|
|
}
|
|
|
|
goto out;
|
|
}
|
|
EXPORT_SYMBOL_GPL(folio_alloc_buffers);
|
|
|
|
static inline void link_dev_buffers(struct folio *folio,
|
|
struct buffer_head *head)
|
|
{
|
|
struct buffer_head *bh, *tail;
|
|
|
|
bh = head;
|
|
do {
|
|
tail = bh;
|
|
bh = bh->b_this_page;
|
|
} while (bh);
|
|
tail->b_this_page = head;
|
|
folio_attach_private(folio, head);
|
|
}
|
|
|
|
static sector_t blkdev_max_block(struct block_device *bdev, unsigned int size)
|
|
{
|
|
sector_t retval = ~((sector_t)0);
|
|
loff_t sz = bdev_nr_bytes(bdev);
|
|
|
|
if (sz) {
|
|
unsigned int sizebits = blksize_bits(size);
|
|
retval = (sz >> sizebits);
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
/*
|
|
* Initialise the state of a blockdev folio's buffers.
|
|
*/
|
|
static sector_t folio_init_buffers(struct folio *folio,
|
|
struct block_device *bdev, unsigned size)
|
|
{
|
|
struct buffer_head *head = folio_buffers(folio);
|
|
struct buffer_head *bh = head;
|
|
bool uptodate = folio_test_uptodate(folio);
|
|
sector_t block = div_u64(folio_pos(folio), size);
|
|
sector_t end_block = blkdev_max_block(bdev, size);
|
|
|
|
do {
|
|
if (!buffer_mapped(bh)) {
|
|
bh->b_private = NULL;
|
|
bh->b_bdev = bdev;
|
|
bh->b_blocknr = block;
|
|
if (uptodate)
|
|
set_buffer_uptodate(bh);
|
|
if (block < end_block)
|
|
set_buffer_mapped(bh);
|
|
}
|
|
block++;
|
|
bh = bh->b_this_page;
|
|
} while (bh != head);
|
|
|
|
/*
|
|
* Caller needs to validate requested block against end of device.
|
|
*/
|
|
return end_block;
|
|
}
|
|
|
|
/*
|
|
* Create the page-cache folio that contains the requested block.
|
|
*
|
|
* This is used purely for blockdev mappings.
|
|
*
|
|
* Returns false if we have a failure which cannot be cured by retrying
|
|
* without sleeping. Returns true if we succeeded, or the caller should retry.
|
|
*/
|
|
static bool grow_dev_folio(struct block_device *bdev, sector_t block,
|
|
pgoff_t index, unsigned size, gfp_t gfp)
|
|
{
|
|
struct address_space *mapping = bdev->bd_mapping;
|
|
struct folio *folio;
|
|
struct buffer_head *bh;
|
|
sector_t end_block = 0;
|
|
|
|
folio = __filemap_get_folio(mapping, index,
|
|
FGP_LOCK | FGP_ACCESSED | FGP_CREAT, gfp);
|
|
if (IS_ERR(folio))
|
|
return false;
|
|
|
|
bh = folio_buffers(folio);
|
|
if (bh) {
|
|
if (bh->b_size == size) {
|
|
end_block = folio_init_buffers(folio, bdev, size);
|
|
goto unlock;
|
|
}
|
|
|
|
/*
|
|
* Retrying may succeed; for example the folio may finish
|
|
* writeback, or buffers may be cleaned. This should not
|
|
* happen very often; maybe we have old buffers attached to
|
|
* this blockdev's page cache and we're trying to change
|
|
* the block size?
|
|
*/
|
|
if (!try_to_free_buffers(folio)) {
|
|
end_block = ~0ULL;
|
|
goto unlock;
|
|
}
|
|
}
|
|
|
|
bh = folio_alloc_buffers(folio, size, gfp | __GFP_ACCOUNT);
|
|
if (!bh)
|
|
goto unlock;
|
|
|
|
/*
|
|
* Link the folio to the buffers and initialise them. Take the
|
|
* lock to be atomic wrt __find_get_block(), which does not
|
|
* run under the folio lock.
|
|
*/
|
|
spin_lock(&mapping->i_private_lock);
|
|
link_dev_buffers(folio, bh);
|
|
end_block = folio_init_buffers(folio, bdev, size);
|
|
spin_unlock(&mapping->i_private_lock);
|
|
unlock:
|
|
folio_unlock(folio);
|
|
folio_put(folio);
|
|
return block < end_block;
|
|
}
|
|
|
|
/*
|
|
* Create buffers for the specified block device block's folio. If
|
|
* that folio was dirty, the buffers are set dirty also. Returns false
|
|
* if we've hit a permanent error.
|
|
*/
|
|
static bool grow_buffers(struct block_device *bdev, sector_t block,
|
|
unsigned size, gfp_t gfp)
|
|
{
|
|
loff_t pos;
|
|
|
|
/*
|
|
* Check for a block which lies outside our maximum possible
|
|
* pagecache index.
|
|
*/
|
|
if (check_mul_overflow(block, (sector_t)size, &pos) || pos > MAX_LFS_FILESIZE) {
|
|
printk(KERN_ERR "%s: requested out-of-range block %llu for device %pg\n",
|
|
__func__, (unsigned long long)block,
|
|
bdev);
|
|
return false;
|
|
}
|
|
|
|
/* Create a folio with the proper size buffers */
|
|
return grow_dev_folio(bdev, block, pos / PAGE_SIZE, size, gfp);
|
|
}
|
|
|
|
static struct buffer_head *
|
|
__getblk_slow(struct block_device *bdev, sector_t block,
|
|
unsigned size, gfp_t gfp)
|
|
{
|
|
bool blocking = gfpflags_allow_blocking(gfp);
|
|
|
|
if (WARN_ON_ONCE(!IS_ALIGNED(size, bdev_logical_block_size(bdev)))) {
|
|
printk(KERN_ERR "getblk(): block size %d not aligned to logical block size %d\n",
|
|
size, bdev_logical_block_size(bdev));
|
|
return NULL;
|
|
}
|
|
|
|
for (;;) {
|
|
struct buffer_head *bh;
|
|
|
|
if (!grow_buffers(bdev, block, size, gfp))
|
|
return NULL;
|
|
|
|
if (blocking)
|
|
bh = __find_get_block_nonatomic(bdev, block, size);
|
|
else
|
|
bh = __find_get_block(bdev, block, size);
|
|
if (bh)
|
|
return bh;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* The relationship between dirty buffers and dirty folios:
|
|
*
|
|
* Whenever a folio has any dirty buffers, the folio's dirty flag is set, and
|
|
* the folio is tagged dirty in the page cache.
|
|
*
|
|
* At all times, the dirtiness of the buffers represents the dirtiness of
|
|
* subsections of the folio. If the folio has buffers, the folio dirty flag is
|
|
* merely a hint about the true dirty state.
|
|
*
|
|
* When a folio is set dirty in its entirety, all its buffers are marked dirty
|
|
* (if the folio has buffers).
|
|
*
|
|
* When a buffer is marked dirty, its folio is dirtied, but the folio's other
|
|
* buffers are not.
|
|
*
|
|
* Also. When blockdev buffers are explicitly read with bread(), they
|
|
* individually become uptodate. But their backing folio remains not
|
|
* uptodate - even if all of its buffers are uptodate. A subsequent
|
|
* block_read_full_folio() against that folio will discover all the uptodate
|
|
* buffers, will set the folio uptodate and will perform no I/O.
|
|
*/
|
|
|
|
/**
|
|
* mark_buffer_dirty - mark a buffer_head as needing writeout
|
|
* @bh: the buffer_head to mark dirty
|
|
*
|
|
* mark_buffer_dirty() will set the dirty bit against the buffer, then set
|
|
* its backing folio dirty, then tag the folio as dirty in the page cache
|
|
* and then attach the address_space's inode to its superblock's dirty
|
|
* inode list.
|
|
*
|
|
* mark_buffer_dirty() is atomic. It takes bh->b_folio->mapping->i_private_lock,
|
|
* i_pages lock and mapping->host->i_lock.
|
|
*/
|
|
void mark_buffer_dirty(struct buffer_head *bh)
|
|
{
|
|
WARN_ON_ONCE(!buffer_uptodate(bh));
|
|
|
|
trace_block_dirty_buffer(bh);
|
|
|
|
/*
|
|
* Very *carefully* optimize the it-is-already-dirty case.
|
|
*
|
|
* Don't let the final "is it dirty" escape to before we
|
|
* perhaps modified the buffer.
|
|
*/
|
|
if (buffer_dirty(bh)) {
|
|
smp_mb();
|
|
if (buffer_dirty(bh))
|
|
return;
|
|
}
|
|
|
|
if (!test_set_buffer_dirty(bh)) {
|
|
struct folio *folio = bh->b_folio;
|
|
struct address_space *mapping = NULL;
|
|
|
|
if (!folio_test_set_dirty(folio)) {
|
|
mapping = folio->mapping;
|
|
if (mapping)
|
|
__folio_mark_dirty(folio, mapping, 0);
|
|
}
|
|
if (mapping)
|
|
__mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(mark_buffer_dirty);
|
|
|
|
void mark_buffer_write_io_error(struct buffer_head *bh)
|
|
{
|
|
struct mapping_metadata_bhs *mmb;
|
|
|
|
set_buffer_write_io_error(bh);
|
|
/* FIXME: do we need to set this in both places? */
|
|
if (bh->b_folio && bh->b_folio->mapping)
|
|
mapping_set_error(bh->b_folio->mapping, -EIO);
|
|
/* Protect us from mmb & inode getting freed while we work on it */
|
|
rcu_read_lock();
|
|
mmb = READ_ONCE(bh->b_mmb);
|
|
if (mmb)
|
|
mapping_set_error(mmb->mapping, -EIO);
|
|
rcu_read_unlock();
|
|
}
|
|
EXPORT_SYMBOL(mark_buffer_write_io_error);
|
|
|
|
/**
|
|
* __brelse - Release a buffer.
|
|
* @bh: The buffer to release.
|
|
*
|
|
* This variant of brelse() can be called if @bh is guaranteed to not be NULL.
|
|
*/
|
|
void __brelse(struct buffer_head *bh)
|
|
{
|
|
if (atomic_read(&bh->b_count)) {
|
|
put_bh(bh);
|
|
return;
|
|
}
|
|
WARN(1, KERN_ERR "VFS: brelse: Trying to free free buffer\n");
|
|
}
|
|
EXPORT_SYMBOL(__brelse);
|
|
|
|
/**
|
|
* __bforget - Discard any dirty data in a buffer.
|
|
* @bh: The buffer to forget.
|
|
*
|
|
* This variant of bforget() can be called if @bh is guaranteed to not
|
|
* be NULL.
|
|
*/
|
|
void __bforget(struct buffer_head *bh)
|
|
{
|
|
clear_buffer_dirty(bh);
|
|
clear_buffer_write_io_error(bh);
|
|
remove_assoc_queue(bh);
|
|
__brelse(bh);
|
|
}
|
|
EXPORT_SYMBOL(__bforget);
|
|
|
|
static void buffer_set_crypto_ctx(struct bio *bio, const struct buffer_head *bh,
|
|
gfp_t gfp_mask)
|
|
{
|
|
const struct address_space *mapping;
|
|
|
|
/*
|
|
* The ext4 journal (jbd2) can submit a buffer_head it directly created
|
|
* for memory that is not in the page cache at all. fscrypt doesn't
|
|
* care about these.
|
|
*/
|
|
if (!bh->b_folio)
|
|
return;
|
|
mapping = bh->b_folio->mapping;
|
|
if (!mapping)
|
|
return;
|
|
fscrypt_set_bio_crypt_ctx(bio, mapping->host,
|
|
folio_pos(bh->b_folio) + bh_offset(bh), gfp_mask);
|
|
}
|
|
|
|
static void __bh_submit(struct buffer_head *bh, blk_opf_t opf,
|
|
enum rw_hint write_hint, struct writeback_control *wbc,
|
|
bio_end_io_t end_bio)
|
|
{
|
|
struct bio *bio;
|
|
|
|
BUG_ON(!buffer_locked(bh));
|
|
BUG_ON(!buffer_mapped(bh));
|
|
BUG_ON(buffer_delay(bh));
|
|
BUG_ON(buffer_unwritten(bh));
|
|
|
|
set_buffer_req(bh);
|
|
|
|
if (buffer_meta(bh))
|
|
opf |= REQ_META;
|
|
if (buffer_prio(bh))
|
|
opf |= REQ_PRIO;
|
|
|
|
bio = bio_alloc(bh->b_bdev, 1, opf, GFP_NOIO);
|
|
|
|
if (bh->b_folio && folio_test_dropbehind(bh->b_folio) &&
|
|
op_is_write(opf))
|
|
bio_set_flag(bio, BIO_COMPLETE_IN_TASK);
|
|
|
|
if (IS_ENABLED(CONFIG_FS_ENCRYPTION))
|
|
buffer_set_crypto_ctx(bio, bh, GFP_NOIO);
|
|
|
|
bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9);
|
|
bio->bi_write_hint = write_hint;
|
|
|
|
if (bh->b_folio)
|
|
bio_add_folio_nofail(bio, bh->b_folio, bh->b_size,
|
|
bh_offset(bh));
|
|
else
|
|
bio_add_virt_nofail(bio, bh->b_data, bh->b_size);
|
|
|
|
bio->bi_end_io = end_bio;
|
|
bio->bi_private = bh;
|
|
|
|
/* Take care of bh's that straddle the end of the device */
|
|
guard_bio_eod(bio);
|
|
|
|
if (wbc) {
|
|
wbc_init_bio(wbc, bio);
|
|
if (bh->b_folio)
|
|
wbc_account_cgroup_owner(wbc, bh->b_folio, bh->b_size);
|
|
}
|
|
|
|
blk_crypto_submit_bio(bio);
|
|
}
|
|
|
|
/**
|
|
* bh_submit - Start I/O against a buffer head
|
|
* @bh: The buffer head to perform I/O on.
|
|
* @opf: Operation and flags for bio.
|
|
* @end_io: The routine to call when I/O has completed.
|
|
*
|
|
* If you need to do I/O on an individual bh (instead of allowing the
|
|
* page cache to do I/O on the folio that it is in), call this function.
|
|
*/
|
|
void bh_submit(struct buffer_head *bh, blk_opf_t opf, bio_end_io_t end_io)
|
|
{
|
|
__bh_submit(bh, opf, WRITE_LIFE_NOT_SET, NULL, end_io);
|
|
}
|
|
EXPORT_SYMBOL(bh_submit);
|
|
|
|
static struct buffer_head *__bread_slow(struct buffer_head *bh)
|
|
{
|
|
lock_buffer(bh);
|
|
if (buffer_uptodate(bh)) {
|
|
unlock_buffer(bh);
|
|
return bh;
|
|
} else {
|
|
bh_submit(bh, REQ_OP_READ, bh_end_read);
|
|
wait_on_buffer(bh);
|
|
if (buffer_uptodate(bh))
|
|
return bh;
|
|
}
|
|
brelse(bh);
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Per-cpu buffer LRU implementation. To reduce the cost of __find_get_block().
|
|
* The bhs[] array is sorted - newest buffer is at bhs[0]. Buffers have their
|
|
* refcount elevated by one when they're in an LRU. A buffer can only appear
|
|
* once in a particular CPU's LRU. A single buffer can be present in multiple
|
|
* CPU's LRUs at the same time.
|
|
*
|
|
* This is a transparent caching front-end to sb_bread(), sb_getblk() and
|
|
* sb_find_get_block().
|
|
*
|
|
* The LRUs themselves only need locking against invalidate_bh_lrus. We use
|
|
* a local interrupt disable for that.
|
|
*/
|
|
|
|
#define BH_LRU_SIZE 16
|
|
|
|
struct bh_lru {
|
|
struct buffer_head *bhs[BH_LRU_SIZE];
|
|
};
|
|
|
|
static DEFINE_PER_CPU(struct bh_lru, bh_lrus) = {{ NULL }};
|
|
|
|
#ifdef CONFIG_SMP
|
|
#define bh_lru_lock() local_irq_disable()
|
|
#define bh_lru_unlock() local_irq_enable()
|
|
#else
|
|
#define bh_lru_lock() preempt_disable()
|
|
#define bh_lru_unlock() preempt_enable()
|
|
#endif
|
|
|
|
static inline void check_irqs_on(void)
|
|
{
|
|
#ifdef irqs_disabled
|
|
BUG_ON(irqs_disabled());
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Install a buffer_head into this cpu's LRU. If not already in the LRU, it is
|
|
* inserted at the front, and the buffer_head at the back if any is evicted.
|
|
* Or, if already in the LRU it is moved to the front.
|
|
*/
|
|
static void bh_lru_install(struct buffer_head *bh)
|
|
{
|
|
struct buffer_head *evictee = bh;
|
|
struct bh_lru *b;
|
|
int i;
|
|
|
|
check_irqs_on();
|
|
bh_lru_lock();
|
|
|
|
/*
|
|
* the refcount of buffer_head in bh_lru prevents dropping the
|
|
* attached folio (i.e., try_to_free_buffers) so it could cause
|
|
* failing page migration.
|
|
* Skip putting upcoming bh into bh_lru until migration is done.
|
|
*/
|
|
if (lru_cache_disabled() || cpu_is_isolated(smp_processor_id())) {
|
|
bh_lru_unlock();
|
|
return;
|
|
}
|
|
|
|
b = this_cpu_ptr(&bh_lrus);
|
|
for (i = 0; i < BH_LRU_SIZE; i++) {
|
|
swap(evictee, b->bhs[i]);
|
|
if (evictee == bh) {
|
|
bh_lru_unlock();
|
|
return;
|
|
}
|
|
}
|
|
|
|
get_bh(bh);
|
|
bh_lru_unlock();
|
|
brelse(evictee);
|
|
}
|
|
|
|
/*
|
|
* Look up the bh in this cpu's LRU. If it's there, move it to the head.
|
|
*/
|
|
static struct buffer_head *
|
|
lookup_bh_lru(struct block_device *bdev, sector_t block, unsigned size)
|
|
{
|
|
struct buffer_head *ret = NULL;
|
|
unsigned int i;
|
|
|
|
check_irqs_on();
|
|
bh_lru_lock();
|
|
if (cpu_is_isolated(smp_processor_id())) {
|
|
bh_lru_unlock();
|
|
return NULL;
|
|
}
|
|
for (i = 0; i < BH_LRU_SIZE; i++) {
|
|
struct buffer_head *bh = __this_cpu_read(bh_lrus.bhs[i]);
|
|
|
|
if (bh && bh->b_blocknr == block && bh->b_bdev == bdev &&
|
|
bh->b_size == size) {
|
|
if (i) {
|
|
while (i) {
|
|
__this_cpu_write(bh_lrus.bhs[i],
|
|
__this_cpu_read(bh_lrus.bhs[i - 1]));
|
|
i--;
|
|
}
|
|
__this_cpu_write(bh_lrus.bhs[0], bh);
|
|
}
|
|
get_bh(bh);
|
|
ret = bh;
|
|
break;
|
|
}
|
|
}
|
|
bh_lru_unlock();
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* Perform a pagecache lookup for the matching buffer. If it's there, refresh
|
|
* it in the LRU and mark it as accessed. If it is not present then return
|
|
* NULL. Atomic context callers may also return NULL if the buffer is being
|
|
* migrated; similarly the folio is not marked accessed either.
|
|
*/
|
|
static struct buffer_head *
|
|
find_get_block_common(struct block_device *bdev, sector_t block,
|
|
unsigned size, bool atomic)
|
|
{
|
|
struct buffer_head *bh = lookup_bh_lru(bdev, block, size);
|
|
|
|
if (bh == NULL) {
|
|
/* __find_get_block_slow will mark the folio accessed */
|
|
bh = __find_get_block_slow(bdev, block, atomic);
|
|
if (bh)
|
|
bh_lru_install(bh);
|
|
} else
|
|
touch_buffer(bh);
|
|
|
|
return bh;
|
|
}
|
|
|
|
struct buffer_head *
|
|
__find_get_block(struct block_device *bdev, sector_t block, unsigned size)
|
|
{
|
|
return find_get_block_common(bdev, block, size, true);
|
|
}
|
|
EXPORT_SYMBOL(__find_get_block);
|
|
|
|
/* same as __find_get_block() but allows sleeping contexts */
|
|
struct buffer_head *
|
|
__find_get_block_nonatomic(struct block_device *bdev, sector_t block,
|
|
unsigned size)
|
|
{
|
|
return find_get_block_common(bdev, block, size, false);
|
|
}
|
|
EXPORT_SYMBOL(__find_get_block_nonatomic);
|
|
|
|
/**
|
|
* bdev_getblk - Get a buffer_head in a block device's buffer cache.
|
|
* @bdev: The block device.
|
|
* @block: The block number.
|
|
* @size: The size of buffer_heads for this @bdev.
|
|
* @gfp: The memory allocation flags to use.
|
|
*
|
|
* The returned buffer head has its reference count incremented, but is
|
|
* not locked. The caller should call brelse() when it has finished
|
|
* with the buffer. The buffer may not be uptodate. If needed, the
|
|
* caller can bring it uptodate either by reading it or overwriting it.
|
|
*
|
|
* Return: The buffer head, or NULL if memory could not be allocated.
|
|
*/
|
|
struct buffer_head *bdev_getblk(struct block_device *bdev, sector_t block,
|
|
unsigned size, gfp_t gfp)
|
|
{
|
|
struct buffer_head *bh;
|
|
|
|
if (gfpflags_allow_blocking(gfp))
|
|
bh = __find_get_block_nonatomic(bdev, block, size);
|
|
else
|
|
bh = __find_get_block(bdev, block, size);
|
|
|
|
might_alloc(gfp);
|
|
if (bh)
|
|
return bh;
|
|
|
|
return __getblk_slow(bdev, block, size, gfp);
|
|
}
|
|
EXPORT_SYMBOL(bdev_getblk);
|
|
|
|
/*
|
|
* Do async read-ahead on a buffer..
|
|
*/
|
|
void __breadahead(struct block_device *bdev, sector_t block, unsigned size)
|
|
{
|
|
struct buffer_head *bh = bdev_getblk(bdev, block, size,
|
|
GFP_NOWAIT | __GFP_MOVABLE);
|
|
|
|
if (likely(bh)) {
|
|
bh_readahead(bh, REQ_RAHEAD);
|
|
brelse(bh);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(__breadahead);
|
|
|
|
/**
|
|
* __bread_gfp() - Read a block.
|
|
* @bdev: The block device to read from.
|
|
* @block: Block number in units of block size.
|
|
* @size: The block size of this device in bytes.
|
|
* @gfp: Not page allocation flags; see below.
|
|
*
|
|
* You are not expected to call this function. You should use one of
|
|
* sb_bread(), sb_bread_unmovable() or __bread().
|
|
*
|
|
* Read a specified block, and return the buffer head that refers to it.
|
|
* If @gfp is 0, the memory will be allocated using the block device's
|
|
* default GFP flags. If @gfp is __GFP_MOVABLE, the memory may be
|
|
* allocated from a movable area. Do not pass in a complete set of
|
|
* GFP flags.
|
|
*
|
|
* The returned buffer head has its refcount increased. The caller should
|
|
* call brelse() when it has finished with the buffer.
|
|
*
|
|
* Context: May sleep waiting for I/O.
|
|
* Return: NULL if the block was unreadable.
|
|
*/
|
|
struct buffer_head *__bread_gfp(struct block_device *bdev, sector_t block,
|
|
unsigned size, gfp_t gfp)
|
|
{
|
|
struct buffer_head *bh;
|
|
|
|
gfp |= mapping_gfp_constraint(bdev->bd_mapping, ~__GFP_FS);
|
|
|
|
/*
|
|
* Prefer looping in the allocator rather than here, at least that
|
|
* code knows what it's doing.
|
|
*/
|
|
gfp |= __GFP_NOFAIL;
|
|
|
|
bh = bdev_getblk(bdev, block, size, gfp);
|
|
|
|
if (likely(bh) && !buffer_uptodate(bh))
|
|
bh = __bread_slow(bh);
|
|
return bh;
|
|
}
|
|
EXPORT_SYMBOL(__bread_gfp);
|
|
|
|
static void __invalidate_bh_lrus(struct bh_lru *b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < BH_LRU_SIZE; i++) {
|
|
brelse(b->bhs[i]);
|
|
b->bhs[i] = NULL;
|
|
}
|
|
}
|
|
/*
|
|
* invalidate_bh_lrus() is called rarely - but not only at unmount.
|
|
* This doesn't race because it runs in each cpu either in irq
|
|
* or with preempt disabled.
|
|
*/
|
|
static void invalidate_bh_lru(void *arg)
|
|
{
|
|
struct bh_lru *b = &get_cpu_var(bh_lrus);
|
|
|
|
__invalidate_bh_lrus(b);
|
|
put_cpu_var(bh_lrus);
|
|
}
|
|
|
|
bool has_bh_in_lru(int cpu, void *dummy)
|
|
{
|
|
struct bh_lru *b = per_cpu_ptr(&bh_lrus, cpu);
|
|
int i;
|
|
|
|
for (i = 0; i < BH_LRU_SIZE; i++) {
|
|
if (b->bhs[i])
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void invalidate_bh_lrus(void)
|
|
{
|
|
on_each_cpu_cond(has_bh_in_lru, invalidate_bh_lru, NULL, 1);
|
|
}
|
|
EXPORT_SYMBOL_GPL(invalidate_bh_lrus);
|
|
|
|
/*
|
|
* It's called from workqueue context so we need a bh_lru_lock to close
|
|
* the race with preemption/irq.
|
|
*/
|
|
void invalidate_bh_lrus_cpu(void)
|
|
{
|
|
struct bh_lru *b;
|
|
|
|
bh_lru_lock();
|
|
b = this_cpu_ptr(&bh_lrus);
|
|
__invalidate_bh_lrus(b);
|
|
bh_lru_unlock();
|
|
}
|
|
|
|
void folio_set_bh(struct buffer_head *bh, struct folio *folio,
|
|
unsigned long offset)
|
|
{
|
|
bh->b_folio = folio;
|
|
BUG_ON(offset >= folio_size(folio));
|
|
if (folio_test_highmem(folio))
|
|
/*
|
|
* This catches illegal uses and preserves the offset:
|
|
*/
|
|
bh->b_data = (char *)(0 + offset);
|
|
else
|
|
bh->b_data = folio_address(folio) + offset;
|
|
}
|
|
EXPORT_SYMBOL(folio_set_bh);
|
|
|
|
/* Bits that are cleared during an invalidate */
|
|
#define BUFFER_FLAGS_DISCARD \
|
|
(1 << BH_Mapped | 1 << BH_New | 1 << BH_Req | \
|
|
1 << BH_Delay | 1 << BH_Unwritten | 1 << BH_Write_EIO)
|
|
|
|
/*
|
|
* Called when truncating a buffer on a folio completely.
|
|
*/
|
|
static void discard_buffer(struct buffer_head * bh)
|
|
{
|
|
unsigned long b_state;
|
|
|
|
lock_buffer(bh);
|
|
clear_buffer_dirty(bh);
|
|
bh->b_bdev = NULL;
|
|
b_state = READ_ONCE(bh->b_state);
|
|
do {
|
|
} while (!try_cmpxchg_relaxed(&bh->b_state, &b_state,
|
|
b_state & ~BUFFER_FLAGS_DISCARD));
|
|
unlock_buffer(bh);
|
|
}
|
|
|
|
/**
|
|
* block_invalidate_folio - Invalidate part or all of a buffer-backed folio.
|
|
* @folio: The folio which is affected.
|
|
* @offset: start of the range to invalidate
|
|
* @length: length of the range to invalidate
|
|
*
|
|
* block_invalidate_folio() is called when all or part of the folio has been
|
|
* invalidated by a truncate operation.
|
|
*
|
|
* block_invalidate_folio() does not have to release all buffers, but it must
|
|
* ensure that no dirty buffer is left outside @offset and that no I/O
|
|
* is underway against any of the blocks which are outside the truncation
|
|
* point. Because the caller is about to free (and possibly reuse) those
|
|
* blocks on-disk.
|
|
*/
|
|
void block_invalidate_folio(struct folio *folio, size_t offset, size_t length)
|
|
{
|
|
struct buffer_head *head, *bh, *next;
|
|
size_t curr_off = 0;
|
|
size_t stop = length + offset;
|
|
|
|
BUG_ON(!folio_test_locked(folio));
|
|
|
|
/*
|
|
* Check for overflow
|
|
*/
|
|
BUG_ON(stop > folio_size(folio) || stop < length);
|
|
|
|
head = folio_buffers(folio);
|
|
if (!head)
|
|
return;
|
|
|
|
bh = head;
|
|
do {
|
|
size_t next_off = curr_off + bh->b_size;
|
|
next = bh->b_this_page;
|
|
|
|
/*
|
|
* Are we still fully in range ?
|
|
*/
|
|
if (next_off > stop)
|
|
goto out;
|
|
|
|
/*
|
|
* is this block fully invalidated?
|
|
*/
|
|
if (offset <= curr_off)
|
|
discard_buffer(bh);
|
|
curr_off = next_off;
|
|
bh = next;
|
|
} while (bh != head);
|
|
|
|
/*
|
|
* We release buffers only if the entire folio is being invalidated.
|
|
* The get_block cached value has been unconditionally invalidated,
|
|
* so real IO is not possible anymore.
|
|
*/
|
|
if (length == folio_size(folio))
|
|
filemap_release_folio(folio, 0);
|
|
out:
|
|
folio_clear_mappedtodisk(folio);
|
|
}
|
|
EXPORT_SYMBOL(block_invalidate_folio);
|
|
|
|
/*
|
|
* We attach and possibly dirty the buffers atomically wrt
|
|
* block_dirty_folio() via i_private_lock. try_to_free_buffers
|
|
* is already excluded via the folio lock.
|
|
*/
|
|
struct buffer_head *create_empty_buffers(struct folio *folio,
|
|
unsigned long blocksize, unsigned long b_state)
|
|
{
|
|
struct buffer_head *bh, *head, *tail;
|
|
gfp_t gfp = GFP_NOFS | __GFP_ACCOUNT | __GFP_NOFAIL;
|
|
|
|
head = folio_alloc_buffers(folio, blocksize, gfp);
|
|
bh = head;
|
|
do {
|
|
bh->b_state |= b_state;
|
|
tail = bh;
|
|
bh = bh->b_this_page;
|
|
} while (bh);
|
|
tail->b_this_page = head;
|
|
|
|
spin_lock(&folio->mapping->i_private_lock);
|
|
if (folio_test_uptodate(folio) || folio_test_dirty(folio)) {
|
|
bh = head;
|
|
do {
|
|
if (folio_test_dirty(folio))
|
|
set_buffer_dirty(bh);
|
|
if (folio_test_uptodate(folio))
|
|
set_buffer_uptodate(bh);
|
|
bh = bh->b_this_page;
|
|
} while (bh != head);
|
|
}
|
|
folio_attach_private(folio, head);
|
|
spin_unlock(&folio->mapping->i_private_lock);
|
|
|
|
return head;
|
|
}
|
|
EXPORT_SYMBOL(create_empty_buffers);
|
|
|
|
/**
|
|
* clean_bdev_aliases: clean a range of buffers in block device
|
|
* @bdev: Block device to clean buffers in
|
|
* @block: Start of a range of blocks to clean
|
|
* @len: Number of blocks to clean
|
|
*
|
|
* We are taking a range of blocks for data and we don't want writeback of any
|
|
* buffer-cache aliases starting from return from this function and until the
|
|
* moment when something will explicitly mark the buffer dirty (hopefully that
|
|
* will not happen until we will free that block ;-) We don't even need to mark
|
|
* it not-uptodate - nobody can expect anything from a newly allocated buffer
|
|
* anyway.
|
|
*
|
|
* Also.. Note that bforget() doesn't lock the buffer. So there can be
|
|
* writeout I/O going on against recently-freed buffers. We don't wait on that
|
|
* I/O in bforget() - it's more efficient to wait on the I/O only if we really
|
|
* need to. That happens here.
|
|
*/
|
|
void clean_bdev_aliases(struct block_device *bdev, sector_t block, sector_t len)
|
|
{
|
|
struct address_space *bd_mapping = bdev->bd_mapping;
|
|
const int blkbits = bd_mapping->host->i_blkbits;
|
|
struct folio_batch fbatch;
|
|
pgoff_t index = ((loff_t)block << blkbits) / PAGE_SIZE;
|
|
pgoff_t end;
|
|
int i, count;
|
|
struct buffer_head *bh;
|
|
struct buffer_head *head;
|
|
|
|
end = ((loff_t)(block + len - 1) << blkbits) / PAGE_SIZE;
|
|
folio_batch_init(&fbatch);
|
|
while (filemap_get_folios(bd_mapping, &index, end, &fbatch)) {
|
|
count = folio_batch_count(&fbatch);
|
|
for (i = 0; i < count; i++) {
|
|
struct folio *folio = fbatch.folios[i];
|
|
|
|
if (!folio_buffers(folio))
|
|
continue;
|
|
/*
|
|
* We use folio lock instead of bd_mapping->i_private_lock
|
|
* to pin buffers here since we can afford to sleep and
|
|
* it scales better than a global spinlock lock.
|
|
*/
|
|
folio_lock(folio);
|
|
/* Recheck when the folio is locked which pins bhs */
|
|
head = folio_buffers(folio);
|
|
if (!head)
|
|
goto unlock_folio;
|
|
bh = head;
|
|
do {
|
|
if (!buffer_mapped(bh) || (bh->b_blocknr < block))
|
|
goto next;
|
|
if (bh->b_blocknr >= block + len)
|
|
break;
|
|
clear_buffer_dirty(bh);
|
|
wait_on_buffer(bh);
|
|
clear_buffer_req(bh);
|
|
next:
|
|
bh = bh->b_this_page;
|
|
} while (bh != head);
|
|
unlock_folio:
|
|
folio_unlock(folio);
|
|
}
|
|
folio_batch_release(&fbatch);
|
|
cond_resched();
|
|
/* End of range already reached? */
|
|
if (index > end || !index)
|
|
break;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(clean_bdev_aliases);
|
|
|
|
static struct buffer_head *folio_create_buffers(struct folio *folio,
|
|
struct inode *inode,
|
|
unsigned int b_state)
|
|
{
|
|
struct buffer_head *bh;
|
|
|
|
BUG_ON(!folio_test_locked(folio));
|
|
|
|
bh = folio_buffers(folio);
|
|
if (!bh)
|
|
bh = create_empty_buffers(folio,
|
|
1 << READ_ONCE(inode->i_blkbits), b_state);
|
|
return bh;
|
|
}
|
|
|
|
/*
|
|
* NOTE! All mapped/uptodate combinations are valid:
|
|
*
|
|
* Mapped Uptodate Meaning
|
|
*
|
|
* No No "unknown" - must do get_block()
|
|
* No Yes "hole" - zero-filled
|
|
* Yes No "allocated" - allocated on disk, not read in
|
|
* Yes Yes "valid" - allocated and up-to-date in memory.
|
|
*
|
|
* "Dirty" is valid only with the last case (mapped+uptodate).
|
|
*/
|
|
|
|
/*
|
|
* While block_write_full_folio is writing back the dirty buffers under
|
|
* the folio lock, whoever dirtied the buffers may decide to clean them
|
|
* again at any time. We handle that by only looking at the buffer
|
|
* state inside lock_buffer().
|
|
*
|
|
* If block_write_full_folio() is called for regular writeback
|
|
* (wbc->sync_mode == WB_SYNC_NONE) then it will redirty a folio which
|
|
* has a locked buffer. This can only happen if someone has written
|
|
* the buffer directly, with bh_submit(). At the address_space level
|
|
* the folio writeback flag prevents this contention from occurring.
|
|
*
|
|
* If block_write_full_folio() is called with wbc->sync_mode ==
|
|
* WB_SYNC_ALL, the writes are posted using REQ_SYNC; this
|
|
* causes the writes to be flagged as synchronous writes.
|
|
*/
|
|
int __block_write_full_folio(struct inode *inode, struct folio *folio,
|
|
get_block_t *get_block, struct writeback_control *wbc)
|
|
{
|
|
int err;
|
|
sector_t block;
|
|
sector_t last_block;
|
|
struct buffer_head *bh, *head;
|
|
size_t blocksize;
|
|
int nr_underway = 0;
|
|
blk_opf_t write_flags = wbc_to_write_flags(wbc);
|
|
|
|
head = folio_create_buffers(folio, inode,
|
|
(1 << BH_Dirty) | (1 << BH_Uptodate));
|
|
|
|
/*
|
|
* Be very careful. We have no exclusion from block_dirty_folio
|
|
* here, and the (potentially unmapped) buffers may become dirty at
|
|
* any time. If a buffer becomes dirty here after we've inspected it
|
|
* then we just miss that fact, and the folio stays dirty.
|
|
*
|
|
* Buffers outside i_size may be dirtied by block_dirty_folio;
|
|
* handle that here by just cleaning them.
|
|
*/
|
|
|
|
bh = head;
|
|
blocksize = bh->b_size;
|
|
|
|
block = div_u64(folio_pos(folio), blocksize);
|
|
last_block = div_u64(i_size_read(inode) - 1, blocksize);
|
|
|
|
/*
|
|
* Get all the dirty buffers mapped to disk addresses and
|
|
* handle any aliases from the underlying blockdev's mapping.
|
|
*/
|
|
do {
|
|
if (block > last_block) {
|
|
/*
|
|
* mapped buffers outside i_size will occur, because
|
|
* this folio can be outside i_size when there is a
|
|
* truncate in progress.
|
|
*/
|
|
/*
|
|
* The buffer was zeroed by block_write_full_folio()
|
|
*/
|
|
clear_buffer_dirty(bh);
|
|
set_buffer_uptodate(bh);
|
|
} else if ((!buffer_mapped(bh) || buffer_delay(bh)) &&
|
|
buffer_dirty(bh)) {
|
|
WARN_ON(bh->b_size != blocksize);
|
|
err = get_block(inode, block, bh, 1);
|
|
if (err)
|
|
goto recover;
|
|
clear_buffer_delay(bh);
|
|
if (buffer_new(bh)) {
|
|
/* blockdev mappings never come here */
|
|
clear_buffer_new(bh);
|
|
clean_bdev_bh_alias(bh);
|
|
}
|
|
}
|
|
bh = bh->b_this_page;
|
|
block++;
|
|
} while (bh != head);
|
|
|
|
do {
|
|
if (!buffer_mapped(bh))
|
|
continue;
|
|
/*
|
|
* If it's a fully non-blocking write attempt and we cannot
|
|
* lock the buffer then redirty the folio. Note that this can
|
|
* potentially cause a busy-wait loop from writeback threads
|
|
* and kswapd activity, but those code paths have their own
|
|
* higher-level throttling.
|
|
*/
|
|
if (wbc->sync_mode != WB_SYNC_NONE) {
|
|
lock_buffer(bh);
|
|
} else if (!trylock_buffer(bh)) {
|
|
folio_redirty_for_writepage(wbc, folio);
|
|
continue;
|
|
}
|
|
if (test_clear_buffer_dirty(bh)) {
|
|
set_buffer_async_write(bh);
|
|
} else {
|
|
unlock_buffer(bh);
|
|
}
|
|
} while ((bh = bh->b_this_page) != head);
|
|
|
|
/*
|
|
* The folio and its buffers are protected by the writeback flag,
|
|
* so we can drop the bh refcounts early.
|
|
*/
|
|
BUG_ON(folio_test_writeback(folio));
|
|
folio_start_writeback(folio);
|
|
|
|
do {
|
|
struct buffer_head *next = bh->b_this_page;
|
|
if (buffer_async_write(bh)) {
|
|
__bh_submit(bh, REQ_OP_WRITE | write_flags,
|
|
inode->i_write_hint, wbc,
|
|
bh_end_async_write);
|
|
nr_underway++;
|
|
}
|
|
bh = next;
|
|
} while (bh != head);
|
|
folio_unlock(folio);
|
|
|
|
err = 0;
|
|
done:
|
|
if (nr_underway == 0) {
|
|
/*
|
|
* The folio was marked dirty, but the buffers were
|
|
* clean. Someone wrote them back by hand with
|
|
* write_dirty_buffer/bh_submit. A rare case.
|
|
*/
|
|
folio_end_writeback(folio);
|
|
|
|
/*
|
|
* The folio and buffer_heads can be released at any time from
|
|
* here on.
|
|
*/
|
|
}
|
|
return err;
|
|
|
|
recover:
|
|
/*
|
|
* ENOSPC, or some other error. We may already have added some
|
|
* blocks to the file, so we need to write these out to avoid
|
|
* exposing stale data.
|
|
* The folio is currently locked and not marked for writeback
|
|
*/
|
|
bh = head;
|
|
/* Recovery: lock and submit the mapped buffers */
|
|
do {
|
|
if (buffer_mapped(bh) && buffer_dirty(bh) &&
|
|
!buffer_delay(bh)) {
|
|
lock_buffer(bh);
|
|
set_buffer_async_write(bh);
|
|
} else {
|
|
/*
|
|
* The buffer may have been set dirty during
|
|
* attachment to a dirty folio.
|
|
*/
|
|
clear_buffer_dirty(bh);
|
|
}
|
|
} while ((bh = bh->b_this_page) != head);
|
|
BUG_ON(folio_test_writeback(folio));
|
|
mapping_set_error(folio->mapping, err);
|
|
folio_start_writeback(folio);
|
|
do {
|
|
struct buffer_head *next = bh->b_this_page;
|
|
if (buffer_async_write(bh)) {
|
|
clear_buffer_dirty(bh);
|
|
__bh_submit(bh, REQ_OP_WRITE | write_flags,
|
|
inode->i_write_hint, wbc,
|
|
bh_end_async_write);
|
|
nr_underway++;
|
|
}
|
|
bh = next;
|
|
} while (bh != head);
|
|
folio_unlock(folio);
|
|
goto done;
|
|
}
|
|
EXPORT_SYMBOL(__block_write_full_folio);
|
|
|
|
/*
|
|
* If a folio has any new buffers, zero them out here, and mark them uptodate
|
|
* and dirty so they'll be written out (in order to prevent uninitialised
|
|
* block data from leaking). And clear the new bit.
|
|
*/
|
|
void folio_zero_new_buffers(struct folio *folio, size_t from, size_t to)
|
|
{
|
|
size_t block_start, block_end;
|
|
struct buffer_head *head, *bh;
|
|
|
|
BUG_ON(!folio_test_locked(folio));
|
|
head = folio_buffers(folio);
|
|
if (!head)
|
|
return;
|
|
|
|
bh = head;
|
|
block_start = 0;
|
|
do {
|
|
block_end = block_start + bh->b_size;
|
|
|
|
if (buffer_new(bh)) {
|
|
if (block_end > from && block_start < to) {
|
|
if (!folio_test_uptodate(folio)) {
|
|
size_t start, xend;
|
|
|
|
start = max(from, block_start);
|
|
xend = min(to, block_end);
|
|
|
|
folio_zero_segment(folio, start, xend);
|
|
set_buffer_uptodate(bh);
|
|
}
|
|
|
|
clear_buffer_new(bh);
|
|
mark_buffer_dirty(bh);
|
|
}
|
|
}
|
|
|
|
block_start = block_end;
|
|
bh = bh->b_this_page;
|
|
} while (bh != head);
|
|
}
|
|
EXPORT_SYMBOL(folio_zero_new_buffers);
|
|
|
|
static int
|
|
iomap_to_bh(struct inode *inode, sector_t block, struct buffer_head *bh,
|
|
const struct iomap *iomap)
|
|
{
|
|
loff_t offset = (loff_t)block << inode->i_blkbits;
|
|
|
|
bh->b_bdev = iomap->bdev;
|
|
|
|
/*
|
|
* Block points to offset in file we need to map, iomap contains
|
|
* the offset at which the map starts. If the map ends before the
|
|
* current block, then do not map the buffer and let the caller
|
|
* handle it.
|
|
*/
|
|
if (offset >= iomap->offset + iomap->length)
|
|
return -EIO;
|
|
|
|
switch (iomap->type) {
|
|
case IOMAP_HOLE:
|
|
/*
|
|
* If the buffer is not up to date or beyond the current EOF,
|
|
* we need to mark it as new to ensure sub-block zeroing is
|
|
* executed if necessary.
|
|
*/
|
|
if (!buffer_uptodate(bh) ||
|
|
(offset >= i_size_read(inode)))
|
|
set_buffer_new(bh);
|
|
return 0;
|
|
case IOMAP_DELALLOC:
|
|
if (!buffer_uptodate(bh) ||
|
|
(offset >= i_size_read(inode)))
|
|
set_buffer_new(bh);
|
|
set_buffer_uptodate(bh);
|
|
set_buffer_mapped(bh);
|
|
set_buffer_delay(bh);
|
|
return 0;
|
|
case IOMAP_UNWRITTEN:
|
|
/*
|
|
* For unwritten regions, we always need to ensure that regions
|
|
* in the block we are not writing to are zeroed. Mark the
|
|
* buffer as new to ensure this.
|
|
*/
|
|
set_buffer_new(bh);
|
|
set_buffer_unwritten(bh);
|
|
fallthrough;
|
|
case IOMAP_MAPPED:
|
|
if ((iomap->flags & IOMAP_F_NEW) ||
|
|
offset >= i_size_read(inode)) {
|
|
/*
|
|
* This can happen if truncating the block device races
|
|
* with the check in the caller as i_size updates on
|
|
* block devices aren't synchronized by i_rwsem for
|
|
* block devices.
|
|
*/
|
|
if (S_ISBLK(inode->i_mode))
|
|
return -EIO;
|
|
set_buffer_new(bh);
|
|
}
|
|
bh->b_blocknr = (iomap->addr + offset - iomap->offset) >>
|
|
inode->i_blkbits;
|
|
set_buffer_mapped(bh);
|
|
return 0;
|
|
default:
|
|
WARN_ON_ONCE(1);
|
|
return -EIO;
|
|
}
|
|
}
|
|
|
|
int __block_write_begin_int(struct folio *folio, loff_t pos, unsigned len,
|
|
get_block_t *get_block, const struct iomap *iomap)
|
|
{
|
|
size_t from = offset_in_folio(folio, pos);
|
|
size_t to = from + len;
|
|
struct inode *inode = folio->mapping->host;
|
|
size_t block_start, block_end;
|
|
sector_t block;
|
|
int err = 0;
|
|
size_t blocksize;
|
|
struct buffer_head *bh, *head, *wait[2], **wait_bh=wait;
|
|
|
|
BUG_ON(!folio_test_locked(folio));
|
|
BUG_ON(to > folio_size(folio));
|
|
BUG_ON(from > to);
|
|
|
|
head = folio_create_buffers(folio, inode, 0);
|
|
blocksize = head->b_size;
|
|
block = div_u64(folio_pos(folio), blocksize);
|
|
|
|
for (bh = head, block_start = 0; bh != head || !block_start;
|
|
block++, block_start=block_end, bh = bh->b_this_page) {
|
|
block_end = block_start + blocksize;
|
|
if (block_end <= from || block_start >= to) {
|
|
if (folio_test_uptodate(folio)) {
|
|
if (!buffer_uptodate(bh))
|
|
set_buffer_uptodate(bh);
|
|
}
|
|
continue;
|
|
}
|
|
if (buffer_new(bh))
|
|
clear_buffer_new(bh);
|
|
if (!buffer_mapped(bh)) {
|
|
WARN_ON(bh->b_size != blocksize);
|
|
if (get_block)
|
|
err = get_block(inode, block, bh, 1);
|
|
else
|
|
err = iomap_to_bh(inode, block, bh, iomap);
|
|
if (err)
|
|
break;
|
|
|
|
if (buffer_new(bh)) {
|
|
clean_bdev_bh_alias(bh);
|
|
if (folio_test_uptodate(folio)) {
|
|
clear_buffer_new(bh);
|
|
set_buffer_uptodate(bh);
|
|
mark_buffer_dirty(bh);
|
|
continue;
|
|
}
|
|
if (block_end > to || block_start < from)
|
|
folio_zero_segments(folio,
|
|
to, block_end,
|
|
block_start, from);
|
|
continue;
|
|
}
|
|
}
|
|
if (folio_test_uptodate(folio)) {
|
|
if (!buffer_uptodate(bh))
|
|
set_buffer_uptodate(bh);
|
|
continue;
|
|
}
|
|
if (!buffer_uptodate(bh) && !buffer_delay(bh) &&
|
|
!buffer_unwritten(bh) &&
|
|
(block_start < from || block_end > to)) {
|
|
bh_read_nowait(bh, 0);
|
|
*wait_bh++=bh;
|
|
}
|
|
}
|
|
/*
|
|
* If we issued read requests - let them complete.
|
|
*/
|
|
while(wait_bh > wait) {
|
|
wait_on_buffer(*--wait_bh);
|
|
if (!buffer_uptodate(*wait_bh))
|
|
err = -EIO;
|
|
}
|
|
if (unlikely(err))
|
|
folio_zero_new_buffers(folio, from, to);
|
|
return err;
|
|
}
|
|
|
|
int __block_write_begin(struct folio *folio, loff_t pos, unsigned len,
|
|
get_block_t *get_block)
|
|
{
|
|
return __block_write_begin_int(folio, pos, len, get_block, NULL);
|
|
}
|
|
EXPORT_SYMBOL(__block_write_begin);
|
|
|
|
void block_commit_write(struct folio *folio, size_t from, size_t to)
|
|
{
|
|
size_t block_start, block_end;
|
|
bool partial = false;
|
|
bool uptodate = folio_test_uptodate(folio);
|
|
unsigned blocksize;
|
|
struct buffer_head *bh, *head;
|
|
|
|
bh = head = folio_buffers(folio);
|
|
if (!bh)
|
|
return;
|
|
blocksize = bh->b_size;
|
|
|
|
block_start = 0;
|
|
do {
|
|
block_end = block_start + blocksize;
|
|
if (block_end <= from || block_start >= to) {
|
|
if (!buffer_uptodate(bh))
|
|
partial = true;
|
|
} else {
|
|
set_buffer_uptodate(bh);
|
|
mark_buffer_dirty(bh);
|
|
}
|
|
if (buffer_new(bh))
|
|
clear_buffer_new(bh);
|
|
|
|
block_start = block_end;
|
|
if (uptodate && block_start >= to)
|
|
break;
|
|
bh = bh->b_this_page;
|
|
} while (bh != head);
|
|
|
|
/*
|
|
* If this is a partial write which happened to make all buffers
|
|
* uptodate then we can optimize away a bogus read_folio() for
|
|
* the next read(). Here we 'discover' whether the folio went
|
|
* uptodate as a result of this (potentially partial) write.
|
|
*/
|
|
if (!partial)
|
|
folio_mark_uptodate(folio);
|
|
}
|
|
EXPORT_SYMBOL(block_commit_write);
|
|
|
|
/*
|
|
* block_write_begin takes care of the basic task of block allocation and
|
|
* bringing partial write blocks uptodate first.
|
|
*
|
|
* The filesystem needs to handle block truncation upon failure.
|
|
*/
|
|
int block_write_begin(struct address_space *mapping, loff_t pos, unsigned len,
|
|
struct folio **foliop, get_block_t *get_block)
|
|
{
|
|
pgoff_t index = pos >> PAGE_SHIFT;
|
|
struct folio *folio;
|
|
int status;
|
|
|
|
folio = __filemap_get_folio(mapping, index, FGP_WRITEBEGIN,
|
|
mapping_gfp_mask(mapping));
|
|
if (IS_ERR(folio))
|
|
return PTR_ERR(folio);
|
|
|
|
status = __block_write_begin_int(folio, pos, len, get_block, NULL);
|
|
if (unlikely(status)) {
|
|
folio_unlock(folio);
|
|
folio_put(folio);
|
|
folio = NULL;
|
|
}
|
|
|
|
*foliop = folio;
|
|
return status;
|
|
}
|
|
EXPORT_SYMBOL(block_write_begin);
|
|
|
|
int block_write_end(loff_t pos, unsigned len, unsigned copied,
|
|
struct folio *folio)
|
|
{
|
|
size_t start = pos - folio_pos(folio);
|
|
|
|
if (unlikely(copied < len)) {
|
|
/*
|
|
* The buffers that were written will now be uptodate, so
|
|
* we don't have to worry about a read_folio reading them
|
|
* and overwriting a partial write. However if we have
|
|
* encountered a short write and only partially written
|
|
* into a buffer, it will not be marked uptodate, so a
|
|
* read_folio might come in and destroy our partial write.
|
|
*
|
|
* Do the simplest thing, and just treat any short write to a
|
|
* non uptodate folio as a zero-length write, and force the
|
|
* caller to redo the whole thing.
|
|
*/
|
|
if (!folio_test_uptodate(folio))
|
|
copied = 0;
|
|
|
|
folio_zero_new_buffers(folio, start+copied, start+len);
|
|
}
|
|
flush_dcache_folio(folio);
|
|
|
|
/* This could be a short (even 0-length) commit */
|
|
block_commit_write(folio, start, start + copied);
|
|
|
|
return copied;
|
|
}
|
|
EXPORT_SYMBOL(block_write_end);
|
|
|
|
int generic_write_end(const struct kiocb *iocb, struct address_space *mapping,
|
|
loff_t pos, unsigned len, unsigned copied,
|
|
struct folio *folio, void *fsdata)
|
|
{
|
|
struct inode *inode = mapping->host;
|
|
loff_t old_size = inode->i_size;
|
|
bool i_size_changed = false;
|
|
|
|
copied = block_write_end(pos, len, copied, folio);
|
|
|
|
/*
|
|
* No need to use i_size_read() here, the i_size cannot change under us
|
|
* because we hold i_rwsem.
|
|
*
|
|
* But it's important to update i_size while still holding folio lock:
|
|
* page writeout could otherwise come in and zero beyond i_size.
|
|
*/
|
|
if (pos + copied > inode->i_size) {
|
|
i_size_write(inode, pos + copied);
|
|
i_size_changed = true;
|
|
}
|
|
|
|
folio_unlock(folio);
|
|
folio_put(folio);
|
|
|
|
if (old_size < pos)
|
|
pagecache_isize_extended(inode, old_size, pos);
|
|
/*
|
|
* Don't mark the inode dirty under folio lock. First, it unnecessarily
|
|
* makes the holding time of folio lock longer. Second, it forces lock
|
|
* ordering of folio lock and transaction start for journaling
|
|
* filesystems.
|
|
*/
|
|
if (i_size_changed)
|
|
mark_inode_dirty(inode);
|
|
return copied;
|
|
}
|
|
EXPORT_SYMBOL(generic_write_end);
|
|
|
|
/*
|
|
* block_is_partially_uptodate checks whether buffers within a folio are
|
|
* uptodate or not.
|
|
*
|
|
* Returns true if all buffers which correspond to the specified part
|
|
* of the folio are uptodate.
|
|
*/
|
|
bool block_is_partially_uptodate(struct folio *folio, size_t from, size_t count)
|
|
{
|
|
unsigned block_start, block_end, blocksize;
|
|
unsigned to;
|
|
struct buffer_head *bh, *head;
|
|
bool ret = true;
|
|
|
|
head = folio_buffers(folio);
|
|
if (!head)
|
|
return false;
|
|
blocksize = head->b_size;
|
|
to = min(folio_size(folio) - from, count);
|
|
to = from + to;
|
|
if (from < blocksize && to > folio_size(folio) - blocksize)
|
|
return false;
|
|
|
|
bh = head;
|
|
block_start = 0;
|
|
do {
|
|
block_end = block_start + blocksize;
|
|
if (block_end > from && block_start < to) {
|
|
if (!buffer_uptodate(bh)) {
|
|
ret = false;
|
|
break;
|
|
}
|
|
if (block_end >= to)
|
|
break;
|
|
}
|
|
block_start = block_end;
|
|
bh = bh->b_this_page;
|
|
} while (bh != head);
|
|
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(block_is_partially_uptodate);
|
|
|
|
/*
|
|
* Generic "read_folio" function for block devices that have the normal
|
|
* get_block functionality. This is most of the block device filesystems.
|
|
* Reads the folio asynchronously --- the unlock_buffer() and
|
|
* set/clear_buffer_uptodate() functions propagate buffer state into the
|
|
* folio once IO has completed.
|
|
*/
|
|
int block_read_full_folio(struct folio *folio, get_block_t *get_block)
|
|
{
|
|
struct inode *inode = folio->mapping->host;
|
|
sector_t iblock, lblock;
|
|
struct buffer_head *bh, *head, *prev = NULL;
|
|
size_t blocksize;
|
|
int fully_mapped = 1;
|
|
bool page_error = false;
|
|
loff_t limit = i_size_read(inode);
|
|
|
|
/* This is needed for ext4. */
|
|
if (IS_ENABLED(CONFIG_FS_VERITY) && IS_VERITY(inode))
|
|
limit = inode->i_sb->s_maxbytes;
|
|
|
|
head = folio_create_buffers(folio, inode, 0);
|
|
blocksize = head->b_size;
|
|
|
|
iblock = div_u64(folio_pos(folio), blocksize);
|
|
lblock = div_u64(limit + blocksize - 1, blocksize);
|
|
bh = head;
|
|
|
|
do {
|
|
if (buffer_uptodate(bh))
|
|
continue;
|
|
|
|
if (!buffer_mapped(bh)) {
|
|
int err = 0;
|
|
|
|
fully_mapped = 0;
|
|
if (iblock < lblock) {
|
|
WARN_ON(bh->b_size != blocksize);
|
|
err = get_block(inode, iblock, bh, 0);
|
|
if (err)
|
|
page_error = true;
|
|
}
|
|
if (!buffer_mapped(bh)) {
|
|
folio_zero_range(folio, bh_offset(bh),
|
|
blocksize);
|
|
if (!err)
|
|
set_buffer_uptodate(bh);
|
|
continue;
|
|
}
|
|
/*
|
|
* get_block() might have updated the buffer
|
|
* synchronously
|
|
*/
|
|
if (buffer_uptodate(bh))
|
|
continue;
|
|
}
|
|
|
|
lock_buffer(bh);
|
|
if (buffer_uptodate(bh)) {
|
|
unlock_buffer(bh);
|
|
continue;
|
|
}
|
|
|
|
/*
|
|
* If a folio's buffers are under async readin
|
|
* (end_buffer_async_read completion) then there is a
|
|
* possibility that another thread of control could lock
|
|
* one of the buffers after it has completed but while
|
|
* some of the other buffers have not completed. This
|
|
* locked buffer would confuse end_buffer_async_read()
|
|
* into not unlocking the folio. So the absence of
|
|
* BH_Async_Read tells end_buffer_async_read() that this
|
|
* buffer is not under async I/O.
|
|
*
|
|
* The folio is unlocked when it has no locked
|
|
* buffer_async buffers left.
|
|
*
|
|
* The folio lock prevents anyone starting new async
|
|
* I/O reads into any of the buffers.
|
|
*
|
|
* The writeback flag is used to prevent simultaneous
|
|
* writeout of the same folio.
|
|
*
|
|
* The folio lock prevents anyone from starting writeback
|
|
* of a folio which is under read I/O (the writeback
|
|
* flag is only ever set on a locked folio).
|
|
*/
|
|
set_buffer_async_read(bh);
|
|
if (prev)
|
|
bh_submit(prev, REQ_OP_READ, bh_end_async_read);
|
|
prev = bh;
|
|
} while (iblock++, (bh = bh->b_this_page) != head);
|
|
|
|
if (fully_mapped)
|
|
folio_set_mappedtodisk(folio);
|
|
|
|
/*
|
|
* All buffers are uptodate or get_block() returned an error
|
|
* when trying to map them - we must finish the read because
|
|
* end_buffer_async_read() will never be called on any buffer
|
|
* in this folio.
|
|
*/
|
|
if (prev)
|
|
bh_submit(prev, REQ_OP_READ, bh_end_async_read);
|
|
else
|
|
folio_end_read(folio, !page_error);
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(block_read_full_folio);
|
|
|
|
/* utility function for filesystems that need to do work on expanding
|
|
* truncates. Uses filesystem pagecache writes to allow the filesystem to
|
|
* deal with the hole.
|
|
*/
|
|
int generic_cont_expand_simple(struct inode *inode, loff_t size)
|
|
{
|
|
struct address_space *mapping = inode->i_mapping;
|
|
const struct address_space_operations *aops = mapping->a_ops;
|
|
struct folio *folio;
|
|
void *fsdata = NULL;
|
|
int err;
|
|
|
|
err = inode_newsize_ok(inode, size);
|
|
if (err)
|
|
goto out;
|
|
|
|
err = aops->write_begin(NULL, mapping, size, 0, &folio, &fsdata);
|
|
if (err)
|
|
goto out;
|
|
|
|
err = aops->write_end(NULL, mapping, size, 0, 0, folio, fsdata);
|
|
BUG_ON(err > 0);
|
|
|
|
out:
|
|
return err;
|
|
}
|
|
EXPORT_SYMBOL(generic_cont_expand_simple);
|
|
|
|
static int cont_expand_zero(const struct kiocb *iocb,
|
|
struct address_space *mapping,
|
|
loff_t pos, loff_t *bytes)
|
|
{
|
|
struct inode *inode = mapping->host;
|
|
const struct address_space_operations *aops = mapping->a_ops;
|
|
unsigned int blocksize = i_blocksize(inode);
|
|
struct folio *folio;
|
|
void *fsdata = NULL;
|
|
pgoff_t index, curidx;
|
|
loff_t curpos;
|
|
unsigned zerofrom, offset, len;
|
|
int err = 0;
|
|
|
|
index = pos >> PAGE_SHIFT;
|
|
offset = pos & ~PAGE_MASK;
|
|
|
|
while (index > (curidx = (curpos = *bytes)>>PAGE_SHIFT)) {
|
|
zerofrom = curpos & ~PAGE_MASK;
|
|
if (zerofrom & (blocksize-1)) {
|
|
*bytes |= (blocksize-1);
|
|
(*bytes)++;
|
|
}
|
|
len = PAGE_SIZE - zerofrom;
|
|
|
|
err = aops->write_begin(iocb, mapping, curpos, len,
|
|
&folio, &fsdata);
|
|
if (err)
|
|
goto out;
|
|
folio_zero_range(folio, offset_in_folio(folio, curpos), len);
|
|
err = aops->write_end(iocb, mapping, curpos, len, len,
|
|
folio, fsdata);
|
|
if (err < 0)
|
|
goto out;
|
|
BUG_ON(err != len);
|
|
err = 0;
|
|
|
|
balance_dirty_pages_ratelimited(mapping);
|
|
|
|
if (fatal_signal_pending(current)) {
|
|
err = -EINTR;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
/* folio crosses the boundary, find the boundary offset */
|
|
if (index == curidx) {
|
|
zerofrom = curpos & ~PAGE_MASK;
|
|
/* if we will expand the thing last block will be filled */
|
|
if (offset <= zerofrom) {
|
|
goto out;
|
|
}
|
|
if (zerofrom & (blocksize-1)) {
|
|
*bytes |= (blocksize-1);
|
|
(*bytes)++;
|
|
}
|
|
len = offset - zerofrom;
|
|
|
|
err = aops->write_begin(iocb, mapping, curpos, len,
|
|
&folio, &fsdata);
|
|
if (err)
|
|
goto out;
|
|
folio_zero_range(folio, offset_in_folio(folio, curpos), len);
|
|
err = aops->write_end(iocb, mapping, curpos, len, len,
|
|
folio, fsdata);
|
|
if (err < 0)
|
|
goto out;
|
|
BUG_ON(err != len);
|
|
err = 0;
|
|
}
|
|
out:
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
* For moronic filesystems that do not allow holes in file.
|
|
* We may have to extend the file.
|
|
*/
|
|
int cont_write_begin(const struct kiocb *iocb, struct address_space *mapping,
|
|
loff_t pos, unsigned len, struct folio **foliop,
|
|
void **fsdata, get_block_t *get_block, loff_t *bytes)
|
|
{
|
|
struct inode *inode = mapping->host;
|
|
unsigned int blocksize = i_blocksize(inode);
|
|
unsigned int zerofrom;
|
|
int err;
|
|
|
|
err = cont_expand_zero(iocb, mapping, pos, bytes);
|
|
if (err)
|
|
return err;
|
|
|
|
zerofrom = *bytes & ~PAGE_MASK;
|
|
if (pos+len > *bytes && zerofrom & (blocksize-1)) {
|
|
*bytes |= (blocksize-1);
|
|
(*bytes)++;
|
|
}
|
|
|
|
return block_write_begin(mapping, pos, len, foliop, get_block);
|
|
}
|
|
EXPORT_SYMBOL(cont_write_begin);
|
|
|
|
/*
|
|
* block_page_mkwrite() is not allowed to change the file size as it gets
|
|
* called from a page fault handler when a folio is first dirtied. Hence we must
|
|
* be careful to check for EOF conditions here. We set the folio up correctly
|
|
* for a written folio which means we get ENOSPC checking when writing into
|
|
* holes and correct delalloc and unwritten extent mapping on filesystems that
|
|
* support these features.
|
|
*
|
|
* We are not allowed to take the i_rwsem here so we have to play games to
|
|
* protect against truncate races as the folio could now be beyond EOF. Because
|
|
* truncate writes the inode size before removing folios, once we have the
|
|
* folio lock we can determine safely if the folio is beyond EOF. If it is not
|
|
* beyond EOF, then the folio is guaranteed safe against truncation until we
|
|
* unlock the folio.
|
|
*
|
|
* Direct callers of this function should protect against filesystem freezing
|
|
* using sb_start_pagefault() - sb_end_pagefault() functions.
|
|
*/
|
|
int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
|
|
get_block_t get_block)
|
|
{
|
|
struct folio *folio = page_folio(vmf->page);
|
|
struct inode *inode = file_inode(vma->vm_file);
|
|
unsigned long end;
|
|
loff_t size;
|
|
int ret;
|
|
|
|
folio_lock(folio);
|
|
size = i_size_read(inode);
|
|
if ((folio->mapping != inode->i_mapping) ||
|
|
(folio_pos(folio) >= size)) {
|
|
/* We overload EFAULT to mean folio got truncated */
|
|
ret = -EFAULT;
|
|
goto out_unlock;
|
|
}
|
|
|
|
end = folio_size(folio);
|
|
/* folio is wholly or partially inside EOF */
|
|
if (folio_pos(folio) + end > size)
|
|
end = size - folio_pos(folio);
|
|
|
|
ret = __block_write_begin_int(folio, 0, end, get_block, NULL);
|
|
if (unlikely(ret))
|
|
goto out_unlock;
|
|
|
|
block_commit_write(folio, 0, end);
|
|
|
|
folio_mark_dirty(folio);
|
|
folio_wait_stable(folio);
|
|
return 0;
|
|
out_unlock:
|
|
folio_unlock(folio);
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(block_page_mkwrite);
|
|
|
|
int block_truncate_page(struct address_space *mapping,
|
|
loff_t from, get_block_t *get_block)
|
|
{
|
|
pgoff_t index = from >> PAGE_SHIFT;
|
|
unsigned blocksize;
|
|
sector_t iblock;
|
|
size_t offset, length, pos;
|
|
struct inode *inode = mapping->host;
|
|
struct folio *folio;
|
|
struct buffer_head *bh;
|
|
int err = 0;
|
|
|
|
blocksize = i_blocksize(inode);
|
|
length = from & (blocksize - 1);
|
|
|
|
/* Block boundary? Nothing to do */
|
|
if (!length)
|
|
return 0;
|
|
|
|
length = blocksize - length;
|
|
iblock = ((loff_t)index * PAGE_SIZE) >> inode->i_blkbits;
|
|
|
|
folio = filemap_grab_folio(mapping, index);
|
|
if (IS_ERR(folio))
|
|
return PTR_ERR(folio);
|
|
|
|
bh = folio_buffers(folio);
|
|
if (!bh)
|
|
bh = create_empty_buffers(folio, blocksize, 0);
|
|
|
|
/* Find the buffer that contains "offset" */
|
|
offset = offset_in_folio(folio, from);
|
|
pos = blocksize;
|
|
while (offset >= pos) {
|
|
bh = bh->b_this_page;
|
|
iblock++;
|
|
pos += blocksize;
|
|
}
|
|
|
|
if (!buffer_mapped(bh)) {
|
|
WARN_ON(bh->b_size != blocksize);
|
|
err = get_block(inode, iblock, bh, 0);
|
|
if (err)
|
|
goto unlock;
|
|
/* unmapped? It's a hole - nothing to do */
|
|
if (!buffer_mapped(bh))
|
|
goto unlock;
|
|
}
|
|
|
|
/* Ok, it's mapped. Make sure it's up-to-date */
|
|
if (folio_test_uptodate(folio))
|
|
set_buffer_uptodate(bh);
|
|
|
|
if (!buffer_uptodate(bh) && !buffer_delay(bh) && !buffer_unwritten(bh)) {
|
|
err = bh_read(bh, 0);
|
|
/* Uhhuh. Read error. Complain and punt. */
|
|
if (err < 0)
|
|
goto unlock;
|
|
}
|
|
|
|
folio_zero_range(folio, offset, length);
|
|
mark_buffer_dirty(bh);
|
|
|
|
unlock:
|
|
folio_unlock(folio);
|
|
folio_put(folio);
|
|
|
|
return err;
|
|
}
|
|
EXPORT_SYMBOL(block_truncate_page);
|
|
|
|
/*
|
|
* The generic write folio function for buffer-backed address_spaces
|
|
*/
|
|
int block_write_full_folio(struct folio *folio, struct writeback_control *wbc,
|
|
void *get_block)
|
|
{
|
|
struct inode * const inode = folio->mapping->host;
|
|
loff_t i_size = i_size_read(inode);
|
|
|
|
/* Is the folio fully inside i_size? */
|
|
if (folio_next_pos(folio) <= i_size)
|
|
return __block_write_full_folio(inode, folio, get_block, wbc);
|
|
|
|
/* Is the folio fully outside i_size? (truncate in progress) */
|
|
if (folio_pos(folio) >= i_size) {
|
|
folio_unlock(folio);
|
|
return 0; /* don't care */
|
|
}
|
|
|
|
/*
|
|
* The folio straddles i_size. It must be zeroed out on each and every
|
|
* writeback invocation because it may be mmapped. "A file is mapped
|
|
* in multiples of the page size. For a file that is not a multiple of
|
|
* the page size, the remaining memory is zeroed when mapped, and
|
|
* writes to that region are not written out to the file."
|
|
*/
|
|
folio_zero_segment(folio, offset_in_folio(folio, i_size),
|
|
folio_size(folio));
|
|
return __block_write_full_folio(inode, folio, get_block, wbc);
|
|
}
|
|
|
|
sector_t generic_block_bmap(struct address_space *mapping, sector_t block,
|
|
get_block_t *get_block)
|
|
{
|
|
struct inode *inode = mapping->host;
|
|
struct buffer_head tmp = {
|
|
.b_size = i_blocksize(inode),
|
|
};
|
|
|
|
get_block(inode, block, &tmp, 0);
|
|
return tmp.b_blocknr;
|
|
}
|
|
EXPORT_SYMBOL(generic_block_bmap);
|
|
|
|
void write_dirty_buffer(struct buffer_head *bh, blk_opf_t op_flags)
|
|
{
|
|
lock_buffer(bh);
|
|
if (!test_clear_buffer_dirty(bh)) {
|
|
unlock_buffer(bh);
|
|
return;
|
|
}
|
|
bh_submit(bh, REQ_OP_WRITE | op_flags, bh_end_write);
|
|
}
|
|
EXPORT_SYMBOL(write_dirty_buffer);
|
|
|
|
/*
|
|
* For a data-integrity writeout, we need to wait upon any in-progress I/O
|
|
* and then start new I/O and then wait upon it. The caller must have a ref on
|
|
* the buffer_head.
|
|
*/
|
|
int __sync_dirty_buffer(struct buffer_head *bh, blk_opf_t op_flags)
|
|
{
|
|
WARN_ON(atomic_read(&bh->b_count) < 1);
|
|
lock_buffer(bh);
|
|
if (test_clear_buffer_dirty(bh)) {
|
|
/*
|
|
* The bh should be mapped, but it might not be if the
|
|
* device was hot-removed. Not much we can do but fail the I/O.
|
|
*/
|
|
if (!buffer_mapped(bh)) {
|
|
unlock_buffer(bh);
|
|
return -EIO;
|
|
}
|
|
|
|
bh_submit(bh, REQ_OP_WRITE | op_flags, bh_end_write);
|
|
wait_on_buffer(bh);
|
|
if (buffer_write_io_error(bh))
|
|
return -EIO;
|
|
} else {
|
|
unlock_buffer(bh);
|
|
}
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(__sync_dirty_buffer);
|
|
|
|
int sync_dirty_buffer(struct buffer_head *bh)
|
|
{
|
|
return __sync_dirty_buffer(bh, REQ_SYNC);
|
|
}
|
|
EXPORT_SYMBOL(sync_dirty_buffer);
|
|
|
|
static inline int buffer_busy(struct buffer_head *bh)
|
|
{
|
|
return atomic_read(&bh->b_count) |
|
|
(bh->b_state & ((1 << BH_Dirty) | (1 << BH_Lock)));
|
|
}
|
|
|
|
static bool
|
|
drop_buffers(struct folio *folio, struct buffer_head **buffers_to_free)
|
|
{
|
|
struct buffer_head *head = folio_buffers(folio);
|
|
struct buffer_head *bh;
|
|
|
|
bh = head;
|
|
do {
|
|
if (buffer_busy(bh))
|
|
goto failed;
|
|
bh = bh->b_this_page;
|
|
} while (bh != head);
|
|
|
|
do {
|
|
struct buffer_head *next = bh->b_this_page;
|
|
|
|
remove_assoc_queue(bh);
|
|
bh = next;
|
|
} while (bh != head);
|
|
*buffers_to_free = head;
|
|
folio_detach_private(folio);
|
|
return true;
|
|
failed:
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* try_to_free_buffers - Release buffers attached to this folio.
|
|
* @folio: The folio.
|
|
*
|
|
* If any buffers are in use (dirty, under writeback, elevated refcount),
|
|
* no buffers will be freed.
|
|
*
|
|
* If the folio is dirty but all the buffers are clean then we need to
|
|
* be sure to mark the folio clean as well. This is because the folio
|
|
* may be against a block device, and a later reattachment of buffers
|
|
* to a dirty folio will set *all* buffers dirty. Which would corrupt
|
|
* filesystem data on the same device.
|
|
*
|
|
* The same applies to regular filesystem folios: if all the buffers are
|
|
* clean then we set the folio clean and proceed. To do that, we require
|
|
* total exclusion from block_dirty_folio(). That is obtained with
|
|
* i_private_lock.
|
|
*
|
|
* Exclusion against try_to_free_buffers may be obtained by either
|
|
* locking the folio or by holding its mapping's i_private_lock.
|
|
*
|
|
* Context: Process context. @folio must be locked. Will not sleep.
|
|
* Return: true if all buffers attached to this folio were freed.
|
|
*/
|
|
bool try_to_free_buffers(struct folio *folio)
|
|
{
|
|
struct address_space * const mapping = folio->mapping;
|
|
struct buffer_head *buffers_to_free = NULL;
|
|
bool ret = 0;
|
|
|
|
BUG_ON(!folio_test_locked(folio));
|
|
if (folio_test_writeback(folio))
|
|
return false;
|
|
|
|
/* Misconfigured folio check */
|
|
if (WARN_ON_ONCE(!folio_buffers(folio)))
|
|
return true;
|
|
|
|
if (mapping == NULL) { /* can this still happen? */
|
|
ret = drop_buffers(folio, &buffers_to_free);
|
|
goto out;
|
|
}
|
|
|
|
spin_lock(&mapping->i_private_lock);
|
|
ret = drop_buffers(folio, &buffers_to_free);
|
|
|
|
/*
|
|
* If the filesystem writes its buffers by hand (eg ext3)
|
|
* then we can have clean buffers against a dirty folio. We
|
|
* clean the folio here; otherwise the VM will never notice
|
|
* that the filesystem did any IO at all.
|
|
*
|
|
* Also, during truncate, discard_buffer will have marked all
|
|
* the folio's buffers clean. We discover that here and clean
|
|
* the folio also.
|
|
*
|
|
* i_private_lock must be held over this entire operation in order
|
|
* to synchronise against block_dirty_folio and prevent the
|
|
* dirty bit from being lost.
|
|
*/
|
|
if (ret)
|
|
folio_cancel_dirty(folio);
|
|
spin_unlock(&mapping->i_private_lock);
|
|
out:
|
|
if (buffers_to_free) {
|
|
struct buffer_head *bh = buffers_to_free;
|
|
|
|
do {
|
|
struct buffer_head *next = bh->b_this_page;
|
|
free_buffer_head(bh);
|
|
bh = next;
|
|
} while (bh != buffers_to_free);
|
|
}
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(try_to_free_buffers);
|
|
|
|
/*
|
|
* Buffer-head allocation
|
|
*/
|
|
static struct kmem_cache *bh_cachep __ro_after_init;
|
|
|
|
/*
|
|
* Once the number of bh's in the machine exceeds this level, we start
|
|
* stripping them in writeback.
|
|
*/
|
|
static unsigned long max_buffer_heads __ro_after_init;
|
|
|
|
int buffer_heads_over_limit;
|
|
|
|
struct bh_accounting {
|
|
int nr; /* Number of live bh's */
|
|
int ratelimit; /* Limit cacheline bouncing */
|
|
};
|
|
|
|
static DEFINE_PER_CPU(struct bh_accounting, bh_accounting) = {0, 0};
|
|
|
|
static void recalc_bh_state(void)
|
|
{
|
|
int i;
|
|
int tot = 0;
|
|
|
|
if (__this_cpu_inc_return(bh_accounting.ratelimit) - 1 < 4096)
|
|
return;
|
|
__this_cpu_write(bh_accounting.ratelimit, 0);
|
|
for_each_online_cpu(i)
|
|
tot += per_cpu(bh_accounting, i).nr;
|
|
buffer_heads_over_limit = (tot > max_buffer_heads);
|
|
}
|
|
|
|
struct buffer_head *alloc_buffer_head(gfp_t gfp_flags)
|
|
{
|
|
struct buffer_head *ret = kmem_cache_zalloc(bh_cachep, gfp_flags);
|
|
if (ret) {
|
|
INIT_LIST_HEAD(&ret->b_assoc_buffers);
|
|
spin_lock_init(&ret->b_uptodate_lock);
|
|
preempt_disable();
|
|
__this_cpu_inc(bh_accounting.nr);
|
|
recalc_bh_state();
|
|
preempt_enable();
|
|
}
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(alloc_buffer_head);
|
|
|
|
void free_buffer_head(struct buffer_head *bh)
|
|
{
|
|
BUG_ON(!list_empty(&bh->b_assoc_buffers));
|
|
kmem_cache_free(bh_cachep, bh);
|
|
preempt_disable();
|
|
__this_cpu_dec(bh_accounting.nr);
|
|
recalc_bh_state();
|
|
preempt_enable();
|
|
}
|
|
EXPORT_SYMBOL(free_buffer_head);
|
|
|
|
static int buffer_exit_cpu_dead(unsigned int cpu)
|
|
{
|
|
int i;
|
|
struct bh_lru *b = &per_cpu(bh_lrus, cpu);
|
|
|
|
for (i = 0; i < BH_LRU_SIZE; i++) {
|
|
brelse(b->bhs[i]);
|
|
b->bhs[i] = NULL;
|
|
}
|
|
this_cpu_add(bh_accounting.nr, per_cpu(bh_accounting, cpu).nr);
|
|
per_cpu(bh_accounting, cpu).nr = 0;
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* bh_uptodate_or_lock - Test whether the buffer is uptodate
|
|
* @bh: struct buffer_head
|
|
*
|
|
* Return true if the buffer is up-to-date and false,
|
|
* with the buffer locked, if not.
|
|
*/
|
|
int bh_uptodate_or_lock(struct buffer_head *bh)
|
|
{
|
|
if (!buffer_uptodate(bh)) {
|
|
lock_buffer(bh);
|
|
if (!buffer_uptodate(bh))
|
|
return 0;
|
|
unlock_buffer(bh);
|
|
}
|
|
return 1;
|
|
}
|
|
EXPORT_SYMBOL(bh_uptodate_or_lock);
|
|
|
|
/**
|
|
* __bh_read - Submit read for a locked buffer
|
|
* @bh: struct buffer_head
|
|
* @op_flags: appending REQ_OP_* flags besides REQ_OP_READ
|
|
* @wait: wait until reading finish
|
|
*
|
|
* Returns zero on success or don't wait, and -EIO on error.
|
|
*/
|
|
int __bh_read(struct buffer_head *bh, blk_opf_t op_flags, bool wait)
|
|
{
|
|
int ret = 0;
|
|
|
|
BUG_ON(!buffer_locked(bh));
|
|
|
|
bh_submit(bh, REQ_OP_READ | op_flags, bh_end_read);
|
|
if (wait) {
|
|
wait_on_buffer(bh);
|
|
if (!buffer_uptodate(bh))
|
|
ret = -EIO;
|
|
}
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(__bh_read);
|
|
|
|
/**
|
|
* __bh_read_batch - Submit read for a batch of unlocked buffers
|
|
* @nr: entry number of the buffer batch
|
|
* @bhs: a batch of struct buffer_head
|
|
* @op_flags: appending REQ_OP_* flags besides REQ_OP_READ
|
|
* @force_lock: force to get a lock on the buffer if set, otherwise drops any
|
|
* buffer that cannot lock.
|
|
*
|
|
* Returns zero on success or don't wait, and -EIO on error.
|
|
*/
|
|
void __bh_read_batch(int nr, struct buffer_head *bhs[],
|
|
blk_opf_t op_flags, bool force_lock)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < nr; i++) {
|
|
struct buffer_head *bh = bhs[i];
|
|
|
|
if (buffer_uptodate(bh))
|
|
continue;
|
|
|
|
if (force_lock)
|
|
lock_buffer(bh);
|
|
else
|
|
if (!trylock_buffer(bh))
|
|
continue;
|
|
|
|
if (buffer_uptodate(bh)) {
|
|
unlock_buffer(bh);
|
|
continue;
|
|
}
|
|
|
|
bh_submit(bh, REQ_OP_READ | op_flags, bh_end_read);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(__bh_read_batch);
|
|
|
|
void __init buffer_init(void)
|
|
{
|
|
unsigned long nrpages;
|
|
int ret;
|
|
|
|
bh_cachep = KMEM_CACHE(buffer_head,
|
|
SLAB_RECLAIM_ACCOUNT|SLAB_PANIC);
|
|
/*
|
|
* Limit the bh occupancy to 10% of ZONE_NORMAL
|
|
*/
|
|
nrpages = (nr_free_buffer_pages() * 10) / 100;
|
|
max_buffer_heads = nrpages * (PAGE_SIZE / sizeof(struct buffer_head));
|
|
ret = cpuhp_setup_state_nocalls(CPUHP_FS_BUFF_DEAD, "fs/buffer:dead",
|
|
NULL, buffer_exit_cpu_dead);
|
|
WARN_ON(ret < 0);
|
|
}
|