s390/dcssblk: Add DAX support

With ZONE_DEVICE now available for s390, struct pages can be allocated
for proper DAX support in dcssblk driver via devm_memremap_pages().

Adding struct pages for a range requires that the range is aligned to
SUBSECTION_SIZE, which is defined as 2 MB in common code. Therefore,
only enable DAX support and allocate struct pages for DCSS ranges that
are aligned to 2 MB.

Signed-off-by: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
Acked-by: Heiko Carstens <hca@linux.ibm.com>
Reviewed-by: Alexander Gordeev <agordeev@linux.ibm.com>
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
This commit is contained in:
Gerald Schaefer
2025-09-16 16:56:39 +02:00
committed by Alexander Gordeev
parent 5450abb0de
commit 5b27dfb1d7
2 changed files with 31 additions and 16 deletions
+2 -10
View File
@@ -5,19 +5,11 @@ comment "S/390 block device drivers"
config DCSSBLK
def_tristate m
prompt "DCSSBLK support"
depends on S390 && BLOCK && (DAX || DAX=n)
depends on S390 && BLOCK && ZONE_DEVICE
select FS_DAX
help
Support for dcss block device
config DCSSBLK_DAX
def_bool y
depends on DCSSBLK
# requires S390 ZONE_DEVICE support
depends on BROKEN
prompt "DCSSBLK DAX support"
help
Enable DAX operation for the dcss block device
config DASD
def_tristate y
prompt "Support for DASD devices"
+29 -6
View File
@@ -79,6 +79,8 @@ struct dcssblk_dev_info {
int num_of_segments;
struct list_head seg_list;
struct dax_device *dax_dev;
struct dev_pagemap pgmap;
void *pgmap_addr;
};
struct segment_info {
@@ -415,6 +417,8 @@ removeseg:
dax_remove_host(dev_info->gd);
kill_dax(dev_info->dax_dev);
put_dax(dev_info->dax_dev);
if (dev_info->pgmap_addr)
devm_memunmap_pages(&dev_info->dev, &dev_info->pgmap);
del_gendisk(dev_info->gd);
put_disk(dev_info->gd);
@@ -537,9 +541,6 @@ static int dcssblk_setup_dax(struct dcssblk_dev_info *dev_info)
{
struct dax_device *dax_dev;
if (!IS_ENABLED(CONFIG_DCSSBLK_DAX))
return 0;
dax_dev = alloc_dax(dev_info, &dcssblk_dax_ops);
if (IS_ERR(dax_dev))
return PTR_ERR(dax_dev);
@@ -562,6 +563,7 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
struct dcssblk_dev_info *dev_info;
struct segment_info *seg_info, *temp;
char *local_buf;
void *addr;
unsigned long seg_byte_size;
dev_info = NULL;
@@ -687,9 +689,26 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
if (rc)
goto put_dev;
rc = dcssblk_setup_dax(dev_info);
if (rc)
goto out_dax;
if (!IS_ALIGNED(dev_info->start, SUBSECTION_SIZE) ||
!IS_ALIGNED(dev_info->end + 1, SUBSECTION_SIZE)) {
pr_info("DCSS %s is not aligned to %lu bytes, DAX support disabled\n",
local_buf, SUBSECTION_SIZE);
} else {
dev_info->pgmap.type = MEMORY_DEVICE_FS_DAX;
dev_info->pgmap.range.start = dev_info->start;
dev_info->pgmap.range.end = dev_info->end;
dev_info->pgmap.nr_range = 1;
addr = devm_memremap_pages(&dev_info->dev, &dev_info->pgmap);
if (IS_ERR(addr)) {
rc = PTR_ERR(addr);
goto put_dev;
}
dev_info->pgmap_addr = addr;
rc = dcssblk_setup_dax(dev_info);
if (rc)
goto out_dax;
pr_info("DAX support enabled for DCSS %s\n", local_buf);
}
get_device(&dev_info->dev);
rc = device_add_disk(&dev_info->dev, dev_info->gd, NULL);
@@ -716,6 +735,8 @@ out_dax_host:
out_dax:
kill_dax(dev_info->dax_dev);
put_dax(dev_info->dax_dev);
if (dev_info->pgmap_addr)
devm_memunmap_pages(&dev_info->dev, &dev_info->pgmap);
put_dev:
list_del(&dev_info->lh);
put_disk(dev_info->gd);
@@ -801,6 +822,8 @@ dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const ch
dax_remove_host(dev_info->gd);
kill_dax(dev_info->dax_dev);
put_dax(dev_info->dax_dev);
if (dev_info->pgmap_addr)
devm_memunmap_pages(&dev_info->dev, &dev_info->pgmap);
del_gendisk(dev_info->gd);
put_disk(dev_info->gd);