scsi: target: iblock: Allow iblock devices to be shared

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>
This commit is contained in:
Mike Christie 2025-07-21 13:51:45 -05:00 committed by Martin K. Petersen
parent 35dabf4503
commit 7ffbf335e3
2 changed files with 29 additions and 5 deletions

View 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"); pr_err("Unable to allocate struct iblock_dev\n");
return NULL; return NULL;
} }
ib_dev->ibd_exclusive = true;
ib_dev->ibd_plug = kcalloc(nr_cpu_ids, sizeof(*ib_dev->ibd_plug), ib_dev->ibd_plug = kcalloc(nr_cpu_ids, sizeof(*ib_dev->ibd_plug),
GFP_KERNEL); GFP_KERNEL);
@ -95,6 +96,7 @@ static int iblock_configure_device(struct se_device *dev)
struct block_device *bd; struct block_device *bd;
struct blk_integrity *bi; struct blk_integrity *bi;
blk_mode_t mode = BLK_OPEN_READ; blk_mode_t mode = BLK_OPEN_READ;
void *holder = ib_dev;
unsigned int max_write_zeroes_sectors; unsigned int max_write_zeroes_sectors;
int ret; int ret;
@ -109,15 +111,18 @@ static int iblock_configure_device(struct se_device *dev)
goto out; goto out;
} }
pr_debug( "IBLOCK: Claiming struct block_device: %s\n", pr_debug("IBLOCK: Claiming struct block_device: %s: %d\n",
ib_dev->ibd_udev_path); ib_dev->ibd_udev_path, ib_dev->ibd_exclusive);
if (!ib_dev->ibd_readonly) if (!ib_dev->ibd_readonly)
mode |= BLK_OPEN_WRITE; mode |= BLK_OPEN_WRITE;
else else
dev->dev_flags |= DF_READ_ONLY; 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); NULL);
if (IS_ERR(bdev_file)) { if (IS_ERR(bdev_file)) {
ret = PTR_ERR(bdev_file); ret = PTR_ERR(bdev_file);
@ -560,13 +565,14 @@ iblock_execute_write_same(struct se_cmd *cmd)
} }
enum { 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 = { static match_table_t tokens = {
{Opt_udev_path, "udev_path=%s"}, {Opt_udev_path, "udev_path=%s"},
{Opt_readonly, "readonly=%d"}, {Opt_readonly, "readonly=%d"},
{Opt_force, "force=%d"}, {Opt_force, "force=%d"},
{Opt_exclusive, "exclusive=%d"},
{Opt_err, NULL} {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); struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
char *orig, *ptr, *arg_p, *opts; char *orig, *ptr, *arg_p, *opts;
substring_t args[MAX_OPT_ARGS]; substring_t args[MAX_OPT_ARGS];
int ret = 0, token; int ret = 0, token, tmp_exclusive;
unsigned long tmp_readonly; unsigned long tmp_readonly;
opts = kstrdup(page, GFP_KERNEL); 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; ib_dev->ibd_readonly = tmp_readonly;
pr_debug("IBLOCK: readonly: %d\n", ib_dev->ibd_readonly); pr_debug("IBLOCK: readonly: %d\n", ib_dev->ibd_readonly);
break; 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: case Opt_force:
break; break;
default: 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", bl += sprintf(b + bl, " UDEV PATH: %s",
ib_dev->ibd_udev_path); ib_dev->ibd_udev_path);
bl += sprintf(b + bl, " readonly: %d\n", ib_dev->ibd_readonly); 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, " "); bl += sprintf(b + bl, " ");
if (bd) { if (bd) {

View File

@ -34,6 +34,7 @@ struct iblock_dev {
struct block_device *ibd_bd; struct block_device *ibd_bd;
struct file *ibd_bdev_file; struct file *ibd_bdev_file;
bool ibd_readonly; bool ibd_readonly;
bool ibd_exclusive;
struct iblock_dev_plug *ibd_plug; struct iblock_dev_plug *ibd_plug;
} ____cacheline_aligned; } ____cacheline_aligned;