fs/jffs2/nodemgmt.c
Source file repositories/reference/linux-study-clean/fs/jffs2/nodemgmt.c
File Facts
- System
- Linux kernel
- Corpus path
fs/jffs2/nodemgmt.c- Extension
.c- Size
- 29318 bytes
- Lines
- 891
- 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/kernel.hlinux/mtd/mtd.hlinux/compiler.hlinux/sched/signal.hlinux/string_choices.hnodelist.hdebug.h
Detected Declarations
function jffs2_rp_can_writefunction jffs2_reserve_spacefunction jffs2_reserve_space_gcfunction jffs2_close_nextblockfunction jffs2_find_nextblockfunction jffs2_do_reserve_spacefunction jffs2_complete_reservationfunction on_listfunction list_for_eachfunction jffs2_mark_node_obsoletefunction D1function jffs2_garbage_collect_deletion_direntfunction jffs2_thread_should_wakefunction list_for_each_entry
Annotated Snippet
while(c->nr_free_blocks + c->nr_erasing_blocks < blocksneeded) {
uint32_t dirty, avail;
/* calculate real dirty size
* dirty_size contains blocks on erase_pending_list
* those blocks are counted in c->nr_erasing_blocks.
* If one block is actually erased, it is not longer counted as dirty_space
* but it is counted in c->nr_erasing_blocks, so we add it and subtract it
* with c->nr_erasing_blocks * c->sector_size again.
* Blocks on erasable_list are counted as dirty_size, but not in c->nr_erasing_blocks
* This helps us to force gc and pick eventually a clean block to spread the load.
* We add unchecked_size here, as we hopefully will find some space to use.
* This will affect the sum only once, as gc first finishes checking
* of nodes.
*/
dirty = c->dirty_size + c->erasing_size - c->nr_erasing_blocks * c->sector_size + c->unchecked_size;
if (dirty < c->nospc_dirty_size) {
if (prio == ALLOC_DELETION && c->nr_free_blocks + c->nr_erasing_blocks >= c->resv_blocks_deletion) {
jffs2_dbg(1, "%s(): Low on dirty space to GC, but it's a deletion. Allowing...\n",
__func__);
break;
}
jffs2_dbg(1, "dirty size 0x%08x + unchecked_size 0x%08x < nospc_dirty_size 0x%08x, returning -ENOSPC\n",
dirty, c->unchecked_size,
c->sector_size);
spin_unlock(&c->erase_completion_lock);
mutex_unlock(&c->alloc_sem);
return -ENOSPC;
}
/* Calc possibly available space. Possibly available means that we
* don't know, if unchecked size contains obsoleted nodes, which could give us some
* more usable space. This will affect the sum only once, as gc first finishes checking
* of nodes.
+ Return -ENOSPC, if the maximum possibly available space is less or equal than
* blocksneeded * sector_size.
* This blocks endless gc looping on a filesystem, which is nearly full, even if
* the check above passes.
*/
avail = c->free_size + c->dirty_size + c->erasing_size + c->unchecked_size;
if ( (avail / c->sector_size) <= blocksneeded) {
if (prio == ALLOC_DELETION && c->nr_free_blocks + c->nr_erasing_blocks >= c->resv_blocks_deletion) {
jffs2_dbg(1, "%s(): Low on possibly available space, but it's a deletion. Allowing...\n",
__func__);
break;
}
jffs2_dbg(1, "max. available size 0x%08x < blocksneeded * sector_size 0x%08x, returning -ENOSPC\n",
avail, blocksneeded * c->sector_size);
spin_unlock(&c->erase_completion_lock);
mutex_unlock(&c->alloc_sem);
return -ENOSPC;
}
mutex_unlock(&c->alloc_sem);
jffs2_dbg(1, "Triggering GC pass. nr_free_blocks %d, nr_erasing_blocks %d, free_size 0x%08x, dirty_size 0x%08x, wasted_size 0x%08x, used_size 0x%08x, erasing_size 0x%08x, bad_size 0x%08x (total 0x%08x of 0x%08x)\n",
c->nr_free_blocks, c->nr_erasing_blocks,
c->free_size, c->dirty_size, c->wasted_size,
c->used_size, c->erasing_size, c->bad_size,
c->free_size + c->dirty_size +
c->wasted_size + c->used_size +
c->erasing_size + c->bad_size,
c->flash_size);
spin_unlock(&c->erase_completion_lock);
ret = jffs2_garbage_collect_pass(c);
if (ret == -EAGAIN) {
spin_lock(&c->erase_completion_lock);
if (c->nr_erasing_blocks &&
list_empty(&c->erase_pending_list) &&
list_empty(&c->erase_complete_list)) {
DECLARE_WAITQUEUE(wait, current);
set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&c->erase_wait, &wait);
jffs2_dbg(1, "%s waiting for erase to complete\n",
__func__);
spin_unlock(&c->erase_completion_lock);
schedule();
remove_wait_queue(&c->erase_wait, &wait);
} else
spin_unlock(&c->erase_completion_lock);
} else if (ret)
return ret;
cond_resched();
Annotation
- Immediate include surface: `linux/kernel.h`, `linux/mtd/mtd.h`, `linux/compiler.h`, `linux/sched/signal.h`, `linux/string_choices.h`, `nodelist.h`, `debug.h`.
- Detected declarations: `function jffs2_rp_can_write`, `function jffs2_reserve_space`, `function jffs2_reserve_space_gc`, `function jffs2_close_nextblock`, `function jffs2_find_nextblock`, `function jffs2_do_reserve_space`, `function jffs2_complete_reservation`, `function on_list`, `function list_for_each`, `function jffs2_mark_node_obsolete`.
- 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.