Re: read only access on 1 LUN for multiple initiators

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Mar 1, 2010 at 10:26 AM, Tomasz Chmielewski <tch@xxxxxxxx> wrote:
...
> Not sure if tgtd allows a target to be truly read only?

It does not.

>
> So that when the kernel detects a drive, it reports:
>
> sd 1:0:0:0: [sdx] Write Protect is on



Please see attached hack for discussion.
It is not tested but should/might work.


While it probably needs a bit of work, this might be one approach to
add a global read-only attribute for a LUN.
Use update an existing lun and use --params readonly=1 to activate.

Or should a readonly attribute be set initiator by initiator as part
of the ACL instead?


regards
ronnie sahlberg
diff --git a/usr/sbc.c b/usr/sbc.c
index a048d53..be8a0e1 100644
--- a/usr/sbc.c
+++ b/usr/sbc.c
@@ -77,11 +77,29 @@ static int sbc_rw(int host_no, struct scsi_cmd *cmd)
 	int ret;
 	unsigned char key = ILLEGAL_REQUEST;
 	uint16_t asc = ASC_LUN_NOT_SUPPORTED;
+	struct scsi_lu *lu = cmd->dev;
 
 	ret = device_reserved(cmd);
 	if (ret)
 		return SAM_STAT_RESERVATION_CONFLICT;
 
+	if (lu->attrs.readonly) {
+		switch (cmd->scb[0]) {
+		case WRITE_6:
+		case WRITE_10:
+		case WRITE_VERIFY:
+		case SYNCHRONIZE_CACHE:
+		case WRITE_12:
+		case WRITE_VERIFY_12:
+		case WRITE_16:
+		case WRITE_VERIFY_16:
+		case SYNCHRONIZE_CACHE_16:
+			key = DATA_PROTECT;
+			asc = ASC_WRITE_PROTECT;
+			goto check_condition;
+			break;
+		}
+	}
 	cmd->scsi_cmd_done = target_cmd_io_done;
 
 	cmd->offset = (scsi_rw_offset(cmd->scb) << BLK_SHIFT);
@@ -94,6 +112,7 @@ static int sbc_rw(int host_no, struct scsi_cmd *cmd)
 		return SAM_STAT_GOOD;
 	}
 
+check_condition:
 	cmd->offset = 0;
 	scsi_set_in_resid_by_actual(cmd, 0);
 	scsi_set_out_resid_by_actual(cmd, 0);
diff --git a/usr/spc.c b/usr/spc.c
index 14a3ee1..00d5189 100644
--- a/usr/spc.c
+++ b/usr/spc.c
@@ -455,6 +455,22 @@ int set_mode_page_changeable_mask(struct scsi_lu *lu, uint8_t pcode,
 	return 1;
 }
 
+static int set_mode_page_control_readonly(struct scsi_lu *lu, uint8_t readonly)
+{
+	struct mode_pg *pg = lu->mode_pgs[0x0a];
+
+	if (pg) {
+		if (readonly) {
+		   	pg->mode_data[2] |= 0x08;
+		} else {
+		   	pg->mode_data[2] &= 0xf7;
+		}
+
+		return 0;
+	}
+	return 1;
+}
+
 /**
  * build_mode_page - static routine used by spc_mode_sense()
  * @data:	destination pointer
@@ -482,7 +498,7 @@ static int build_mode_page(uint8_t *data, struct mode_pg *pg,
 	p = &data[2];
 	len += 2;
 	if (*alloc_len >= pg->pcode_size) {
-		if (pc == 1)
+		if (pc == 1) 
 			mode_data = pg->mode_data + pg->pcode_size;
 		else
 			mode_data = pg->mode_data;
@@ -1578,7 +1594,7 @@ enum {
 	Opt_scsi_id, Opt_scsi_sn,
 	Opt_vendor_id, Opt_product_id,
 	Opt_product_rev, Opt_sense_format,
-	Opt_removable, Opt_online,
+	Opt_removable, Opt_readonly, Opt_online,
 	Opt_mode_page,
 	Opt_path,
 	Opt_err,
@@ -1592,6 +1608,7 @@ static match_table_t tokens = {
 	{Opt_product_rev, "product_rev=%s"},
 	{Opt_sense_format, "sense_format=%s"},
 	{Opt_removable, "removable=%s"},
+	{Opt_readonly, "readonly=%s"},
 	{Opt_online, "online=%s"},
 	{Opt_mode_page, "mode_page=%s"},
 	{Opt_path, "path=%s"},
@@ -1661,6 +1678,11 @@ int lu_config(struct scsi_lu *lu, char *params, match_fn_t *fn)
 			match_strncpy(buf, &args[0], sizeof(buf));
 			attrs->removable = atoi(buf);
 			break;
+		case Opt_readonly:
+			match_strncpy(buf, &args[0], sizeof(buf));
+			attrs->readonly = atoi(buf);
+			set_mode_page_control_readonly(lu, attrs->readonly);
+			break;
 		case Opt_online:
 			match_strncpy(buf, &args[0], sizeof(buf));
 			if (atoi(buf))
@@ -1719,6 +1741,7 @@ int spc_lu_init(struct scsi_lu *lu)
 	lu_vpd[pg]->vpd_update(lu, lu->attrs.scsi_id);
 
 	lu->attrs.removable = 0;
+	lu->attrs.readonly = 0;
 	lu->attrs.sense_format = 0;
 	lu->dev_type_template.lu_offline(lu);
 
diff --git a/usr/tgtd.h b/usr/tgtd.h
index 3323a9b..1e87a64 100644
--- a/usr/tgtd.h
+++ b/usr/tgtd.h
@@ -63,6 +63,7 @@ struct lu_phy_attr {
 	char device_type;	/* Peripheral device type */
 	char qualifier;		/* Peripheral Qualifier */
 	char removable;		/* Removable media */
+	char readonly;		/* Read-Only media */
 	char online;		/* Logical Unit online */
 	char sense_format;	/* Descrptor format sense data supported */
 

[Index of Archives]     [Linux SCSI]     [Linux RAID]     [Linux Clusters]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]

  Powered by Linux