Skip to content

Commit

Permalink
dax: introduce dax_direct_access()
Browse files Browse the repository at this point in the history
Replace bdev_direct_access() with dax_direct_access() that uses
dax_device and dax_operations instead of a block_device and
block_device_operations for dax. Once all consumers of the old api have
been converted bdev_direct_access() will be deleted.

Given that block device partitioning decisions can cause dax page
alignment constraints to be violated this also introduces the
bdev_dax_pgoff() helper. It handles calculating a logical pgoff relative
to the dax_device and also checks for page alignment.

Signed-off-by: Dan Williams <[email protected]>
  • Loading branch information
djbw committed Apr 20, 2017
1 parent d8f07ae commit b068626
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 0 deletions.
1 change: 1 addition & 0 deletions block/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ menuconfig BLOCK
default y
select SBITMAP
select SRCU
select DAX
help
Provide block layer support for the kernel.

Expand Down
39 changes: 39 additions & 0 deletions drivers/dax/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,45 @@ struct dax_device {
const struct dax_operations *ops;
};

/**
* dax_direct_access() - translate a device pgoff to an absolute pfn
* @dax_dev: a dax_device instance representing the logical memory range
* @pgoff: offset in pages from the start of the device to translate
* @nr_pages: number of consecutive pages caller can handle relative to @pfn
* @kaddr: output parameter that returns a virtual address mapping of pfn
* @pfn: output parameter that returns an absolute pfn translation of @pgoff
*
* Return: negative errno if an error occurs, otherwise the number of
* pages accessible at the device relative @pgoff.
*/
long dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages,
void **kaddr, pfn_t *pfn)
{
long avail;

/*
* The device driver is allowed to sleep, in order to make the
* memory directly accessible.
*/
might_sleep();

if (!dax_dev)
return -EOPNOTSUPP;

if (!dax_alive(dax_dev))
return -ENXIO;

if (nr_pages < 0)
return nr_pages;

avail = dax_dev->ops->direct_access(dax_dev, pgoff, nr_pages,
kaddr, pfn);
if (!avail)
return -ERANGE;
return min(avail, nr_pages);
}
EXPORT_SYMBOL_GPL(dax_direct_access);

bool dax_alive(struct dax_device *dax_dev)
{
lockdep_assert_held(&dax_srcu);
Expand Down
14 changes: 14 additions & 0 deletions fs/block_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/blkpg.h>
#include <linux/magic.h>
#include <linux/dax.h>
#include <linux/buffer_head.h>
#include <linux/swap.h>
#include <linux/pagevec.h>
Expand Down Expand Up @@ -762,6 +763,19 @@ long bdev_direct_access(struct block_device *bdev, struct blk_dax_ctl *dax)
}
EXPORT_SYMBOL_GPL(bdev_direct_access);

int bdev_dax_pgoff(struct block_device *bdev, sector_t sector, size_t size,
pgoff_t *pgoff)
{
phys_addr_t phys_off = (get_start_sect(bdev) + sector) * 512;

if (pgoff)
*pgoff = PHYS_PFN(phys_off);
if (phys_off % PAGE_SIZE || size % PAGE_SIZE)
return -EINVAL;
return 0;
}
EXPORT_SYMBOL(bdev_dax_pgoff);

/**
* bdev_dax_supported() - Check if the device supports dax for filesystem
* @sb: The superblock of the device
Expand Down
1 change: 1 addition & 0 deletions include/linux/blkdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -1958,6 +1958,7 @@ 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 */

struct block_device;
Expand Down
2 changes: 2 additions & 0 deletions include/linux/dax.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ void put_dax(struct dax_device *dax_dev);
bool dax_alive(struct dax_device *dax_dev);
void kill_dax(struct dax_device *dax_dev);
void *dax_get_private(struct dax_device *dax_dev);
long dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages,
void **kaddr, pfn_t *pfn);

/*
* We use lowest available bit in exceptional entry for locking, one bit for
Expand Down

0 comments on commit b068626

Please sign in to comment.