Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 75acb9cd authored by Nick Piggin's avatar Nick Piggin Committed by Linus Torvalds
Browse files

rd: support XIP



Support direct_access XIP method with brd.

Signed-off-by: default avatarNick Piggin <npiggin@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 9db5579b
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -357,6 +357,16 @@ config BLK_DEV_RAM_SIZE
	  The default value is 4096 kilobytes. Only change this if you know
	  what you are doing.

config BLK_DEV_XIP
	bool "Support XIP filesystems on RAM block device"
	depends on BLK_DEV_RAM
	default n
	help
	  Support XIP filesystems (such as ext2 with XIP support on) on
	  top of block ram device. This will slightly enlarge the kernel, and
	  will prevent RAM block device backing store memory from being
	  allocated from highmem (only a problem for highmem systems).

config CDROM_PKTCDVD
	tristate "Packet writing on CD/DVD media"
	depends on !UML
+37 −2
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@ static struct page *brd_insert_page(struct brd_device *brd, sector_t sector)
{
	pgoff_t idx;
	struct page *page;
	gfp_t gfp_flags;

	page = brd_lookup_page(brd, sector);
	if (page)
@@ -97,7 +98,16 @@ static struct page *brd_insert_page(struct brd_device *brd, sector_t sector)
	/*
	 * Must use NOIO because we don't want to recurse back into the
	 * block or filesystem layers from page reclaim.
	 *
	 * Cannot support XIP and highmem, because our ->direct_access
	 * routine for XIP must return memory that is always addressable.
	 * If XIP was reworked to use pfns and kmap throughout, this
	 * restriction might be able to be lifted.
	 */
	gfp_flags = GFP_NOIO | __GFP_ZERO;
#ifndef CONFIG_BLK_DEV_XIP
	gfp_flags |= __GFP_HIGHMEM;
#endif
	page = alloc_page(GFP_NOIO | __GFP_HIGHMEM | __GFP_ZERO);
	if (!page)
		return NULL;
@@ -307,6 +317,28 @@ static int brd_make_request(struct request_queue *q, struct bio *bio)
	return 0;
}

#ifdef CONFIG_BLK_DEV_XIP
static int brd_direct_access (struct block_device *bdev, sector_t sector,
			unsigned long *data)
{
	struct brd_device *brd = bdev->bd_disk->private_data;
	struct page *page;

	if (!brd)
		return -ENODEV;
	if (sector & (PAGE_SECTORS-1))
		return -EINVAL;
	if (sector + PAGE_SECTORS > get_capacity(bdev->bd_disk))
		return -ERANGE;
	page = brd_insert_page(brd, sector);
	if (!page)
		return -ENOMEM;
	*data = (unsigned long)page_address(page);

	return 0;
}
#endif

static int brd_ioctl(struct inode *inode, struct file *file,
			unsigned int cmd, unsigned long arg)
{
@@ -344,6 +376,9 @@ static int brd_ioctl(struct inode *inode, struct file *file,
static struct block_device_operations brd_fops = {
	.owner =		THIS_MODULE,
	.ioctl =		brd_ioctl,
#ifdef CONFIG_BLK_DEV_XIP
	.direct_access =	brd_direct_access,
#endif
};

/*