static void nd_detach_and_reset(struct device *dev, struct nd_namespace_common **_ndns) { /* detach the namespace and destroy / reset the device */ nd_detach_ndns(dev, _ndns); if (is_idle(dev, *_ndns)) { nd_device_unregister(dev, ND_ASYNC); } else if (is_nd_btt(dev)) { struct nd_btt *nd_btt = to_nd_btt(dev); nd_btt->lbasize = 0; kfree(nd_btt->uuid); nd_btt->uuid = NULL; } else if (is_nd_pfn(dev) || is_nd_dax(dev)) { struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev); kfree(nd_pfn->uuid); nd_pfn->uuid = NULL; nd_pfn->mode = PFN_MODE_NONE; } }
static ssize_t __namespace_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct nd_btt *nd_btt = to_nd_btt(dev); struct nd_namespace_common *ndns; struct device *found; char *name; if (dev->driver) { dev_dbg(dev, "%s: -EBUSY\n", __func__); return -EBUSY; } name = kstrndup(buf, len, GFP_KERNEL); if (!name) return -ENOMEM; strim(name); if (strncmp(name, "namespace", 9) == 0 || strcmp(name, "") == 0) /* pass */; else { len = -EINVAL; goto out; } ndns = nd_btt->ndns; if (strcmp(name, "") == 0) { /* detach the namespace and destroy / reset the btt device */ nd_btt_detach_ndns(nd_btt); if (is_nd_btt_idle(dev)) nd_device_unregister(dev, ND_ASYNC); else { nd_btt->lbasize = 0; kfree(nd_btt->uuid); nd_btt->uuid = NULL; } goto out; } else if (ndns) { dev_dbg(dev, "namespace already set to: %s\n", dev_name(&ndns->dev)); len = -EBUSY; goto out; } found = device_find_child(dev->parent, name, namespace_match); if (!found) { dev_dbg(dev, "'%s' not found under %s\n", name, dev_name(dev->parent)); len = -ENODEV; goto out; } ndns = to_ndns(found); if (__nvdimm_namespace_capacity(ndns) < SZ_16M) { dev_dbg(dev, "%s too small to host btt\n", name); len = -ENXIO; goto out_attach; } WARN_ON_ONCE(!is_nvdimm_bus_locked(&nd_btt->dev)); if (!nd_btt_attach_ndns(nd_btt, ndns)) { dev_dbg(dev, "%s already claimed\n", dev_name(&ndns->dev)); len = -EBUSY; } out_attach: put_device(&ndns->dev); /* from device_find_child */ out: kfree(name); return len; }
static int child_unregister(struct device *dev, void *data) { nd_device_unregister(dev, ND_SYNC); return 0; }