/* * Each block ramdisk device has a xarray brd_pages of pages that stores * the pages containing the block device's contents.
*/ struct brd_device { int brd_number; struct gendisk *brd_disk; struct list_head brd_list;
/* * Backing store of pages. This is the contents of the block device.
*/ struct xarray brd_pages;
u64 brd_nr_pages;
};
/* * Look up and return a brd's page for a given sector.
*/ staticstruct page *brd_lookup_page(struct brd_device *brd, sector_t sector)
{ return xa_load(&brd->brd_pages, sector >> PAGE_SECTORS_SHIFT);
}
/* * Insert a new page for a given sector, if one does not already exist.
*/ staticstruct page *brd_insert_page(struct brd_device *brd, sector_t sector,
blk_opf_t opf)
__releases(rcu)
__acquires(rcu)
{
gfp_t gfp = (opf & REQ_NOWAIT) ? GFP_NOWAIT : GFP_NOIO; struct page *page, *ret;
xa_lock(&brd->brd_pages);
ret = __xa_cmpxchg(&brd->brd_pages, sector >> PAGE_SECTORS_SHIFT, NULL,
page, gfp);
rcu_read_lock(); if (ret) {
xa_unlock(&brd->brd_pages);
__free_page(page); if (xa_is_err(ret)) return ERR_PTR(xa_err(ret)); return ret;
}
brd->brd_nr_pages++;
xa_unlock(&brd->brd_pages); return page;
}
/* * Free all backing store pages and xarray. This must only be called when * there are no other users of the device.
*/ staticvoid brd_free_pages(struct brd_device *brd)
{ struct page *page;
pgoff_t idx;
/* * Process a single segment. The segment is capped to not cross page boundaries * in both the bio and the brd backing memory.
*/ staticbool brd_rw_bvec(struct brd_device *brd, struct bio *bio)
{ struct bio_vec bv = bio_iter_iovec(bio, bio->bi_iter);
sector_t sector = bio->bi_iter.bi_sector;
u32 offset = (sector & (PAGE_SECTORS - 1)) << SECTOR_SHIFT;
blk_opf_t opf = bio->bi_opf; struct page *page; void *kaddr;
/* * And now the modules code and kernel interface.
*/ staticint rd_nr = CONFIG_BLK_DEV_RAM_COUNT;
module_param(rd_nr, int, 0444);
MODULE_PARM_DESC(rd_nr, "Maximum number of brd devices");
unsignedlong rd_size = CONFIG_BLK_DEV_RAM_SIZE;
module_param(rd_size, ulong, 0444);
MODULE_PARM_DESC(rd_size, "Size of each RAM disk in kbytes.");
staticint max_part = 1;
module_param(max_part, int, 0444);
MODULE_PARM_DESC(max_part, "Num Minors to reserve between devices");
/* * The device scheme is derived from loop.c. Keep them in synch where possible * (should share code eventually).
*/ static LIST_HEAD(brd_devices); static DEFINE_MUTEX(brd_devices_mutex); staticstruct dentry *brd_debugfs_dir;
staticint brd_alloc(int i)
{ struct brd_device *brd; struct gendisk *disk; char buf[DISK_NAME_LEN]; int err = -ENOMEM; struct queue_limits lim = { /* * This is so fdisk will align partitions on 4k, because of * direct_access API needing 4k alignment, returning a PFN * (This is only a problem on very small devices <= 4M, * otherwise fdisk will align on 1M. Regardless this call * is harmless)
*/
.physical_block_size = PAGE_SIZE,
.max_hw_discard_sectors = UINT_MAX,
.max_discard_segments = 1,
.discard_granularity = PAGE_SIZE,
.features = BLK_FEAT_SYNCHRONOUS |
BLK_FEAT_NOWAIT,
};
brd = brd_find_or_alloc_device(i); if (IS_ERR(brd)) return PTR_ERR(brd);
xa_init(&brd->brd_pages);
snprintf(buf, DISK_NAME_LEN, "ram%d", i); if (!IS_ERR_OR_NULL(brd_debugfs_dir))
debugfs_create_u64(buf, 0444, brd_debugfs_dir,
&brd->brd_nr_pages);
staticinlinevoid brd_check_and_reset_par(void)
{ if (unlikely(!max_part))
max_part = 1;
/* * make sure 'max_part' can be divided exactly by (1U << MINORBITS), * otherwise, it is possiable to get same dev_t when adding partitions.
*/ if ((1U << MINORBITS) % max_part != 0)
max_part = 1UL << fls(max_part);
if (max_part > DISK_MAX_PARTS) {
pr_info("brd: max_part can't be larger than %d, reset max_part = %d.\n",
DISK_MAX_PARTS, DISK_MAX_PARTS);
max_part = DISK_MAX_PARTS;
}
}
staticint __init brd_init(void)
{ int err, i;
/* * brd module now has a feature to instantiate underlying device * structure on-demand, provided that there is an access dev node. * * (1) if rd_nr is specified, create that many upfront. else * it defaults to CONFIG_BLK_DEV_RAM_COUNT * (2) User can further extend brd devices by create dev node themselves * and have kernel automatically instantiate actual device * on-demand. Example: * mknod /path/devnod_name b 1 X # 1 is the rd major * fdisk -l /path/devnod_name * If (X / max_part) was not already created it will be created * dynamically.
*/
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.