Skip to content

Commit

Permalink
Merge branch 'for-5.7/libnvdimm' into libnvdimm-for-next
Browse files Browse the repository at this point in the history
- Introduce 'zero_page_range' as a dax operation. This facilitates
  filesystem-dax operation without a block-device.

- Advertise a persistence-domain for of_pmem and papr_scm. The
  persistence domain indicates where cpu-store cycles need to reach in
  the platform-memory subsystem before the platform will consider them
  power-fail protected.

- Fixup some flexible-array declarations.
  • Loading branch information
djbw committed Apr 3, 2020
2 parents d3b8865 + 4e4ced9 commit f6d2b80
Show file tree
Hide file tree
Showing 17 changed files with 251 additions and 110 deletions.
4 changes: 3 additions & 1 deletion arch/powerpc/platforms/pseries/papr_scm.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,8 +342,10 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p)

if (p->is_volatile)
p->region = nvdimm_volatile_region_create(p->bus, &ndr_desc);
else
else {
set_bit(ND_REGION_PERSIST_MEMCTRL, &ndr_desc.flags);
p->region = nvdimm_pmem_region_create(p->bus, &ndr_desc);
}
if (!p->region) {
dev_err(dev, "Error registering region %pR from %pOF\n",
ndr_desc.res, p->dn);
Expand Down
12 changes: 6 additions & 6 deletions drivers/acpi/nfit/nfit.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,32 +145,32 @@ struct nfit_spa {
unsigned long ars_state;
u32 clear_err_unit;
u32 max_ars;
struct acpi_nfit_system_address spa[0];
struct acpi_nfit_system_address spa[];
};

struct nfit_dcr {
struct list_head list;
struct acpi_nfit_control_region dcr[0];
struct acpi_nfit_control_region dcr[];
};

struct nfit_bdw {
struct list_head list;
struct acpi_nfit_data_region bdw[0];
struct acpi_nfit_data_region bdw[];
};

struct nfit_idt {
struct list_head list;
struct acpi_nfit_interleave idt[0];
struct acpi_nfit_interleave idt[];
};

struct nfit_flush {
struct list_head list;
struct acpi_nfit_flush_address flush[0];
struct acpi_nfit_flush_address flush[];
};

struct nfit_memdev {
struct list_head list;
struct acpi_nfit_memory_map memdev[0];
struct acpi_nfit_memory_map memdev[];
};

enum nfit_mem_flags {
Expand Down
4 changes: 3 additions & 1 deletion drivers/dax/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -421,8 +421,10 @@ struct dev_dax *__devm_create_dev_dax(struct dax_region *dax_region, int id,
* device outside of mmap of the resulting character device.
*/
dax_dev = alloc_dax(dev_dax, NULL, NULL, DAXDEV_F_SYNC);
if (!dax_dev)
if (IS_ERR(dax_dev)) {
rc = PTR_ERR(dax_dev);
goto err;
}

/* a device_dax instance is dead while the driver is not attached */
kill_dax(dax_dev);
Expand Down
28 changes: 26 additions & 2 deletions drivers/dax/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,23 @@ size_t dax_copy_to_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr,
}
EXPORT_SYMBOL_GPL(dax_copy_to_iter);

int dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff,
size_t nr_pages)
{
if (!dax_alive(dax_dev))
return -ENXIO;
/*
* There are no callers that want to zero more than one page as of now.
* Once users are there, this check can be removed after the
* device mapper code has been updated to split ranges across targets.
*/
if (nr_pages != 1)
return -EIO;

return dax_dev->ops->zero_page_range(dax_dev, pgoff, nr_pages);
}
EXPORT_SYMBOL_GPL(dax_zero_page_range);

#ifdef CONFIG_ARCH_HAS_PMEM_API
void arch_wb_cache_pmem(void *addr, size_t size);
void dax_flush(struct dax_device *dax_dev, void *addr, size_t size)
Expand Down Expand Up @@ -551,9 +568,16 @@ struct dax_device *alloc_dax(void *private, const char *__host,
dev_t devt;
int minor;

if (ops && !ops->zero_page_range) {
pr_debug("%s: error: device does not provide dax"
" operation zero_page_range()\n",
__host ? __host : "Unknown");
return ERR_PTR(-EINVAL);
}

host = kstrdup(__host, GFP_KERNEL);
if (__host && !host)
return NULL;
return ERR_PTR(-ENOMEM);

minor = ida_simple_get(&dax_minor_ida, 0, MINORMASK+1, GFP_KERNEL);
if (minor < 0)
Expand All @@ -576,7 +600,7 @@ struct dax_device *alloc_dax(void *private, const char *__host,
ida_simple_remove(&dax_minor_ida, minor);
err_minor:
kfree(host);
return NULL;
return ERR_PTR(-ENOMEM);
}
EXPORT_SYMBOL_GPL(alloc_dax);

Expand Down
18 changes: 18 additions & 0 deletions drivers/md/dm-linear.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,27 @@ static size_t linear_dax_copy_to_iter(struct dm_target *ti, pgoff_t pgoff,
return dax_copy_to_iter(dax_dev, pgoff, addr, bytes, i);
}

static int linear_dax_zero_page_range(struct dm_target *ti, pgoff_t pgoff,
size_t nr_pages)
{
int ret;
struct linear_c *lc = ti->private;
struct block_device *bdev = lc->dev->bdev;
struct dax_device *dax_dev = lc->dev->dax_dev;
sector_t dev_sector, sector = pgoff * PAGE_SECTORS;

dev_sector = linear_map_sector(ti, sector);
ret = bdev_dax_pgoff(bdev, dev_sector, nr_pages << PAGE_SHIFT, &pgoff);
if (ret)
return ret;
return dax_zero_page_range(dax_dev, pgoff, nr_pages);
}

#else
#define linear_dax_direct_access NULL
#define linear_dax_copy_from_iter NULL
#define linear_dax_copy_to_iter NULL
#define linear_dax_zero_page_range NULL
#endif

static struct target_type linear_target = {
Expand All @@ -226,6 +243,7 @@ static struct target_type linear_target = {
.direct_access = linear_dax_direct_access,
.dax_copy_from_iter = linear_dax_copy_from_iter,
.dax_copy_to_iter = linear_dax_copy_to_iter,
.dax_zero_page_range = linear_dax_zero_page_range,
};

int __init dm_linear_init(void)
Expand Down
17 changes: 17 additions & 0 deletions drivers/md/dm-log-writes.c
Original file line number Diff line number Diff line change
Expand Up @@ -994,10 +994,26 @@ static size_t log_writes_dax_copy_to_iter(struct dm_target *ti,
return dax_copy_to_iter(lc->dev->dax_dev, pgoff, addr, bytes, i);
}

static int log_writes_dax_zero_page_range(struct dm_target *ti, pgoff_t pgoff,
size_t nr_pages)
{
int ret;
struct log_writes_c *lc = ti->private;
sector_t sector = pgoff * PAGE_SECTORS;

ret = bdev_dax_pgoff(lc->dev->bdev, sector, nr_pages << PAGE_SHIFT,
&pgoff);
if (ret)
return ret;
return dax_zero_page_range(lc->dev->dax_dev, pgoff,
nr_pages << PAGE_SHIFT);
}

#else
#define log_writes_dax_direct_access NULL
#define log_writes_dax_copy_from_iter NULL
#define log_writes_dax_copy_to_iter NULL
#define log_writes_dax_zero_page_range NULL
#endif

static struct target_type log_writes_target = {
Expand All @@ -1016,6 +1032,7 @@ static struct target_type log_writes_target = {
.direct_access = log_writes_dax_direct_access,
.dax_copy_from_iter = log_writes_dax_copy_from_iter,
.dax_copy_to_iter = log_writes_dax_copy_to_iter,
.dax_zero_page_range = log_writes_dax_zero_page_range,
};

static int __init dm_log_writes_init(void)
Expand Down
23 changes: 23 additions & 0 deletions drivers/md/dm-stripe.c
Original file line number Diff line number Diff line change
Expand Up @@ -360,10 +360,32 @@ static size_t stripe_dax_copy_to_iter(struct dm_target *ti, pgoff_t pgoff,
return dax_copy_to_iter(dax_dev, pgoff, addr, bytes, i);
}

static int stripe_dax_zero_page_range(struct dm_target *ti, pgoff_t pgoff,
size_t nr_pages)
{
int ret;
sector_t dev_sector, sector = pgoff * PAGE_SECTORS;
struct stripe_c *sc = ti->private;
struct dax_device *dax_dev;
struct block_device *bdev;
uint32_t stripe;

stripe_map_sector(sc, sector, &stripe, &dev_sector);
dev_sector += sc->stripe[stripe].physical_start;
dax_dev = sc->stripe[stripe].dev->dax_dev;
bdev = sc->stripe[stripe].dev->bdev;

ret = bdev_dax_pgoff(bdev, dev_sector, nr_pages << PAGE_SHIFT, &pgoff);
if (ret)
return ret;
return dax_zero_page_range(dax_dev, pgoff, nr_pages);
}

#else
#define stripe_dax_direct_access NULL
#define stripe_dax_copy_from_iter NULL
#define stripe_dax_copy_to_iter NULL
#define stripe_dax_zero_page_range NULL
#endif

/*
Expand Down Expand Up @@ -486,6 +508,7 @@ static struct target_type stripe_target = {
.direct_access = stripe_dax_direct_access,
.dax_copy_from_iter = stripe_dax_copy_from_iter,
.dax_copy_to_iter = stripe_dax_copy_to_iter,
.dax_zero_page_range = stripe_dax_zero_page_range,
};

int __init dm_stripe_init(void)
Expand Down
32 changes: 31 additions & 1 deletion drivers/md/dm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1198,6 +1198,35 @@ static size_t dm_dax_copy_to_iter(struct dax_device *dax_dev, pgoff_t pgoff,
return ret;
}

static int dm_dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff,
size_t nr_pages)
{
struct mapped_device *md = dax_get_private(dax_dev);
sector_t sector = pgoff * PAGE_SECTORS;
struct dm_target *ti;
int ret = -EIO;
int srcu_idx;

ti = dm_dax_get_live_target(md, sector, &srcu_idx);

if (!ti)
goto out;
if (WARN_ON(!ti->type->dax_zero_page_range)) {
/*
* ->zero_page_range() is mandatory dax operation. If we are
* here, something is wrong.
*/
dm_put_live_table(md, srcu_idx);
goto out;
}
ret = ti->type->dax_zero_page_range(ti, pgoff, nr_pages);

out:
dm_put_live_table(md, srcu_idx);

return ret;
}

/*
* A target may call dm_accept_partial_bio only from the map routine. It is
* allowed for all bio types except REQ_PREFLUSH, REQ_OP_ZONE_RESET,
Expand Down Expand Up @@ -1976,7 +2005,7 @@ static struct mapped_device *alloc_dev(int minor)
if (IS_ENABLED(CONFIG_DAX_DRIVER)) {
md->dax_dev = alloc_dax(md, md->disk->disk_name,
&dm_dax_ops, 0);
if (!md->dax_dev)
if (IS_ERR(md->dax_dev))
goto bad;
}

Expand Down Expand Up @@ -3199,6 +3228,7 @@ static const struct dax_operations dm_dax_ops = {
.dax_supported = dm_dax_supported,
.copy_from_iter = dm_dax_copy_from_iter,
.copy_to_iter = dm_dax_copy_to_iter,
.zero_page_range = dm_dax_zero_page_range,
};

/*
Expand Down
2 changes: 1 addition & 1 deletion drivers/nvdimm/label.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ struct nd_namespace_index {
__le16 major;
__le16 minor;
__le64 checksum;
u8 free[0];
u8 free[];
};

/**
Expand Down
4 changes: 2 additions & 2 deletions drivers/nvdimm/nd.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ struct nd_region_data {
int ns_count;
int ns_active;
unsigned int hints_shift;
void __iomem *flush_wpq[0];
void __iomem *flush_wpq[];
};

static inline void __iomem *ndrd_get_flush_wpq(struct nd_region_data *ndrd,
Expand Down Expand Up @@ -157,7 +157,7 @@ struct nd_region {
struct nd_interleave_set *nd_set;
struct nd_percpu_lane __percpu *lane;
int (*flush)(struct nd_region *nd_region, struct bio *bio);
struct nd_mapping mapping[0];
struct nd_mapping mapping[];
};

struct nd_blk_region {
Expand Down
4 changes: 3 additions & 1 deletion drivers/nvdimm/of_pmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,10 @@ static int of_pmem_region_probe(struct platform_device *pdev)

if (is_volatile)
region = nvdimm_volatile_region_create(bus, &ndr_desc);
else
else {
set_bit(ND_REGION_PERSIST_MEMCTRL, &ndr_desc.flags);
region = nvdimm_pmem_region_create(bus, &ndr_desc);
}

if (!region)
dev_warn(&pdev->dev, "Unable to register region %pR from %pOF\n",
Expand Down
Loading

0 comments on commit f6d2b80

Please sign in to comment.