diff mbox series

[3/6] scsi: target: core: dynamic opcode support in RSOC

Message ID 20220718120117.4435-4-d.bogdanov@yadro.com (mailing list archive)
State Changes Requested
Headers show
Series add support of RSOC command | expand

Commit Message

Dmitry Bogdanov July 18, 2022, 12:01 p.m. UTC
Report supported opcodes depending on a dynamic device configuration

Reviewed-by: Roman Bolshakov <r.bolshakov@yadro.com>
Signed-off-by: Dmitry Bogdanov <d.bogdanov@yadro.com>
---
 drivers/target/target_core_spc.c  | 118 ++++++++++++++++++++++++++++--
 include/target/target_core_base.h |   1 +
 2 files changed, 114 insertions(+), 5 deletions(-)

Comments

kernel test robot July 19, 2022, 12:40 p.m. UTC | #1
Hi Dmitry,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on mkp-scsi/for-next]
[also build test WARNING on jejb-scsi/for-next linus/master v5.19-rc7 next-20220719]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Dmitry-Bogdanov/add-support-of-RSOC-command/20220718-200622
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git for-next
config: nios2-randconfig-s042-20220718 (https://download.01.org/0day-ci/archive/20220719/202207192030.yfVYkp2d-lkp@intel.com/config)
compiler: nios2-linux-gcc (GCC) 12.1.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # apt-get install sparse
        # sparse version: v0.6.4-39-gce1a6720-dirty
        # https://github.com/intel-lab-lkp/linux/commit/5aa6c10f37c99c3321ff7675ffbb6fea99219263
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Dmitry-Bogdanov/add-support-of-RSOC-command/20220718-200622
        git checkout 5aa6c10f37c99c3321ff7675ffbb6fea99219263
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=nios2 SHELL=/bin/bash drivers/target/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)
>> drivers/target/target_core_spc.c:1927:20: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected struct t10_alua_tg_pt_gp *l_tg_pt_gp @@     got struct t10_alua_tg_pt_gp [noderef] __rcu *lun_tg_pt_gp @@
   drivers/target/target_core_spc.c:1927:20: sparse:     expected struct t10_alua_tg_pt_gp *l_tg_pt_gp
   drivers/target/target_core_spc.c:1927:20: sparse:     got struct t10_alua_tg_pt_gp [noderef] __rcu *lun_tg_pt_gp
   drivers/target/target_core_spc.c:2159:21: sparse: sparse: incorrect type in assignment (different base types) @@     expected int ret @@     got restricted sense_reason_t @@
   drivers/target/target_core_spc.c:2159:21: sparse:     expected int ret
   drivers/target/target_core_spc.c:2159:21: sparse:     got restricted sense_reason_t
   drivers/target/target_core_spc.c:2166:21: sparse: sparse: incorrect type in assignment (different base types) @@     expected int ret @@     got restricted sense_reason_t @@
   drivers/target/target_core_spc.c:2166:21: sparse:     expected int ret
   drivers/target/target_core_spc.c:2166:21: sparse:     got restricted sense_reason_t
   drivers/target/target_core_spc.c:2178:21: sparse: sparse: incorrect type in assignment (different base types) @@     expected int ret @@     got restricted sense_reason_t @@
   drivers/target/target_core_spc.c:2178:21: sparse:     expected int ret
   drivers/target/target_core_spc.c:2178:21: sparse:     got restricted sense_reason_t
   drivers/target/target_core_spc.c:2207:16: sparse: sparse: incorrect type in return expression (different base types) @@     expected restricted sense_reason_t @@     got int ret @@
   drivers/target/target_core_spc.c:2207:16: sparse:     expected restricted sense_reason_t
   drivers/target/target_core_spc.c:2207:16: sparse:     got int ret

vim +1927 drivers/target/target_core_spc.c

  1920	
  1921	static bool tcm_is_set_tpg_enabled(struct se_cmd *cmd)
  1922	{
  1923		struct t10_alua_tg_pt_gp *l_tg_pt_gp;
  1924		struct se_lun *l_lun = cmd->se_lun;
  1925	
  1926		spin_lock(&l_lun->lun_tg_pt_gp_lock);
> 1927		l_tg_pt_gp = l_lun->lun_tg_pt_gp;
  1928		if (!l_tg_pt_gp) {
  1929			spin_unlock(&l_lun->lun_tg_pt_gp_lock);
  1930			return false;
  1931		}
  1932		if (!(l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA)) {
  1933			spin_unlock(&l_lun->lun_tg_pt_gp_lock);
  1934			return false;
  1935		}
  1936		spin_unlock(&l_lun->lun_tg_pt_gp_lock);
  1937	
  1938		return true;
  1939	}
  1940
Mike Christie Aug. 12, 2022, 3:43 a.m. UTC | #2
On 7/18/22 7:01 AM, Dmitry Bogdanov wrote:
> Report supported opcodes depending on a dynamic device configuration
> 
> Reviewed-by: Roman Bolshakov <r.bolshakov@yadro.com>
> Signed-off-by: Dmitry Bogdanov <d.bogdanov@yadro.com>
> ---
>  drivers/target/target_core_spc.c  | 118 ++++++++++++++++++++++++++++--
>  include/target/target_core_base.h |   1 +
>  2 files changed, 114 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
> index 506e28b14e5a..cf516136b933 100644
> --- a/drivers/target/target_core_spc.c
> +++ b/drivers/target/target_core_spc.c
> @@ -1424,6 +1424,13 @@ static struct target_opcode_descriptor tcm_opcode_xdwriteread32 = {
>  		       0xff, 0xff, 0xff, 0xff},
>  };
>  
> +static bool tcm_is_ws_enabled(struct se_cmd *cmd)
> +{
> +	struct se_device *dev = cmd->se_dev;
> +
> +	return dev->dev_attrib.emulate_tpws;
> +}
> +
>  static struct target_opcode_descriptor tcm_opcode_write_same32 = {
>  	.support = SCSI_SUPPORT_FULL,
>  	.serv_action_valid = 1,
> @@ -1438,8 +1445,16 @@ static struct target_opcode_descriptor tcm_opcode_write_same32 = {
>  		       0x00, 0x00, 0x00, 0x00,
>  		       0x00, 0x00, 0x00, 0x00,
>  		       0xff, 0xff, 0xff, 0xff},
> +	.enabled = tcm_is_ws_enabled,
>  };

I'm not sure what's incorrect. I think your patch is correct but the write
same code is wrong.

If emulate_tpws is 0, we will still execute the command. We actually only fail
with TCM_UNSUPPORTED_SCSI_OPCODE if it's a WRITE_SAME with the UNMAP bit = 1
and emulate_tpws=0.

If it's just a normal WRITE_SAME we maybe go by if by max_write_same_len is
greater than zero? Maybe that was a mistake and sbc_setup_write_same needs
a emulate_tpws check.



>  static struct target_opcode_descriptor tcm_opcode_sync_cache = {
> @@ -1502,6 +1533,14 @@ static struct target_opcode_descriptor tcm_opcode_sync_cache16 = {
>  		       0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
>  };
>  
> +static bool tcm_is_unmap_enabled(struct se_cmd *cmd)
> +{
> +	struct sbc_ops *ops = cmd->protocol_data;
> +	struct se_device *dev = cmd->se_dev;
> +
> +	return ops->execute_unmap  && dev->dev_attrib.emulate_tpu;
> +}

Just a trivial nit. You had an extra space there.
Dmitry Bogdanov Aug. 12, 2022, 11:30 a.m. UTC | #3
On Thu, Aug 11, 2022 at 10:43:05PM -0500, Mike Christie wrote:
> «Внимание! Данное письмо от внешнего адресата!»
> 
> On 7/18/22 7:01 AM, Dmitry Bogdanov wrote:
> > Report supported opcodes depending on a dynamic device configuration
> >
> > Reviewed-by: Roman Bolshakov <r.bolshakov@yadro.com>
> > Signed-off-by: Dmitry Bogdanov <d.bogdanov@yadro.com>
> > ---
> >  drivers/target/target_core_spc.c  | 118 ++++++++++++++++++++++++++++--
> >  include/target/target_core_base.h |   1 +
> >  2 files changed, 114 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
> > index 506e28b14e5a..cf516136b933 100644
> > --- a/drivers/target/target_core_spc.c
> > +++ b/drivers/target/target_core_spc.c
> > @@ -1424,6 +1424,13 @@ static struct target_opcode_descriptor tcm_opcode_xdwriteread32 = {
> >                      0xff, 0xff, 0xff, 0xff},
> >  };
> >
> > +static bool tcm_is_ws_enabled(struct se_cmd *cmd)
> > +{
> > +     struct se_device *dev = cmd->se_dev;
> > +
> > +     return dev->dev_attrib.emulate_tpws;
> > +}
> > +
> >  static struct target_opcode_descriptor tcm_opcode_write_same32 = {
> >       .support = SCSI_SUPPORT_FULL,
> >       .serv_action_valid = 1,
> > @@ -1438,8 +1445,16 @@ static struct target_opcode_descriptor tcm_opcode_write_same32 = {
> >                      0x00, 0x00, 0x00, 0x00,
> >                      0x00, 0x00, 0x00, 0x00,
> >                      0xff, 0xff, 0xff, 0xff},
> > +     .enabled = tcm_is_ws_enabled,
> >  };
> 
> I'm not sure what's incorrect. I think your patch is correct but the write
> same code is wrong.
> 
> If emulate_tpws is 0, we will still execute the command. We actually only fail
> with TCM_UNSUPPORTED_SCSI_OPCODE if it's a WRITE_SAME with the UNMAP bit = 1
> and emulate_tpws=0.
> 
> If it's just a normal WRITE_SAME we maybe go by if by max_write_same_len is
> greater than zero? Maybe that was a mistake and sbc_setup_write_same needs
> a emulate_tpws check.
Looks like emulate_tpws was introduced exaclty for WS+UNMAP bit case
and it can not be used in tcm_is_ws_enabled as only check. Because of
WS is actually two different commands selected by UNMAP bit it is
unable somehow to differentiate them in RSOC. So I will reformulate
the check in tcm_is_ws_enabled to be true if some of cases is
supported by the backstore device.
+	return (dev->dev_attrib.emulate_tpws && !!ops->execute_unmap) ||
+	       !!ops->execute_write_same;

> 
> >  static struct target_opcode_descriptor tcm_opcode_sync_cache = {
> > @@ -1502,6 +1533,14 @@ static struct target_opcode_descriptor tcm_opcode_sync_cache16 = {
> >                      0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
> >  };
> >
> > +static bool tcm_is_unmap_enabled(struct se_cmd *cmd)
> > +{
> > +     struct sbc_ops *ops = cmd->protocol_data;
> > +     struct se_device *dev = cmd->se_dev;
> > +
> > +     return ops->execute_unmap  && dev->dev_attrib.emulate_tpu;
> > +}
> 
> Just a trivial nit. You had an extra space there.
yep, will fix
diff mbox series

Patch

diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
index 506e28b14e5a..cf516136b933 100644
--- a/drivers/target/target_core_spc.c
+++ b/drivers/target/target_core_spc.c
@@ -1424,6 +1424,13 @@  static struct target_opcode_descriptor tcm_opcode_xdwriteread32 = {
 		       0xff, 0xff, 0xff, 0xff},
 };
 
+static bool tcm_is_ws_enabled(struct se_cmd *cmd)
+{
+	struct se_device *dev = cmd->se_dev;
+
+	return dev->dev_attrib.emulate_tpws;
+}
+
 static struct target_opcode_descriptor tcm_opcode_write_same32 = {
 	.support = SCSI_SUPPORT_FULL,
 	.serv_action_valid = 1,
@@ -1438,8 +1445,16 @@  static struct target_opcode_descriptor tcm_opcode_write_same32 = {
 		       0x00, 0x00, 0x00, 0x00,
 		       0x00, 0x00, 0x00, 0x00,
 		       0xff, 0xff, 0xff, 0xff},
+	.enabled = tcm_is_ws_enabled,
 };
 
+static bool tcm_is_caw_enabled(struct se_cmd *cmd)
+{
+	struct se_device *dev = cmd->se_dev;
+
+	return dev->dev_attrib.emulate_caw;
+}
+
 static struct target_opcode_descriptor tcm_opcode_compare_write = {
 	.support = SCSI_SUPPORT_FULL,
 	.opcode = COMPARE_AND_WRITE,
@@ -1448,6 +1463,7 @@  static struct target_opcode_descriptor tcm_opcode_compare_write = {
 		       0xff, 0xff, 0xff, 0xff,
 		       0xff, 0xff, 0x00, 0x00,
 		       0x00, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
+	.enabled = tcm_is_caw_enabled,
 };
 
 static struct target_opcode_descriptor tcm_opcode_read_capacity = {
@@ -1471,6 +1487,20 @@  static struct target_opcode_descriptor tcm_opcode_read_capacity16 = {
 		       0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
 };
 
+static bool tcm_is_rep_ref_enabled(struct se_cmd *cmd)
+{
+	struct se_device *dev = cmd->se_dev;
+
+	spin_lock(&dev->t10_alua.lba_map_lock);
+	if (list_empty(&dev->t10_alua.lba_map_list)) {
+		spin_unlock(&dev->t10_alua.lba_map_lock);
+		return false;
+	}
+	spin_unlock(&dev->t10_alua.lba_map_lock);
+	return true;
+
+}
+
 static struct target_opcode_descriptor tcm_opcode_read_report_refferals = {
 	.support = SCSI_SUPPORT_FULL,
 	.serv_action_valid = 1,
@@ -1481,6 +1511,7 @@  static struct target_opcode_descriptor tcm_opcode_read_report_refferals = {
 		       0x00, 0x00, 0x00, 0x00,
 		       0x00, 0x00, 0xff, 0xff,
 		       0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
+	.enabled = tcm_is_rep_ref_enabled,
 };
 
 static struct target_opcode_descriptor tcm_opcode_sync_cache = {
@@ -1502,6 +1533,14 @@  static struct target_opcode_descriptor tcm_opcode_sync_cache16 = {
 		       0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
 };
 
+static bool tcm_is_unmap_enabled(struct se_cmd *cmd)
+{
+	struct sbc_ops *ops = cmd->protocol_data;
+	struct se_device *dev = cmd->se_dev;
+
+	return ops->execute_unmap  && dev->dev_attrib.emulate_tpu;
+}
+
 static struct target_opcode_descriptor tcm_opcode_unmap = {
 	.support = SCSI_SUPPORT_FULL,
 	.opcode = UNMAP,
@@ -1509,6 +1548,7 @@  static struct target_opcode_descriptor tcm_opcode_unmap = {
 	.usage_bits = {UNMAP, 0x00, 0x00, 0x00,
 		       0x00, 0x00, SCSI_GROUP_NUMBER_MASK, 0xff,
 		       0xff, SCSI_CONTROL_MASK},
+	.enabled = tcm_is_unmap_enabled,
 };
 
 static struct target_opcode_descriptor tcm_opcode_write_same = {
@@ -1518,6 +1558,7 @@  static struct target_opcode_descriptor tcm_opcode_write_same = {
 	.usage_bits = {WRITE_SAME, 0xe8, 0xff, 0xff,
 		       0xff, 0xff, SCSI_GROUP_NUMBER_MASK, 0xff,
 		       0xff, SCSI_CONTROL_MASK},
+	.enabled = tcm_is_ws_enabled,
 };
 
 static struct target_opcode_descriptor tcm_opcode_write_same16 = {
@@ -1528,6 +1569,7 @@  static struct target_opcode_descriptor tcm_opcode_write_same16 = {
 		       0xff, 0xff, 0xff, 0xff,
 		       0xff, 0xff, 0xff, 0xff,
 		       0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK},
+	.enabled = tcm_is_ws_enabled,
 };
 
 static struct target_opcode_descriptor tcm_opcode_verify = {
@@ -1613,6 +1655,13 @@  static struct target_opcode_descriptor tcm_opcode_pri_read_resrv = {
 		       0xff, SCSI_CONTROL_MASK},
 };
 
+static bool tcm_is_pr_enabled(struct se_cmd *cmd)
+{
+	struct se_device *dev = cmd->se_dev;
+
+	return dev->dev_attrib.emulate_pr;
+}
+
 static struct target_opcode_descriptor tcm_opcode_pri_read_caps = {
 	.support = SCSI_SUPPORT_FULL,
 	.serv_action_valid = 1,
@@ -1622,6 +1671,7 @@  static struct target_opcode_descriptor tcm_opcode_pri_read_caps = {
 	.usage_bits = {PERSISTENT_RESERVE_IN, PRI_REPORT_CAPABILITIES, 0x00, 0x00,
 		       0x00, 0x00, 0x00, 0xff,
 		       0xff, SCSI_CONTROL_MASK},
+	.enabled = tcm_is_pr_enabled,
 };
 
 static struct target_opcode_descriptor tcm_opcode_pri_read_full_status = {
@@ -1633,6 +1683,7 @@  static struct target_opcode_descriptor tcm_opcode_pri_read_full_status = {
 	.usage_bits = {PERSISTENT_RESERVE_IN, PRI_READ_FULL_STATUS, 0x00, 0x00,
 		       0x00, 0x00, 0x00, 0xff,
 		       0xff, SCSI_CONTROL_MASK},
+	.enabled = tcm_is_pr_enabled,
 };
 
 static struct target_opcode_descriptor tcm_opcode_pro_register = {
@@ -1644,6 +1695,7 @@  static struct target_opcode_descriptor tcm_opcode_pro_register = {
 	.usage_bits = {PERSISTENT_RESERVE_OUT, PRO_REGISTER, 0xff, 0x00,
 		       0x00, 0xff, 0xff, 0xff,
 		       0xff, SCSI_CONTROL_MASK},
+	.enabled = tcm_is_pr_enabled,
 };
 
 static struct target_opcode_descriptor tcm_opcode_pro_reserve = {
@@ -1655,6 +1707,7 @@  static struct target_opcode_descriptor tcm_opcode_pro_reserve = {
 	.usage_bits = {PERSISTENT_RESERVE_OUT, PRO_RESERVE, 0xff, 0x00,
 		       0x00, 0xff, 0xff, 0xff,
 		       0xff, SCSI_CONTROL_MASK},
+	.enabled = tcm_is_pr_enabled,
 };
 
 static struct target_opcode_descriptor tcm_opcode_pro_release = {
@@ -1666,6 +1719,7 @@  static struct target_opcode_descriptor tcm_opcode_pro_release = {
 	.usage_bits = {PERSISTENT_RESERVE_OUT, PRO_RELEASE, 0xff, 0x00,
 		       0x00, 0xff, 0xff, 0xff,
 		       0xff, SCSI_CONTROL_MASK},
+	.enabled = tcm_is_pr_enabled,
 };
 
 static struct target_opcode_descriptor tcm_opcode_pro_clear = {
@@ -1677,6 +1731,7 @@  static struct target_opcode_descriptor tcm_opcode_pro_clear = {
 	.usage_bits = {PERSISTENT_RESERVE_OUT, PRO_CLEAR, 0xff, 0x00,
 		       0x00, 0xff, 0xff, 0xff,
 		       0xff, SCSI_CONTROL_MASK},
+	.enabled = tcm_is_pr_enabled,
 };
 
 static struct target_opcode_descriptor tcm_opcode_pro_preempt = {
@@ -1688,6 +1743,7 @@  static struct target_opcode_descriptor tcm_opcode_pro_preempt = {
 	.usage_bits = {PERSISTENT_RESERVE_OUT, PRO_PREEMPT, 0xff, 0x00,
 		       0x00, 0xff, 0xff, 0xff,
 		       0xff, SCSI_CONTROL_MASK},
+	.enabled = tcm_is_pr_enabled,
 };
 
 static struct target_opcode_descriptor tcm_opcode_pro_preempt_abort = {
@@ -1699,6 +1755,7 @@  static struct target_opcode_descriptor tcm_opcode_pro_preempt_abort = {
 	.usage_bits = {PERSISTENT_RESERVE_OUT, PRO_PREEMPT_AND_ABORT, 0xff, 0x00,
 		       0x00, 0xff, 0xff, 0xff,
 		       0xff, SCSI_CONTROL_MASK},
+	.enabled = tcm_is_pr_enabled,
 };
 
 static struct target_opcode_descriptor tcm_opcode_pro_reg_ign_exist = {
@@ -1712,6 +1769,7 @@  static struct target_opcode_descriptor tcm_opcode_pro_reg_ign_exist = {
 		0xff, 0x00,
 		0x00, 0xff, 0xff, 0xff,
 		0xff, SCSI_CONTROL_MASK},
+	.enabled = tcm_is_pr_enabled,
 };
 
 static struct target_opcode_descriptor tcm_opcode_pro_register_move = {
@@ -1723,14 +1781,23 @@  static struct target_opcode_descriptor tcm_opcode_pro_register_move = {
 	.usage_bits = {PERSISTENT_RESERVE_OUT, PRO_REGISTER_AND_MOVE, 0xff, 0x00,
 		       0x00, 0xff, 0xff, 0xff,
 		       0xff, SCSI_CONTROL_MASK},
+	.enabled = tcm_is_pr_enabled,
 };
 
+static bool tcm_is_scsi2_reservations_enabled(struct se_cmd *cmd)
+{
+	struct se_device *dev = cmd->se_dev;
+
+	return dev->dev_attrib.emulate_pr;
+}
+
 static struct target_opcode_descriptor tcm_opcode_release = {
 	.support = SCSI_SUPPORT_FULL,
 	.opcode = RELEASE,
 	.cdb_size = 6,
 	.usage_bits = {RELEASE, 0x00, 0x00, 0x00,
 		       0x00, SCSI_CONTROL_MASK},
+	.enabled = tcm_is_scsi2_reservations_enabled,
 };
 
 static struct target_opcode_descriptor tcm_opcode_release10 = {
@@ -1740,6 +1807,7 @@  static struct target_opcode_descriptor tcm_opcode_release10 = {
 	.usage_bits = {RELEASE_10, 0x00, 0x00, 0x00,
 		       0x00, 0x00, 0x00, 0xff,
 		       0xff, SCSI_CONTROL_MASK},
+	.enabled = tcm_is_scsi2_reservations_enabled,
 };
 
 static struct target_opcode_descriptor tcm_opcode_reserve = {
@@ -1748,6 +1816,7 @@  static struct target_opcode_descriptor tcm_opcode_reserve = {
 	.cdb_size = 6,
 	.usage_bits = {RESERVE, 0x00, 0x00, 0x00,
 		       0x00, SCSI_CONTROL_MASK},
+	.enabled = tcm_is_scsi2_reservations_enabled,
 };
 
 static struct target_opcode_descriptor tcm_opcode_reserve10 = {
@@ -1757,6 +1826,7 @@  static struct target_opcode_descriptor tcm_opcode_reserve10 = {
 	.usage_bits = {RESERVE_10, 0x00, 0x00, 0x00,
 		       0x00, 0x00, 0x00, 0xff,
 		       0xff, SCSI_CONTROL_MASK},
+	.enabled = tcm_is_scsi2_reservations_enabled,
 };
 
 static struct target_opcode_descriptor tcm_opcode_request_sense = {
@@ -1775,6 +1845,13 @@  static struct target_opcode_descriptor tcm_opcode_inquiry = {
 		       0xff, SCSI_CONTROL_MASK},
 };
 
+static bool tcm_is_3pc_enabled(struct se_cmd *cmd)
+{
+	struct se_device *dev = cmd->se_dev;
+
+	return dev->dev_attrib.emulate_3pc;
+}
+
 static struct target_opcode_descriptor tcm_opcode_extended_copy_lid1 = {
 	.support = SCSI_SUPPORT_FULL,
 	.serv_action_valid = 1,
@@ -1784,6 +1861,7 @@  static struct target_opcode_descriptor tcm_opcode_extended_copy_lid1 = {
 		       0x00, 0x00, 0x00, 0x00,
 		       0x00, 0x00, 0xff, 0xff,
 		       0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
+	.enabled = tcm_is_3pc_enabled,
 };
 
 static struct target_opcode_descriptor tcm_opcode_rcv_copy_res_op_params = {
@@ -1797,6 +1875,7 @@  static struct target_opcode_descriptor tcm_opcode_rcv_copy_res_op_params = {
 		       0x00, 0x00, 0x00, 0x00,
 		       0x00, 0x00, 0xff, 0xff,
 		       0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
+	.enabled = tcm_is_3pc_enabled,
 };
 
 static struct target_opcode_descriptor tcm_opcode_report_luns = {
@@ -1839,6 +1918,26 @@  static struct target_opcode_descriptor tcm_opcode_report_supp_opcodes = {
 		       0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
 };
 
+static bool tcm_is_set_tpg_enabled(struct se_cmd *cmd)
+{
+	struct t10_alua_tg_pt_gp *l_tg_pt_gp;
+	struct se_lun *l_lun = cmd->se_lun;
+
+	spin_lock(&l_lun->lun_tg_pt_gp_lock);
+	l_tg_pt_gp = l_lun->lun_tg_pt_gp;
+	if (!l_tg_pt_gp) {
+		spin_unlock(&l_lun->lun_tg_pt_gp_lock);
+		return false;
+	}
+	if (!(l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA)) {
+		spin_unlock(&l_lun->lun_tg_pt_gp_lock);
+		return false;
+	}
+	spin_unlock(&l_lun->lun_tg_pt_gp_lock);
+
+	return true;
+}
+
 static struct target_opcode_descriptor tcm_opcode_set_tpg = {
 	.support = SCSI_SUPPORT_FULL,
 	.serv_action_valid = 1,
@@ -1848,6 +1947,7 @@  static struct target_opcode_descriptor tcm_opcode_set_tpg = {
 	.usage_bits = {MAINTENANCE_OUT, MO_SET_TARGET_PGS, 0x00, 0x00,
 		       0x00, 0x00, 0xff, 0xff,
 		       0xff, 0xff, 0x00, SCSI_CONTROL_MASK},
+	.enabled = tcm_is_set_tpg_enabled,
 };
 
 static struct target_opcode_descriptor *tcm_supported_opcodes[] = {
@@ -2003,7 +2103,9 @@  spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode)
 			 */
 			if (descr->serv_action_valid)
 				return TCM_INVALID_CDB_FIELD;
-			*opcode = descr;
+
+			if (!descr->enabled || descr->enabled(cmd))
+				*opcode = descr;
 			break;
 		case 0x2:
 			/*
@@ -2015,9 +2117,10 @@  spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode)
 			 * and the additional sense code set to INVALID FIELD IN CDB.
 			 */
 			if (descr->serv_action_valid &&
-			    descr->service_action == requested_sa)
-				*opcode = descr;
-			else if (!descr->serv_action_valid)
+			    descr->service_action == requested_sa) {
+				if (!descr->enabled || descr->enabled(cmd))
+					*opcode = descr;
+			} else if (!descr->serv_action_valid)
 				return TCM_INVALID_CDB_FIELD;
 			break;
 		case 0x3:
@@ -2028,10 +2131,12 @@  spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode)
 			 * be returned in the one_command parameter data format.
 			 */
 			if (descr->service_action == requested_sa)
-				*opcode = descr;
+				if (!descr->enabled || descr->enabled(cmd))
+					*opcode = descr;
 			break;
 		}
 	}
+
 	return 0;
 }
 
@@ -2080,6 +2185,9 @@  spc_emulate_report_supp_op_codes(struct se_cmd *cmd)
 
 		for (i = 0; i < ARRAY_SIZE(tcm_supported_opcodes); i++) {
 			descr = tcm_supported_opcodes[i];
+			if (descr->enabled && !descr->enabled(cmd))
+				continue;
+
 			response_length += spc_rsoc_encode_command_descriptor(
 					&buf[response_length], rctd, descr);
 		}
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index d93c65bcbc11..329f88680367 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -876,6 +876,7 @@  struct target_opcode_descriptor {
 	u8			specific_timeout;
 	u16			nominal_timeout;
 	u16			recommended_timeout;
+	bool			(*enabled)(struct se_cmd *cmd);
 	u8			usage_bits[];
 };