drivers/nvdimm/pmem.c
Source file repositories/reference/linux-study-clean/drivers/nvdimm/pmem.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/nvdimm/pmem.c- Extension
.c- Size
- 19857 bytes
- Lines
- 767
- Domain
- Driver Families
- Bucket
- drivers/nvdimm
- 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.
- 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
linux/blkdev.hlinux/pagemap.hlinux/hdreg.hlinux/init.hlinux/platform_device.hlinux/set_memory.hlinux/module.hlinux/moduleparam.hlinux/badblocks.hlinux/memremap.hlinux/kstrtox.hlinux/vmalloc.hlinux/blk-mq.hlinux/slab.hlinux/uio.hlinux/dax.hlinux/nd.hlinux/mm.hasm/cacheflush.hpmem.hbtt.hpfn.hnd.h
Detected Declarations
function Copyrightfunction pmem_to_physfunction to_sectfunction to_offsetfunction pmem_mkpage_presentfunction pmem_clear_bbfunction __pmem_clear_poisonfunction pmem_clear_poisonfunction write_pmemfunction read_pmemfunction pmem_do_readfunction pmem_do_writefunction pmem_submit_biofunction __pmem_direct_accessfunction pmem_dax_zero_page_rangefunction pmem_dax_direct_accessfunction dax_iomap_rwfunction write_cache_showfunction write_cache_storefunction dax_visiblefunction pmem_release_diskfunction pmem_pagemap_memory_failurefunction pmem_attach_diskfunction nd_pmem_probefunction nd_pmem_removefunction nd_pmem_shutdownfunction pmem_revalidate_poisonfunction pmem_revalidate_regionfunction nd_pmem_notify
Annotated Snippet
if (rc) {
bio->bi_status = rc;
break;
}
}
if (do_acct)
bio_end_io_acct(bio, start);
if (bio->bi_opf & REQ_FUA)
ret = nvdimm_flush(nd_region, bio);
if (ret)
bio->bi_status = errno_to_blk_status(ret);
bio_endio(bio);
}
/* see "strong" declaration in tools/testing/nvdimm/pmem-dax.c */
__weak long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff,
long nr_pages, enum dax_access_mode mode, void **kaddr,
unsigned long *pfn)
{
resource_size_t offset = PFN_PHYS(pgoff) + pmem->data_offset;
sector_t sector = PFN_PHYS(pgoff) >> SECTOR_SHIFT;
unsigned int num = PFN_PHYS(nr_pages) >> SECTOR_SHIFT;
struct badblocks *bb = &pmem->bb;
sector_t first_bad;
sector_t num_bad;
if (kaddr)
*kaddr = pmem->virt_addr + offset;
if (pfn)
*pfn = PHYS_PFN(pmem->phys_addr + offset);
if (bb->count &&
badblocks_check(bb, sector, num, &first_bad, &num_bad)) {
long actual_nr;
if (mode != DAX_RECOVERY_WRITE)
return -EHWPOISON;
/*
* Set the recovery stride is set to kernel page size because
* the underlying driver and firmware clear poison functions
* don't appear to handle large chunk(such as 2MiB) reliably.
*/
actual_nr = PHYS_PFN(
PAGE_ALIGN((first_bad - sector) << SECTOR_SHIFT));
dev_dbg(pmem->bb.dev, "start sector(%llu), nr_pages(%ld), first_bad(%llu), actual_nr(%ld)\n",
sector, nr_pages, first_bad, actual_nr);
if (actual_nr)
return actual_nr;
return 1;
}
/*
* If badblocks are present but not in the range, limit known good range
* to the requested range.
*/
if (bb->count)
return nr_pages;
return PHYS_PFN(pmem->size - pmem->pfn_pad - offset);
}
static const struct block_device_operations pmem_fops = {
.owner = THIS_MODULE,
.submit_bio = pmem_submit_bio,
};
static int pmem_dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff,
size_t nr_pages)
{
struct pmem_device *pmem = dax_get_private(dax_dev);
return blk_status_to_errno(pmem_do_write(pmem, ZERO_PAGE(0), 0,
PFN_PHYS(pgoff) >> SECTOR_SHIFT,
PAGE_SIZE));
}
static long pmem_dax_direct_access(struct dax_device *dax_dev,
pgoff_t pgoff, long nr_pages, enum dax_access_mode mode,
void **kaddr, unsigned long *pfn)
{
struct pmem_device *pmem = dax_get_private(dax_dev);
return __pmem_direct_access(pmem, pgoff, nr_pages, mode, kaddr, pfn);
}
/*
* The recovery write thread started out as a normal pwrite thread and
Annotation
- Immediate include surface: `linux/blkdev.h`, `linux/pagemap.h`, `linux/hdreg.h`, `linux/init.h`, `linux/platform_device.h`, `linux/set_memory.h`, `linux/module.h`, `linux/moduleparam.h`.
- Detected declarations: `function Copyright`, `function pmem_to_phys`, `function to_sect`, `function to_offset`, `function pmem_mkpage_present`, `function pmem_clear_bb`, `function __pmem_clear_poison`, `function pmem_clear_poison`, `function write_pmem`, `function read_pmem`.
- Atlas domain: Driver Families / drivers/nvdimm.
- 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.