Commit 0ba1c634 authored by Dan Williams's avatar Dan Williams

libnvdimm: write blk label set

After 'uuid', 'size', 'sector_size', and optionally 'alt_name' have been
set to valid values the labels on the dimm can be updated.  The
difference with the pmem case is that blk namespaces are limited to one
dimm and can cover discontiguous ranges in dpa space.

Also, after allocating label slots, it is useful for userspace to know
how many slots are left.  Export this information in sysfs.

Cc: Greg KH <gregkh@linuxfoundation.org>
Cc: Neil Brown <neilb@suse.de>
Acked-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent f524bf27
......@@ -155,6 +155,10 @@ static void nd_async_device_unregister(void *d, async_cookie_t cookie)
{
struct device *dev = d;
/* flush bus operations before delete */
nvdimm_bus_lock(dev);
nvdimm_bus_unlock(dev);
device_unregister(dev);
put_device(dev);
}
......
......@@ -19,6 +19,7 @@
#include <linux/fs.h>
#include <linux/mm.h>
#include "nd-core.h"
#include "label.h"
#include "nd.h"
static DEFINE_IDA(dimm_ida);
......@@ -296,9 +297,33 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RO(state);
static ssize_t available_slots_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct nvdimm_drvdata *ndd = dev_get_drvdata(dev);
ssize_t rc;
u32 nfree;
if (!ndd)
return -ENXIO;
nvdimm_bus_lock(dev);
nfree = nd_label_nfree(ndd);
if (nfree - 1 > nfree) {
dev_WARN_ONCE(dev, 1, "we ate our last label?\n");
nfree = 0;
} else
nfree--;
rc = sprintf(buf, "%d\n", nfree);
nvdimm_bus_unlock(dev);
return rc;
}
static DEVICE_ATTR_RO(available_slots);
static struct attribute *nvdimm_attributes[] = {
&dev_attr_state.attr,
&dev_attr_commands.attr,
&dev_attr_available_slots.attr,
NULL,
};
......
This diff is collapsed.
......@@ -128,9 +128,14 @@ void nd_label_copy(struct nvdimm_drvdata *ndd, struct nd_namespace_index *dst,
size_t sizeof_namespace_index(struct nvdimm_drvdata *ndd);
int nd_label_active_count(struct nvdimm_drvdata *ndd);
struct nd_namespace_label *nd_label_active(struct nvdimm_drvdata *ndd, int n);
u32 nd_label_alloc_slot(struct nvdimm_drvdata *ndd);
bool nd_label_free_slot(struct nvdimm_drvdata *ndd, u32 slot);
u32 nd_label_nfree(struct nvdimm_drvdata *ndd);
struct nd_region;
struct nd_namespace_pmem;
struct nd_namespace_blk;
int nd_pmem_namespace_label_update(struct nd_region *nd_region,
struct nd_namespace_pmem *nspm, resource_size_t size);
int nd_blk_namespace_label_update(struct nd_region *nd_region,
struct nd_namespace_blk *nsblk, resource_size_t size);
#endif /* __LABEL_H__ */
......@@ -163,8 +163,7 @@ static int nd_namespace_label_update(struct nd_region *nd_region,
*/
if (is_namespace_pmem(dev)) {
struct nd_namespace_pmem *nspm = to_nd_namespace_pmem(dev);
struct resource *res = &nspm->nsio.res;
resource_size_t size = resource_size(res);
resource_size_t size = resource_size(&nspm->nsio.res);
if (size == 0 && nspm->uuid)
/* delete allocation */;
......@@ -173,8 +172,15 @@ static int nd_namespace_label_update(struct nd_region *nd_region,
return nd_pmem_namespace_label_update(nd_region, nspm, size);
} else if (is_namespace_blk(dev)) {
/* TODO: implement blk labels */
struct nd_namespace_blk *nsblk = to_nd_namespace_blk(dev);
resource_size_t size = nd_namespace_blk_size(nsblk);
if (size == 0 && nsblk->uuid)
/* delete allocation */;
else if (!nsblk->uuid || !nsblk->lbasize)
return 0;
return nd_blk_namespace_label_update(nd_region, nsblk, size);
} else
return -ENXIO;
}
......@@ -986,6 +992,48 @@ static ssize_t sector_size_store(struct device *dev,
}
static DEVICE_ATTR_RW(sector_size);
static ssize_t dpa_extents_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct nd_region *nd_region = to_nd_region(dev->parent);
struct nd_label_id label_id;
int count = 0, i;
u8 *uuid = NULL;
u32 flags = 0;
nvdimm_bus_lock(dev);
if (is_namespace_pmem(dev)) {
struct nd_namespace_pmem *nspm = to_nd_namespace_pmem(dev);
uuid = nspm->uuid;
flags = 0;
} else if (is_namespace_blk(dev)) {
struct nd_namespace_blk *nsblk = to_nd_namespace_blk(dev);
uuid = nsblk->uuid;
flags = NSLABEL_FLAG_LOCAL;
}
if (!uuid)
goto out;
nd_label_gen_id(&label_id, uuid, flags);
for (i = 0; i < nd_region->ndr_mappings; i++) {
struct nd_mapping *nd_mapping = &nd_region->mapping[i];
struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
struct resource *res;
for_each_dpa_resource(ndd, res)
if (strcmp(res->name, label_id.id) == 0)
count++;
}
out:
nvdimm_bus_unlock(dev);
return sprintf(buf, "%d\n", count);
}
static DEVICE_ATTR_RO(dpa_extents);
static struct attribute *nd_namespace_attributes[] = {
&dev_attr_nstype.attr,
&dev_attr_size.attr,
......@@ -993,6 +1041,7 @@ static struct attribute *nd_namespace_attributes[] = {
&dev_attr_resource.attr,
&dev_attr_alt_name.attr,
&dev_attr_sector_size.attr,
&dev_attr_dpa_extents.attr,
NULL,
};
......
......@@ -75,5 +75,6 @@ struct nd_mapping;
struct resource *nsblk_add_resource(struct nd_region *nd_region,
struct nvdimm_drvdata *ndd, struct nd_namespace_blk *nsblk,
resource_size_t start);
int nvdimm_num_label_slots(struct nvdimm_drvdata *ndd);
void get_ndd(struct nvdimm_drvdata *ndd);
#endif /* __ND_CORE_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment