From 1647b9b959c7b1b3c20e8efa2c40529e7dce756a Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 25 Jan 2017 16:54:45 -0800 Subject: brd: add dax_operations support Setup a dax_inode to have the same lifetime as the brd block device and add a ->direct_access() method that is equivalent to brd_direct_access(). Once fs/dax.c has been converted to use dax_operations the old brd_direct_access() will be removed. Signed-off-by: Dan Williams --- drivers/block/Kconfig | 1 + drivers/block/brd.c | 65 ++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 55 insertions(+), 11 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index f744de7a0f9b..e66956fc2c88 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -339,6 +339,7 @@ config BLK_DEV_SX8 config BLK_DEV_RAM tristate "RAM block device support" + select DAX if BLK_DEV_RAM_DAX ---help--- Saying Y here will allow you to use a portion of your RAM memory as a block device, so that you can make file systems on it, read and diff --git a/drivers/block/brd.c b/drivers/block/brd.c index 3adc32a3153b..60f3193c9ce2 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -21,6 +21,7 @@ #include #ifdef CONFIG_BLK_DEV_RAM_DAX #include +#include #endif #include @@ -41,6 +42,9 @@ struct brd_device { struct request_queue *brd_queue; struct gendisk *brd_disk; +#ifdef CONFIG_BLK_DEV_RAM_DAX + struct dax_device *dax_dev; +#endif struct list_head brd_list; /* @@ -375,30 +379,53 @@ static int brd_rw_page(struct block_device *bdev, sector_t sector, } #ifdef CONFIG_BLK_DEV_RAM_DAX -static long brd_direct_access(struct block_device *bdev, sector_t sector, - void **kaddr, pfn_t *pfn, long size) +static long __brd_direct_access(struct brd_device *brd, pgoff_t pgoff, + long nr_pages, void **kaddr, pfn_t *pfn) { - struct brd_device *brd = bdev->bd_disk->private_data; struct page *page; if (!brd) return -ENODEV; - page = brd_insert_page(brd, sector); + page = brd_insert_page(brd, PFN_PHYS(pgoff) / 512); if (!page) return -ENOSPC; *kaddr = page_address(page); *pfn = page_to_pfn_t(page); - return PAGE_SIZE; + return 1; +} + +static long brd_blk_direct_access(struct block_device *bdev, sector_t sector, + void **kaddr, pfn_t *pfn, long size) +{ + struct brd_device *brd = bdev->bd_disk->private_data; + long nr_pages = __brd_direct_access(brd, PHYS_PFN(sector * 512), + PHYS_PFN(size), kaddr, pfn); + + if (nr_pages < 0) + return nr_pages; + return nr_pages * PAGE_SIZE; +} + +static long brd_dax_direct_access(struct dax_device *dax_dev, + pgoff_t pgoff, long nr_pages, void **kaddr, pfn_t *pfn) +{ + struct brd_device *brd = dax_get_private(dax_dev); + + return __brd_direct_access(brd, pgoff, nr_pages, kaddr, pfn); } + +static const struct dax_operations brd_dax_ops = { + .direct_access = brd_dax_direct_access, +}; #else -#define brd_direct_access NULL +#define brd_blk_direct_access NULL #endif static const struct block_device_operations brd_fops = { .owner = THIS_MODULE, .rw_page = brd_rw_page, - .direct_access = brd_direct_access, + .direct_access = brd_blk_direct_access, }; /* @@ -441,7 +468,9 @@ static struct brd_device *brd_alloc(int i) { struct brd_device *brd; struct gendisk *disk; - +#ifdef CONFIG_BLK_DEV_RAM_DAX + struct dax_device *dax_dev; +#endif brd = kzalloc(sizeof(*brd), GFP_KERNEL); if (!brd) goto out; @@ -469,9 +498,6 @@ static struct brd_device *brd_alloc(int i) blk_queue_max_discard_sectors(brd->brd_queue, UINT_MAX); brd->brd_queue->limits.discard_zeroes_data = 1; queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, brd->brd_queue); -#ifdef CONFIG_BLK_DEV_RAM_DAX - queue_flag_set_unlocked(QUEUE_FLAG_DAX, brd->brd_queue); -#endif disk = brd->brd_disk = alloc_disk(max_part); if (!disk) goto out_free_queue; @@ -484,8 +510,21 @@ static struct brd_device *brd_alloc(int i) sprintf(disk->disk_name, "ram%d", i); set_capacity(disk, rd_size * 2); +#ifdef CONFIG_BLK_DEV_RAM_DAX + queue_flag_set_unlocked(QUEUE_FLAG_DAX, brd->brd_queue); + dax_dev = alloc_dax(brd, disk->disk_name, &brd_dax_ops); + if (!dax_dev) + goto out_free_inode; +#endif + + return brd; +#ifdef CONFIG_BLK_DEV_RAM_DAX +out_free_inode: + kill_dax(dax_dev); + put_dax(dax_dev); +#endif out_free_queue: blk_cleanup_queue(brd->brd_queue); out_free_dev: @@ -525,6 +564,10 @@ out: static void brd_del_one(struct brd_device *brd) { list_del(&brd->brd_list); +#ifdef CONFIG_BLK_DEV_RAM_DAX + kill_dax(brd->dax_dev); + put_dax(brd->dax_dev); +#endif del_gendisk(brd->brd_disk); brd_free(brd); } -- cgit v1.2.3 From d4b29fd78ea6fc2be219be3af1a992149b4ff0f6 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 27 Jan 2017 17:22:03 -0800 Subject: block: remove block_device_operations ->direct_access() Now that all the producers and consumers of dax interfaces have been converted to using dax_operations on a dax_device, remove the block device direct_access enabling. Signed-off-by: Dan Williams --- arch/powerpc/sysdev/axonram.c | 23 ++++------------------ drivers/block/brd.c | 15 --------------- drivers/md/dm.c | 13 ------------- drivers/nvdimm/pmem.c | 10 ---------- drivers/s390/block/dcssblk.c | 16 --------------- fs/block_dev.c | 45 ------------------------------------------- include/linux/blkdev.h | 17 ---------------- 7 files changed, 4 insertions(+), 135 deletions(-) (limited to 'drivers/block') diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c index 171ba86a3494..a7fe5fee744f 100644 --- a/arch/powerpc/sysdev/axonram.c +++ b/arch/powerpc/sysdev/axonram.c @@ -139,6 +139,10 @@ axon_ram_make_request(struct request_queue *queue, struct bio *bio) return BLK_QC_T_NONE; } +static const struct block_device_operations axon_ram_devops = { + .owner = THIS_MODULE, +}; + static long __axon_ram_direct_access(struct axon_ram_bank *bank, pgoff_t pgoff, long nr_pages, void **kaddr, pfn_t *pfn) @@ -150,25 +154,6 @@ __axon_ram_direct_access(struct axon_ram_bank *bank, pgoff_t pgoff, long nr_page return (bank->size - offset) / PAGE_SIZE; } -/** - * axon_ram_direct_access - direct_access() method for block device - * @device, @sector, @data: see block_device_operations method - */ -static long -axon_ram_blk_direct_access(struct block_device *device, sector_t sector, - void **kaddr, pfn_t *pfn, long size) -{ - struct axon_ram_bank *bank = device->bd_disk->private_data; - - return __axon_ram_direct_access(bank, (sector * 512) / PAGE_SIZE, - size / PAGE_SIZE, kaddr, pfn) * PAGE_SIZE; -} - -static const struct block_device_operations axon_ram_devops = { - .owner = THIS_MODULE, - .direct_access = axon_ram_blk_direct_access -}; - static long axon_ram_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages, void **kaddr, pfn_t *pfn) diff --git a/drivers/block/brd.c b/drivers/block/brd.c index 60f3193c9ce2..bfa4ed2c75ef 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -395,18 +395,6 @@ static long __brd_direct_access(struct brd_device *brd, pgoff_t pgoff, return 1; } -static long brd_blk_direct_access(struct block_device *bdev, sector_t sector, - void **kaddr, pfn_t *pfn, long size) -{ - struct brd_device *brd = bdev->bd_disk->private_data; - long nr_pages = __brd_direct_access(brd, PHYS_PFN(sector * 512), - PHYS_PFN(size), kaddr, pfn); - - if (nr_pages < 0) - return nr_pages; - return nr_pages * PAGE_SIZE; -} - static long brd_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages, void **kaddr, pfn_t *pfn) { @@ -418,14 +406,11 @@ static long brd_dax_direct_access(struct dax_device *dax_dev, static const struct dax_operations brd_dax_ops = { .direct_access = brd_dax_direct_access, }; -#else -#define brd_blk_direct_access NULL #endif static const struct block_device_operations brd_fops = { .owner = THIS_MODULE, .rw_page = brd_rw_page, - .direct_access = brd_blk_direct_access, }; /* diff --git a/drivers/md/dm.c b/drivers/md/dm.c index ef4c6f8cad47..79d5f5fd823e 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -957,18 +957,6 @@ static long dm_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, return ret; } -static long dm_blk_direct_access(struct block_device *bdev, sector_t sector, - void **kaddr, pfn_t *pfn, long size) -{ - struct mapped_device *md = bdev->bd_disk->private_data; - struct dax_device *dax_dev = md->dax_dev; - long nr_pages = size / PAGE_SIZE; - - nr_pages = dm_dax_direct_access(dax_dev, sector / PAGE_SECTORS, - nr_pages, kaddr, pfn); - return nr_pages < 0 ? nr_pages : nr_pages * PAGE_SIZE; -} - /* * A target may call dm_accept_partial_bio only from the map routine. It is * allowed for all bio types except REQ_PREFLUSH. @@ -2823,7 +2811,6 @@ static const struct block_device_operations dm_blk_dops = { .open = dm_blk_open, .release = dm_blk_close, .ioctl = dm_blk_ioctl, - .direct_access = dm_blk_direct_access, .getgeo = dm_blk_getgeo, .pr_ops = &dm_pr_ops, .owner = THIS_MODULE diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index fbbcf8154eec..85b85633d674 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -220,19 +220,9 @@ __weak long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff, return PHYS_PFN(pmem->size - pmem->pfn_pad - offset); } -static long pmem_blk_direct_access(struct block_device *bdev, sector_t sector, - void **kaddr, pfn_t *pfn, long size) -{ - struct pmem_device *pmem = bdev->bd_queue->queuedata; - - return __pmem_direct_access(pmem, PHYS_PFN(sector * 512), - PHYS_PFN(size), kaddr, pfn); -} - static const struct block_device_operations pmem_fops = { .owner = THIS_MODULE, .rw_page = pmem_rw_page, - .direct_access = pmem_blk_direct_access, .revalidate_disk = nvdimm_revalidate_disk, }; diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index dc84cfd4e438..36e5280af3e4 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -31,8 +31,6 @@ static int dcssblk_open(struct block_device *bdev, fmode_t mode); static void dcssblk_release(struct gendisk *disk, fmode_t mode); static blk_qc_t dcssblk_make_request(struct request_queue *q, struct bio *bio); -static long dcssblk_blk_direct_access(struct block_device *bdev, sector_t secnum, - void **kaddr, pfn_t *pfn, long size); static long dcssblk_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages, void **kaddr, pfn_t *pfn); @@ -43,7 +41,6 @@ static const struct block_device_operations dcssblk_devops = { .owner = THIS_MODULE, .open = dcssblk_open, .release = dcssblk_release, - .direct_access = dcssblk_blk_direct_access, }; static const struct dax_operations dcssblk_dax_ops = { @@ -915,19 +912,6 @@ __dcssblk_direct_access(struct dcssblk_dev_info *dev_info, pgoff_t pgoff, return (dev_sz - offset) / PAGE_SIZE; } -static long -dcssblk_blk_direct_access(struct block_device *bdev, sector_t secnum, - void **kaddr, pfn_t *pfn, long size) -{ - struct dcssblk_dev_info *dev_info; - - dev_info = bdev->bd_disk->private_data; - if (!dev_info) - return -ENODEV; - return __dcssblk_direct_access(dev_info, PHYS_PFN(secnum * 512), - PHYS_PFN(size), kaddr, pfn) * PAGE_SIZE; -} - static long dcssblk_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages, void **kaddr, pfn_t *pfn) diff --git a/fs/block_dev.c b/fs/block_dev.c index ecbdc8f9f718..10e21465d5a9 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -718,51 +718,6 @@ int bdev_write_page(struct block_device *bdev, sector_t sector, } EXPORT_SYMBOL_GPL(bdev_write_page); -/** - * bdev_direct_access() - Get the address for directly-accessibly memory - * @bdev: The device containing the memory - * @dax: control and output parameters for ->direct_access - * - * If a block device is made up of directly addressable memory, this function - * will tell the caller the PFN and the address of the memory. The address - * may be directly dereferenced within the kernel without the need to call - * ioremap(), kmap() or similar. The PFN is suitable for inserting into - * page tables. - * - * Return: negative errno if an error occurs, otherwise the number of bytes - * accessible at this address. - */ -long bdev_direct_access(struct block_device *bdev, struct blk_dax_ctl *dax) -{ - sector_t sector = dax->sector; - long avail, size = dax->size; - const struct block_device_operations *ops = bdev->bd_disk->fops; - - /* - * The device driver is allowed to sleep, in order to make the - * memory directly accessible. - */ - might_sleep(); - - if (size < 0) - return size; - if (!blk_queue_dax(bdev_get_queue(bdev)) || !ops->direct_access) - return -EOPNOTSUPP; - if ((sector + DIV_ROUND_UP(size, 512)) > - part_nr_sects_read(bdev->bd_part)) - return -ERANGE; - sector += get_start_sect(bdev); - if (sector % (PAGE_SIZE / 512)) - return -EINVAL; - avail = ops->direct_access(bdev, sector, &dax->addr, &dax->pfn, size); - if (!avail) - return -ERANGE; - if (avail > 0 && avail & ~PAGE_MASK) - return -ENXIO; - return min(avail, size); -} -EXPORT_SYMBOL_GPL(bdev_direct_access); - int bdev_dax_pgoff(struct block_device *bdev, sector_t sector, size_t size, pgoff_t *pgoff) { diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 612c497d1461..848f87eb1905 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1916,28 +1916,12 @@ static inline bool integrity_req_gap_front_merge(struct request *req, #endif /* CONFIG_BLK_DEV_INTEGRITY */ -/** - * struct blk_dax_ctl - control and output parameters for ->direct_access - * @sector: (input) offset relative to a block_device - * @addr: (output) kernel virtual address for @sector populated by driver - * @pfn: (output) page frame number for @addr populated by driver - * @size: (input) number of bytes requested - */ -struct blk_dax_ctl { - sector_t sector; - void *addr; - long size; - pfn_t pfn; -}; - struct block_device_operations { int (*open) (struct block_device *, fmode_t); void (*release) (struct gendisk *, fmode_t); int (*rw_page)(struct block_device *, sector_t, struct page *, bool); int (*ioctl) (struct block_device *, fmode_t, unsigned, unsigned long); int (*compat_ioctl) (struct block_device *, fmode_t, unsigned, unsigned long); - long (*direct_access)(struct block_device *, sector_t, void **, pfn_t *, - long); unsigned int (*check_events) (struct gendisk *disk, unsigned int clearing); /* ->media_changed() is DEPRECATED, use ->check_events() instead */ @@ -1956,7 +1940,6 @@ extern int __blkdev_driver_ioctl(struct block_device *, fmode_t, unsigned int, extern int bdev_read_page(struct block_device *, sector_t, struct page *); extern int bdev_write_page(struct block_device *, sector_t, struct page *, struct writeback_control *); -extern long bdev_direct_access(struct block_device *, struct blk_dax_ctl *); extern int bdev_dax_supported(struct super_block *, int); int bdev_dax_pgoff(struct block_device *, sector_t, size_t, pgoff_t *pgoff); #else /* CONFIG_BLOCK */ -- cgit v1.2.3 From 1ef97fe4f8abd3317d5c3c860f990e02c2633959 Mon Sep 17 00:00:00 2001 From: Gerald Schaefer Date: Wed, 3 May 2017 14:56:02 +0200 Subject: brd: fix uninitialized use of brd->dax_dev commit 1647b9b9 "brd: add dax_operations support" introduced the allocation and freeing of a dax_device, but the allocated dax_device is not stored into the brd_device, so brd_del_one() will eventually operate on an uninitialized brd->dax_dev. Fix this by storing the allocated dax_device to brd->dax_dev. Signed-off-by: Gerald Schaefer Signed-off-by: Dan Williams --- drivers/block/brd.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/brd.c b/drivers/block/brd.c index bfa4ed2c75ef..ec00c01b8dc3 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -453,9 +453,7 @@ static struct brd_device *brd_alloc(int i) { struct brd_device *brd; struct gendisk *disk; -#ifdef CONFIG_BLK_DEV_RAM_DAX - struct dax_device *dax_dev; -#endif + brd = kzalloc(sizeof(*brd), GFP_KERNEL); if (!brd) goto out; @@ -497,8 +495,8 @@ static struct brd_device *brd_alloc(int i) #ifdef CONFIG_BLK_DEV_RAM_DAX queue_flag_set_unlocked(QUEUE_FLAG_DAX, brd->brd_queue); - dax_dev = alloc_dax(brd, disk->disk_name, &brd_dax_ops); - if (!dax_dev) + brd->dax_dev = alloc_dax(brd, disk->disk_name, &brd_dax_ops); + if (!brd->dax_dev) goto out_free_inode; #endif @@ -507,8 +505,8 @@ static struct brd_device *brd_alloc(int i) #ifdef CONFIG_BLK_DEV_RAM_DAX out_free_inode: - kill_dax(dax_dev); - put_dax(dax_dev); + kill_dax(brd->dax_dev); + put_dax(brd->dax_dev); #endif out_free_queue: blk_cleanup_queue(brd->brd_queue); -- cgit v1.2.3