diff options
Diffstat (limited to 'drivers/nvdimm')
-rw-r--r-- | drivers/nvdimm/blk.c | 2 | ||||
-rw-r--r-- | drivers/nvdimm/btt.c | 10 | ||||
-rw-r--r-- | drivers/nvdimm/bus.c | 18 | ||||
-rw-r--r-- | drivers/nvdimm/nd.h | 3 | ||||
-rw-r--r-- | drivers/nvdimm/pmem.c | 2 | ||||
-rw-r--r-- | drivers/nvdimm/region_devs.c | 29 |
6 files changed, 61 insertions, 3 deletions
diff --git a/drivers/nvdimm/blk.c b/drivers/nvdimm/blk.c index 96ef38ceeceb..4f97b248c236 100644 --- a/drivers/nvdimm/blk.c +++ b/drivers/nvdimm/blk.c @@ -232,6 +232,7 @@ static int nd_blk_rw_bytes(struct nd_namespace_common *ndns, static const struct block_device_operations nd_blk_fops = { .owner = THIS_MODULE, + .revalidate_disk = nvdimm_revalidate_disk, }; static int nd_blk_attach_disk(struct nd_namespace_common *ndns, @@ -283,6 +284,7 @@ static int nd_blk_attach_disk(struct nd_namespace_common *ndns, } set_capacity(disk, available_disk_size >> SECTOR_SHIFT); + revalidate_disk(disk); return 0; } diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c index c02065aed03d..411c7b2bb37a 100644 --- a/drivers/nvdimm/btt.c +++ b/drivers/nvdimm/btt.c @@ -1245,6 +1245,7 @@ static const struct block_device_operations btt_fops = { .owner = THIS_MODULE, .rw_page = btt_rw_page, .getgeo = btt_getgeo, + .revalidate_disk = nvdimm_revalidate_disk, }; static int btt_blk_init(struct btt *btt) @@ -1292,6 +1293,7 @@ static int btt_blk_init(struct btt *btt) } } set_capacity(btt->btt_disk, btt->nlba * btt->sector_size >> 9); + revalidate_disk(btt->btt_disk); return 0; } @@ -1346,7 +1348,11 @@ static struct btt *btt_init(struct nd_btt *nd_btt, unsigned long long rawsize, goto out_free; } - if (btt->init_state != INIT_READY) { + if (btt->init_state != INIT_READY && nd_region->ro) { + dev_info(dev, "%s is read-only, unable to init btt metadata\n", + dev_name(&nd_region->dev)); + goto out_free; + } else if (btt->init_state != INIT_READY) { btt->num_arenas = (rawsize / ARENA_MAX_SIZE) + ((rawsize % ARENA_MAX_SIZE) ? 1 : 0); dev_dbg(dev, "init: %d arenas for %llu rawsize\n", @@ -1361,7 +1367,7 @@ static struct btt *btt_init(struct nd_btt *nd_btt, unsigned long long rawsize, ret = btt_meta_init(btt); if (ret) { dev_err(dev, "init: error in meta_init: %d\n", ret); - return NULL; + goto out_free; } } diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index dd12f38397db..ec59f1f26d95 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c @@ -227,6 +227,24 @@ int __nd_driver_register(struct nd_device_driver *nd_drv, struct module *owner, } EXPORT_SYMBOL(__nd_driver_register); +int nvdimm_revalidate_disk(struct gendisk *disk) +{ + struct device *dev = disk->driverfs_dev; + struct nd_region *nd_region = to_nd_region(dev->parent); + const char *pol = nd_region->ro ? "only" : "write"; + + if (nd_region->ro == get_disk_ro(disk)) + return 0; + + dev_info(dev, "%s read-%s, marking %s read-%s\n", + dev_name(&nd_region->dev), pol, disk->disk_name, pol); + set_disk_ro(disk, nd_region->ro); + + return 0; + +} +EXPORT_SYMBOL(nvdimm_revalidate_disk); + static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h index 4614b00542d1..48b09a210689 100644 --- a/drivers/nvdimm/nd.h +++ b/drivers/nvdimm/nd.h @@ -97,7 +97,7 @@ struct nd_region { u16 ndr_mappings; u64 ndr_size; u64 ndr_start; - int id, num_lanes; + int id, num_lanes, ro; void *provider_data; struct nd_interleave_set *nd_set; struct nd_percpu_lane __percpu *lane; @@ -189,6 +189,7 @@ u64 nd_region_interleave_set_cookie(struct nd_region *nd_region); void nvdimm_bus_lock(struct device *dev); void nvdimm_bus_unlock(struct device *dev); bool is_nvdimm_bus_locked(struct device *dev); +int nvdimm_revalidate_disk(struct gendisk *disk); void nvdimm_drvdata_release(struct kref *kref); void put_ndd(struct nvdimm_drvdata *ndd); int nd_label_reserve_dpa(struct nvdimm_drvdata *ndd); diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index a9709db0704c..42b766f33e59 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -104,6 +104,7 @@ static const struct block_device_operations pmem_fops = { .owner = THIS_MODULE, .rw_page = pmem_rw_page, .direct_access = pmem_direct_access, + .revalidate_disk = nvdimm_revalidate_disk, }; static struct pmem_device *pmem_alloc(struct device *dev, @@ -178,6 +179,7 @@ static int pmem_attach_disk(struct nd_namespace_common *ndns, pmem->pmem_disk = disk; add_disk(disk); + revalidate_disk(disk); return 0; } diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c index 2cfb3f74bcbf..482ee3e4e04a 100644 --- a/drivers/nvdimm/region_devs.c +++ b/drivers/nvdimm/region_devs.c @@ -345,11 +345,35 @@ static ssize_t btt_seed_show(struct device *dev, } static DEVICE_ATTR_RO(btt_seed); +static ssize_t read_only_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct nd_region *nd_region = to_nd_region(dev); + + return sprintf(buf, "%d\n", nd_region->ro); +} + +static ssize_t read_only_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + bool ro; + int rc = strtobool(buf, &ro); + struct nd_region *nd_region = to_nd_region(dev); + + if (rc) + return rc; + + nd_region->ro = ro; + return len; +} +static DEVICE_ATTR_RW(read_only); + static struct attribute *nd_region_attributes[] = { &dev_attr_size.attr, &dev_attr_nstype.attr, &dev_attr_mappings.attr, &dev_attr_btt_seed.attr, + &dev_attr_read_only.attr, &dev_attr_set_cookie.attr, &dev_attr_available_size.attr, &dev_attr_namespace_seed.attr, @@ -641,6 +665,7 @@ static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus, struct device *dev; void *region_buf; unsigned int i; + int ro = 0; for (i = 0; i < ndr_desc->num_mappings; i++) { struct nd_mapping *nd_mapping = &ndr_desc->nd_mapping[i]; @@ -652,6 +677,9 @@ static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus, return NULL; } + + if (nvdimm->flags & NDD_UNARMED) + ro = 1; } if (dev_type == &nd_blk_device_type) { @@ -707,6 +735,7 @@ static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus, nd_region->provider_data = ndr_desc->provider_data; nd_region->nd_set = ndr_desc->nd_set; nd_region->num_lanes = ndr_desc->num_lanes; + nd_region->ro = ro; ida_init(&nd_region->ns_ida); ida_init(&nd_region->btt_ida); dev = &nd_region->dev; |