target/iblock: Add parameter to specify read-only devices
authorAndy Grover <agrover@redhat.com>
Thu, 7 Jun 2012 17:38:51 +0000 (10:38 -0700)
committerNicholas Bellinger <nab@linux-iscsi.org>
Tue, 17 Jul 2012 00:29:11 +0000 (17:29 -0700)
see https://bugzilla.redhat.com/show_bug.cgi?id=818855

Adds a parameter so read-only block devices may be registered as
LIO backstores.

Signed-off-by: Andy Grover <agrover@redhat.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
drivers/target/target_core_iblock.c
drivers/target/target_core_iblock.h

index 244fff4aaf5a18d85572e05bceba9d00c7aa4a97..c2d4ccbb7133bf09b8e68c13d5c68fdb6ffd78b0 100644 (file)
@@ -96,6 +96,7 @@ static struct se_device *iblock_create_virtdevice(
        struct request_queue *q;
        struct queue_limits *limits;
        u32 dev_flags = 0;
+       fmode_t mode;
        int ret = -EINVAL;
 
        if (!ib_dev) {
@@ -117,8 +118,11 @@ static struct se_device *iblock_create_virtdevice(
        pr_debug( "IBLOCK: Claiming struct block_device: %s\n",
                        ib_dev->ibd_udev_path);
 
-       bd = blkdev_get_by_path(ib_dev->ibd_udev_path,
-                               FMODE_WRITE|FMODE_READ|FMODE_EXCL, ib_dev);
+       mode = FMODE_READ|FMODE_EXCL;
+       if (!ib_dev->ibd_readonly)
+               mode |= FMODE_WRITE;
+
+       bd = blkdev_get_by_path(ib_dev->ibd_udev_path, mode, ib_dev);
        if (IS_ERR(bd)) {
                ret = PTR_ERR(bd);
                goto failed;
@@ -323,11 +327,12 @@ static int iblock_do_discard(struct se_device *dev, sector_t lba, u32 range)
 }
 
 enum {
-       Opt_udev_path, Opt_force, Opt_err
+       Opt_udev_path, Opt_readonly, Opt_force, Opt_err
 };
 
 static match_table_t tokens = {
        {Opt_udev_path, "udev_path=%s"},
+       {Opt_readonly, "readonly=%d"},
        {Opt_force, "force=%d"},
        {Opt_err, NULL}
 };
@@ -340,6 +345,7 @@ static ssize_t iblock_set_configfs_dev_params(struct se_hba *hba,
        char *orig, *ptr, *arg_p, *opts;
        substring_t args[MAX_OPT_ARGS];
        int ret = 0, token;
+       unsigned long tmp_readonly;
 
        opts = kstrdup(page, GFP_KERNEL);
        if (!opts)
@@ -372,6 +378,22 @@ static ssize_t iblock_set_configfs_dev_params(struct se_hba *hba,
                                        ib_dev->ibd_udev_path);
                        ib_dev->ibd_flags |= IBDF_HAS_UDEV_PATH;
                        break;
+               case Opt_readonly:
+                       arg_p = match_strdup(&args[0]);
+                       if (!arg_p) {
+                               ret = -ENOMEM;
+                               break;
+                       }
+                       ret = strict_strtoul(arg_p, 0, &tmp_readonly);
+                       kfree(arg_p);
+                       if (ret < 0) {
+                               pr_err("strict_strtoul() failed for"
+                                               " readonly=\n");
+                               goto out;
+                       }
+                       ib_dev->ibd_readonly = tmp_readonly;
+                       pr_debug("IBLOCK: readonly: %d\n", ib_dev->ibd_readonly);
+                       break;
                case Opt_force:
                        break;
                default:
@@ -411,11 +433,10 @@ static ssize_t iblock_show_configfs_dev_params(
        if (bd)
                bl += sprintf(b + bl, "iBlock device: %s",
                                bdevname(bd, buf));
-       if (ibd->ibd_flags & IBDF_HAS_UDEV_PATH) {
-               bl += sprintf(b + bl, "  UDEV PATH: %s\n",
+       if (ibd->ibd_flags & IBDF_HAS_UDEV_PATH)
+               bl += sprintf(b + bl, "  UDEV PATH: %s",
                                ibd->ibd_udev_path);
-       } else
-               bl += sprintf(b + bl, "\n");
+       bl += sprintf(b + bl, "  readonly: %d\n", ibd->ibd_readonly);
 
        bl += sprintf(b + bl, "        ");
        if (bd) {
index 66cf7b9e205edbf799ff77d963bd841f8d87972c..533627ae79ec8b1d49d4d2288e08e645d562a725 100644 (file)
@@ -18,6 +18,7 @@ struct iblock_dev {
        u32     ibd_flags;
        struct bio_set  *ibd_bio_set;
        struct block_device *ibd_bd;
+       bool ibd_readonly;
 } ____cacheline_aligned;
 
 #endif /* TARGET_CORE_IBLOCK_H */