static int nd_namespace_label_update(struct nd_region *nd_region, struct device *dev) { dev_WARN_ONCE(dev, dev->driver || to_ndns(dev)->claim, "namespace must be idle during label update\n"); if (dev->driver || to_ndns(dev)->claim) return 0; /* * Only allow label writes that will result in a valid namespace * or deletion of an existing namespace. */ if (is_namespace_pmem(dev)) { struct nd_namespace_pmem *nspm = to_nd_namespace_pmem(dev); resource_size_t size = resource_size(&nspm->nsio.res); if (size == 0 && nspm->uuid) /* delete allocation */; else if (!nspm->uuid) return 0; return nd_pmem_namespace_label_update(nd_region, nspm, size); } else if (is_namespace_blk(dev)) { 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; }
static int is_uuid_busy(struct device *dev, void *data) { u8 *uuid1 = data, *uuid2 = NULL; if (is_namespace_pmem(dev)) { struct nd_namespace_pmem *nspm = to_nd_namespace_pmem(dev); uuid2 = nspm->uuid; } else if (is_namespace_blk(dev)) { struct nd_namespace_blk *nsblk = to_nd_namespace_blk(dev); uuid2 = nsblk->uuid; } else if (is_nd_btt(dev)) { struct nd_btt *nd_btt = to_nd_btt(dev); uuid2 = nd_btt->uuid; } else if (is_nd_pfn(dev)) { struct nd_pfn *nd_pfn = to_nd_pfn(dev); uuid2 = nd_pfn->uuid; } if (uuid2 && memcmp(uuid1, uuid2, NSLABEL_UUID_LEN) == 0) return -EBUSY; return 0; }
const char *nvdimm_namespace_disk_name(struct nd_namespace_common *ndns, char *name) { struct nd_region *nd_region = to_nd_region(ndns->dev.parent); const char *suffix = NULL; if (ndns->claim) { if (is_nd_btt(ndns->claim)) suffix = "s"; else if (is_nd_pfn(ndns->claim)) suffix = "m"; else dev_WARN_ONCE(&ndns->dev, 1, "unknown claim type by %s\n", dev_name(ndns->claim)); } if (is_namespace_pmem(&ndns->dev) || is_namespace_io(&ndns->dev)) { if (!suffix && pmem_should_map_pages(&ndns->dev)) suffix = "m"; sprintf(name, "pmem%d%s", nd_region->id, suffix ? suffix : ""); } else if (is_namespace_blk(&ndns->dev)) { struct nd_namespace_blk *nsblk; nsblk = to_nd_namespace_blk(&ndns->dev); sprintf(name, "ndblk%d.%d%s", nd_region->id, nsblk->id, suffix ? suffix : ""); } else { return NULL; } return name; }
static int is_uuid_busy(struct device *dev, void *data) { struct nd_region *nd_region = to_nd_region(dev->parent); u8 *uuid = data; switch (nd_region_to_nstype(nd_region)) { case ND_DEVICE_NAMESPACE_PMEM: { struct nd_namespace_pmem *nspm = to_nd_namespace_pmem(dev); if (!nspm->uuid) break; if (memcmp(uuid, nspm->uuid, NSLABEL_UUID_LEN) == 0) return -EBUSY; break; } case ND_DEVICE_NAMESPACE_BLK: { struct nd_namespace_blk *nsblk = to_nd_namespace_blk(dev); if (!nsblk->uuid) break; if (memcmp(uuid, nsblk->uuid, NSLABEL_UUID_LEN) == 0) return -EBUSY; break; } default: break; } return 0; }
static void namespace_blk_release(struct device *dev) { struct nd_namespace_blk *nsblk = to_nd_namespace_blk(dev); struct nd_region *nd_region = to_nd_region(dev->parent); if (nsblk->id >= 0) ida_simple_remove(&nd_region->ns_ida, nsblk->id); kfree(nsblk->alt_name); kfree(nsblk->uuid); kfree(nsblk->res); kfree(nsblk); }
static ssize_t __alt_name_store(struct device *dev, const char *buf, const size_t len) { char *input, *pos, *alt_name, **ns_altname; ssize_t rc; if (is_namespace_pmem(dev)) { struct nd_namespace_pmem *nspm = to_nd_namespace_pmem(dev); ns_altname = &nspm->alt_name; } else if (is_namespace_blk(dev)) { struct nd_namespace_blk *nsblk = to_nd_namespace_blk(dev); ns_altname = &nsblk->alt_name; } else return -ENXIO; if (dev->driver || to_ndns(dev)->claim) return -EBUSY; input = kmemdup(buf, len + 1, GFP_KERNEL); if (!input) return -ENOMEM; input[len] = '\0'; pos = strim(input); if (strlen(pos) + 1 > NSLABEL_NAME_LEN) { rc = -EINVAL; goto out; } alt_name = kzalloc(NSLABEL_NAME_LEN, GFP_KERNEL); if (!alt_name) { rc = -ENOMEM; goto out; } kfree(*ns_altname); *ns_altname = alt_name; sprintf(*ns_altname, "%s", pos); rc = len; out: kfree(input); return rc; }
static ssize_t alt_name_show(struct device *dev, struct device_attribute *attr, char *buf) { char *ns_altname; if (is_namespace_pmem(dev)) { struct nd_namespace_pmem *nspm = to_nd_namespace_pmem(dev); ns_altname = nspm->alt_name; } else if (is_namespace_blk(dev)) { struct nd_namespace_blk *nsblk = to_nd_namespace_blk(dev); ns_altname = nsblk->alt_name; } else return -ENXIO; return sprintf(buf, "%s\n", ns_altname ? ns_altname : ""); }
const u8 *nd_dev_to_uuid(struct device *dev) { static const u8 null_uuid[16]; if (!dev) return null_uuid; if (is_namespace_pmem(dev)) { struct nd_namespace_pmem *nspm = to_nd_namespace_pmem(dev); return nspm->uuid; } else if (is_namespace_blk(dev)) { struct nd_namespace_blk *nsblk = to_nd_namespace_blk(dev); return nsblk->uuid; } else return null_uuid; }
const char *nvdimm_namespace_disk_name(struct nd_namespace_common *ndns, char *name) { struct nd_region *nd_region = to_nd_region(ndns->dev.parent); const char *suffix = ""; if (ndns->claim && is_nd_btt(ndns->claim)) suffix = "s"; if (is_namespace_pmem(&ndns->dev) || is_namespace_io(&ndns->dev)) sprintf(name, "pmem%d%s", nd_region->id, suffix); else if (is_namespace_blk(&ndns->dev)) { struct nd_namespace_blk *nsblk; nsblk = to_nd_namespace_blk(&ndns->dev); sprintf(name, "ndblk%d.%d%s", nd_region->id, nsblk->id, suffix); } else { return NULL; } return name; }