in namespace_devs.c [949:1045]
static ssize_t __size_store(struct device *dev, unsigned long long val)
{
resource_size_t allocated = 0, available = 0;
struct nd_region *nd_region = to_nd_region(dev->parent);
struct nd_namespace_common *ndns = to_ndns(dev);
struct nd_mapping *nd_mapping;
struct nvdimm_drvdata *ndd;
struct nd_label_id label_id;
u32 flags = 0, remainder;
int rc, i, id = -1;
uuid_t *uuid = NULL;
if (dev->driver || ndns->claim)
return -EBUSY;
if (is_namespace_pmem(dev)) {
struct nd_namespace_pmem *nspm = to_nd_namespace_pmem(dev);
uuid = nspm->uuid;
id = nspm->id;
} else if (is_namespace_blk(dev)) {
struct nd_namespace_blk *nsblk = to_nd_namespace_blk(dev);
uuid = nsblk->uuid;
flags = NSLABEL_FLAG_LOCAL;
id = nsblk->id;
}
/*
* We need a uuid for the allocation-label and dimm(s) on which
* to store the label.
*/
if (uuid_not_set(uuid, dev, __func__))
return -ENXIO;
if (nd_region->ndr_mappings == 0) {
dev_dbg(dev, "not associated with dimm(s)\n");
return -ENXIO;
}
div_u64_rem(val, nd_region->align, &remainder);
if (remainder) {
dev_dbg(dev, "%llu is not %ldK aligned\n", val,
nd_region->align / SZ_1K);
return -EINVAL;
}
nd_label_gen_id(&label_id, uuid, flags);
for (i = 0; i < nd_region->ndr_mappings; i++) {
nd_mapping = &nd_region->mapping[i];
ndd = to_ndd(nd_mapping);
/*
* All dimms in an interleave set, or the base dimm for a blk
* region, need to be enabled for the size to be changed.
*/
if (!ndd)
return -ENXIO;
allocated += nvdimm_allocated_dpa(ndd, &label_id);
}
available = nd_region_allocatable_dpa(nd_region);
if (val > available + allocated)
return -ENOSPC;
if (val == allocated)
return 0;
val = div_u64(val, nd_region->ndr_mappings);
allocated = div_u64(allocated, nd_region->ndr_mappings);
if (val < allocated)
rc = shrink_dpa_allocation(nd_region, &label_id,
allocated - val);
else
rc = grow_dpa_allocation(nd_region, &label_id, val - allocated);
if (rc)
return rc;
if (is_namespace_pmem(dev)) {
struct nd_namespace_pmem *nspm = to_nd_namespace_pmem(dev);
nd_namespace_pmem_set_resource(nd_region, nspm,
val * nd_region->ndr_mappings);
}
/*
* Try to delete the namespace if we deleted all of its
* allocation, this is not the seed or 0th device for the
* region, and it is not actively claimed by a btt, pfn, or dax
* instance.
*/
if (val == 0 && id != 0 && nd_region->ns_seed != dev && !ndns->claim)
nd_device_unregister(dev, ND_ASYNC);
return rc;
}