libnvdimm: write pmem label set
After 'uuid', 'size', and optionally 'alt_name' have been set to valid values the labels on the dimms can be updated. Write procedure is: 1/ Allocate and write new labels in the "next" index 2/ Free the old labels in the working copy 3/ Write the bitmap and the label space on the dimm 4/ Write the index to make the update valid Label ranges directly mirror the dpa resource values for the given label_id of the namespace. Cc: Greg KH <gregkh@linuxfoundation.org> Cc: Neil Brown <neilb@suse.de> Acked-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
@@ -132,6 +132,55 @@ int nvdimm_init_config_data(struct nvdimm_drvdata *ndd)
|
||||
return rc;
|
||||
}
|
||||
|
||||
int nvdimm_set_config_data(struct nvdimm_drvdata *ndd, size_t offset,
|
||||
void *buf, size_t len)
|
||||
{
|
||||
int rc = validate_dimm(ndd);
|
||||
size_t max_cmd_size, buf_offset;
|
||||
struct nd_cmd_set_config_hdr *cmd;
|
||||
struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(ndd->dev);
|
||||
struct nvdimm_bus_descriptor *nd_desc = nvdimm_bus->nd_desc;
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (!ndd->data)
|
||||
return -ENXIO;
|
||||
|
||||
if (offset + len > ndd->nsarea.config_size)
|
||||
return -ENXIO;
|
||||
|
||||
max_cmd_size = min_t(u32, PAGE_SIZE, len);
|
||||
max_cmd_size = min_t(u32, max_cmd_size, ndd->nsarea.max_xfer);
|
||||
cmd = kzalloc(max_cmd_size + sizeof(*cmd) + sizeof(u32), GFP_KERNEL);
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
for (buf_offset = 0; len; len -= cmd->in_length,
|
||||
buf_offset += cmd->in_length) {
|
||||
size_t cmd_size;
|
||||
u32 *status;
|
||||
|
||||
cmd->in_offset = offset + buf_offset;
|
||||
cmd->in_length = min(max_cmd_size, len);
|
||||
memcpy(cmd->in_buf, buf + buf_offset, cmd->in_length);
|
||||
|
||||
/* status is output in the last 4-bytes of the command buffer */
|
||||
cmd_size = sizeof(*cmd) + cmd->in_length + sizeof(u32);
|
||||
status = ((void *) cmd) + cmd_size - sizeof(u32);
|
||||
|
||||
rc = nd_desc->ndctl(nd_desc, to_nvdimm(ndd->dev),
|
||||
ND_CMD_SET_CONFIG_DATA, cmd, cmd_size);
|
||||
if (rc || *status) {
|
||||
rc = rc ? rc : -ENXIO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
kfree(cmd);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void nvdimm_release(struct device *dev)
|
||||
{
|
||||
struct nvdimm *nvdimm = to_nvdimm(dev);
|
||||
|
Reference in New Issue
Block a user