]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
scsi: target: iblock: Allow iblock devices to be shared
authorMike Christie <michael.christie@oracle.com>
Mon, 21 Jul 2025 18:51:45 +0000 (13:51 -0500)
committerMartin K. Petersen <martin.petersen@oracle.com>
Fri, 25 Jul 2025 01:39:01 +0000 (21:39 -0400)
We might be running a local application that also interacts with the
backing device. In this setup we have some clustering type of software
that manages the ownwer of it, so we don't want the kernel to restrict
us. This patch allows the user to control if the driver gets exclusive
access.

Signed-off-by: Mike Christie <michael.christie@oracle.com>
Link: https://lore.kernel.org/r/20250721185145.20913-1-michael.christie@oracle.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/target/target_core_iblock.c
drivers/target/target_core_iblock.h

index 73564efd11d299f37859213bf4df10144fcfa3d2..66c292b7d74bc65bebde76ea6d935561123942e8 100644 (file)
@@ -64,6 +64,7 @@ static struct se_device *iblock_alloc_device(struct se_hba *hba, const char *nam
                pr_err("Unable to allocate struct iblock_dev\n");
                return NULL;
        }
+       ib_dev->ibd_exclusive = true;
 
        ib_dev->ibd_plug = kcalloc(nr_cpu_ids, sizeof(*ib_dev->ibd_plug),
                                   GFP_KERNEL);
@@ -95,6 +96,7 @@ static int iblock_configure_device(struct se_device *dev)
        struct block_device *bd;
        struct blk_integrity *bi;
        blk_mode_t mode = BLK_OPEN_READ;
+       void *holder = ib_dev;
        unsigned int max_write_zeroes_sectors;
        int ret;
 
@@ -109,15 +111,18 @@ static int iblock_configure_device(struct se_device *dev)
                goto out;
        }
 
-       pr_debug( "IBLOCK: Claiming struct block_device: %s\n",
-                       ib_dev->ibd_udev_path);
+       pr_debug("IBLOCK: Claiming struct block_device: %s: %d\n",
+                ib_dev->ibd_udev_path, ib_dev->ibd_exclusive);
 
        if (!ib_dev->ibd_readonly)
                mode |= BLK_OPEN_WRITE;
        else
                dev->dev_flags |= DF_READ_ONLY;
 
-       bdev_file = bdev_file_open_by_path(ib_dev->ibd_udev_path, mode, ib_dev,
+       if (!ib_dev->ibd_exclusive)
+               holder = NULL;
+
+       bdev_file = bdev_file_open_by_path(ib_dev->ibd_udev_path, mode, holder,
                                        NULL);
        if (IS_ERR(bdev_file)) {
                ret = PTR_ERR(bdev_file);
@@ -560,13 +565,14 @@ fail:
 }
 
 enum {
-       Opt_udev_path, Opt_readonly, Opt_force, Opt_err
+       Opt_udev_path, Opt_readonly, Opt_force, Opt_exclusive, Opt_err,
 };
 
 static match_table_t tokens = {
        {Opt_udev_path, "udev_path=%s"},
        {Opt_readonly, "readonly=%d"},
        {Opt_force, "force=%d"},
+       {Opt_exclusive, "exclusive=%d"},
        {Opt_err, NULL}
 };
 
@@ -576,7 +582,7 @@ static ssize_t iblock_set_configfs_dev_params(struct se_device *dev,
        struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
        char *orig, *ptr, *arg_p, *opts;
        substring_t args[MAX_OPT_ARGS];
-       int ret = 0, token;
+       int ret = 0, token, tmp_exclusive;
        unsigned long tmp_readonly;
 
        opts = kstrdup(page, GFP_KERNEL);
@@ -623,6 +629,22 @@ static ssize_t iblock_set_configfs_dev_params(struct se_device *dev,
                        ib_dev->ibd_readonly = tmp_readonly;
                        pr_debug("IBLOCK: readonly: %d\n", ib_dev->ibd_readonly);
                        break;
+               case Opt_exclusive:
+                       arg_p = match_strdup(&args[0]);
+                       if (!arg_p) {
+                               ret = -ENOMEM;
+                               break;
+                       }
+                       ret = kstrtoint(arg_p, 0, &tmp_exclusive);
+                       kfree(arg_p);
+                       if (ret < 0) {
+                               pr_err("kstrtoul() failed for exclusive=\n");
+                               goto out;
+                       }
+                       ib_dev->ibd_exclusive = tmp_exclusive;
+                       pr_debug("IBLOCK: exclusive: %d\n",
+                                ib_dev->ibd_exclusive);
+                       break;
                case Opt_force:
                        break;
                default:
@@ -647,6 +669,7 @@ static ssize_t iblock_show_configfs_dev_params(struct se_device *dev, char *b)
                bl += sprintf(b + bl, "  UDEV PATH: %s",
                                ib_dev->ibd_udev_path);
        bl += sprintf(b + bl, "  readonly: %d\n", ib_dev->ibd_readonly);
+       bl += sprintf(b + bl, "  exclusive: %d\n", ib_dev->ibd_exclusive);
 
        bl += sprintf(b + bl, "        ");
        if (bd) {
index 91f6f4280666cb08d694d458bb53fb96c8719eae..e2f28a69a11c2afc1f62fc9b70804bbc8c26c2a6 100644 (file)
@@ -34,6 +34,7 @@ struct iblock_dev {
        struct block_device *ibd_bd;
        struct file *ibd_bdev_file;
        bool ibd_readonly;
+       bool ibd_exclusive;
        struct iblock_dev_plug *ibd_plug;
 } ____cacheline_aligned;