fs/btrfs/fiemap.c
Source file repositories/reference/linux-study-clean/fs/btrfs/fiemap.c
File Facts
- System
- Linux kernel
- Corpus path
fs/btrfs/fiemap.c- Extension
.c- Size
- 28962 bytes
- Lines
- 929
- Domain
- Core OS
- Bucket
- VFS And Filesystem Core
- Inferred role
- Core OS: implementation source
- Status
- source implementation candidate
Why This File Exists
Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.
- Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
backref.hbtrfs_inode.hfiemap.hfile.hfile-item.h
Detected Declarations
struct btrfs_fiemap_entrystruct fiemap_cachefunction flush_fiemap_cachefunction fiemap_fill_next_extentfunction compressedfunction extent_fiemapfunction fiemap_next_leaf_itemfunction fiemap_search_slotfunction fiemap_process_holefunction fiemap_find_last_extent_offsetfunction extent_fiemapfunction btrfs_fiemapfunction fiemap_prep
Annotated Snippet
struct btrfs_fiemap_entry {
u64 offset;
u64 phys;
u64 len;
u32 flags;
};
/*
* Indicate the caller of emit_fiemap_extent() that it needs to unlock the file
* range from the inode's io tree, unlock the subvolume tree search path, flush
* the fiemap cache and relock the file range and research the subvolume tree.
* The value here is something negative that can't be confused with a valid
* errno value and different from 1 because that's also a return value from
* fiemap_fill_next_extent() and also it's often used to mean some btree search
* did not find a key, so make it some distinct negative value.
*/
#define BTRFS_FIEMAP_FLUSH_CACHE (-(MAX_ERRNO + 1))
/*
* Used to:
*
* - Cache the next entry to be emitted to the fiemap buffer, so that we can
* merge extents that are contiguous and can be grouped as a single one;
*
* - Store extents ready to be written to the fiemap buffer in an intermediary
* buffer. This intermediary buffer is to ensure that in case the fiemap
* buffer is memory mapped to the fiemap target file, we don't deadlock
* during btrfs_page_mkwrite(). This is because during fiemap we are locking
* an extent range in order to prevent races with delalloc flushing and
* ordered extent completion, which is needed in order to reliably detect
* delalloc in holes and prealloc extents. And this can lead to a deadlock
* if the fiemap buffer is memory mapped to the file we are running fiemap
* against (a silly, useless in practice scenario, but possible) because
* btrfs_page_mkwrite() will try to lock the same extent range.
*/
struct fiemap_cache {
/* An array of ready fiemap entries. */
struct btrfs_fiemap_entry *entries;
/* Number of entries in the entries array. */
int entries_size;
/* Index of the next entry in the entries array to write to. */
int entries_pos;
/*
* Once the entries array is full, this indicates what's the offset for
* the next file extent item we must search for in the inode's subvolume
* tree after unlocking the extent range in the inode's io tree and
* releasing the search path.
*/
u64 next_search_offset;
/*
* This matches struct fiemap_extent_info::fi_mapped_extents, we use it
* to count ourselves emitted extents and stop instead of relying on
* fiemap_fill_next_extent() because we buffer ready fiemap entries at
* the @entries array, and we want to stop as soon as we hit the max
* amount of extents to map, not just to save time but also to make the
* logic at extent_fiemap() simpler.
*/
unsigned int extents_mapped;
/* Fields for the cached extent (unsubmitted, not ready, extent). */
u64 offset;
u64 phys;
u64 len;
u32 flags;
bool cached;
};
static int flush_fiemap_cache(struct fiemap_extent_info *fieinfo,
struct fiemap_cache *cache)
{
for (int i = 0; i < cache->entries_pos; i++) {
struct btrfs_fiemap_entry *entry = &cache->entries[i];
int ret;
ret = fiemap_fill_next_extent(fieinfo, entry->offset,
entry->phys, entry->len,
entry->flags);
/*
* Ignore 1 (reached max entries) because we keep track of that
* ourselves in emit_fiemap_extent().
*/
if (ret < 0)
return ret;
}
cache->entries_pos = 0;
return 0;
}
/*
* Helper to submit fiemap extent.
Annotation
- Immediate include surface: `backref.h`, `btrfs_inode.h`, `fiemap.h`, `file.h`, `file-item.h`.
- Detected declarations: `struct btrfs_fiemap_entry`, `struct fiemap_cache`, `function flush_fiemap_cache`, `function fiemap_fill_next_extent`, `function compressed`, `function extent_fiemap`, `function fiemap_next_leaf_item`, `function fiemap_search_slot`, `function fiemap_process_hole`, `function fiemap_find_last_extent_offset`.
- Atlas domain: Core OS / VFS And Filesystem Core.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.