drivers/md/bcache/alloc.c
Source file repositories/reference/linux-study-clean/drivers/md/bcache/alloc.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/md/bcache/alloc.c- Extension
.c- Size
- 18893 bytes
- Lines
- 721
- Domain
- Driver Families
- Bucket
- drivers/md
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- 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
bcache.hbtree.hlinux/blkdev.hlinux/kthread.hlinux/random.htrace/events/bcache.h
Detected Declarations
struct open_bucketfunction prio_writefunction bch_rescale_prioritiesfunction can_inc_bucket_genfunction bch_can_invalidate_bucketfunction __bch_invalidate_one_bucketfunction bch_invalidate_one_bucketfunction invalidate_buckets_lrufunction for_each_bucketfunction invalidate_buckets_fifofunction invalidate_buckets_randomfunction invalidate_bucketsfunction bch_allocator_pushfunction bch_allocator_threadfunction bch_bucket_allocfunction __bch_bucket_freefunction bch_bucket_freefunction __bch_bucket_alloc_setfunction bch_bucket_alloc_setfunction bch_alloc_sectorsfunction bch_open_buckets_freefunction bch_open_buckets_allocfunction bch_cache_allocator_start
Annotated Snippet
struct open_bucket {
struct list_head list;
unsigned int last_write_point;
unsigned int sectors_free;
BKEY_PADDED(key);
};
/*
* We keep multiple buckets open for writes, and try to segregate different
* write streams for better cache utilization: first we try to segregate flash
* only volume write streams from cached devices, secondly we look for a bucket
* where the last write to it was sequential with the current write, and
* failing that we look for a bucket that was last used by the same task.
*
* The ideas is if you've got multiple tasks pulling data into the cache at the
* same time, you'll get better cache utilization if you try to segregate their
* data and preserve locality.
*
* For example, dirty sectors of flash only volume is not reclaimable, if their
* dirty sectors mixed with dirty sectors of cached device, such buckets will
* be marked as dirty and won't be reclaimed, though the dirty data of cached
* device have been written back to backend device.
*
* And say you've starting Firefox at the same time you're copying a
* bunch of files. Firefox will likely end up being fairly hot and stay in the
* cache awhile, but the data you copied might not be; if you wrote all that
* data to the same buckets it'd get invalidated at the same time.
*
* Both of those tasks will be doing fairly random IO so we can't rely on
* detecting sequential IO to segregate their data, but going off of the task
* should be a sane heuristic.
*/
static struct open_bucket *pick_data_bucket(struct cache_set *c,
const struct bkey *search,
unsigned int write_point,
struct bkey *alloc)
{
struct open_bucket *ret, *ret_task = NULL;
list_for_each_entry_reverse(ret, &c->data_buckets, list)
if (UUID_FLASH_ONLY(&c->uuids[KEY_INODE(&ret->key)]) !=
UUID_FLASH_ONLY(&c->uuids[KEY_INODE(search)]))
continue;
else if (!bkey_cmp(&ret->key, search))
goto found;
else if (ret->last_write_point == write_point)
ret_task = ret;
ret = ret_task ?: list_first_entry(&c->data_buckets,
struct open_bucket, list);
found:
if (!ret->sectors_free && KEY_PTRS(alloc)) {
ret->sectors_free = c->cache->sb.bucket_size;
bkey_copy(&ret->key, alloc);
bkey_init(alloc);
}
if (!ret->sectors_free)
ret = NULL;
return ret;
}
/*
* Allocates some space in the cache to write to, and k to point to the newly
* allocated space, and updates KEY_SIZE(k) and KEY_OFFSET(k) (to point to the
* end of the newly allocated space).
*
* May allocate fewer sectors than @sectors, KEY_SIZE(k) indicates how many
* sectors were actually allocated.
*
* If s->writeback is true, will not fail.
*/
bool bch_alloc_sectors(struct cache_set *c,
struct bkey *k,
unsigned int sectors,
unsigned int write_point,
unsigned int write_prio,
bool wait)
{
struct open_bucket *b;
BKEY_PADDED(key) alloc;
unsigned int i;
/*
* We might have to allocate a new bucket, which we can't do with a
* spinlock held. So if we have to allocate, we drop the lock, allocate
* and then retry. KEY_PTRS() indicates whether alloc points to
* allocated bucket(s).
*/
Annotation
- Immediate include surface: `bcache.h`, `btree.h`, `linux/blkdev.h`, `linux/kthread.h`, `linux/random.h`, `trace/events/bcache.h`.
- Detected declarations: `struct open_bucket`, `function prio_write`, `function bch_rescale_priorities`, `function can_inc_bucket_gen`, `function bch_can_invalidate_bucket`, `function __bch_invalidate_one_bucket`, `function bch_invalidate_one_bucket`, `function invalidate_buckets_lru`, `function for_each_bucket`, `function invalidate_buckets_fifo`.
- Atlas domain: Driver Families / drivers/md.
- 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.