I have also added a utility iscsi-swp to libiscsi that can be used to manage the SWP flag of an iSCSI LUN. ./bin/iscsi-swp iscsi://127.0.0.1/iqn.ronnie.test/1 --swp on On Sat, Jul 6, 2013 at 11:13 PM, Ronnie Sahlberg <ronniesahlberg@xxxxxxxxx> wrote: > Fix a bug in sbc_mode_page_update. We only have a subpagecode in byte 1 > IFF the SPF bit in byte 0 is set. > > Add support for using modeselect for the CONTROLS page and set the > mask to allow SWP to be changed. > > Add a SWP flag to the device attributes and update this as the CONTROLS/SWP > flag is set by the initiator. > > Update SBC so that we treat writeprotect as either the current ->readonly flag > that is used to se the hard property for the lun, or the ->swp flag > that is set in software by the initiators. > Thus like on a real disk, SWP can be used to turn a read-write LUN to become > temporarily readonly, but SWP can NOT be used to turn a physically readonly > medium to become read-write. > > Signed-off-by: Ronnie Sahlberg <ronniesahlberg@xxxxxxxxx> > --- > usr/sbc.c | 37 +++++++++++++++++++++++++++++++------ > usr/spc.c | 1 + > usr/target.c | 2 ++ > usr/tgtd.h | 1 + > 4 files changed, 35 insertions(+), 6 deletions(-) > > diff --git a/usr/sbc.c b/usr/sbc.c > index 1f50191..c4f012c 100644 > --- a/usr/sbc.c > +++ b/usr/sbc.c > @@ -69,17 +69,21 @@ static off_t find_next_hole(struct scsi_lu *dev, off_t offset) > static int sbc_mode_page_update(struct scsi_cmd *cmd, uint8_t *data, int *changed) > { > uint8_t pcode = data[0] & 0x3f; > - uint8_t subpcode = data[1]; > + uint8_t subpcode = 0; > struct mode_pg *pg; > uint8_t old; > > + if (data[0] & 0x40) > + subpcode = data[1]; > + > pg = find_mode_page(cmd->dev, pcode, subpcode); > if (pg == NULL) > return 1; > > eprintf("%x %x\n", pg->mode_data[0], data[2]); > > - if (pcode == 0x08) { > + switch (pcode) { > + case 0x08: /* Cachning mode page */ > old = pg->mode_data[0]; > if (0x4 & data[2]) > pg->mode_data[0] |= 0x4; > @@ -90,6 +94,19 @@ static int sbc_mode_page_update(struct scsi_cmd *cmd, uint8_t *data, int *change > *changed = 1; > > return 0; > + case 0x0a: /* Control mode page */ > + old = pg->mode_data[2]; > + if (0x8 & data[4]) > + pg->mode_data[2] |= 0x8; > + else > + pg->mode_data[2] &= ~0x8; > + > + if (old != pg->mode_data[2]) > + *changed = 1; > + > + cmd->dev->attrs.swp = (0x8 & data[4]) ? 1 : 0; > + > + return 0; > } > > return 1; > @@ -110,7 +127,8 @@ static int sbc_mode_sense(int host_no, struct scsi_cmd *cmd) > * If this is a read-only lun, we must modify the data and set the > * write protect bit > */ > - if (cmd->dev->attrs.readonly && ret == SAM_STAT_GOOD) { > + if ((cmd->dev->attrs.readonly || cmd->dev->attrs.swp) > + && ret == SAM_STAT_GOOD) { > uint8_t *data, mode6; > > mode6 = (cmd->scb[0] == 0x1a); > @@ -141,7 +159,7 @@ static int sbc_format_unit(int host_no, struct scsi_cmd *cmd) > goto sense; > } > > - if (cmd->dev->attrs.readonly) { > + if (cmd->dev->attrs.readonly || cmd->dev->attrs.swp) { > key = DATA_PROTECT; > asc = ASC_WRITE_PROTECT; > goto sense; > @@ -199,7 +217,7 @@ static int sbc_unmap(int host_no, struct scsi_cmd *cmd) > goto sense; > } > > - if (lu->attrs.readonly) { > + if (lu->attrs.readonly || cmd->dev->attrs.swp) { > key = DATA_PROTECT; > asc = ASC_WRITE_PROTECT; > goto sense; > @@ -290,7 +308,7 @@ static int sbc_rw(int host_no, struct scsi_cmd *cmd) > break; > } > > - if (lu->attrs.readonly) { > + if (lu->attrs.readonly || cmd->dev->attrs.swp) { > switch (cmd->scb[0]) { > case WRITE_6: > case WRITE_10: > @@ -736,6 +754,13 @@ static tgtadm_err sbc_lu_init(struct scsi_lu *lu) > > /* Control page */ > add_mode_page(lu, "0x0a:0:10:2:0x10:0:0:0:0:0:0:2:0"); > + { > + uint8_t mask[10]; > + memset(mask, 0, sizeof(mask)); > + mask[2] = 0x08; /* allow changing SWP */ > + > + set_mode_page_changeable_mask(lu, 0x0a, 0, mask); > + } > > /* Control Extensions mode page: TCMOS:1 */ > add_mode_page(lu, "0x0a:1:0x1c:0x04:0x00:0x00"); > diff --git a/usr/spc.c b/usr/spc.c > index 0cbba95..15077ca 100644 > --- a/usr/spc.c > +++ b/usr/spc.c > @@ -2028,6 +2028,7 @@ int spc_lu_init(struct scsi_lu *lu) > lu->attrs.thinprovisioning = 0; > lu->attrs.removable = 0; > lu->attrs.readonly = 0; > + lu->attrs.swp = 0; > lu->attrs.sense_format = 0; > > snprintf(lu->attrs.vendor_id, sizeof(lu->attrs.vendor_id), > diff --git a/usr/target.c b/usr/target.c > index 9a8f2fd..fd087ad 100644 > --- a/usr/target.c > +++ b/usr/target.c > @@ -2023,6 +2023,7 @@ tgtadm_err tgt_target_show_all(struct concat_buf *b) > _TAB3 "Removable media: %s\n" > _TAB3 "Prevent removal: %s\n" > _TAB3 "Readonly: %s\n" > + _TAB3 "SWP: %s\n" > _TAB3 "Thin-provisioning: %s\n" > _TAB3 "Backing store type: %s\n" > _TAB3 "Backing store path: %s\n" > @@ -2037,6 +2038,7 @@ tgtadm_err tgt_target_show_all(struct concat_buf *b) > lu->attrs.removable ? "Yes" : "No", > lu_prevent_removal(lu) ? "Yes" : "No", > lu->attrs.readonly ? "Yes" : "No", > + lu->attrs.swp ? "Yes" : "No", > lu->attrs.thinprovisioning ? "Yes" : "No", > lu->bst ? > (lu->bst->bs_name ? : "Unknown") : > diff --git a/usr/tgtd.h b/usr/tgtd.h > index f3d9674..484e6e9 100644 > --- a/usr/tgtd.h > +++ b/usr/tgtd.h > @@ -74,6 +74,7 @@ struct lu_phy_attr { > char qualifier; /* Peripheral Qualifier */ > char removable; /* Removable media */ > char readonly; /* Read-Only media */ > + char swp; /* Software Write Protect */ > char thinprovisioning; /* Use thin-provisioning for this LUN */ > char online; /* Logical Unit online */ > char sense_format; /* Descrptor format sense data supported */ > -- > 1.7.3.1 > -- To unsubscribe from this list: send the line "unsubscribe stgt" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html