^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Ram backed block device driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2007 Nick Piggin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2007 Novell Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Parts derived from drivers/block/rd.c, and drivers/block/loop.c, copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * of their respective owners.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/initrd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/major.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/blkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/bio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/highmem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/radix-tree.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/backing-dev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define PAGE_SECTORS_SHIFT (PAGE_SHIFT - SECTOR_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define PAGE_SECTORS (1 << PAGE_SECTORS_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * Each block ramdisk device has a radix_tree brd_pages of pages that stores
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * the pages containing the block device's contents. A brd page's ->index is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * its offset in PAGE_SIZE units. This is similar to, but in no way connected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * with, the kernel's pagecache or buffer cache (which sit above our block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * device).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct brd_device {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) int brd_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct request_queue *brd_queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct gendisk *brd_disk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct list_head brd_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * Backing store of pages and lock to protect it. This is the contents
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * of the block device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) spinlock_t brd_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct radix_tree_root brd_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * Look up and return a brd's page for a given sector.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static struct page *brd_lookup_page(struct brd_device *brd, sector_t sector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) pgoff_t idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * The page lifetime is protected by the fact that we have opened the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * device node -- brd pages will never be deleted under us, so we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * don't need any further locking or refcounting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * This is strictly true for the radix-tree nodes as well (ie. we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * don't actually need the rcu_read_lock()), however that is not a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * documented feature of the radix-tree API so it is better to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * safe here (we don't have total exclusion from radix tree updates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * here, only deletes).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) idx = sector >> PAGE_SECTORS_SHIFT; /* sector to page index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) page = radix_tree_lookup(&brd->brd_pages, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) BUG_ON(page && page->index != idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * Look up and return a brd's page for a given sector.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * If one does not exist, allocate an empty page, and insert that. Then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * return it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static struct page *brd_insert_page(struct brd_device *brd, sector_t sector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) pgoff_t idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) gfp_t gfp_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) page = brd_lookup_page(brd, sector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * Must use NOIO because we don't want to recurse back into the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * block or filesystem layers from page reclaim.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) gfp_flags = GFP_NOIO | __GFP_ZERO | __GFP_HIGHMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) page = alloc_page(gfp_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (!page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (radix_tree_preload(GFP_NOIO)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) __free_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) spin_lock(&brd->brd_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) idx = sector >> PAGE_SECTORS_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) page->index = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (radix_tree_insert(&brd->brd_pages, idx, page)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) __free_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) page = radix_tree_lookup(&brd->brd_pages, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) BUG_ON(!page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) BUG_ON(page->index != idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) spin_unlock(&brd->brd_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) radix_tree_preload_end();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * Free all backing store pages and radix tree. This must only be called when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * there are no other users of the device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define FREE_BATCH 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static void brd_free_pages(struct brd_device *brd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) unsigned long pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct page *pages[FREE_BATCH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) int nr_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) nr_pages = radix_tree_gang_lookup(&brd->brd_pages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) (void **)pages, pos, FREE_BATCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) for (i = 0; i < nr_pages; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) void *ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) BUG_ON(pages[i]->index < pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) pos = pages[i]->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) ret = radix_tree_delete(&brd->brd_pages, pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) BUG_ON(!ret || ret != pages[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) __free_page(pages[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * It takes 3.4 seconds to remove 80GiB ramdisk.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * So, we need cond_resched to avoid stalling the CPU.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * This assumes radix_tree_gang_lookup always returns as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * many pages as possible. If the radix-tree code changes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * so will this have to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) } while (nr_pages == FREE_BATCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * copy_to_brd_setup must be called before copy_to_brd. It may sleep.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static int copy_to_brd_setup(struct brd_device *brd, sector_t sector, size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) unsigned int offset = (sector & (PAGE_SECTORS-1)) << SECTOR_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) size_t copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) copy = min_t(size_t, n, PAGE_SIZE - offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (!brd_insert_page(brd, sector))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (copy < n) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) sector += copy >> SECTOR_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (!brd_insert_page(brd, sector))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * Copy n bytes from src to the brd starting at sector. Does not sleep.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static void copy_to_brd(struct brd_device *brd, const void *src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) sector_t sector, size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) void *dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) unsigned int offset = (sector & (PAGE_SECTORS-1)) << SECTOR_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) size_t copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) copy = min_t(size_t, n, PAGE_SIZE - offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) page = brd_lookup_page(brd, sector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) BUG_ON(!page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) dst = kmap_atomic(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) memcpy(dst + offset, src, copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) kunmap_atomic(dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (copy < n) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) src += copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) sector += copy >> SECTOR_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) copy = n - copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) page = brd_lookup_page(brd, sector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) BUG_ON(!page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) dst = kmap_atomic(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) memcpy(dst, src, copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) kunmap_atomic(dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * Copy n bytes to dst from the brd starting at sector. Does not sleep.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) static void copy_from_brd(void *dst, struct brd_device *brd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) sector_t sector, size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) void *src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) unsigned int offset = (sector & (PAGE_SECTORS-1)) << SECTOR_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) size_t copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) copy = min_t(size_t, n, PAGE_SIZE - offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) page = brd_lookup_page(brd, sector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (page) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) src = kmap_atomic(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) memcpy(dst, src + offset, copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) kunmap_atomic(src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) memset(dst, 0, copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (copy < n) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) dst += copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) sector += copy >> SECTOR_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) copy = n - copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) page = brd_lookup_page(brd, sector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (page) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) src = kmap_atomic(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) memcpy(dst, src, copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) kunmap_atomic(src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) memset(dst, 0, copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * Process a single bvec of a bio.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) static int brd_do_bvec(struct brd_device *brd, struct page *page,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) unsigned int len, unsigned int off, unsigned int op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) sector_t sector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) void *mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (op_is_write(op)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) err = copy_to_brd_setup(brd, sector, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) mem = kmap_atomic(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (!op_is_write(op)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) copy_from_brd(mem + off, brd, sector, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) flush_dcache_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) flush_dcache_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) copy_to_brd(brd, mem + off, sector, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) kunmap_atomic(mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) static blk_qc_t brd_submit_bio(struct bio *bio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) struct brd_device *brd = bio->bi_disk->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) struct bio_vec bvec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) sector_t sector;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct bvec_iter iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) sector = bio->bi_iter.bi_sector;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (bio_end_sector(bio) > get_capacity(bio->bi_disk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) goto io_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) bio_for_each_segment(bvec, bio, iter) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) unsigned int len = bvec.bv_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) /* Don't support un-aligned buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) WARN_ON_ONCE((bvec.bv_offset & (SECTOR_SIZE - 1)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) (len & (SECTOR_SIZE - 1)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) err = brd_do_bvec(brd, bvec.bv_page, len, bvec.bv_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) bio_op(bio), sector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) goto io_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) sector += len >> SECTOR_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) bio_endio(bio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return BLK_QC_T_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) io_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) bio_io_error(bio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return BLK_QC_T_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) static int brd_rw_page(struct block_device *bdev, sector_t sector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct page *page, unsigned int op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) struct brd_device *brd = bdev->bd_disk->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (PageTransHuge(page))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) err = brd_do_bvec(brd, page, PAGE_SIZE, 0, op, sector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) page_endio(page, op_is_write(op), err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) static const struct block_device_operations brd_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) .submit_bio = brd_submit_bio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) .rw_page = brd_rw_page,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) * And now the modules code and kernel interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static int rd_nr = CONFIG_BLK_DEV_RAM_COUNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) module_param(rd_nr, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) MODULE_PARM_DESC(rd_nr, "Maximum number of brd devices");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) unsigned long rd_size = CONFIG_BLK_DEV_RAM_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) module_param(rd_size, ulong, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) MODULE_PARM_DESC(rd_size, "Size of each RAM disk in kbytes.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) static int max_part = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) module_param(max_part, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) MODULE_PARM_DESC(max_part, "Num Minors to reserve between devices");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) MODULE_ALIAS_BLOCKDEV_MAJOR(RAMDISK_MAJOR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) MODULE_ALIAS("rd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) #ifndef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) /* Legacy boot options - nonmodular */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) static int __init ramdisk_size(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) rd_size = simple_strtol(str, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) __setup("ramdisk_size=", ramdisk_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * The device scheme is derived from loop.c. Keep them in synch where possible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * (should share code eventually).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static LIST_HEAD(brd_devices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) static DEFINE_MUTEX(brd_devices_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) static struct brd_device *brd_alloc(int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) struct brd_device *brd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) struct gendisk *disk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) brd = kzalloc(sizeof(*brd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (!brd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) brd->brd_number = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) spin_lock_init(&brd->brd_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) INIT_RADIX_TREE(&brd->brd_pages, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) brd->brd_queue = blk_alloc_queue(NUMA_NO_NODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (!brd->brd_queue)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) goto out_free_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) /* This is so fdisk will align partitions on 4k, because of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) * direct_access API needing 4k alignment, returning a PFN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) * (This is only a problem on very small devices <= 4M,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) * otherwise fdisk will align on 1M. Regardless this call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * is harmless)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) blk_queue_physical_block_size(brd->brd_queue, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) disk = brd->brd_disk = alloc_disk(max_part);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (!disk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) goto out_free_queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) disk->major = RAMDISK_MAJOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) disk->first_minor = i * max_part;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) disk->fops = &brd_fops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) disk->private_data = brd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) disk->flags = GENHD_FL_EXT_DEVT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) sprintf(disk->disk_name, "ram%d", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) set_capacity(disk, rd_size * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) /* Tell the block layer that this is not a rotational device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) blk_queue_flag_set(QUEUE_FLAG_NONROT, brd->brd_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, brd->brd_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) return brd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) out_free_queue:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) blk_cleanup_queue(brd->brd_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) out_free_dev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) kfree(brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) static void brd_free(struct brd_device *brd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) put_disk(brd->brd_disk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) blk_cleanup_queue(brd->brd_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) brd_free_pages(brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) kfree(brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) static struct brd_device *brd_init_one(int i, bool *new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) struct brd_device *brd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) *new = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) list_for_each_entry(brd, &brd_devices, brd_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (brd->brd_number == i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) brd = brd_alloc(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (brd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) brd->brd_disk->queue = brd->brd_queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) add_disk(brd->brd_disk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) list_add_tail(&brd->brd_list, &brd_devices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) *new = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) return brd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) static void brd_del_one(struct brd_device *brd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) list_del(&brd->brd_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) del_gendisk(brd->brd_disk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) brd_free(brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) static struct kobject *brd_probe(dev_t dev, int *part, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) struct brd_device *brd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) struct kobject *kobj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) bool new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) mutex_lock(&brd_devices_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) brd = brd_init_one(MINOR(dev) / max_part, &new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) kobj = brd ? get_disk_and_module(brd->brd_disk) : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) mutex_unlock(&brd_devices_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) *part = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) return kobj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) static inline void brd_check_and_reset_par(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (unlikely(!max_part))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) max_part = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) * make sure 'max_part' can be divided exactly by (1U << MINORBITS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) * otherwise, it is possiable to get same dev_t when adding partitions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if ((1U << MINORBITS) % max_part != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) max_part = 1UL << fls(max_part);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (max_part > DISK_MAX_PARTS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) pr_info("brd: max_part can't be larger than %d, reset max_part = %d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) DISK_MAX_PARTS, DISK_MAX_PARTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) max_part = DISK_MAX_PARTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) static int __init brd_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) struct brd_device *brd, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) * brd module now has a feature to instantiate underlying device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) * structure on-demand, provided that there is an access dev node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) * (1) if rd_nr is specified, create that many upfront. else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) * it defaults to CONFIG_BLK_DEV_RAM_COUNT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) * (2) User can further extend brd devices by create dev node themselves
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) * and have kernel automatically instantiate actual device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) * on-demand. Example:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * mknod /path/devnod_name b 1 X # 1 is the rd major
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) * fdisk -l /path/devnod_name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) * If (X / max_part) was not already created it will be created
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) * dynamically.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (register_blkdev(RAMDISK_MAJOR, "ramdisk"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) brd_check_and_reset_par();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) for (i = 0; i < rd_nr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) brd = brd_alloc(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (!brd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) list_add_tail(&brd->brd_list, &brd_devices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) /* point of no return */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) list_for_each_entry(brd, &brd_devices, brd_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) * associate with queue just before adding disk for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) * avoiding to mess up failure path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) brd->brd_disk->queue = brd->brd_queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) add_disk(brd->brd_disk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) blk_register_region(MKDEV(RAMDISK_MAJOR, 0), 1UL << MINORBITS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) THIS_MODULE, brd_probe, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) pr_info("brd: module loaded\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) list_for_each_entry_safe(brd, next, &brd_devices, brd_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) list_del(&brd->brd_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) brd_free(brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) unregister_blkdev(RAMDISK_MAJOR, "ramdisk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) pr_info("brd: module NOT loaded !!!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) static void __exit brd_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) struct brd_device *brd, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) list_for_each_entry_safe(brd, next, &brd_devices, brd_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) brd_del_one(brd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) blk_unregister_region(MKDEV(RAMDISK_MAJOR, 0), 1UL << MINORBITS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) unregister_blkdev(RAMDISK_MAJOR, "ramdisk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) pr_info("brd: module unloaded\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) module_init(brd_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) module_exit(brd_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)