net/rds/page.c
Source file repositories/reference/linux-study-clean/net/rds/page.c
File Facts
- System
- Linux kernel
- Corpus path
net/rds/page.c- Extension
.c- Size
- 4859 bytes
- Lines
- 171
- Domain
- Networking Core
- Bucket
- Sockets, Protocols, Packet Path, And Network Policy
- Inferred role
- Networking Core: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.
- Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/highmem.hlinux/gfp.hlinux/cpu.hlinux/export.hrds.h
Detected Declarations
struct rds_page_remainderfunction alloc_pagefunction rds_page_exitfunction for_each_possible_cpuexport rds_page_remainder_alloc
Annotated Snippet
struct rds_page_remainder {
struct page *r_page;
unsigned long r_offset;
local_lock_t bh_lock;
};
static DEFINE_PER_CPU_SHARED_ALIGNED(struct rds_page_remainder, rds_page_remainders) = {
.bh_lock = INIT_LOCAL_LOCK(bh_lock),
};
/**
* rds_page_remainder_alloc - build up regions of a message.
*
* @scat: Scatter list for message
* @bytes: the number of bytes needed.
* @gfp: the waiting behaviour of the allocation
*
* @gfp is always ored with __GFP_HIGHMEM. Callers must be prepared to
* kmap the pages, etc.
*
* If @bytes is at least a full page then this just returns a page from
* alloc_page().
*
* If @bytes is a partial page then this stores the unused region of the
* page in a per-cpu structure. Future partial-page allocations may be
* satisfied from that cached region. This lets us waste less memory on
* small allocations with minimal complexity. It works because the transmit
* path passes read-only page regions down to devices. They hold a page
* reference until they are done with the region.
*/
int rds_page_remainder_alloc(struct scatterlist *scat, unsigned long bytes,
gfp_t gfp)
{
struct rds_page_remainder *rem;
struct page *page;
int ret;
gfp |= __GFP_HIGHMEM;
/* jump straight to allocation if we're trying for a huge page */
if (bytes >= PAGE_SIZE) {
page = alloc_page(gfp);
if (!page) {
ret = -ENOMEM;
} else {
sg_set_page(scat, page, PAGE_SIZE, 0);
ret = 0;
}
goto out;
}
local_bh_disable();
local_lock_nested_bh(&rds_page_remainders.bh_lock);
rem = this_cpu_ptr(&rds_page_remainders);
while (1) {
/* avoid a tiny region getting stuck by tossing it */
if (rem->r_page && bytes > (PAGE_SIZE - rem->r_offset)) {
rds_stats_inc(s_page_remainder_miss);
__free_page(rem->r_page);
rem->r_page = NULL;
}
/* hand out a fragment from the cached page */
if (rem->r_page && bytes <= (PAGE_SIZE - rem->r_offset)) {
sg_set_page(scat, rem->r_page, bytes, rem->r_offset);
get_page(sg_page(scat));
if (rem->r_offset != 0)
rds_stats_inc(s_page_remainder_hit);
rem->r_offset += ALIGN(bytes, 8);
if (rem->r_offset >= PAGE_SIZE) {
__free_page(rem->r_page);
rem->r_page = NULL;
}
ret = 0;
break;
}
/* alloc if there is nothing for us to use */
local_unlock_nested_bh(&rds_page_remainders.bh_lock);
local_bh_enable();
page = alloc_page(gfp);
local_bh_disable();
local_lock_nested_bh(&rds_page_remainders.bh_lock);
rem = this_cpu_ptr(&rds_page_remainders);
Annotation
- Immediate include surface: `linux/highmem.h`, `linux/gfp.h`, `linux/cpu.h`, `linux/export.h`, `rds.h`.
- Detected declarations: `struct rds_page_remainder`, `function alloc_page`, `function rds_page_exit`, `function for_each_possible_cpu`, `export rds_page_remainder_alloc`.
- Atlas domain: Networking Core / Sockets, Protocols, Packet Path, And Network Policy.
- Implementation status: integration 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.