]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
s390/dcssblk: Add DAX support
authorGerald Schaefer <gerald.schaefer@linux.ibm.com>
Tue, 9 Sep 2025 13:46:26 +0000 (15:46 +0200)
committerAlexander Gordeev <agordeev@linux.ibm.com>
Tue, 16 Sep 2025 14:56:39 +0000 (16:56 +0200)
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>
drivers/s390/block/Kconfig
drivers/s390/block/dcssblk.c

index 8c1c908d2c6e72239a48969990937aa5c344be27..877a9bc7f04b935aef4d6b57eed26eb139be7337 100644 (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"
index 94fa5edecaddf8dfd88df711078eb92ea92d367a..86fef4b15015d16e26d6de335bc6cb88f2e6eda2 100644 (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);