fs/btrfs/extent_map.c
Source file repositories/reference/linux-study-clean/fs/btrfs/extent_map.c
File Facts
- System
- Linux kernel
- Corpus path
fs/btrfs/extent_map.c- Extension
.c- Size
- 40448 bytes
- Lines
- 1397
- 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.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/err.hlinux/slab.hlinux/spinlock.hmessages.hctree.hextent_map.hcompression.hbtrfs_inode.hdisk-io.h
Detected Declarations
struct btrfs_em_shrink_ctxfunction btrfs_extent_map_initfunction btrfs_extent_map_exitfunction btrfs_extent_map_tree_initfunction free_extent_mapfunction btrfs_free_extent_mapfunction range_endfunction remove_emfunction tree_insertfunction extent_map_block_lenfunction extent_map_block_endfunction can_merge_extent_mapfunction mergeable_mapsfunction merge_ondisk_extentsfunction dump_extent_mapfunction validate_extent_mapfunction try_merge_mapfunction fsyncfunction btrfs_clear_em_loggingfunction setup_extent_mappingfunction add_extent_mappingfunction btrfs_remove_extent_mappingfunction replace_extent_mappingfunction merge_extent_mappingfunction btrfs_add_extent_mappingfunction drop_all_extent_maps_fastfunction btrfs_drop_extent_map_rangefunction extentsfunction btrfs_split_extent_mapfunction btrfs_scan_inodefunction statfunction btrfs_scan_rootfunction btrfs_extent_map_shrinker_workerfunction btrfs_free_extent_mapsfunction btrfs_init_extent_map_shrinker_work
Annotated Snippet
struct btrfs_em_shrink_ctx {
long nr_to_scan;
long scanned;
};
static long btrfs_scan_inode(struct btrfs_inode *inode, struct btrfs_em_shrink_ctx *ctx)
{
struct btrfs_fs_info *fs_info = inode->root->fs_info;
const u64 cur_fs_gen = btrfs_get_fs_generation(fs_info);
struct extent_map_tree *tree = &inode->extent_tree;
long nr_dropped = 0;
struct rb_node *node;
lockdep_assert_held_write(&tree->lock);
/*
* Take the mmap lock so that we serialize with the inode logging phase
* of fsync because we may need to set the full sync flag on the inode,
* in case we have to remove extent maps in the tree's list of modified
* extents. If we set the full sync flag in the inode while an fsync is
* in progress, we may risk missing new extents because before the flag
* is set, fsync decides to only wait for writeback to complete and then
* during inode logging it sees the flag set and uses the subvolume tree
* to find new extents, which may not be there yet because ordered
* extents haven't completed yet.
*
* We also do a try lock because we don't want to block for too long and
* we are holding the extent map tree's lock in write mode.
*/
if (!down_read_trylock(&inode->i_mmap_lock))
return 0;
node = rb_first(&tree->root);
while (node) {
struct rb_node *next = rb_next(node);
struct extent_map *em;
em = rb_entry(node, struct extent_map, rb_node);
ctx->scanned++;
if (em->flags & EXTENT_FLAG_PINNED)
goto next;
/*
* If the inode is in the list of modified extents (new) and its
* generation is the same (or is greater than) the current fs
* generation, it means it was not yet persisted so we have to
* set the full sync flag so that the next fsync will not miss
* it.
*/
if (!list_empty(&em->list) && em->generation >= cur_fs_gen)
btrfs_set_inode_full_sync(inode);
btrfs_remove_extent_mapping(inode, em);
trace_btrfs_extent_map_shrinker_remove_em(inode, em);
/* Drop the reference for the tree. */
btrfs_free_extent_map(em);
nr_dropped++;
next:
if (ctx->scanned >= ctx->nr_to_scan)
break;
/*
* Stop if we need to reschedule or there's contention on the
* lock. This is to avoid slowing other tasks trying to take the
* lock.
*/
if (need_resched() || rwlock_needbreak(&tree->lock) ||
btrfs_fs_closing(fs_info))
break;
node = next;
}
up_read(&inode->i_mmap_lock);
return nr_dropped;
}
static struct btrfs_inode *find_first_inode_to_shrink(struct btrfs_root *root,
u64 min_ino)
{
struct btrfs_inode *inode;
unsigned long from = min_ino;
xa_lock(&root->inodes);
while (true) {
struct extent_map_tree *tree;
inode = xa_find(&root->inodes, &from, ULONG_MAX, XA_PRESENT);
if (!inode)
break;
Annotation
- Immediate include surface: `linux/err.h`, `linux/slab.h`, `linux/spinlock.h`, `messages.h`, `ctree.h`, `extent_map.h`, `compression.h`, `btrfs_inode.h`.
- Detected declarations: `struct btrfs_em_shrink_ctx`, `function btrfs_extent_map_init`, `function btrfs_extent_map_exit`, `function btrfs_extent_map_tree_init`, `function free_extent_map`, `function btrfs_free_extent_map`, `function range_end`, `function remove_em`, `function tree_insert`, `function extent_map_block_len`.
- Atlas domain: Core OS / VFS And Filesystem Core.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.