Skip to content

Commit

Permalink
dax: introduce DAX_RECOVERY_WRITE dax access mode
Browse files Browse the repository at this point in the history
Up till now, dax_direct_access() is used implicitly for normal
access, but for the purpose of recovery write, dax range with
poison is requested.  To make the interface clear, introduce
	enum dax_access_mode {
		DAX_ACCESS,
		DAX_RECOVERY_WRITE,
	}
where DAX_ACCESS is used for normal dax access, and
DAX_RECOVERY_WRITE is used for dax recovery write.

Suggested-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jane Chu <jane.chu@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Cc: Mike Snitzer <snitzer@redhat.com>
Reviewed-by: Vivek Goyal <vgoyal@redhat.com>
Link: https://lore.kernel.org/r/165247982851.52965.11024212198889762949.stgit@dwillia2-desk3.amr.corp.intel.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
  • Loading branch information
Jane Chu authored and Dan Williams committed May 16, 2022
1 parent 5898b43 commit e511c4a
Show file tree
Hide file tree
Showing 16 changed files with 61 additions and 33 deletions.
5 changes: 3 additions & 2 deletions drivers/dax/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,15 @@ enum dax_device_flags {
* @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
* @mode: indicator on normal access or recovery write
* @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)
enum dax_access_mode mode, void **kaddr, pfn_t *pfn)
{
long avail;

Expand All @@ -138,7 +139,7 @@ long dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages,
return -EINVAL;

avail = dax_dev->ops->direct_access(dax_dev, pgoff, nr_pages,
kaddr, pfn);
mode, kaddr, pfn);
if (!avail)
return -ERANGE;
return min(avail, nr_pages);
Expand Down
5 changes: 3 additions & 2 deletions drivers/md/dm-linear.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,11 +172,12 @@ static struct dax_device *linear_dax_pgoff(struct dm_target *ti, pgoff_t *pgoff)
}

static long linear_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
long nr_pages, void **kaddr, pfn_t *pfn)
long nr_pages, enum dax_access_mode mode, void **kaddr,
pfn_t *pfn)
{
struct dax_device *dax_dev = linear_dax_pgoff(ti, &pgoff);

return dax_direct_access(dax_dev, pgoff, nr_pages, kaddr, pfn);
return dax_direct_access(dax_dev, pgoff, nr_pages, mode, kaddr, pfn);
}

static int linear_dax_zero_page_range(struct dm_target *ti, pgoff_t pgoff,
Expand Down
5 changes: 3 additions & 2 deletions drivers/md/dm-log-writes.c
Original file line number Diff line number Diff line change
Expand Up @@ -889,11 +889,12 @@ static struct dax_device *log_writes_dax_pgoff(struct dm_target *ti,
}

static long log_writes_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
long nr_pages, void **kaddr, pfn_t *pfn)
long nr_pages, enum dax_access_mode mode, void **kaddr,
pfn_t *pfn)
{
struct dax_device *dax_dev = log_writes_dax_pgoff(ti, &pgoff);

return dax_direct_access(dax_dev, pgoff, nr_pages, kaddr, pfn);
return dax_direct_access(dax_dev, pgoff, nr_pages, mode, kaddr, pfn);
}

static int log_writes_dax_zero_page_range(struct dm_target *ti, pgoff_t pgoff,
Expand Down
5 changes: 3 additions & 2 deletions drivers/md/dm-stripe.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,11 +315,12 @@ static struct dax_device *stripe_dax_pgoff(struct dm_target *ti, pgoff_t *pgoff)
}

static long stripe_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
long nr_pages, void **kaddr, pfn_t *pfn)
long nr_pages, enum dax_access_mode mode, void **kaddr,
pfn_t *pfn)
{
struct dax_device *dax_dev = stripe_dax_pgoff(ti, &pgoff);

return dax_direct_access(dax_dev, pgoff, nr_pages, kaddr, pfn);
return dax_direct_access(dax_dev, pgoff, nr_pages, mode, kaddr, pfn);
}

static int stripe_dax_zero_page_range(struct dm_target *ti, pgoff_t pgoff,
Expand Down
4 changes: 3 additions & 1 deletion drivers/md/dm-target.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <linux/init.h>
#include <linux/kmod.h>
#include <linux/bio.h>
#include <linux/dax.h>

#define DM_MSG_PREFIX "target"

Expand Down Expand Up @@ -142,7 +143,8 @@ static void io_err_release_clone_rq(struct request *clone,
}

static long io_err_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
long nr_pages, void **kaddr, pfn_t *pfn)
long nr_pages, enum dax_access_mode mode, void **kaddr,
pfn_t *pfn)
{
return -EIO;
}
Expand Down
7 changes: 4 additions & 3 deletions drivers/md/dm-writecache.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,8 @@ static int persistent_memory_claim(struct dm_writecache *wc)

id = dax_read_lock();

da = dax_direct_access(wc->ssd_dev->dax_dev, offset, p, &wc->memory_map, &pfn);
da = dax_direct_access(wc->ssd_dev->dax_dev, offset, p, DAX_ACCESS,
&wc->memory_map, &pfn);
if (da < 0) {
wc->memory_map = NULL;
r = da;
Expand All @@ -308,8 +309,8 @@ static int persistent_memory_claim(struct dm_writecache *wc)
i = 0;
do {
long daa;
daa = dax_direct_access(wc->ssd_dev->dax_dev, offset + i, p - i,
NULL, &pfn);
daa = dax_direct_access(wc->ssd_dev->dax_dev, offset + i,
p - i, DAX_ACCESS, NULL, &pfn);
if (daa <= 0) {
r = daa ? daa : -EINVAL;
goto err3;
Expand Down
5 changes: 3 additions & 2 deletions drivers/md/dm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1093,7 +1093,8 @@ static struct dm_target *dm_dax_get_live_target(struct mapped_device *md,
}

static long dm_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff,
long nr_pages, void **kaddr, pfn_t *pfn)
long nr_pages, enum dax_access_mode mode, void **kaddr,
pfn_t *pfn)
{
struct mapped_device *md = dax_get_private(dax_dev);
sector_t sector = pgoff * PAGE_SECTORS;
Expand All @@ -1111,7 +1112,7 @@ static long dm_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff,
if (len < 1)
goto out;
nr_pages = min(len, nr_pages);
ret = ti->type->direct_access(ti, pgoff, nr_pages, kaddr, pfn);
ret = ti->type->direct_access(ti, pgoff, nr_pages, mode, kaddr, pfn);

out:
dm_put_live_table(md, srcu_idx);
Expand Down
8 changes: 5 additions & 3 deletions drivers/nvdimm/pmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,8 @@ static int pmem_rw_page(struct block_device *bdev, sector_t sector,

/* see "strong" declaration in tools/testing/nvdimm/pmem-dax.c */
__weak long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff,
long nr_pages, void **kaddr, pfn_t *pfn)
long nr_pages, enum dax_access_mode mode, void **kaddr,
pfn_t *pfn)
{
resource_size_t offset = PFN_PHYS(pgoff) + pmem->data_offset;

Expand Down Expand Up @@ -278,11 +279,12 @@ static int pmem_dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff,
}

static long pmem_dax_direct_access(struct dax_device *dax_dev,
pgoff_t pgoff, long nr_pages, void **kaddr, pfn_t *pfn)
pgoff_t pgoff, long nr_pages, enum dax_access_mode mode,
void **kaddr, pfn_t *pfn)
{
struct pmem_device *pmem = dax_get_private(dax_dev);

return __pmem_direct_access(pmem, pgoff, nr_pages, kaddr, pfn);
return __pmem_direct_access(pmem, pgoff, nr_pages, mode, kaddr, pfn);
}

static const struct dax_operations pmem_dax_ops = {
Expand Down
5 changes: 4 additions & 1 deletion drivers/nvdimm/pmem.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <linux/pfn_t.h>
#include <linux/fs.h>

enum dax_access_mode;

/* this definition is in it's own header for tools/testing/nvdimm to consume */
struct pmem_device {
/* One contiguous memory region per device */
Expand All @@ -28,7 +30,8 @@ struct pmem_device {
};

long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff,
long nr_pages, void **kaddr, pfn_t *pfn);
long nr_pages, enum dax_access_mode mode, void **kaddr,
pfn_t *pfn);

#ifdef CONFIG_MEMORY_FAILURE
static inline bool test_and_clear_pmem_poison(struct page *page)
Expand Down
9 changes: 6 additions & 3 deletions drivers/s390/block/dcssblk.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ static int dcssblk_open(struct block_device *bdev, fmode_t mode);
static void dcssblk_release(struct gendisk *disk, fmode_t mode);
static void dcssblk_submit_bio(struct bio *bio);
static long dcssblk_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff,
long nr_pages, void **kaddr, pfn_t *pfn);
long nr_pages, enum dax_access_mode mode, void **kaddr,
pfn_t *pfn);

static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0";

Expand All @@ -50,7 +51,8 @@ static int dcssblk_dax_zero_page_range(struct dax_device *dax_dev,
long rc;
void *kaddr;

rc = dax_direct_access(dax_dev, pgoff, nr_pages, &kaddr, NULL);
rc = dax_direct_access(dax_dev, pgoff, nr_pages, DAX_ACCESS,
&kaddr, NULL);
if (rc < 0)
return rc;
memset(kaddr, 0, nr_pages << PAGE_SHIFT);
Expand Down Expand Up @@ -927,7 +929,8 @@ __dcssblk_direct_access(struct dcssblk_dev_info *dev_info, pgoff_t pgoff,

static long
dcssblk_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff,
long nr_pages, void **kaddr, pfn_t *pfn)
long nr_pages, enum dax_access_mode mode, void **kaddr,
pfn_t *pfn)
{
struct dcssblk_dev_info *dev_info = dax_get_private(dax_dev);

Expand Down
9 changes: 5 additions & 4 deletions fs/dax.c
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,8 @@ static int copy_cow_page_dax(struct vm_fault *vmf, const struct iomap_iter *iter
int id;

id = dax_read_lock();
rc = dax_direct_access(iter->iomap.dax_dev, pgoff, 1, &kaddr, NULL);
rc = dax_direct_access(iter->iomap.dax_dev, pgoff, 1, DAX_ACCESS,
&kaddr, NULL);
if (rc < 0) {
dax_read_unlock(id);
return rc;
Expand Down Expand Up @@ -1013,7 +1014,7 @@ static int dax_iomap_pfn(const struct iomap *iomap, loff_t pos, size_t size,

id = dax_read_lock();
length = dax_direct_access(iomap->dax_dev, pgoff, PHYS_PFN(size),
NULL, pfnp);
DAX_ACCESS, NULL, pfnp);
if (length < 0) {
rc = length;
goto out;
Expand Down Expand Up @@ -1122,7 +1123,7 @@ static int dax_memzero(struct dax_device *dax_dev, pgoff_t pgoff,
void *kaddr;
long ret;

ret = dax_direct_access(dax_dev, pgoff, 1, &kaddr, NULL);
ret = dax_direct_access(dax_dev, pgoff, 1, DAX_ACCESS, &kaddr, NULL);
if (ret > 0) {
memset(kaddr + offset, 0, size);
dax_flush(dax_dev, kaddr + offset, size);
Expand Down Expand Up @@ -1247,7 +1248,7 @@ static loff_t dax_iomap_iter(const struct iomap_iter *iomi,
}

map_len = dax_direct_access(dax_dev, pgoff, PHYS_PFN(size),
&kaddr, NULL);
DAX_ACCESS, &kaddr, NULL);
if (map_len < 0) {
ret = map_len;
break;
Expand Down
4 changes: 2 additions & 2 deletions fs/fuse/dax.c
Original file line number Diff line number Diff line change
Expand Up @@ -1241,8 +1241,8 @@ static int fuse_dax_mem_range_init(struct fuse_conn_dax *fcd)
INIT_DELAYED_WORK(&fcd->free_work, fuse_dax_free_mem_worker);

id = dax_read_lock();
nr_pages = dax_direct_access(fcd->dev, 0, PHYS_PFN(dax_size), NULL,
NULL);
nr_pages = dax_direct_access(fcd->dev, 0, PHYS_PFN(dax_size),
DAX_ACCESS, NULL, NULL);
dax_read_unlock(id);
if (nr_pages < 0) {
pr_debug("dax_direct_access() returned %ld\n", nr_pages);
Expand Down
6 changes: 4 additions & 2 deletions fs/fuse/virtio_fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,8 @@ static void virtio_fs_cleanup_vqs(struct virtio_device *vdev,
* offset.
*/
static long virtio_fs_direct_access(struct dax_device *dax_dev, pgoff_t pgoff,
long nr_pages, void **kaddr, pfn_t *pfn)
long nr_pages, enum dax_access_mode mode,
void **kaddr, pfn_t *pfn)
{
struct virtio_fs *fs = dax_get_private(dax_dev);
phys_addr_t offset = PFN_PHYS(pgoff);
Expand All @@ -772,7 +773,8 @@ static int virtio_fs_zero_page_range(struct dax_device *dax_dev,
long rc;
void *kaddr;

rc = dax_direct_access(dax_dev, pgoff, nr_pages, &kaddr, NULL);
rc = dax_direct_access(dax_dev, pgoff, nr_pages, DAX_ACCESS, &kaddr,
NULL);
if (rc < 0)
return rc;
memset(kaddr, 0, nr_pages << PAGE_SHIFT);
Expand Down
9 changes: 7 additions & 2 deletions include/linux/dax.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,19 @@ struct iomap_ops;
struct iomap_iter;
struct iomap;

enum dax_access_mode {
DAX_ACCESS,
DAX_RECOVERY_WRITE,
};

struct dax_operations {
/*
* direct_access: translate a device-relative
* logical-page-offset into an absolute physical pfn. Return the
* number of pages available for DAX at that pfn.
*/
long (*direct_access)(struct dax_device *, pgoff_t, long,
void **, pfn_t *);
enum dax_access_mode, void **, pfn_t *);
/*
* Validate whether this device is usable as an fsdax backing
* device.
Expand Down Expand Up @@ -178,7 +183,7 @@ static inline void dax_read_unlock(int id)
bool dax_alive(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);
enum dax_access_mode mode, void **kaddr, pfn_t *pfn);
size_t dax_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr,
size_t bytes, struct iov_iter *i);
size_t dax_copy_to_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr,
Expand Down
4 changes: 3 additions & 1 deletion include/linux/device-mapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ struct dm_table;
struct dm_report_zones_args;
struct mapped_device;
struct bio_vec;
enum dax_access_mode;

/*
* Type of table, mapped_device's mempool and request_queue
Expand Down Expand Up @@ -146,7 +147,8 @@ typedef int (*dm_busy_fn) (struct dm_target *ti);
* >= 0 : the number of bytes accessible at the address
*/
typedef long (*dm_dax_direct_access_fn) (struct dm_target *ti, pgoff_t pgoff,
long nr_pages, void **kaddr, pfn_t *pfn);
long nr_pages, enum dax_access_mode node, void **kaddr,
pfn_t *pfn);
typedef int (*dm_dax_zero_page_range_fn)(struct dm_target *ti, pgoff_t pgoff,
size_t nr_pages);

Expand Down
4 changes: 3 additions & 1 deletion tools/testing/nvdimm/pmem-dax.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
*/
#include "test/nfit_test.h"
#include <linux/blkdev.h>
#include <linux/dax.h>
#include <pmem.h>
#include <nd.h>

long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff,
long nr_pages, void **kaddr, pfn_t *pfn)
long nr_pages, enum dax_access_mode mode, void **kaddr,
pfn_t *pfn)
{
resource_size_t offset = PFN_PHYS(pgoff) + pmem->data_offset;

Expand Down

0 comments on commit e511c4a

Please sign in to comment.