From 0fd97ccf45be26fb01b3a412f1f6c6b5044b2f16 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 8 Oct 2012 00:03:19 -0400 Subject: target: kill struct se_subsystem_dev Simplify the code a lot by killing the superflous struct se_subsystem_dev. Instead se_device is allocated early on by the backend driver, which allocates it as part of its own per-device structure, borrowing the scheme that is for example used for inode allocation. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- include/target/target_core_backend.h | 25 ++++----- include/target/target_core_base.h | 104 +++++++++-------------------------- 2 files changed, 38 insertions(+), 91 deletions(-) (limited to 'include') diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index 2acd54018b64..6c5bfb5ac17f 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -9,6 +9,8 @@ struct se_subsystem_api { struct list_head sub_api_list; char name[16]; + char inquiry_prod[16]; + char inquiry_rev[4]; struct module *owner; u8 transport_type; @@ -16,21 +18,20 @@ struct se_subsystem_api { int (*attach_hba)(struct se_hba *, u32); void (*detach_hba)(struct se_hba *); int (*pmode_enable_hba)(struct se_hba *, unsigned long); - void *(*allocate_virtdevice)(struct se_hba *, const char *); - struct se_device *(*create_virtdevice)(struct se_hba *, - struct se_subsystem_dev *, void *); - void (*free_device)(void *); + + struct se_device *(*alloc_device)(struct se_hba *, const char *); + int (*configure_device)(struct se_device *); + void (*free_device)(struct se_device *device); + + ssize_t (*set_configfs_dev_params)(struct se_device *, + const char *, ssize_t); + ssize_t (*show_configfs_dev_params)(struct se_device *, char *); + void (*transport_complete)(struct se_cmd *cmd, struct scatterlist *, unsigned char *); int (*parse_cdb)(struct se_cmd *cmd); - ssize_t (*check_configfs_dev_params)(struct se_hba *, - struct se_subsystem_dev *); - ssize_t (*set_configfs_dev_params)(struct se_hba *, - struct se_subsystem_dev *, const char *, ssize_t); - ssize_t (*show_configfs_dev_params)(struct se_hba *, - struct se_subsystem_dev *, char *); u32 (*get_device_rev)(struct se_device *); u32 (*get_device_type)(struct se_device *); sector_t (*get_blocks)(struct se_device *); @@ -47,10 +48,6 @@ struct spc_ops { int transport_subsystem_register(struct se_subsystem_api *); void transport_subsystem_release(struct se_subsystem_api *); -struct se_device *transport_add_device_to_core_hba(struct se_hba *, - struct se_subsystem_api *, struct se_subsystem_dev *, u32, - void *, struct se_dev_limits *, const char *, const char *); - void target_complete_cmd(struct se_cmd *, u8); int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 5be89373ceac..f6355fc325a8 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -62,20 +62,6 @@ #define PYX_TRANSPORT_STATUS_INTERVAL 5 /* In seconds */ -/* - * struct se_subsystem_dev->su_dev_flags -*/ -#define SDF_FIRMWARE_VPD_UNIT_SERIAL 0x00000001 -#define SDF_EMULATED_VPD_UNIT_SERIAL 0x00000002 -#define SDF_USING_UDEV_PATH 0x00000004 -#define SDF_USING_ALIAS 0x00000008 - -/* - * struct se_device->dev_flags - */ -#define DF_SPC2_RESERVATIONS 0x00000001 -#define DF_SPC2_RESERVATIONS_WITH_ISID 0x00000002 - /* struct se_dev_attrib sanity values */ /* Default max_unmap_lba_count */ #define DA_MAX_UNMAP_LBA_COUNT 0 @@ -182,16 +168,6 @@ enum transport_lunflags_table { TRANSPORT_LUNFLAGS_READ_WRITE = 0x04, }; -/* struct se_device->dev_status */ -enum transport_device_status_table { - TRANSPORT_DEVICE_ACTIVATED = 0x01, - TRANSPORT_DEVICE_DEACTIVATED = 0x02, - TRANSPORT_DEVICE_QUEUE_FULL = 0x04, - TRANSPORT_DEVICE_SHUTDOWN = 0x08, - TRANSPORT_DEVICE_OFFLINE_ACTIVATED = 0x10, - TRANSPORT_DEVICE_OFFLINE_DEACTIVATED = 0x20, -}; - /* * Used by transport_send_check_condition_and_sense() and se_cmd->scsi_sense_reason * to signal which ASC/ASCQ sense payload should be built. @@ -246,10 +222,6 @@ enum tcm_tmrsp_table { TMR_FUNCTION_REJECTED = 255, }; -struct se_obj { - atomic_t obj_access_count; -}; - /* * Used by TCM Core internally to signal if ALUA emulation is enabled or * disabled, or running in with TCM/pSCSI passthrough mode @@ -288,7 +260,7 @@ struct t10_alua { u16 alua_tg_pt_gps_counter; u32 alua_tg_pt_gps_count; spinlock_t tg_pt_gps_lock; - struct se_subsystem_dev *t10_sub_dev; + struct se_device *t10_dev; /* Used for default ALUA Target Port Group */ struct t10_alua_tg_pt_gp *default_tg_pt_gp; /* Used for default ALUA Target Port Group ConfigFS group */ @@ -335,7 +307,7 @@ struct t10_alua_tg_pt_gp { atomic_t tg_pt_gp_ref_cnt; spinlock_t tg_pt_gp_lock; struct mutex tg_pt_gp_md_mutex; - struct se_subsystem_dev *tg_pt_gp_su_dev; + struct se_device *tg_pt_gp_dev; struct config_group tg_pt_gp_group; struct list_head tg_pt_gp_list; struct list_head tg_pt_gp_mem_list; @@ -366,7 +338,7 @@ struct t10_wwn { char revision[4]; char unit_serial[INQUIRY_VPD_SERIAL_LEN]; spinlock_t t10_vpd_lock; - struct se_subsystem_dev *t10_sub_dev; + struct se_device *t10_dev; struct config_group t10_wwn_group; struct list_head t10_vpd_list; }; @@ -662,15 +634,6 @@ struct se_dev_entry { struct list_head ua_list; }; -struct se_dev_limits { - /* Max supported HW queue depth */ - u32 hw_queue_depth; - /* Max supported virtual queue depth */ - u32 queue_depth; - /* From include/linux/blkdev.h for the other HW/SW limits. */ - struct queue_limits limits; -}; - struct se_dev_attrib { int emulate_dpo; int emulate_fua_write; @@ -696,7 +659,7 @@ struct se_dev_attrib { u32 max_unmap_block_desc_count; u32 unmap_granularity; u32 unmap_granularity_alignment; - struct se_subsystem_dev *da_sub_dev; + struct se_device *da_dev; struct config_group da_group; }; @@ -707,48 +670,24 @@ struct se_dev_stat_grps { struct config_group scsi_lu_group; }; -struct se_subsystem_dev { -/* Used for struct se_subsystem_dev-->se_dev_alias, must be less than PAGE_SIZE */ -#define SE_DEV_ALIAS_LEN 512 - unsigned char se_dev_alias[SE_DEV_ALIAS_LEN]; -/* Used for struct se_subsystem_dev->se_dev_udev_path[], must be less than PAGE_SIZE */ -#define SE_UDEV_PATH_LEN 512 - unsigned char se_dev_udev_path[SE_UDEV_PATH_LEN]; - u32 su_dev_flags; - struct se_hba *se_dev_hba; - struct se_device *se_dev_ptr; - struct se_dev_attrib se_dev_attrib; - /* T10 Asymmetric Logical Unit Assignment for Target Ports */ - struct t10_alua t10_alua; - /* T10 Inquiry and VPD WWN Information */ - struct t10_wwn t10_wwn; - /* T10 SPC-2 + SPC-3 Reservations */ - struct t10_reservation t10_pr; - spinlock_t se_dev_lock; - void *se_dev_su_ptr; - struct config_group se_dev_group; - /* For T10 Reservations */ - struct config_group se_dev_pr_group; - /* For target_core_stat.c groups */ - struct se_dev_stat_grps dev_stat_grps; -}; - struct se_device { /* RELATIVE TARGET PORT IDENTIFER Counter */ u16 dev_rpti_counter; /* Used for SAM Task Attribute ordering */ u32 dev_cur_ordered_id; u32 dev_flags; +#define DF_CONFIGURED 0x00000001 +#define DF_FIRMWARE_VPD_UNIT_SERIAL 0x00000002 +#define DF_EMULATED_VPD_UNIT_SERIAL 0x00000004 +#define DF_USING_UDEV_PATH 0x00000008 +#define DF_USING_ALIAS 0x00000010 u32 dev_port_count; - /* See transport_device_status_table */ - u32 dev_status; /* Physical device queue depth */ u32 queue_depth; /* Used for SPC-2 reservations enforce of ISIDs */ u64 dev_res_bin_isid; t10_task_attr_index_t dev_task_attr_type; /* Pointer to transport specific device structure */ - void *dev_ptr; u32 dev_index; u64 creation_time; u32 num_resets; @@ -761,13 +700,13 @@ struct se_device { atomic_t dev_ordered_id; atomic_t dev_ordered_sync; atomic_t dev_qf_count; - struct se_obj dev_obj; - struct se_obj dev_access_obj; - struct se_obj dev_export_obj; + int export_count; spinlock_t delayed_cmd_lock; spinlock_t execute_task_lock; spinlock_t dev_reservation_lock; - spinlock_t dev_status_lock; + unsigned int dev_reservation_flags; +#define DRF_SPC2_RESERVATIONS 0x00000001 +#define DRF_SPC2_RESERVATIONS_WITH_ISID 0x00000002 spinlock_t se_port_lock; spinlock_t se_tmr_lock; spinlock_t qf_cmd_lock; @@ -786,7 +725,20 @@ struct se_device { struct list_head qf_cmd_list; /* Pointer to associated SE HBA */ struct se_hba *se_hba; - struct se_subsystem_dev *se_sub_dev; + /* T10 Inquiry and VPD WWN Information */ + struct t10_wwn t10_wwn; + /* T10 Asymmetric Logical Unit Assignment for Target Ports */ + struct t10_alua t10_alua; + /* T10 SPC-2 + SPC-3 Reservations */ + struct t10_reservation t10_pr; + struct se_dev_attrib dev_attrib; + struct config_group dev_group; + struct config_group dev_pr_group; + struct se_dev_stat_grps dev_stat_grps; +#define SE_DEV_ALIAS_LEN 512 /* must be less than PAGE_SIZE */ + unsigned char dev_alias[SE_DEV_ALIAS_LEN]; +#define SE_UDEV_PATH_LEN 512 /* must be less than PAGE_SIZE */ + unsigned char udev_path[SE_UDEV_PATH_LEN]; /* Pointer to template of function pointers for transport */ struct se_subsystem_api *transport; /* Linked list for struct se_hba struct se_device list */ @@ -803,8 +755,6 @@ struct se_hba { u32 hba_index; /* Pointer to transport specific host structure. */ void *hba_ptr; - /* Linked list for struct se_device */ - struct list_head hba_dev_list; struct list_head hba_node; spinlock_t device_lock; struct config_group hba_group; -- cgit v1.2.3 From 9e999a6c51fe74a41a76038c64ce038ff9243bfb Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 7 Oct 2012 10:55:50 -0400 Subject: target: rename spc_ops These really are sbc_ops, so name them correctly. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_file.c | 4 ++-- drivers/target/target_core_iblock.c | 4 ++-- drivers/target/target_core_rd.c | 4 ++-- drivers/target/target_core_sbc.c | 2 +- include/target/target_core_backend.h | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index a89d80dacad2..571d3645f58a 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -528,14 +528,14 @@ static sector_t fd_get_blocks(struct se_device *dev) return div_u64(dev_size, dev->dev_attrib.block_size); } -static struct spc_ops fd_spc_ops = { +static struct sbc_ops fd_sbc_ops = { .execute_rw = fd_execute_rw, .execute_sync_cache = fd_execute_sync_cache, }; static int fd_parse_cdb(struct se_cmd *cmd) { - return sbc_parse_cdb(cmd, &fd_spc_ops); + return sbc_parse_cdb(cmd, &fd_sbc_ops); } static struct se_subsystem_api fileio_template = { diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index dd6cd92cd9d8..969eed8bff52 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -709,7 +709,7 @@ static void iblock_bio_done(struct bio *bio, int err) iblock_complete_cmd(cmd); } -static struct spc_ops iblock_spc_ops = { +static struct sbc_ops iblock_sbc_ops = { .execute_rw = iblock_execute_rw, .execute_sync_cache = iblock_execute_sync_cache, .execute_write_same = iblock_execute_write_same, @@ -718,7 +718,7 @@ static struct spc_ops iblock_spc_ops = { static int iblock_parse_cdb(struct se_cmd *cmd) { - return sbc_parse_cdb(cmd, &iblock_spc_ops); + return sbc_parse_cdb(cmd, &iblock_sbc_ops); } static struct se_subsystem_api iblock_template = { diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c index d083f39c4b67..1b36e67b1153 100644 --- a/drivers/target/target_core_rd.c +++ b/drivers/target/target_core_rd.c @@ -437,13 +437,13 @@ static sector_t rd_get_blocks(struct se_device *dev) return blocks_long; } -static struct spc_ops rd_spc_ops = { +static struct sbc_ops rd_sbc_ops = { .execute_rw = rd_execute_rw, }; static int rd_parse_cdb(struct se_cmd *cmd) { - return sbc_parse_cdb(cmd, &rd_spc_ops); + return sbc_parse_cdb(cmd, &rd_sbc_ops); } static struct se_subsystem_api rd_mcp_template = { diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 035193d04fa2..a77a19c8d923 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -313,7 +313,7 @@ out: kfree(buf); } -int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops) +int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) { struct se_device *dev = cmd->se_dev; unsigned char *cdb = cmd->t_task_cdb; diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index 6c5bfb5ac17f..1c43955f4cb5 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -38,7 +38,7 @@ struct se_subsystem_api { unsigned char *(*get_sense_buffer)(struct se_cmd *); }; -struct spc_ops { +struct sbc_ops { int (*execute_rw)(struct se_cmd *cmd); int (*execute_sync_cache)(struct se_cmd *cmd); int (*execute_write_same)(struct se_cmd *cmd); @@ -50,7 +50,7 @@ void transport_subsystem_release(struct se_subsystem_api *); void target_complete_cmd(struct se_cmd *, u8); -int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops); +int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops); int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size); int spc_get_write_same_sectors(struct se_cmd *cmd); -- cgit v1.2.3 From 8de530a523fd3cc46b5d8d96f3016298c5c808ac Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 7 Oct 2012 10:55:52 -0400 Subject: target/pscsi: call spc_emulate_report_luns directly No need to indirect through spc_parse_cdb if we only ever call it for REPORT LUNS emulation. (nab: Add missing EXPORT_SYMBOL for spc_emulate_report_luns) Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pscsi.c | 11 ++--------- drivers/target/target_core_spc.c | 3 ++- include/target/target_core_backend.h | 1 + 3 files changed, 5 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index b2965084eb4f..dc10e29934d7 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -985,8 +985,6 @@ static inline void pscsi_clear_cdb_lun(unsigned char *cdb) static int pscsi_parse_cdb(struct se_cmd *cmd) { unsigned char *cdb = cmd->t_task_cdb; - unsigned int dummy_size; - int ret; if (cmd->se_cmd_flags & SCF_BIDI) { cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; @@ -1003,10 +1001,7 @@ static int pscsi_parse_cdb(struct se_cmd *cmd) */ switch (cdb[0]) { case REPORT_LUNS: - ret = spc_parse_cdb(cmd, &dummy_size); - if (ret) - return ret; - break; + return spc_emulate_report_luns(cmd); case READ_6: case READ_10: case READ_12: @@ -1020,10 +1015,8 @@ static int pscsi_parse_cdb(struct se_cmd *cmd) /* FALLTHROUGH*/ default: cmd->execute_cmd = pscsi_execute_cmd; - break; + return 0; } - - return 0; } static int pscsi_execute_cmd(struct se_cmd *cmd) diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 07b82700dcd8..1f1ddb8183c7 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -908,7 +908,7 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) return 0; } -static int spc_emulate_report_luns(struct se_cmd *cmd) +int spc_emulate_report_luns(struct se_cmd *cmd) { struct se_dev_entry *deve; struct se_session *sess = cmd->se_sess; @@ -970,6 +970,7 @@ done: target_complete_cmd(cmd, GOOD); return 0; } +EXPORT_SYMBOL(spc_emulate_report_luns); static int spc_emulate_testunitready(struct se_cmd *cmd) { diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index 1c43955f4cb5..e7a03056c957 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -52,6 +52,7 @@ void target_complete_cmd(struct se_cmd *, u8); int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops); int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size); +int spc_emulate_report_luns(struct se_cmd *cmd); int spc_get_write_same_sectors(struct se_cmd *cmd); void transport_set_vpd_proto_id(struct t10_vpd *, unsigned char *); -- cgit v1.2.3 From 6f23ac8a39418d6c6711f4fd73cc4519067d7f08 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 7 Oct 2012 10:55:53 -0400 Subject: target: provide generic sbc device type/revision helpers Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_file.c | 22 ++-------------------- drivers/target/target_core_iblock.c | 14 ++------------ drivers/target/target_core_rd.c | 14 ++------------ drivers/target/target_core_sbc.c | 12 ++++++++++++ include/target/target_core_backend.h | 5 ++++- 5 files changed, 22 insertions(+), 45 deletions(-) (limited to 'include') diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 571d3645f58a..2a3e2bbd8078 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -491,24 +491,6 @@ static ssize_t fd_show_configfs_dev_params(struct se_device *dev, char *b) return bl; } -/* fd_get_device_rev(): (Part of se_subsystem_api_t template) - * - * - */ -static u32 fd_get_device_rev(struct se_device *dev) -{ - return SCSI_SPC_2; /* Returns SPC-3 in Initiator Data */ -} - -/* fd_get_device_type(): (Part of se_subsystem_api_t template) - * - * - */ -static u32 fd_get_device_type(struct se_device *dev) -{ - return TYPE_DISK; -} - static sector_t fd_get_blocks(struct se_device *dev) { struct fd_dev *fd_dev = FD_DEV(dev); @@ -552,8 +534,8 @@ static struct se_subsystem_api fileio_template = { .parse_cdb = fd_parse_cdb, .set_configfs_dev_params = fd_set_configfs_dev_params, .show_configfs_dev_params = fd_show_configfs_dev_params, - .get_device_rev = fd_get_device_rev, - .get_device_type = fd_get_device_type, + .get_device_rev = sbc_get_device_rev, + .get_device_type = sbc_get_device_type, .get_blocks = fd_get_blocks, }; diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 969eed8bff52..701877f9cd33 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -664,16 +664,6 @@ fail: return -ENOMEM; } -static u32 iblock_get_device_rev(struct se_device *dev) -{ - return SCSI_SPC_2; /* Returns SPC-3 in Initiator Data */ -} - -static u32 iblock_get_device_type(struct se_device *dev) -{ - return TYPE_DISK; -} - static sector_t iblock_get_blocks(struct se_device *dev) { struct iblock_dev *ib_dev = IBLOCK_DEV(dev); @@ -735,8 +725,8 @@ static struct se_subsystem_api iblock_template = { .parse_cdb = iblock_parse_cdb, .set_configfs_dev_params = iblock_set_configfs_dev_params, .show_configfs_dev_params = iblock_show_configfs_dev_params, - .get_device_rev = iblock_get_device_rev, - .get_device_type = iblock_get_device_type, + .get_device_rev = sbc_get_device_rev, + .get_device_type = sbc_get_device_type, .get_blocks = iblock_get_blocks, }; diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c index 1b36e67b1153..6348b6672526 100644 --- a/drivers/target/target_core_rd.c +++ b/drivers/target/target_core_rd.c @@ -417,16 +417,6 @@ static ssize_t rd_show_configfs_dev_params(struct se_device *dev, char *b) return bl; } -static u32 rd_get_device_rev(struct se_device *dev) -{ - return SCSI_SPC_2; /* Returns SPC-3 in Initiator Data */ -} - -static u32 rd_get_device_type(struct se_device *dev) -{ - return TYPE_DISK; -} - static sector_t rd_get_blocks(struct se_device *dev) { struct rd_dev *rd_dev = RD_DEV(dev); @@ -459,8 +449,8 @@ static struct se_subsystem_api rd_mcp_template = { .parse_cdb = rd_parse_cdb, .set_configfs_dev_params = rd_set_configfs_dev_params, .show_configfs_dev_params = rd_show_configfs_dev_params, - .get_device_rev = rd_get_device_rev, - .get_device_type = rd_get_device_type, + .get_device_rev = sbc_get_device_rev, + .get_device_type = sbc_get_device_type, .get_blocks = rd_get_blocks, }; diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index a77a19c8d923..01686954cfa0 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -603,3 +603,15 @@ out_invalid_cdb_field: return -EINVAL; } EXPORT_SYMBOL(sbc_parse_cdb); + +u32 sbc_get_device_rev(struct se_device *dev) +{ + return SCSI_SPC_2; /* Returns SPC-3 in Initiator Data */ +} +EXPORT_SYMBOL(sbc_get_device_rev); + +u32 sbc_get_device_type(struct se_device *dev) +{ + return TYPE_DISK; +} +EXPORT_SYMBOL(sbc_get_device_type); diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index e7a03056c957..b7f3936453e1 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -50,11 +50,14 @@ void transport_subsystem_release(struct se_subsystem_api *); void target_complete_cmd(struct se_cmd *, u8); -int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops); int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size); int spc_emulate_report_luns(struct se_cmd *cmd); int spc_get_write_same_sectors(struct se_cmd *cmd); +int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops); +u32 sbc_get_device_rev(struct se_device *dev); +u32 sbc_get_device_type(struct se_device *dev); + void transport_set_vpd_proto_id(struct t10_vpd *, unsigned char *); int transport_set_vpd_assoc(struct t10_vpd *, unsigned char *); int transport_set_vpd_ident_type(struct t10_vpd *, unsigned char *); -- cgit v1.2.3 From 019c4ca621488739b1bfb7597a14ac7f0cbcc908 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 10 Oct 2012 17:37:14 -0400 Subject: target: kill dev->dev_task_attr_type We can just key off ordered tag emulation of the transport_type field. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_device.c | 5 -- drivers/target/target_core_spc.c | 6 +- drivers/target/target_core_transport.c | 130 +++++++++++++++++---------------- include/target/target_core_base.h | 11 --- 4 files changed, 69 insertions(+), 83 deletions(-) (limited to 'include') diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index e45a70970548..6a27e7fd33fb 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -1412,11 +1412,6 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) dev->dev_attrib.fabric_max_sectors = DA_FABRIC_MAX_SECTORS; dev->dev_attrib.optimal_sectors = DA_FABRIC_MAX_SECTORS; - if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) - dev->dev_task_attr_type = SAM_TASK_ATTR_PASSTHROUGH; - else - dev->dev_task_attr_type = SAM_TASK_ATTR_EMULATED; - return dev; } diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 1f1ddb8183c7..8ca62631ec7f 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -1054,8 +1054,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) * Do implict HEAD_OF_QUEUE processing for INQUIRY. * See spc4r17 section 5.3 */ - if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) - cmd->sam_task_attr = MSG_HEAD_TAG; + cmd->sam_task_attr = MSG_HEAD_TAG; cmd->execute_cmd = spc_emulate_inquiry; break; case SECURITY_PROTOCOL_IN: @@ -1083,8 +1082,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) * Do implict HEAD_OF_QUEUE processing for REPORT_LUNS * See spc4r17 section 5.3 */ - if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) - cmd->sam_task_attr = MSG_HEAD_TAG; + cmd->sam_task_attr = MSG_HEAD_TAG; break; case TEST_UNIT_READY: cmd->execute_cmd = spc_emulate_testunitready; diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index c80d88435f90..757e3777ce79 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1068,11 +1068,13 @@ EXPORT_SYMBOL(transport_init_se_cmd); static int transport_check_alloc_task_attr(struct se_cmd *cmd) { + struct se_device *dev = cmd->se_dev; + /* * Check if SAM Task Attribute emulation is enabled for this * struct se_device storage object */ - if (cmd->se_dev->dev_task_attr_type != SAM_TASK_ATTR_EMULATED) + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) return 0; if (cmd->sam_task_attr == MSG_ACA_TAG) { @@ -1084,11 +1086,11 @@ static int transport_check_alloc_task_attr(struct se_cmd *cmd) * Used to determine when ORDERED commands should go from * Dormant to Active status. */ - cmd->se_ordered_id = atomic_inc_return(&cmd->se_dev->dev_ordered_id); + cmd->se_ordered_id = atomic_inc_return(&dev->dev_ordered_id); smp_mb__after_atomic_inc(); pr_debug("Allocated se_ordered_id: %u for Task Attr: 0x%02x on %s\n", cmd->se_ordered_id, cmd->sam_task_attr, - cmd->se_dev->transport->name); + dev->transport->name); return 0; } @@ -1534,8 +1536,7 @@ void transport_generic_request_failure(struct se_cmd *cmd) /* * For SAM Task Attribute emulation for failed struct se_cmd */ - if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) - transport_complete_task_attr(cmd); + transport_complete_task_attr(cmd); switch (cmd->scsi_sense_reason) { case TCM_NON_EXISTENT_LUN: @@ -1619,49 +1620,12 @@ static void __target_execute_cmd(struct se_cmd *cmd) } } -void target_execute_cmd(struct se_cmd *cmd) +static bool target_handle_task_attr(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; - /* - * If the received CDB has aleady been aborted stop processing it here. - */ - if (transport_check_aborted_status(cmd, 1)) - return; - - /* - * Determine if IOCTL context caller in requesting the stopping of this - * command for LUN shutdown purposes. - */ - spin_lock_irq(&cmd->t_state_lock); - if (cmd->transport_state & CMD_T_LUN_STOP) { - pr_debug("%s:%d CMD_T_LUN_STOP for ITT: 0x%08x\n", - __func__, __LINE__, cmd->se_tfo->get_task_tag(cmd)); - - cmd->transport_state &= ~CMD_T_ACTIVE; - spin_unlock_irq(&cmd->t_state_lock); - complete(&cmd->transport_lun_stop_comp); - return; - } - /* - * Determine if frontend context caller is requesting the stopping of - * this command for frontend exceptions. - */ - if (cmd->transport_state & CMD_T_STOP) { - pr_debug("%s:%d CMD_T_STOP for ITT: 0x%08x\n", - __func__, __LINE__, - cmd->se_tfo->get_task_tag(cmd)); - - spin_unlock_irq(&cmd->t_state_lock); - complete(&cmd->t_transport_stop_comp); - return; - } - - cmd->t_state = TRANSPORT_PROCESSING; - spin_unlock_irq(&cmd->t_state_lock); - - if (dev->dev_task_attr_type != SAM_TASK_ATTR_EMULATED) - goto execute; + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) + return false; /* * Check for the existence of HEAD_OF_QUEUE, and if true return 1 @@ -1672,7 +1636,7 @@ void target_execute_cmd(struct se_cmd *cmd) pr_debug("Added HEAD_OF_QUEUE for CDB: 0x%02x, " "se_ordered_id: %u\n", cmd->t_task_cdb[0], cmd->se_ordered_id); - goto execute; + return false; case MSG_ORDERED_TAG: atomic_inc(&dev->dev_ordered_sync); smp_mb__after_atomic_inc(); @@ -1686,7 +1650,7 @@ void target_execute_cmd(struct se_cmd *cmd) * exist that need to be completed first. */ if (!atomic_read(&dev->simple_cmds)) - goto execute; + return false; break; default: /* @@ -1697,23 +1661,61 @@ void target_execute_cmd(struct se_cmd *cmd) break; } - if (atomic_read(&dev->dev_ordered_sync) != 0) { - spin_lock(&dev->delayed_cmd_lock); - list_add_tail(&cmd->se_delayed_node, &dev->delayed_cmd_list); - spin_unlock(&dev->delayed_cmd_lock); + if (atomic_read(&dev->dev_ordered_sync) == 0) + return false; - pr_debug("Added CDB: 0x%02x Task Attr: 0x%02x to" - " delayed CMD list, se_ordered_id: %u\n", - cmd->t_task_cdb[0], cmd->sam_task_attr, - cmd->se_ordered_id); + spin_lock(&dev->delayed_cmd_lock); + list_add_tail(&cmd->se_delayed_node, &dev->delayed_cmd_list); + spin_unlock(&dev->delayed_cmd_lock); + + pr_debug("Added CDB: 0x%02x Task Attr: 0x%02x to" + " delayed CMD list, se_ordered_id: %u\n", + cmd->t_task_cdb[0], cmd->sam_task_attr, + cmd->se_ordered_id); + return true; +} + +void target_execute_cmd(struct se_cmd *cmd) +{ + /* + * If the received CDB has aleady been aborted stop processing it here. + */ + if (transport_check_aborted_status(cmd, 1)) return; - } -execute: /* - * Otherwise, no ORDERED task attributes exist.. + * Determine if IOCTL context caller in requesting the stopping of this + * command for LUN shutdown purposes. */ - __target_execute_cmd(cmd); + spin_lock_irq(&cmd->t_state_lock); + if (cmd->transport_state & CMD_T_LUN_STOP) { + pr_debug("%s:%d CMD_T_LUN_STOP for ITT: 0x%08x\n", + __func__, __LINE__, cmd->se_tfo->get_task_tag(cmd)); + + cmd->transport_state &= ~CMD_T_ACTIVE; + spin_unlock_irq(&cmd->t_state_lock); + complete(&cmd->transport_lun_stop_comp); + return; + } + /* + * Determine if frontend context caller is requesting the stopping of + * this command for frontend exceptions. + */ + if (cmd->transport_state & CMD_T_STOP) { + pr_debug("%s:%d CMD_T_STOP for ITT: 0x%08x\n", + __func__, __LINE__, + cmd->se_tfo->get_task_tag(cmd)); + + spin_unlock_irq(&cmd->t_state_lock); + complete(&cmd->t_transport_stop_comp); + return; + } + + cmd->t_state = TRANSPORT_PROCESSING; + spin_unlock_irq(&cmd->t_state_lock); + + if (!target_handle_task_attr(cmd)) + __target_execute_cmd(cmd); } EXPORT_SYMBOL(target_execute_cmd); @@ -1752,6 +1754,9 @@ static void transport_complete_task_attr(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) + return; + if (cmd->sam_task_attr == MSG_SIMPLE_TAG) { atomic_dec(&dev->simple_cmds); smp_mb__after_atomic_dec(); @@ -1780,8 +1785,7 @@ static void transport_complete_qf(struct se_cmd *cmd) { int ret = 0; - if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) - transport_complete_task_attr(cmd); + transport_complete_task_attr(cmd); if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) { ret = cmd->se_tfo->queue_status(cmd); @@ -1839,8 +1843,8 @@ static void target_complete_ok_work(struct work_struct *work) * delayed execution list after a HEAD_OF_QUEUE or ORDERED Task * Attribute. */ - if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) - transport_complete_task_attr(cmd); + transport_complete_task_attr(cmd); + /* * Check to schedule QUEUE_FULL work, or execute an existing * cmd->transport_qf_callback() diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index f6355fc325a8..15af1307d064 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -232,16 +232,6 @@ typedef enum { SPC3_ALUA_EMULATED } t10_alua_index_t; -/* - * Used by TCM Core internally to signal if SAM Task Attribute emulation - * is enabled or disabled, or running in with TCM/pSCSI passthrough mode - */ -typedef enum { - SAM_TASK_ATTR_PASSTHROUGH, - SAM_TASK_ATTR_UNTAGGED, - SAM_TASK_ATTR_EMULATED -} t10_task_attr_index_t; - /* * Used for target SCSI statistics */ @@ -686,7 +676,6 @@ struct se_device { u32 queue_depth; /* Used for SPC-2 reservations enforce of ISIDs */ u64 dev_res_bin_isid; - t10_task_attr_index_t dev_task_attr_type; /* Pointer to transport specific device structure */ u32 dev_index; u64 creation_time; -- cgit v1.2.3 From d977f4377fbc396b888e12fdb3b13118b09ca7db Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 10 Oct 2012 17:37:15 -0400 Subject: target: simplify reservations code We do not support host-level reservations for the pscsi backend, and all virtual backends are newere than SCSI-2, so just make the combined SPC-3 + SCSI-2 support the only supported variant and kill the switches for the different implementations, given that this code handles the no-op version just fine. (hch: Update DRF_SPC2_RESERVATIONS lock usage) Signed-off-by: Christoph Hellwig --- drivers/target/target_core_configfs.c | 158 +++++++++------------------ drivers/target/target_core_device.c | 3 - drivers/target/target_core_pr.c | 192 +++++++++++---------------------- drivers/target/target_core_pr.h | 2 +- drivers/target/target_core_spc.c | 19 +--- drivers/target/target_core_transport.c | 22 ++-- include/target/target_core_base.h | 29 ----- 7 files changed, 127 insertions(+), 298 deletions(-) (limited to 'include') diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 7272016ed05f..3d5570da41eb 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -970,13 +970,8 @@ static struct target_core_dev_pr_attribute target_core_dev_pr_##_name = \ __CONFIGFS_EATTR_RO(_name, \ target_core_dev_pr_show_attr_##_name); -/* - * res_holder - */ -static ssize_t target_core_dev_pr_show_spc3_res( - struct se_device *dev, - char *page, - ssize_t *len) +static ssize_t target_core_dev_pr_show_spc3_res(struct se_device *dev, + char *page) { struct se_node_acl *se_nacl; struct t10_pr_registration *pr_reg; @@ -985,68 +980,52 @@ static ssize_t target_core_dev_pr_show_spc3_res( memset(i_buf, 0, PR_REG_ISID_ID_LEN); - spin_lock(&dev->dev_reservation_lock); pr_reg = dev->dev_pr_res_holder; - if (!pr_reg) { - *len += sprintf(page + *len, "No SPC-3 Reservation holder\n"); - spin_unlock(&dev->dev_reservation_lock); - return *len; - } + if (!pr_reg) + return sprintf(page, "No SPC-3 Reservation holder\n"); + se_nacl = pr_reg->pr_reg_nacl; prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0], PR_REG_ISID_ID_LEN); - *len += sprintf(page + *len, "SPC-3 Reservation: %s Initiator: %s%s\n", + return sprintf(page, "SPC-3 Reservation: %s Initiator: %s%s\n", se_nacl->se_tpg->se_tpg_tfo->get_fabric_name(), se_nacl->initiatorname, (prf_isid) ? &i_buf[0] : ""); - spin_unlock(&dev->dev_reservation_lock); - - return *len; } -static ssize_t target_core_dev_pr_show_spc2_res( - struct se_device *dev, - char *page, - ssize_t *len) +static ssize_t target_core_dev_pr_show_spc2_res(struct se_device *dev, + char *page) { struct se_node_acl *se_nacl; + ssize_t len; - spin_lock(&dev->dev_reservation_lock); se_nacl = dev->dev_reserved_node_acl; - if (!se_nacl) { - *len += sprintf(page + *len, "No SPC-2 Reservation holder\n"); - spin_unlock(&dev->dev_reservation_lock); - return *len; + if (se_nacl) { + len = sprintf(page, + "SPC-2 Reservation: %s Initiator: %s\n", + se_nacl->se_tpg->se_tpg_tfo->get_fabric_name(), + se_nacl->initiatorname); + } else { + len = sprintf(page, "No SPC-2 Reservation holder\n"); } - *len += sprintf(page + *len, "SPC-2 Reservation: %s Initiator: %s\n", - se_nacl->se_tpg->se_tpg_tfo->get_fabric_name(), - se_nacl->initiatorname); - spin_unlock(&dev->dev_reservation_lock); - - return *len; + return len; } static ssize_t target_core_dev_pr_show_attr_res_holder(struct se_device *dev, char *page) { - ssize_t len = 0; + int ret; - switch (dev->t10_pr.res_type) { - case SPC3_PERSISTENT_RESERVATIONS: - target_core_dev_pr_show_spc3_res(dev, page, &len); - break; - case SPC2_RESERVATIONS: - target_core_dev_pr_show_spc2_res(dev, page, &len); - break; - case SPC_PASSTHROUGH: - len += sprintf(page+len, "Passthrough\n"); - break; - default: - len += sprintf(page+len, "Unknown\n"); - break; - } + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) + return sprintf(page, "Passthrough\n"); - return len; + spin_lock(&dev->dev_reservation_lock); + if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) + ret = target_core_dev_pr_show_spc2_res(dev, page); + else + ret = target_core_dev_pr_show_spc3_res(dev, page); + spin_unlock(&dev->dev_reservation_lock); + return ret; } SE_DEV_PR_ATTR_RO(res_holder); @@ -1054,31 +1033,20 @@ SE_DEV_PR_ATTR_RO(res_holder); static ssize_t target_core_dev_pr_show_attr_res_pr_all_tgt_pts( struct se_device *dev, char *page) { - struct t10_pr_registration *pr_reg; ssize_t len = 0; - if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) - return len; - spin_lock(&dev->dev_reservation_lock); - pr_reg = dev->dev_pr_res_holder; - if (!pr_reg) { + if (!dev->dev_pr_res_holder) { len = sprintf(page, "No SPC-3 Reservation holder\n"); - spin_unlock(&dev->dev_reservation_lock); - return len; - } - /* - * See All Target Ports (ALL_TG_PT) bit in spcr17, section 6.14.3 - * Basic PERSISTENT RESERVER OUT parameter list, page 290 - */ - if (pr_reg->pr_reg_all_tg_pt) + } else if (dev->dev_pr_res_holder->pr_reg_all_tg_pt) { len = sprintf(page, "SPC-3 Reservation: All Target" " Ports registration\n"); - else + } else { len = sprintf(page, "SPC-3 Reservation: Single" " Target Port registration\n"); - spin_unlock(&dev->dev_reservation_lock); + } + spin_unlock(&dev->dev_reservation_lock); return len; } @@ -1087,9 +1055,6 @@ SE_DEV_PR_ATTR_RO(res_pr_all_tgt_pts); static ssize_t target_core_dev_pr_show_attr_res_pr_generation( struct se_device *dev, char *page) { - if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) - return 0; - return sprintf(page, "0x%08x\n", dev->t10_pr.pr_generation); } @@ -1108,16 +1073,13 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port( struct target_core_fabric_ops *tfo; ssize_t len = 0; - if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) - return len; - spin_lock(&dev->dev_reservation_lock); pr_reg = dev->dev_pr_res_holder; if (!pr_reg) { len = sprintf(page, "No SPC-3 Reservation holder\n"); - spin_unlock(&dev->dev_reservation_lock); - return len; + goto out_unlock; } + se_nacl = pr_reg->pr_reg_nacl; se_tpg = se_nacl->se_tpg; lun = pr_reg->pr_reg_tg_pt_lun; @@ -1131,8 +1093,9 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port( " %s Logical Unit: %u\n", lun->lun_sep->sep_rtpi, tfo->get_fabric_name(), tfo->tpg_get_tag(se_tpg), tfo->get_fabric_name(), lun->unpacked_lun); - spin_unlock(&dev->dev_reservation_lock); +out_unlock: + spin_unlock(&dev->dev_reservation_lock); return len; } @@ -1148,9 +1111,6 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts( ssize_t len = 0; int reg_count = 0, prf_isid; - if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) - return len; - len += sprintf(page+len, "SPC-3 PR Registrations:\n"); spin_lock(&dev->t10_pr.registration_lock); @@ -1190,20 +1150,16 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_type( struct t10_pr_registration *pr_reg; ssize_t len = 0; - if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) - return len; - spin_lock(&dev->dev_reservation_lock); pr_reg = dev->dev_pr_res_holder; - if (!pr_reg) { + if (pr_reg) { + len = sprintf(page, "SPC-3 Reservation Type: %s\n", + core_scsi3_pr_dump_type(pr_reg->pr_res_type)); + } else { len = sprintf(page, "No SPC-3 Reservation holder\n"); - spin_unlock(&dev->dev_reservation_lock); - return len; } - len = sprintf(page, "SPC-3 Reservation Type: %s\n", - core_scsi3_pr_dump_type(pr_reg->pr_res_type)); - spin_unlock(&dev->dev_reservation_lock); + spin_unlock(&dev->dev_reservation_lock); return len; } @@ -1212,24 +1168,12 @@ SE_DEV_PR_ATTR_RO(res_pr_type); static ssize_t target_core_dev_pr_show_attr_res_type( struct se_device *dev, char *page) { - ssize_t len = 0; - - switch (dev->t10_pr.res_type) { - case SPC3_PERSISTENT_RESERVATIONS: - len = sprintf(page, "SPC3_PERSISTENT_RESERVATIONS\n"); - break; - case SPC2_RESERVATIONS: - len = sprintf(page, "SPC2_RESERVATIONS\n"); - break; - case SPC_PASSTHROUGH: - len = sprintf(page, "SPC_PASSTHROUGH\n"); - break; - default: - len = sprintf(page, "UNKNOWN\n"); - break; - } - - return len; + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) + return sprintf(page, "SPC_PASSTHROUGH\n"); + else if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) + return sprintf(page, "SPC2_RESERVATIONS\n"); + else + return sprintf(page, "SPC3_PERSISTENT_RESERVATIONS\n"); } SE_DEV_PR_ATTR_RO(res_type); @@ -1237,7 +1181,7 @@ SE_DEV_PR_ATTR_RO(res_type); static ssize_t target_core_dev_pr_show_attr_res_aptpl_active( struct se_device *dev, char *page) { - if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) return 0; return sprintf(page, "APTPL Bit Status: %s\n", @@ -1252,7 +1196,7 @@ SE_DEV_PR_ATTR_RO(res_aptpl_active); static ssize_t target_core_dev_pr_show_attr_res_aptpl_metadata( struct se_device *dev, char *page) { - if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) return 0; return sprintf(page, "Ready to process PR APTPL metadata..\n"); @@ -1299,7 +1243,9 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( u16 port_rpti = 0, tpgt = 0; u8 type = 0, scope; - if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) + return 0; + if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) return 0; if (dev->export_count) { diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 6a27e7fd33fb..4ae1d3913821 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -1398,7 +1398,6 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) dev->dev_attrib.emulate_tas = DA_EMULATE_TAS; dev->dev_attrib.emulate_tpu = DA_EMULATE_TPU; dev->dev_attrib.emulate_tpws = DA_EMULATE_TPWS; - dev->dev_attrib.emulate_reservations = DA_EMULATE_RESERVATIONS; dev->dev_attrib.emulate_alua = DA_EMULATE_ALUA; dev->dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS; dev->dev_attrib.is_nonrot = DA_IS_NONROT; @@ -1447,8 +1446,6 @@ int target_configure_device(struct se_device *dev) dev->dev_index = scsi_get_new_index(SCSI_DEVICE_INDEX); dev->creation_time = get_jiffies_64(); - core_setup_reservations(dev); - ret = core_setup_alua(dev); if (ret) goto out; diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 2b289891672f..f561a08ff8e5 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -68,49 +68,32 @@ int core_pr_dump_initiator_port( static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *, struct t10_pr_registration *, int); -static int core_scsi2_reservation_seq_non_holder( - struct se_cmd *cmd, - unsigned char *cdb, - u32 pr_reg_type) +static int target_scsi2_reservation_check(struct se_cmd *cmd) { - switch (cdb[0]) { + struct se_device *dev = cmd->se_dev; + struct se_session *sess = cmd->se_sess; + + switch (cmd->t_task_cdb[0]) { case INQUIRY: case RELEASE: case RELEASE_10: return 0; default: - return 1; + break; } - return 1; -} - -static int core_scsi2_reservation_check(struct se_cmd *cmd, u32 *pr_reg_type) -{ - struct se_device *dev = cmd->se_dev; - struct se_session *sess = cmd->se_sess; - int ret; - - if (!sess) + if (!dev->dev_reserved_node_acl || !sess) return 0; - spin_lock(&dev->dev_reservation_lock); - if (!dev->dev_reserved_node_acl || !sess) { - spin_unlock(&dev->dev_reservation_lock); - return 0; - } - if (dev->dev_reserved_node_acl != sess->se_node_acl) { - spin_unlock(&dev->dev_reservation_lock); - return -EINVAL; - } - if (!(dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS_WITH_ISID)) { - spin_unlock(&dev->dev_reservation_lock); - return 0; + if (dev->dev_reserved_node_acl != sess->se_node_acl) + return -EBUSY; + + if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS_WITH_ISID) { + if (dev->dev_res_bin_isid != sess->sess_bin_isid) + return -EBUSY; } - ret = (dev->dev_res_bin_isid == sess->sess_bin_isid) ? 0 : -EINVAL; - spin_unlock(&dev->dev_reservation_lock); - return ret; + return 0; } static struct t10_pr_registration *core_scsi3_locate_pr_reg(struct se_device *, @@ -123,12 +106,8 @@ static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd) struct se_device *dev = cmd->se_dev; struct t10_pr_registration *pr_reg; struct t10_reservation *pr_tmpl = &dev->t10_pr; - int crh = (dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS); int conflict = 0; - if (!crh) - return -EINVAL; - pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl, se_sess); if (pr_reg) { @@ -319,9 +298,9 @@ out: */ static int core_scsi3_pr_seq_non_holder( struct se_cmd *cmd, - unsigned char *cdb, u32 pr_reg_type) { + unsigned char *cdb = cmd->t_task_cdb; struct se_dev_entry *se_deve; struct se_session *se_sess = cmd->se_sess; int other_cdb = 0, ignore_reg; @@ -330,17 +309,11 @@ static int core_scsi3_pr_seq_non_holder( int we = 0; /* Write Exclusive */ int legacy = 0; /* Act like a legacy device and return * RESERVATION CONFLICT on some CDBs */ - /* - * A legacy SPC-2 reservation is being held. - */ - if (cmd->se_dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) - return core_scsi2_reservation_seq_non_holder(cmd, - cdb, pr_reg_type); se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun]; /* * Determine if the registration should be ignored due to - * non-matching ISIDs in core_scsi3_pr_reservation_check(). + * non-matching ISIDs in target_scsi3_pr_reservation_check(). */ ignore_reg = (pr_reg_type & 0x80000000); if (ignore_reg) @@ -563,6 +536,36 @@ static int core_scsi3_pr_seq_non_holder( return 1; /* Conflict by default */ } +static int target_scsi3_pr_reservation_check(struct se_cmd *cmd) +{ + struct se_device *dev = cmd->se_dev; + struct se_session *sess = cmd->se_sess; + u32 pr_reg_type; + + if (!dev->dev_pr_res_holder) + return 0; + + pr_reg_type = dev->dev_pr_res_holder->pr_res_type; + cmd->pr_res_key = dev->dev_pr_res_holder->pr_res_key; + if (dev->dev_pr_res_holder->pr_reg_nacl != sess->se_node_acl) + goto check_nonholder; + + if (dev->dev_pr_res_holder->isid_present_at_reg) { + if (dev->dev_pr_res_holder->pr_reg_bin_isid != + sess->sess_bin_isid) { + pr_reg_type |= 0x80000000; + goto check_nonholder; + } + } + + return 0; + +check_nonholder: + if (core_scsi3_pr_seq_non_holder(cmd, pr_reg_type)) + return -EBUSY; + return 0; +} + static u32 core_scsi3_pr_generation(struct se_device *dev) { u32 prg; @@ -583,50 +586,6 @@ static u32 core_scsi3_pr_generation(struct se_device *dev) return prg; } -static int core_scsi3_pr_reservation_check( - struct se_cmd *cmd, - u32 *pr_reg_type) -{ - struct se_device *dev = cmd->se_dev; - struct se_session *sess = cmd->se_sess; - int ret; - - if (!sess) - return 0; - /* - * A legacy SPC-2 reservation is being held. - */ - if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) - return core_scsi2_reservation_check(cmd, pr_reg_type); - - spin_lock(&dev->dev_reservation_lock); - if (!dev->dev_pr_res_holder) { - spin_unlock(&dev->dev_reservation_lock); - return 0; - } - *pr_reg_type = dev->dev_pr_res_holder->pr_res_type; - cmd->pr_res_key = dev->dev_pr_res_holder->pr_res_key; - if (dev->dev_pr_res_holder->pr_reg_nacl != sess->se_node_acl) { - spin_unlock(&dev->dev_reservation_lock); - return -EINVAL; - } - if (!dev->dev_pr_res_holder->isid_present_at_reg) { - spin_unlock(&dev->dev_reservation_lock); - return 0; - } - ret = (dev->dev_pr_res_holder->pr_reg_bin_isid == - sess->sess_bin_isid) ? 0 : -EINVAL; - /* - * Use bit in *pr_reg_type to notify ISID mismatch in - * core_scsi3_pr_seq_non_holder(). - */ - if (ret != 0) - *pr_reg_type |= 0x80000000; - spin_unlock(&dev->dev_reservation_lock); - - return ret; -} - static struct t10_pr_registration *__core_scsi3_do_alloc_registration( struct se_device *dev, struct se_node_acl *nacl, @@ -998,7 +957,7 @@ int core_scsi3_check_aptpl_registration( struct se_node_acl *nacl = lun_acl->se_lun_nacl; struct se_dev_entry *deve = nacl->device_list[lun_acl->mapped_lun]; - if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) + if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) return 0; return __core_scsi3_check_aptpl_registration(dev, tpg, lun, @@ -4343,49 +4302,24 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd) return ret; } -static int core_pt_reservation_check(struct se_cmd *cmd, u32 *pr_res_type) +int target_check_reservation(struct se_cmd *cmd) { - return 0; -} + struct se_device *dev = cmd->se_dev; + int ret; -static int core_pt_seq_non_holder( - struct se_cmd *cmd, - unsigned char *cdb, - u32 pr_reg_type) -{ - return 0; -} + if (!cmd->se_sess) + return 0; + if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE) + return 0; + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) + return 0; -void core_setup_reservations(struct se_device *dev) -{ - struct t10_reservation *rest = &dev->t10_pr; + spin_lock(&dev->dev_reservation_lock); + if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) + ret = target_scsi2_reservation_check(cmd); + else + ret = target_scsi3_pr_reservation_check(cmd); + spin_unlock(&dev->dev_reservation_lock); - /* - * If this device is from Target_Core_Mod/pSCSI, use the reservations - * of the Underlying SCSI hardware. In Linux/SCSI terms, this can - * cause a problem because libata and some SATA RAID HBAs appear - * under Linux/SCSI, but to emulate reservations themselves. - */ - if ((dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE) || - (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV && - !dev->dev_attrib.emulate_reservations)) { - rest->res_type = SPC_PASSTHROUGH; - rest->pr_ops.t10_reservation_check = &core_pt_reservation_check; - rest->pr_ops.t10_seq_non_holder = &core_pt_seq_non_holder; - pr_debug("%s: Using SPC_PASSTHROUGH, no reservation" - " emulation\n", dev->transport->name); - } else if (dev->transport->get_device_rev(dev) >= SCSI_3) { - rest->res_type = SPC3_PERSISTENT_RESERVATIONS; - rest->pr_ops.t10_reservation_check = &core_scsi3_pr_reservation_check; - rest->pr_ops.t10_seq_non_holder = &core_scsi3_pr_seq_non_holder; - pr_debug("%s: Using SPC3_PERSISTENT_RESERVATIONS" - " emulation\n", dev->transport->name); - } else { - rest->res_type = SPC2_RESERVATIONS; - rest->pr_ops.t10_reservation_check = &core_scsi2_reservation_check; - rest->pr_ops.t10_seq_non_holder = - &core_scsi2_reservation_seq_non_holder; - pr_debug("%s: Using SPC2_RESERVATIONS emulation\n", - dev->transport->name); - } + return ret; } diff --git a/drivers/target/target_core_pr.h b/drivers/target/target_core_pr.h index 78451437d2c2..7616f2690ca0 100644 --- a/drivers/target/target_core_pr.h +++ b/drivers/target/target_core_pr.h @@ -63,6 +63,6 @@ extern unsigned char *core_scsi3_pr_dump_type(int); extern int target_scsi3_emulate_pr_in(struct se_cmd *); extern int target_scsi3_emulate_pr_out(struct se_cmd *); -extern void core_setup_reservations(struct se_device *); +extern int target_check_reservation(struct se_cmd *cmd); #endif /* TARGET_CORE_PR_H */ diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 8ca62631ec7f..862e4347f68f 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -1003,14 +1003,12 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) *size = (cdb[7] << 8) + cdb[8]; break; case PERSISTENT_RESERVE_IN: - if (dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS) - cmd->execute_cmd = target_scsi3_emulate_pr_in; *size = (cdb[7] << 8) + cdb[8]; + cmd->execute_cmd = target_scsi3_emulate_pr_in; break; case PERSISTENT_RESERVE_OUT: - if (dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS) - cmd->execute_cmd = target_scsi3_emulate_pr_out; *size = (cdb[7] << 8) + cdb[8]; + cmd->execute_cmd = target_scsi3_emulate_pr_out; break; case RELEASE: case RELEASE_10: @@ -1019,8 +1017,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) else *size = cmd->data_length; - if (dev->t10_pr.res_type != SPC_PASSTHROUGH) - cmd->execute_cmd = target_scsi2_reservation_release; + cmd->execute_cmd = target_scsi2_reservation_release; break; case RESERVE: case RESERVE_10: @@ -1033,15 +1030,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) else *size = cmd->data_length; - /* - * Setup the legacy emulated handler for SPC-2 and - * >= SPC-3 compatible reservation handling (CRH=1) - * Otherwise, we assume the underlying SCSI logic is - * is running in SPC_PASSTHROUGH, and wants reservations - * emulation disabled. - */ - if (dev->t10_pr.res_type != SPC_PASSTHROUGH) - cmd->execute_cmd = target_scsi2_reservation_reserve; + cmd->execute_cmd = target_scsi2_reservation_reserve; break; case REQUEST_SENSE: *size = cdb[4]; diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 757e3777ce79..e996bdf480cf 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1103,7 +1103,6 @@ int target_setup_cmd_from_cdb( unsigned char *cdb) { struct se_device *dev = cmd->se_dev; - u32 pr_reg_type = 0; u8 alua_ascq = 0; unsigned long flags; int ret; @@ -1180,20 +1179,13 @@ int target_setup_cmd_from_cdb( /* * Check status for SPC-3 Persistent Reservations */ - if (dev->t10_pr.pr_ops.t10_reservation_check(cmd, &pr_reg_type)) { - if (dev->t10_pr.pr_ops.t10_seq_non_holder( - cmd, cdb, pr_reg_type) != 0) { - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT; - cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT; - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EBUSY; - } - /* - * This means the CDB is allowed for the SCSI Initiator port - * when said port is *NOT* holding the legacy SPC-2 or - * SPC-3 Persistent Reservation. - */ + ret = target_check_reservation(cmd); + if (ret) { + cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; + cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT; + cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT; + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + return ret; } ret = dev->transport->parse_cdb(cmd); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 15af1307d064..892a93dec19c 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -93,8 +93,6 @@ */ #define DA_EMULATE_TPWS 0 /* No Emulation for PSCSI by default */ -#define DA_EMULATE_RESERVATIONS 0 -/* No Emulation for PSCSI by default */ #define DA_EMULATE_ALUA 0 /* Enforce SCSI Initiator Port TransportID with 'ISID' for PR */ #define DA_ENFORCE_PR_ISIDS 1 @@ -333,18 +331,6 @@ struct t10_wwn { struct list_head t10_vpd_list; }; - -/* - * Used by TCM Core internally to signal if >= SPC-3 persistent reservations - * emulation is enabled or disabled, or running in with TCM/pSCSI passthrough - * mode - */ -typedef enum { - SPC_PASSTHROUGH, - SPC2_RESERVATIONS, - SPC3_PERSISTENT_RESERVATIONS -} t10_reservations_index_t; - struct t10_pr_registration { /* Used for fabrics that contain WWN+ISID */ #define PR_REG_ISID_LEN 16 @@ -386,18 +372,6 @@ struct t10_pr_registration { struct list_head pr_reg_atp_mem_list; }; -/* - * This set of function pointer ops is set based upon SPC3_PERSISTENT_RESERVATIONS, - * SPC2_RESERVATIONS or SPC_PASSTHROUGH in drivers/target/target_core_pr.c: - * core_setup_reservations() - */ -struct t10_reservation_ops { - int (*t10_reservation_check)(struct se_cmd *, u32 *); - int (*t10_seq_non_holder)(struct se_cmd *, unsigned char *, u32); - int (*t10_pr_register)(struct se_cmd *); - int (*t10_pr_clear)(struct se_cmd *); -}; - struct t10_reservation { /* Reservation effects all target ports */ int pr_all_tg_pt; @@ -408,7 +382,6 @@ struct t10_reservation { #define PR_APTPL_BUF_LEN 8192 u32 pr_aptpl_buf_len; u32 pr_generation; - t10_reservations_index_t res_type; spinlock_t registration_lock; spinlock_t aptpl_reg_lock; /* @@ -424,7 +397,6 @@ struct t10_reservation { struct se_node_acl *pr_res_holder; struct list_head registration_list; struct list_head aptpl_reg_list; - struct t10_reservation_ops pr_ops; }; struct se_tmr_req { @@ -633,7 +605,6 @@ struct se_dev_attrib { int emulate_tas; int emulate_tpu; int emulate_tpws; - int emulate_reservations; int emulate_alua; int enforce_pr_isids; int is_nonrot; -- cgit v1.2.3 From c87fbd5656f263f0fc1c37d20f402797c068232e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 10 Oct 2012 17:37:16 -0400 Subject: target: simplify alua support We always support ALUA for virtual backends, and never for physical ones. Simplify the code to just deal with these two cases and remove the superflous abstractions. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_alua.c | 135 ++++++++++++--------------------- drivers/target/target_core_alua.h | 1 + drivers/target/target_core_configfs.c | 28 ++----- drivers/target/target_core_device.c | 4 +- drivers/target/target_core_spc.c | 12 +-- drivers/target/target_core_transport.c | 38 ++-------- include/target/target_core_base.h | 13 ---- 7 files changed, 65 insertions(+), 166 deletions(-) (limited to 'include') diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 15c127b780d8..b3302a9200a2 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -522,40 +522,26 @@ static inline int core_alua_state_transition( } /* - * Used for alua_type SPC_ALUA_PASSTHROUGH and SPC2_ALUA_DISABLED - * in transport_cmd_sequencer(). This function is assigned to - * struct t10_alua *->state_check() in core_setup_alua() - */ -static int core_alua_state_check_nop( - struct se_cmd *cmd, - unsigned char *cdb, - u8 *alua_ascq) -{ - return 0; -} - -/* - * Used for alua_type SPC3_ALUA_EMULATED in transport_cmd_sequencer(). - * This function is assigned to struct t10_alua *->state_check() in - * core_setup_alua() - * - * Also, this function can return three different return codes to - * signal transport_generic_cmd_sequencer() - * * return 1: Is used to signal LUN not accecsable, and check condition/not ready * return 0: Used to signal success * reutrn -1: Used to signal failure, and invalid cdb field */ -static int core_alua_state_check( - struct se_cmd *cmd, - unsigned char *cdb, - u8 *alua_ascq) +int target_alua_state_check(struct se_cmd *cmd) { + struct se_device *dev = cmd->se_dev; + unsigned char *cdb = cmd->t_task_cdb; struct se_lun *lun = cmd->se_lun; struct se_port *port = lun->lun_sep; struct t10_alua_tg_pt_gp *tg_pt_gp; struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; int out_alua_state, nonop_delay_msecs; + u8 alua_ascq; + int ret; + + if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE) + return 0; + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) + return 0; if (!port) return 0; @@ -564,11 +550,11 @@ static int core_alua_state_check( * access state: OFFLINE */ if (atomic_read(&port->sep_tg_pt_secondary_offline)) { - *alua_ascq = ASCQ_04H_ALUA_OFFLINE; pr_debug("ALUA: Got secondary offline status for local" " target port\n"); - *alua_ascq = ASCQ_04H_ALUA_OFFLINE; - return 1; + alua_ascq = ASCQ_04H_ALUA_OFFLINE; + ret = 1; + goto out; } /* * Second, obtain the struct t10_alua_tg_pt_gp_member pointer to the @@ -593,14 +579,18 @@ static int core_alua_state_check( switch (out_alua_state) { case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED: - return core_alua_state_nonoptimized(cmd, cdb, - nonop_delay_msecs, alua_ascq); + ret = core_alua_state_nonoptimized(cmd, cdb, + nonop_delay_msecs, &alua_ascq); + break; case ALUA_ACCESS_STATE_STANDBY: - return core_alua_state_standby(cmd, cdb, alua_ascq); + ret = core_alua_state_standby(cmd, cdb, &alua_ascq); + break; case ALUA_ACCESS_STATE_UNAVAILABLE: - return core_alua_state_unavailable(cmd, cdb, alua_ascq); + ret = core_alua_state_unavailable(cmd, cdb, &alua_ascq); + break; case ALUA_ACCESS_STATE_TRANSITION: - return core_alua_state_transition(cmd, cdb, alua_ascq); + ret = core_alua_state_transition(cmd, cdb, &alua_ascq); + break; /* * OFFLINE is a secondary ALUA target port group access state, that is * handled above with struct se_port->sep_tg_pt_secondary_offline=1 @@ -609,10 +599,27 @@ static int core_alua_state_check( default: pr_err("Unknown ALUA access state: 0x%02x\n", out_alua_state); - return -EINVAL; + ret = -EINVAL; + break; } - return 0; +out: + if (ret > 0) { + /* + * Set SCSI additional sense code (ASC) to 'LUN Not Accessible'; + * The ALUA additional sense code qualifier (ASCQ) is determined + * by the ALUA primary or secondary access state.. + */ + pr_debug("[%s]: ALUA TG Port not available, " + "SenseKey: NOT_READY, ASC/ASCQ: " + "0x04/0x%02x\n", + cmd->se_tfo->get_fabric_name(), alua_ascq); + + cmd->scsi_asc = 0x04; + cmd->scsi_ascq = alua_ascq; + } + + return ret; } /* @@ -1264,13 +1271,9 @@ void core_alua_free_lu_gp(struct t10_alua_lu_gp *lu_gp) void core_alua_free_lu_gp_mem(struct se_device *dev) { - struct t10_alua *alua = &dev->t10_alua; struct t10_alua_lu_gp *lu_gp; struct t10_alua_lu_gp_member *lu_gp_mem; - if (alua->alua_type != SPC3_ALUA_EMULATED) - return; - lu_gp_mem = dev->dev_alua_lu_gp_mem; if (!lu_gp_mem) return; @@ -1538,13 +1541,9 @@ void core_alua_free_tg_pt_gp( void core_alua_free_tg_pt_gp_mem(struct se_port *port) { - struct t10_alua *alua = &port->sep_lun->lun_se_dev->t10_alua; struct t10_alua_tg_pt_gp *tg_pt_gp; struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; - if (alua->alua_type != SPC3_ALUA_EMULATED) - return; - tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; if (!tg_pt_gp_mem) return; @@ -1636,14 +1635,10 @@ static void __core_alua_drop_tg_pt_gp_mem( ssize_t core_alua_show_tg_pt_gp_info(struct se_port *port, char *page) { struct config_item *tg_pt_ci; - struct t10_alua *alua = &port->sep_lun->lun_se_dev->t10_alua; struct t10_alua_tg_pt_gp *tg_pt_gp; struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; ssize_t len = 0; - if (alua->alua_type != SPC3_ALUA_EMULATED) - return len; - tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; if (!tg_pt_gp_mem) return len; @@ -1686,13 +1681,9 @@ ssize_t core_alua_store_tg_pt_gp_info( tpg = port->sep_tpg; lun = port->sep_lun; - if (dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) { - pr_warn("SPC3_ALUA_EMULATED not enabled for" - " %s/tpgt_%hu/%s\n", tpg->se_tpg_tfo->tpg_get_wwn(tpg), - tpg->se_tpg_tfo->tpg_get_tag(tpg), - config_item_name(&lun->lun_group.cg_item)); - return -EINVAL; - } + tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; + if (!tg_pt_gp_mem) + return 0; if (count > TG_PT_GROUP_NAME_BUF) { pr_err("ALUA Target Port Group alias too large!\n"); @@ -1715,13 +1706,6 @@ ssize_t core_alua_store_tg_pt_gp_info( if (!tg_pt_gp_new) return -ENODEV; } - tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; - if (!tg_pt_gp_mem) { - if (tg_pt_gp_new) - core_alua_put_tg_pt_gp_from_name(tg_pt_gp_new); - pr_err("NULL struct se_port->sep_alua_tg_pt_gp_mem pointer\n"); - return -EINVAL; - } spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; @@ -2050,26 +2034,9 @@ ssize_t core_alua_store_secondary_write_metadata( int core_setup_alua(struct se_device *dev) { - struct t10_alua *alua = &dev->t10_alua; - struct t10_alua_lu_gp_member *lu_gp_mem; - - /* - * If this device is from Target_Core_Mod/pSCSI, use the ALUA logic - * of the Underlying SCSI hardware. In Linux/SCSI terms, this can - * cause a problem because libata and some SATA RAID HBAs appear - * under Linux/SCSI, but emulate SCSI logic themselves. - */ - if ((dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE) || - (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV && - !dev->dev_attrib.emulate_alua)) { - pr_debug("%s: Using SPC_ALUA_PASSTHROUGH, no ALUA" - " emulation\n", dev->transport->name); - - alua->alua_type = SPC_ALUA_PASSTHROUGH; - alua->alua_state_check = &core_alua_state_check_nop; - } else if (dev->transport->get_device_rev(dev) >= SCSI_3) { - pr_debug("%s: Enabling ALUA Emulation for SPC-3" - " device\n", dev->transport->name); + if (dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV && + !(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) { + struct t10_alua_lu_gp_member *lu_gp_mem; /* * Associate this struct se_device with the default ALUA @@ -2079,8 +2046,6 @@ int core_setup_alua(struct se_device *dev) if (IS_ERR(lu_gp_mem)) return PTR_ERR(lu_gp_mem); - alua->alua_type = SPC3_ALUA_EMULATED; - alua->alua_state_check = &core_alua_state_check; spin_lock(&lu_gp_mem->lu_gp_mem_lock); __core_alua_attach_lu_gp_mem(lu_gp_mem, default_lu_gp); @@ -2089,12 +2054,6 @@ int core_setup_alua(struct se_device *dev) pr_debug("%s: Adding to default ALUA LU Group:" " core/alua/lu_gps/default_lu_gp\n", dev->transport->name); - } else { - pr_debug("%s: Disabling ALUA Emulation for SPC-2" - " device\n", dev->transport->name); - - alua->alua_type = SPC2_ALUA_DISABLED; - alua->alua_state_check = &core_alua_state_check_nop; } return 0; diff --git a/drivers/target/target_core_alua.h b/drivers/target/target_core_alua.h index 5019157ffe69..a2af8aa15b98 100644 --- a/drivers/target/target_core_alua.h +++ b/drivers/target/target_core_alua.h @@ -132,5 +132,6 @@ extern ssize_t core_alua_show_secondary_write_metadata(struct se_lun *, extern ssize_t core_alua_store_secondary_write_metadata(struct se_lun *, const char *, size_t); extern int core_setup_alua(struct se_device *); +extern int target_alua_state_check(struct se_cmd *cmd); #endif /* TARGET_CORE_ALUA_H */ diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 3d5570da41eb..7b473b66da7b 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -1615,15 +1615,9 @@ static ssize_t target_core_show_alua_lu_gp(void *p, char *page) struct t10_alua_lu_gp_member *lu_gp_mem; ssize_t len = 0; - if (dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) - return len; - lu_gp_mem = dev->dev_alua_lu_gp_mem; - if (!lu_gp_mem) { - pr_err("NULL struct se_device->dev_alua_lu_gp_mem" - " pointer\n"); - return -EINVAL; - } + if (!lu_gp_mem) + return 0; spin_lock(&lu_gp_mem->lu_gp_mem_lock); lu_gp = lu_gp_mem->lu_gp; @@ -1649,12 +1643,10 @@ static ssize_t target_core_store_alua_lu_gp( unsigned char buf[LU_GROUP_NAME_BUF]; int move = 0; - if (dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) { - pr_warn("SPC3_ALUA_EMULATED not enabled for %s/%s\n", - config_item_name(&hba->hba_group.cg_item), - config_item_name(&dev->dev_group.cg_item)); - return -EINVAL; - } + lu_gp_mem = dev->dev_alua_lu_gp_mem; + if (!lu_gp_mem) + return 0; + if (count > LU_GROUP_NAME_BUF) { pr_err("ALUA LU Group Alias too large!\n"); return -EINVAL; @@ -1675,14 +1667,6 @@ static ssize_t target_core_store_alua_lu_gp( if (!lu_gp_new) return -ENODEV; } - lu_gp_mem = dev->dev_alua_lu_gp_mem; - if (!lu_gp_mem) { - if (lu_gp_new) - core_alua_put_lu_gp_from_name(lu_gp_new); - pr_err("NULL struct se_device->dev_alua_lu_gp_mem" - " pointer\n"); - return -EINVAL; - } spin_lock(&lu_gp_mem->lu_gp_mem_lock); lu_gp = lu_gp_mem->lu_gp; diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 4ae1d3913821..3c3a3019ce7b 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -556,7 +556,8 @@ static void core_export_port( list_add_tail(&port->sep_list, &dev->dev_sep_list); spin_unlock(&dev->se_port_lock); - if (dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) { + if (dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV && + !(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) { tg_pt_gp_mem = core_alua_allocate_tg_pt_gp_mem(port); if (IS_ERR(tg_pt_gp_mem) || !tg_pt_gp_mem) { pr_err("Unable to allocate t10_alua_tg_pt" @@ -1398,7 +1399,6 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) dev->dev_attrib.emulate_tas = DA_EMULATE_TAS; dev->dev_attrib.emulate_tpu = DA_EMULATE_TPU; dev->dev_attrib.emulate_tpws = DA_EMULATE_TPWS; - dev->dev_attrib.emulate_alua = DA_EMULATE_ALUA; dev->dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS; dev->dev_attrib.is_nonrot = DA_IS_NONROT; dev->dev_attrib.emulate_rest_reord = DA_EMULATE_REST_REORD; diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 862e4347f68f..7ecac453b11a 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -95,8 +95,7 @@ static int spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf) /* * Enable SCCS and TPGS fields for Emulated ALUA */ - if (dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) - spc_fill_alua_data(lun->lun_sep, buf); + spc_fill_alua_data(lun->lun_sep, buf); buf[7] = 0x2; /* CmdQue=1 */ @@ -294,9 +293,6 @@ check_t10_vend_desc: * Get the PROTOCOL IDENTIFIER as defined by spc4r17 * section 7.5.1 Table 362 */ - if (dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) - goto check_scsi_name; - tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; if (!tg_pt_gp_mem) goto check_lu_gp; @@ -1083,8 +1079,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) * MAINTENANCE_IN from SCC-2 * Check for emulated MI_REPORT_TARGET_PGS */ - if ((cdb[1] & 0x1f) == MI_REPORT_TARGET_PGS && - dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) { + if ((cdb[1] & 0x1f) == MI_REPORT_TARGET_PGS) { cmd->execute_cmd = target_emulate_report_target_port_groups; } @@ -1102,8 +1097,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) * MAINTENANCE_OUT from SCC-2 * Check for emulated MO_SET_TARGET_PGS. */ - if (cdb[1] == MO_SET_TARGET_PGS && - dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) { + if (cdb[1] == MO_SET_TARGET_PGS) { cmd->execute_cmd = target_emulate_set_target_port_groups; } diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index e996bdf480cf..c4c931b525d2 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -70,7 +70,6 @@ static void transport_handle_queue_full(struct se_cmd *cmd, static int transport_generic_get_mem(struct se_cmd *cmd); static int target_get_sess_cmd(struct se_session *, struct se_cmd *, bool); static void transport_put_cmd(struct se_cmd *cmd); -static int transport_set_sense_codes(struct se_cmd *cmd, u8 asc, u8 ascq); static void target_complete_ok_work(struct work_struct *work); int init_se_kmem_caches(void) @@ -1103,7 +1102,6 @@ int target_setup_cmd_from_cdb( unsigned char *cdb) { struct se_device *dev = cmd->se_dev; - u8 alua_ascq = 0; unsigned long flags; int ret; @@ -1153,26 +1151,13 @@ int target_setup_cmd_from_cdb( return -EINVAL; } - ret = dev->t10_alua.alua_state_check(cmd, cdb, &alua_ascq); - if (ret != 0) { - /* - * Set SCSI additional sense code (ASC) to 'LUN Not Accessible'; - * The ALUA additional sense code qualifier (ASCQ) is determined - * by the ALUA primary or secondary access state.. - */ - if (ret > 0) { - pr_debug("[%s]: ALUA TG Port not available, " - "SenseKey: NOT_READY, ASC/ASCQ: " - "0x04/0x%02x\n", - cmd->se_tfo->get_fabric_name(), alua_ascq); - - transport_set_sense_codes(cmd, 0x04, alua_ascq); - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_CHECK_CONDITION_NOT_READY; - return -EINVAL; - } + ret = target_alua_state_check(cmd); + if (ret) { cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + if (ret > 0) + cmd->scsi_sense_reason = TCM_CHECK_CONDITION_NOT_READY; + else + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; return -EINVAL; } @@ -2640,17 +2625,6 @@ static int transport_get_sense_codes( return 0; } -static int transport_set_sense_codes( - struct se_cmd *cmd, - u8 asc, - u8 ascq) -{ - cmd->scsi_asc = asc; - cmd->scsi_ascq = ascq; - - return 0; -} - int transport_send_check_condition_and_sense( struct se_cmd *cmd, u8 reason, diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 892a93dec19c..11b0a68dc765 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -220,16 +220,6 @@ enum tcm_tmrsp_table { TMR_FUNCTION_REJECTED = 255, }; -/* - * Used by TCM Core internally to signal if ALUA emulation is enabled or - * disabled, or running in with TCM/pSCSI passthrough mode - */ -typedef enum { - SPC_ALUA_PASSTHROUGH, - SPC2_ALUA_DISABLED, - SPC3_ALUA_EMULATED -} t10_alua_index_t; - /* * Used for target SCSI statistics */ @@ -243,7 +233,6 @@ typedef enum { struct se_cmd; struct t10_alua { - t10_alua_index_t alua_type; /* ALUA Target Port Group ID */ u16 alua_tg_pt_gps_counter; u32 alua_tg_pt_gps_count; @@ -253,7 +242,6 @@ struct t10_alua { struct t10_alua_tg_pt_gp *default_tg_pt_gp; /* Used for default ALUA Target Port Group ConfigFS group */ struct config_group alua_tg_pt_gps_group; - int (*alua_state_check)(struct se_cmd *, unsigned char *, u8 *); struct list_head tg_pt_gps_list; }; @@ -605,7 +593,6 @@ struct se_dev_attrib { int emulate_tas; int emulate_tpu; int emulate_tpws; - int emulate_alua; int enforce_pr_isids; int is_nonrot; int emulate_rest_reord; -- cgit v1.2.3 From 48c2567d1a10b5a2cab72b37775b886b08f88726 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 10 Oct 2012 17:37:17 -0400 Subject: target: remove ->get_device_rev Now that the reservations and ALUA code have been cleaned up there is no need for the get_device_rev method, as we only need the standards revision in the inquiry data, where we can hardcode it. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_device.c | 2 -- drivers/target/target_core_file.c | 1 - drivers/target/target_core_iblock.c | 1 - drivers/target/target_core_pscsi.c | 13 ------------- drivers/target/target_core_rd.c | 1 - drivers/target/target_core_sbc.c | 6 ------ drivers/target/target_core_spc.c | 2 +- include/target/target_core_backend.h | 1 - 8 files changed, 1 insertion(+), 26 deletions(-) (limited to 'include') diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 3c3a3019ce7b..066e8159afcd 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -1348,8 +1348,6 @@ static void scsi_dump_inquiry(struct se_device *dev) device_type = dev->transport->get_device_type(dev); pr_debug(" Type: %s ", scsi_device_type(device_type)); - pr_debug(" ANSI SCSI revision: %02x\n", - dev->transport->get_device_rev(dev)); } struct se_device *target_alloc_device(struct se_hba *hba, const char *name) diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 2a3e2bbd8078..342a6a6dcca0 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -534,7 +534,6 @@ static struct se_subsystem_api fileio_template = { .parse_cdb = fd_parse_cdb, .set_configfs_dev_params = fd_set_configfs_dev_params, .show_configfs_dev_params = fd_show_configfs_dev_params, - .get_device_rev = sbc_get_device_rev, .get_device_type = sbc_get_device_type, .get_blocks = fd_get_blocks, }; diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 701877f9cd33..17fc01d6baea 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -725,7 +725,6 @@ static struct se_subsystem_api iblock_template = { .parse_cdb = iblock_parse_cdb, .set_configfs_dev_params = iblock_set_configfs_dev_params, .show_configfs_dev_params = iblock_show_configfs_dev_params, - .get_device_rev = sbc_get_device_rev, .get_device_type = sbc_get_device_type, .get_blocks = iblock_get_blocks, }; diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index dd6ac7c380c9..aa3e80a2f8db 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -1106,18 +1106,6 @@ fail: return -ENOMEM; } -/* pscsi_get_device_rev(): - * - * - */ -static u32 pscsi_get_device_rev(struct se_device *dev) -{ - struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); - struct scsi_device *sd = pdv->pdv_sd; - - return (sd->scsi_level - 1) ? sd->scsi_level - 1 : 1; -} - /* pscsi_get_device_type(): * * @@ -1187,7 +1175,6 @@ static struct se_subsystem_api pscsi_template = { .parse_cdb = pscsi_parse_cdb, .set_configfs_dev_params = pscsi_set_configfs_dev_params, .show_configfs_dev_params = pscsi_show_configfs_dev_params, - .get_device_rev = pscsi_get_device_rev, .get_device_type = pscsi_get_device_type, .get_blocks = pscsi_get_blocks, }; diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c index 6348b6672526..92b1307a9931 100644 --- a/drivers/target/target_core_rd.c +++ b/drivers/target/target_core_rd.c @@ -449,7 +449,6 @@ static struct se_subsystem_api rd_mcp_template = { .parse_cdb = rd_parse_cdb, .set_configfs_dev_params = rd_set_configfs_dev_params, .show_configfs_dev_params = rd_show_configfs_dev_params, - .get_device_rev = sbc_get_device_rev, .get_device_type = sbc_get_device_type, .get_blocks = rd_get_blocks, }; diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 01686954cfa0..a4eb9c553654 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -604,12 +604,6 @@ out_invalid_cdb_field: } EXPORT_SYMBOL(sbc_parse_cdb); -u32 sbc_get_device_rev(struct se_device *dev) -{ - return SCSI_SPC_2; /* Returns SPC-3 in Initiator Data */ -} -EXPORT_SYMBOL(sbc_get_device_rev); - u32 sbc_get_device_type(struct se_device *dev) { return TYPE_DISK; diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 7ecac453b11a..71d440f0573e 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -78,7 +78,7 @@ static int spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf) if (dev->transport->get_device_type(dev) == TYPE_TAPE) buf[1] = 0x80; - buf[2] = dev->transport->get_device_rev(dev); + buf[2] = 0x05; /* SPC-3 */ /* * NORMACA and HISUP = 0, RESPONSE DATA FORMAT = 2 diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index b7f3936453e1..e57f738f04f9 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -32,7 +32,6 @@ struct se_subsystem_api { unsigned char *); int (*parse_cdb)(struct se_cmd *cmd); - u32 (*get_device_rev)(struct se_device *); u32 (*get_device_type)(struct se_device *); sector_t (*get_blocks)(struct se_device *); unsigned char *(*get_sense_buffer)(struct se_cmd *); -- cgit v1.2.3 From de103c93aff0bed0ae984274e5dc8b95899badab Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 6 Nov 2012 12:24:09 -0800 Subject: target: pass sense_reason as a return value Pass the sense reason as an explicit return value from the I/O submission path instead of storing it in struct se_cmd and using negative return values. This cleans up a lot of the code pathes, and with the sparse annotations for the new sense_reason_t type allows for much better error checking. (nab: Convert spc_emulate_modesense + spc_emulate_modeselect to use sense_reason_t with Roland's MODE SELECT changes) Signed-off-by: Christoph Hellwig Cc: Roland Dreier Signed-off-by: Nicholas Bellinger --- drivers/infiniband/ulp/srpt/ib_srpt.c | 43 +- drivers/scsi/qla2xxx/tcm_qla2xxx.c | 4 +- drivers/target/iscsi/iscsi_target.c | 80 +-- drivers/target/iscsi/iscsi_target_core.h | 2 +- drivers/target/iscsi/iscsi_target_erl1.c | 11 +- drivers/target/target_core_alua.c | 98 ++-- drivers/target/target_core_alua.h | 6 +- drivers/target/target_core_device.c | 31 +- drivers/target/target_core_file.c | 22 +- drivers/target/target_core_iblock.c | 55 +- drivers/target/target_core_internal.h | 2 +- drivers/target/target_core_pr.c | 918 ++++++++++++++----------------- drivers/target/target_core_pr.h | 10 +- drivers/target/target_core_pscsi.c | 51 +- drivers/target/target_core_rd.c | 10 +- drivers/target/target_core_sbc.c | 87 ++- drivers/target/target_core_spc.c | 126 ++--- drivers/target/target_core_transport.c | 252 ++++----- drivers/target/target_core_ua.c | 11 +- drivers/target/target_core_ua.h | 2 +- drivers/vhost/tcm_vhost.c | 4 - include/target/target_core_backend.h | 16 +- include/target/target_core_base.h | 46 +- include/target/target_core_fabric.h | 13 +- 24 files changed, 841 insertions(+), 1059 deletions(-) (limited to 'include') diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index cf23c46185b2..e6fafc62acae 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -1730,7 +1730,7 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, uint64_t unpacked_lun; u64 data_len; enum dma_data_direction dir; - int ret; + sense_reason_t ret; BUG_ON(!send_ioctx); @@ -1755,12 +1755,10 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, break; } - ret = srpt_get_desc_tbl(send_ioctx, srp_cmd, &dir, &data_len); - if (ret) { + if (srpt_get_desc_tbl(send_ioctx, srp_cmd, &dir, &data_len)) { printk(KERN_ERR "0x%llx: parsing SRP descriptor table failed.\n", srp_cmd->tag); - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + ret = TCM_INVALID_CDB_FIELD; kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref); goto send_sense; } @@ -1769,26 +1767,26 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, cmd->data_direction = dir; unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_cmd->lun, sizeof(srp_cmd->lun)); - if (transport_lookup_cmd_lun(cmd, unpacked_lun) < 0) { + ret = transport_lookup_cmd_lun(cmd, unpacked_lun); + if (ret) { kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref); goto send_sense; } ret = target_setup_cmd_from_cdb(cmd, srp_cmd->cdb); - if (ret < 0) { + if (ret) { kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref); - if (cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT) { + if (ret == TCM_RESERVATION_CONFLICT) { srpt_queue_status(cmd); return 0; - } else - goto send_sense; + } + goto send_sense; } transport_handle_cdb_direct(cmd); return 0; send_sense: - transport_send_check_condition_and_sense(cmd, cmd->scsi_sense_reason, - 0); + transport_send_check_condition_and_sense(cmd, ret, 0); return -1; } @@ -1882,16 +1880,14 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch, send_ioctx->tag = srp_tsk->tag; tcm_tmr = srp_tmr_to_tcm(srp_tsk->tsk_mgmt_func); if (tcm_tmr < 0) { - send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; send_ioctx->cmd.se_tmr_req->response = TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED; - goto process_tmr; + goto fail; } res = core_tmr_alloc_req(cmd, NULL, tcm_tmr, GFP_KERNEL); if (res < 0) { - send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED; - goto process_tmr; + goto fail; } unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_tsk->lun, @@ -1899,22 +1895,19 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch, res = transport_lookup_tmr_lun(&send_ioctx->cmd, unpacked_lun); if (res) { pr_debug("rejecting TMR for LUN %lld\n", unpacked_lun); - send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; send_ioctx->cmd.se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST; - goto process_tmr; + goto fail; } if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK) srpt_rx_mgmt_fn_tag(send_ioctx, srp_tsk->task_tag); -process_tmr: kref_get(&send_ioctx->kref); - if (!(send_ioctx->cmd.se_cmd_flags & SCF_SCSI_CDB_EXCEPTION)) - transport_generic_handle_tmr(&send_ioctx->cmd); - else - transport_send_check_condition_and_sense(cmd, - cmd->scsi_sense_reason, 0); - + transport_generic_handle_tmr(&send_ioctx->cmd); + return; +fail: + kref_get(&send_ioctx->kref); + transport_send_check_condition_and_sense(cmd, 0, 0); // XXX: } /** diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 3d74f2f39ae1..c5696240d8f6 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -620,8 +620,8 @@ static void tcm_qla2xxx_handle_data_work(struct work_struct *work) return; } - cmd->se_cmd.scsi_sense_reason = TCM_CHECK_CONDITION_ABORT_CMD; - transport_generic_request_failure(&cmd->se_cmd); + transport_generic_request_failure(&cmd->se_cmd, + TCM_CHECK_CONDITION_ABORT_CMD); return; } diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 035c2c762537..093fb6010272 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -767,9 +767,8 @@ static int iscsit_handle_scsi_cmd( struct iscsi_conn *conn, unsigned char *buf) { - int data_direction, cmdsn_ret = 0, immed_ret, ret, transport_ret; - int dump_immediate_data = 0, send_check_condition = 0, payload_length; - struct iscsi_cmd *cmd = NULL; + int data_direction, payload_length, cmdsn_ret = 0, immed_ret; + struct iscsi_cmd *cmd = NULL; struct iscsi_scsi_req *hdr; int iscsi_task_attr; int sam_task_attr; @@ -956,38 +955,26 @@ done: " ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt, hdr->cmdsn, hdr->data_length, payload_length, conn->cid); - /* - * The CDB is going to an se_device_t. - */ - ret = transport_lookup_cmd_lun(&cmd->se_cmd, - scsilun_to_int(&hdr->lun)); - if (ret < 0) { - if (cmd->se_cmd.scsi_sense_reason == TCM_NON_EXISTENT_LUN) { - pr_debug("Responding to non-acl'ed," - " non-existent or non-exported iSCSI LUN:" - " 0x%016Lx\n", get_unaligned_le64(&hdr->lun)); + cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd, + scsilun_to_int(&hdr->lun)); + if (cmd->sense_reason) + goto attach_cmd; + + cmd->sense_reason = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb); + if (cmd->sense_reason) { + if (cmd->sense_reason == TCM_OUT_OF_RESOURCES) { + return iscsit_add_reject_from_cmd( + ISCSI_REASON_BOOKMARK_NO_RESOURCES, + 1, 1, buf, cmd); } - send_check_condition = 1; + goto attach_cmd; } - transport_ret = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb); - if (transport_ret == -ENOMEM) { + if (iscsit_build_pdu_and_seq_lists(cmd, payload_length) < 0) { return iscsit_add_reject_from_cmd( - ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, 1, buf, cmd); - } else if (transport_ret < 0) { - /* - * Unsupported SAM Opcode. CHECK_CONDITION will be sent - * in iscsit_execute_cmd() during the CmdSN OOO Execution - * Mechinism. - */ - send_check_condition = 1; - } else { - if (iscsit_build_pdu_and_seq_lists(cmd, payload_length) < 0) - return iscsit_add_reject_from_cmd( - ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, 1, buf, cmd); + ISCSI_REASON_BOOKMARK_NO_RESOURCES, + 1, 1, buf, cmd); } attach_cmd: @@ -1000,11 +987,12 @@ attach_cmd: */ core_alua_check_nonop_delay(&cmd->se_cmd); - ret = iscsit_allocate_iovecs(cmd); - if (ret < 0) + if (iscsit_allocate_iovecs(cmd) < 0) { return iscsit_add_reject_from_cmd( ISCSI_REASON_BOOKMARK_NO_RESOURCES, 1, 0, buf, cmd); + } + /* * Check the CmdSN against ExpCmdSN/MaxCmdSN here if * the Immediate Bit is not set, and no Immediate @@ -1031,10 +1019,7 @@ attach_cmd: * If no Immediate Data is attached, it's OK to return now. */ if (!cmd->immediate_data) { - if (send_check_condition) - return 0; - - if (cmd->unsolicited_data) { + if (!cmd->sense_reason && cmd->unsolicited_data) { iscsit_set_dataout_sequence_values(cmd); spin_lock_bh(&cmd->dataout_timeout_lock); @@ -1050,19 +1035,17 @@ attach_cmd: * thread. They are processed in CmdSN order by * iscsit_check_received_cmdsn() below. */ - if (send_check_condition) { + if (cmd->sense_reason) { immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION; - dump_immediate_data = 1; goto after_immediate_data; } /* * Call directly into transport_generic_new_cmd() to perform * the backend memory allocation. */ - ret = transport_generic_new_cmd(&cmd->se_cmd); - if (ret < 0) { + cmd->sense_reason = transport_generic_new_cmd(&cmd->se_cmd); + if (cmd->sense_reason) { immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION; - dump_immediate_data = 1; goto after_immediate_data; } @@ -1079,7 +1062,7 @@ after_immediate_data: * Special case for Unsupported SAM WRITE Opcodes * and ImmediateData=Yes. */ - if (dump_immediate_data) { + if (cmd->sense_reason) { if (iscsit_dump_data_payload(conn, payload_length, 1) < 0) return -1; } else if (cmd->unsolicited_data) { @@ -1272,8 +1255,7 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf) spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); spin_lock_irqsave(&se_cmd->t_state_lock, flags); - if (!(se_cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE) || - (se_cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION)) + if (!(se_cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE)) dump_unsolicited_data = 1; spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); @@ -1742,7 +1724,6 @@ static int iscsit_handle_task_mgt_cmd( ret = transport_lookup_tmr_lun(&cmd->se_cmd, scsilun_to_int(&hdr->lun)); if (ret < 0) { - cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; se_tmr->response = ISCSI_TMF_RSP_NO_LUN; goto attach; } @@ -1751,10 +1732,8 @@ static int iscsit_handle_task_mgt_cmd( switch (function) { case ISCSI_TM_FUNC_ABORT_TASK: se_tmr->response = iscsit_tmr_abort_task(cmd, buf); - if (se_tmr->response != ISCSI_TMF_RSP_COMPLETE) { - cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; + if (se_tmr->response) goto attach; - } break; case ISCSI_TM_FUNC_ABORT_TASK_SET: case ISCSI_TM_FUNC_CLEAR_ACA: @@ -1763,14 +1742,12 @@ static int iscsit_handle_task_mgt_cmd( break; case ISCSI_TM_FUNC_TARGET_WARM_RESET: if (iscsit_tmr_task_warm_reset(conn, tmr_req, buf) < 0) { - cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED; goto attach; } break; case ISCSI_TM_FUNC_TARGET_COLD_RESET: if (iscsit_tmr_task_cold_reset(conn, tmr_req, buf) < 0) { - cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; se_tmr->response = ISCSI_TMF_RSP_AUTH_FAILED; goto attach; } @@ -1781,7 +1758,7 @@ static int iscsit_handle_task_mgt_cmd( * Perform sanity checks on the ExpDataSN only if the * TASK_REASSIGN was successful. */ - if (se_tmr->response != ISCSI_TMF_RSP_COMPLETE) + if (se_tmr->response) break; if (iscsit_check_task_reassign_expdatasn(tmr_req, conn) < 0) @@ -1792,7 +1769,6 @@ static int iscsit_handle_task_mgt_cmd( default: pr_err("Unknown TMR function: 0x%02x, protocol" " error.\n", function); - cmd->se_cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; se_tmr->response = ISCSI_TMF_RSP_NOT_SUPPORTED; goto attach; } diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index 21048dbf7d13..7a333d28d9a2 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -474,7 +474,7 @@ struct iscsi_cmd { struct scatterlist *first_data_sg; u32 first_data_sg_off; u32 kmapped_nents; - + sense_reason_t sense_reason; } ____cacheline_aligned; struct iscsi_tmr_req { diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c index 21f29d91a8cb..0b52a2371305 100644 --- a/drivers/target/iscsi/iscsi_target_erl1.c +++ b/drivers/target/iscsi/iscsi_target_erl1.c @@ -929,11 +929,10 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo) case ISCSI_OP_SCSI_CMD: /* * Go ahead and send the CHECK_CONDITION status for - * any SCSI CDB exceptions that may have occurred, also - * handle the SCF_SCSI_RESERVATION_CONFLICT case here as well. + * any SCSI CDB exceptions that may have occurred. */ - if (se_cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION) { - if (se_cmd->scsi_sense_reason == TCM_RESERVATION_CONFLICT) { + if (cmd->sense_reason) { + if (cmd->sense_reason == TCM_RESERVATION_CONFLICT) { cmd->i_state = ISTATE_SEND_STATUS; spin_unlock_bh(&cmd->istate_lock); iscsit_add_cmd_to_response_queue(cmd, cmd->conn, @@ -956,7 +955,7 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo) * exception */ return transport_send_check_condition_and_sense(se_cmd, - se_cmd->scsi_sense_reason, 0); + cmd->sense_reason, 0); } /* * Special case for delayed CmdSN with Immediate @@ -1013,7 +1012,7 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo) iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state); break; case ISCSI_OP_SCSI_TMFUNC: - if (se_cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION) { + if (cmd->se_cmd.se_tmr_req->response) { spin_unlock_bh(&cmd->istate_lock); iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state); diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index b3302a9200a2..e62dc529e516 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -41,7 +41,7 @@ #include "target_core_alua.h" #include "target_core_ua.h" -static int core_alua_check_transition(int state, int *primary); +static sense_reason_t core_alua_check_transition(int state, int *primary); static int core_alua_set_tg_pt_secondary_state( struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, struct se_port *port, int explict, int offline); @@ -59,7 +59,8 @@ struct t10_alua_lu_gp *default_lu_gp; * * See spc4r17 section 6.27 */ -int target_emulate_report_target_port_groups(struct se_cmd *cmd) +sense_reason_t +target_emulate_report_target_port_groups(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_port *port; @@ -68,6 +69,7 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd) unsigned char *buf; u32 rd_len = 0, off; int ext_hdr = (cmd->t_task_cdb[1] & 0x20); + /* * Skip over RESERVED area to first Target port group descriptor * depending on the PARAMETER DATA FORMAT type.. @@ -81,10 +83,11 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd) pr_warn("REPORT TARGET PORT GROUPS allocation length %u too" " small for %s header\n", cmd->data_length, (ext_hdr) ? "extended" : "normal"); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; spin_lock(&dev->t10_alua.tg_pt_gps_lock); list_for_each_entry(tg_pt_gp, &dev->t10_alua.tg_pt_gps_list, @@ -200,7 +203,8 @@ int target_emulate_report_target_port_groups(struct se_cmd *cmd) * * See spc4r17 section 6.35 */ -int target_emulate_set_target_port_groups(struct se_cmd *cmd) +sense_reason_t +target_emulate_set_target_port_groups(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_port *port, *l_port = cmd->se_lun->lun_sep; @@ -209,22 +213,23 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *l_tg_pt_gp_mem; unsigned char *buf; unsigned char *ptr; + sense_reason_t rc; u32 len = 4; /* Skip over RESERVED area in header */ - int alua_access_state, primary = 0, rc; + int alua_access_state, primary = 0; u16 tg_pt_id, rtpi; - if (!l_port) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; - } + if (!l_port) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + if (cmd->data_length < 4) { pr_warn("SET TARGET PORT GROUPS parameter list length %u too" " small\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + return TCM_INVALID_PARAMETER_LIST; } buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; /* * Determine if explict ALUA via SET_TARGET_PORT_GROUPS is allowed @@ -233,8 +238,7 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) l_tg_pt_gp_mem = l_port->sep_alua_tg_pt_gp_mem; if (!l_tg_pt_gp_mem) { pr_err("Unable to access l_port->sep_alua_tg_pt_gp_mem\n"); - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; - rc = -EINVAL; + rc = TCM_UNSUPPORTED_SCSI_OPCODE; goto out; } spin_lock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); @@ -242,24 +246,22 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) if (!l_tg_pt_gp) { spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); pr_err("Unable to access *l_tg_pt_gp_mem->tg_pt_gp\n"); - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; - rc = -EINVAL; + rc = TCM_UNSUPPORTED_SCSI_OPCODE; goto out; } - rc = (l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA); spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); - if (!rc) { + if (l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA) { pr_debug("Unable to process SET_TARGET_PORT_GROUPS" " while TPGS_EXPLICT_ALUA is disabled\n"); - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; - rc = -EINVAL; + rc = TCM_UNSUPPORTED_SCSI_OPCODE; goto out; } ptr = &buf[4]; /* Skip over RESERVED area in header */ while (len < cmd->data_length) { + bool found = false; alua_access_state = (ptr[0] & 0x0f); /* * Check the received ALUA access state, and determine if @@ -267,7 +269,7 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) * access state. */ rc = core_alua_check_transition(alua_access_state, &primary); - if (rc != 0) { + if (rc) { /* * If the SET TARGET PORT GROUPS attempts to establish * an invalid combination of target port asymmetric @@ -278,11 +280,9 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) * REQUEST, and the additional sense code set to INVALID * FIELD IN PARAMETER LIST. */ - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - rc = -EINVAL; goto out; } - rc = -1; + /* * If the ASYMMETRIC ACCESS STATE field (see table 267) * specifies a primary target port asymmetric access state, @@ -314,11 +314,13 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); smp_mb__after_atomic_inc(); + spin_unlock(&dev->t10_alua.tg_pt_gps_lock); - rc = core_alua_do_port_transition(tg_pt_gp, + if (!core_alua_do_port_transition(tg_pt_gp, dev, l_port, nacl, - alua_access_state, 1); + alua_access_state, 1)) + found = true; spin_lock(&dev->t10_alua.tg_pt_gps_lock); atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); @@ -326,15 +328,6 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) break; } spin_unlock(&dev->t10_alua.tg_pt_gps_lock); - /* - * If not matching target port group ID can be located - * throw an exception with ASCQ: INVALID_PARAMETER_LIST - */ - if (rc != 0) { - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - rc = -EINVAL; - goto out; - } } else { /* * Extact the RELATIVE TARGET PORT IDENTIFIER to identify @@ -353,25 +346,22 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) continue; tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; + spin_unlock(&dev->se_port_lock); - rc = core_alua_set_tg_pt_secondary_state( - tg_pt_gp_mem, port, 1, 1); + if (!core_alua_set_tg_pt_secondary_state( + tg_pt_gp_mem, port, 1, 1)) + found = true; spin_lock(&dev->se_port_lock); break; } spin_unlock(&dev->se_port_lock); - /* - * If not matching relative target port identifier can - * be located, throw an exception with ASCQ: - * INVALID_PARAMETER_LIST - */ - if (rc != 0) { - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - rc = -EINVAL; - goto out; - } + } + + if (!found) { + rc = TCM_INVALID_PARAMETER_LIST; + goto out; } ptr += 4; @@ -526,7 +516,8 @@ static inline int core_alua_state_transition( * return 0: Used to signal success * reutrn -1: Used to signal failure, and invalid cdb field */ -int target_alua_state_check(struct se_cmd *cmd) +sense_reason_t +target_alua_state_check(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; unsigned char *cdb = cmd->t_task_cdb; @@ -599,8 +590,7 @@ int target_alua_state_check(struct se_cmd *cmd) default: pr_err("Unknown ALUA access state: 0x%02x\n", out_alua_state); - ret = -EINVAL; - break; + return TCM_INVALID_CDB_FIELD; } out: @@ -617,15 +607,17 @@ out: cmd->scsi_asc = 0x04; cmd->scsi_ascq = alua_ascq; + return TCM_CHECK_CONDITION_NOT_READY; } - return ret; + return 0; } /* * Check implict and explict ALUA state change request. */ -static int core_alua_check_transition(int state, int *primary) +static sense_reason_t +core_alua_check_transition(int state, int *primary) { switch (state) { case ALUA_ACCESS_STATE_ACTIVE_OPTMIZED: @@ -647,7 +639,7 @@ static int core_alua_check_transition(int state, int *primary) break; default: pr_err("Unknown ALUA access state: 0x%02x\n", state); - return -EINVAL; + return TCM_INVALID_PARAMETER_LIST; } return 0; diff --git a/drivers/target/target_core_alua.h b/drivers/target/target_core_alua.h index a2af8aa15b98..e539c3e7f4ad 100644 --- a/drivers/target/target_core_alua.h +++ b/drivers/target/target_core_alua.h @@ -72,8 +72,8 @@ extern struct kmem_cache *t10_alua_lu_gp_mem_cache; extern struct kmem_cache *t10_alua_tg_pt_gp_cache; extern struct kmem_cache *t10_alua_tg_pt_gp_mem_cache; -extern int target_emulate_report_target_port_groups(struct se_cmd *); -extern int target_emulate_set_target_port_groups(struct se_cmd *); +extern sense_reason_t target_emulate_report_target_port_groups(struct se_cmd *); +extern sense_reason_t target_emulate_set_target_port_groups(struct se_cmd *); extern int core_alua_check_nonop_delay(struct se_cmd *); extern int core_alua_do_port_transition(struct t10_alua_tg_pt_gp *, struct se_device *, struct se_port *, @@ -132,6 +132,6 @@ extern ssize_t core_alua_show_secondary_write_metadata(struct se_lun *, extern ssize_t core_alua_store_secondary_write_metadata(struct se_lun *, const char *, size_t); extern int core_setup_alua(struct se_device *); -extern int target_alua_state_check(struct se_cmd *cmd); +extern sense_reason_t target_alua_state_check(struct se_cmd *cmd); #endif /* TARGET_CORE_ALUA_H */ diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 066e8159afcd..599374e6d245 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -54,18 +54,16 @@ static struct se_hba *lun0_hba; /* not static, needed by tpg.c */ struct se_device *g_lun0_dev; -int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun) +sense_reason_t +transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun) { struct se_lun *se_lun = NULL; struct se_session *se_sess = se_cmd->se_sess; struct se_device *dev; unsigned long flags; - if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) { - se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN; - se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - return -ENODEV; - } + if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) + return TCM_NON_EXISTENT_LUN; spin_lock_irqsave(&se_sess->se_node_acl->device_list_lock, flags); se_cmd->se_deve = se_sess->se_node_acl->device_list[unpacked_lun]; @@ -77,14 +75,12 @@ int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun) if ((se_cmd->data_direction == DMA_TO_DEVICE) && (deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)) { - se_cmd->scsi_sense_reason = TCM_WRITE_PROTECTED; - se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; pr_err("TARGET_CORE[%s]: Detected WRITE_PROTECTED LUN" " Access for 0x%08x\n", se_cmd->se_tfo->get_fabric_name(), unpacked_lun); spin_unlock_irqrestore(&se_sess->se_node_acl->device_list_lock, flags); - return -EACCES; + return TCM_WRITE_PROTECTED; } if (se_cmd->data_direction == DMA_TO_DEVICE) @@ -109,23 +105,18 @@ int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun) * MappedLUN=0 exists for this Initiator Port. */ if (unpacked_lun != 0) { - se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN; - se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; pr_err("TARGET_CORE[%s]: Detected NON_EXISTENT_LUN" " Access for 0x%08x\n", se_cmd->se_tfo->get_fabric_name(), unpacked_lun); - return -ENODEV; + return TCM_NON_EXISTENT_LUN; } /* * Force WRITE PROTECT for virtual LUN 0 */ if ((se_cmd->data_direction != DMA_FROM_DEVICE) && - (se_cmd->data_direction != DMA_NONE)) { - se_cmd->scsi_sense_reason = TCM_WRITE_PROTECTED; - se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - return -EACCES; - } + (se_cmd->data_direction != DMA_NONE)) + return TCM_WRITE_PROTECTED; se_lun = &se_sess->se_tpg->tpg_virt_lun0; se_cmd->se_lun = &se_sess->se_tpg->tpg_virt_lun0; @@ -162,11 +153,8 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd, u32 unpacked_lun) struct se_tmr_req *se_tmr = se_cmd->se_tmr_req; unsigned long flags; - if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) { - se_cmd->scsi_sense_reason = TCM_NON_EXISTENT_LUN; - se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; + if (unpacked_lun >= TRANSPORT_MAX_LUNS_PER_TPG) return -ENODEV; - } spin_lock_irqsave(&se_sess->se_node_acl->device_list_lock, flags); se_cmd->se_deve = se_sess->se_node_acl->device_list[unpacked_lun]; @@ -186,7 +174,6 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd, u32 unpacked_lun) " Access for 0x%08x\n", se_cmd->se_tfo->get_fabric_name(), unpacked_lun); - se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; return -ENODEV; } diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 342a6a6dcca0..3ccef831a641 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -309,7 +309,8 @@ static int fd_do_writev(struct se_cmd *cmd, struct scatterlist *sgl, return 1; } -static int fd_execute_sync_cache(struct se_cmd *cmd) +static sense_reason_t +fd_execute_sync_cache(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct fd_dev *fd_dev = FD_DEV(dev); @@ -345,17 +346,16 @@ static int fd_execute_sync_cache(struct se_cmd *cmd) if (immed) return 0; - if (ret) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + if (ret) target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION); - } else { + else target_complete_cmd(cmd, SAM_STAT_GOOD); - } return 0; } -static int fd_execute_rw(struct se_cmd *cmd) +static sense_reason_t +fd_execute_rw(struct se_cmd *cmd) { struct scatterlist *sgl = cmd->t_data_sg; u32 sgl_nents = cmd->t_data_nents; @@ -388,10 +388,9 @@ static int fd_execute_rw(struct se_cmd *cmd) } } - if (ret < 0) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return ret; - } + if (ret < 0) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + if (ret) target_complete_cmd(cmd, SAM_STAT_GOOD); return 0; @@ -515,7 +514,8 @@ static struct sbc_ops fd_sbc_ops = { .execute_sync_cache = fd_execute_sync_cache, }; -static int fd_parse_cdb(struct se_cmd *cmd) +static sense_reason_t +fd_parse_cdb(struct se_cmd *cmd) { return sbc_parse_cdb(cmd, &fd_sbc_ops); } diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 17fc01d6baea..53f4501819f9 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -261,13 +261,10 @@ static void iblock_end_io_flush(struct bio *bio, int err) pr_err("IBLOCK: cache flush failed: %d\n", err); if (cmd) { - if (err) { - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + if (err) target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION); - } else { + else target_complete_cmd(cmd, SAM_STAT_GOOD); - } } bio_put(bio); @@ -277,7 +274,8 @@ static void iblock_end_io_flush(struct bio *bio, int err) * Implement SYCHRONIZE CACHE. Note that we can't handle lba ranges and must * always flush the whole cache. */ -static int iblock_execute_sync_cache(struct se_cmd *cmd) +static sense_reason_t +iblock_execute_sync_cache(struct se_cmd *cmd) { struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev); int immed = (cmd->t_task_cdb[1] & 0x2); @@ -299,7 +297,8 @@ static int iblock_execute_sync_cache(struct se_cmd *cmd) return 0; } -static int iblock_execute_unmap(struct se_cmd *cmd) +static sense_reason_t +iblock_execute_unmap(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct iblock_dev *ib_dev = IBLOCK_DEV(dev); @@ -307,17 +306,18 @@ static int iblock_execute_unmap(struct se_cmd *cmd) sector_t lba; int size; u32 range; - int ret = 0; - int dl, bd_dl; + sense_reason_t ret = 0; + int dl, bd_dl, err; if (cmd->data_length < 8) { pr_warn("UNMAP parameter list length %u too small\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + return TCM_INVALID_PARAMETER_LIST; } buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; dl = get_unaligned_be16(&buf[0]); bd_dl = get_unaligned_be16(&buf[2]); @@ -330,8 +330,7 @@ static int iblock_execute_unmap(struct se_cmd *cmd) size = bd_dl; if (size / 16 > dev->dev_attrib.max_unmap_block_desc_count) { - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto err; } @@ -347,22 +346,21 @@ static int iblock_execute_unmap(struct se_cmd *cmd) (unsigned long long)lba, range); if (range > dev->dev_attrib.max_unmap_lba_count) { - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto err; } if (lba + range > dev->transport->get_blocks(dev) + 1) { - cmd->scsi_sense_reason = TCM_ADDRESS_OUT_OF_RANGE; - ret = -EINVAL; + ret = TCM_ADDRESS_OUT_OF_RANGE; goto err; } - ret = blkdev_issue_discard(ib_dev->ibd_bd, lba, range, + err = blkdev_issue_discard(ib_dev->ibd_bd, lba, range, GFP_KERNEL, 0); - if (ret < 0) { + if (err < 0) { pr_err("blkdev_issue_discard() failed: %d\n", - ret); + err); + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; goto err; } @@ -377,7 +375,8 @@ err: return ret; } -static int iblock_execute_write_same(struct se_cmd *cmd) +static sense_reason_t +iblock_execute_write_same(struct se_cmd *cmd) { struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev); int ret; @@ -387,7 +386,7 @@ static int iblock_execute_write_same(struct se_cmd *cmd) 0); if (ret < 0) { pr_debug("blkdev_issue_discard() failed for WRITE_SAME\n"); - return ret; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } target_complete_cmd(cmd, GOOD); @@ -552,7 +551,8 @@ static void iblock_submit_bios(struct bio_list *list, int rw) blk_finish_plug(&plug); } -static int iblock_execute_rw(struct se_cmd *cmd) +static sense_reason_t +iblock_execute_rw(struct se_cmd *cmd) { struct scatterlist *sgl = cmd->t_data_sg; u32 sgl_nents = cmd->t_data_nents; @@ -598,8 +598,7 @@ static int iblock_execute_rw(struct se_cmd *cmd) else { pr_err("Unsupported SCSI -> BLOCK LBA conversion:" " %u\n", dev->dev_attrib.block_size); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -ENOSYS; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL); @@ -659,9 +658,8 @@ fail_put_bios: bio_put(bio); fail_free_ibr: kfree(ibr); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; fail: - return -ENOMEM; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } static sector_t iblock_get_blocks(struct se_device *dev) @@ -706,7 +704,8 @@ static struct sbc_ops iblock_sbc_ops = { .execute_unmap = iblock_execute_unmap, }; -static int iblock_parse_cdb(struct se_cmd *cmd) +static sense_reason_t +iblock_parse_cdb(struct se_cmd *cmd) { return sbc_parse_cdb(cmd, &iblock_sbc_ops); } diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index 2f37720c4db3..bc9c52284845 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -101,7 +101,7 @@ int transport_dump_vpd_ident(struct t10_vpd *, unsigned char *, int); bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags); int transport_clear_lun_from_sessions(struct se_lun *); void transport_send_task_abort(struct se_cmd *); -int target_cmd_size_check(struct se_cmd *cmd, unsigned int size); +sense_reason_t target_cmd_size_check(struct se_cmd *cmd, unsigned int size); void target_qf_do_work(struct work_struct *work); /* target_core_stat.c */ diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index f561a08ff8e5..ffbe0ea9bbad 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -68,7 +68,8 @@ int core_pr_dump_initiator_port( static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *, struct t10_pr_registration *, int); -static int target_scsi2_reservation_check(struct se_cmd *cmd) +static sense_reason_t +target_scsi2_reservation_check(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_session *sess = cmd->se_sess; @@ -86,11 +87,11 @@ static int target_scsi2_reservation_check(struct se_cmd *cmd) return 0; if (dev->dev_reserved_node_acl != sess->se_node_acl) - return -EBUSY; + return TCM_RESERVATION_CONFLICT; if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS_WITH_ISID) { if (dev->dev_res_bin_isid != sess->sess_bin_isid) - return -EBUSY; + return TCM_RESERVATION_CONFLICT; } return 0; @@ -165,32 +166,28 @@ static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd) pr_err("Received legacy SPC-2 RESERVE/RELEASE" " while active SPC-3 registrations exist," " returning RESERVATION_CONFLICT\n"); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; return -EBUSY; } return 0; } -int target_scsi2_reservation_release(struct se_cmd *cmd) +sense_reason_t +target_scsi2_reservation_release(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_session *sess = cmd->se_sess; struct se_portal_group *tpg; - int ret = 0, rc; + int rc; if (!sess || !sess->se_tpg) goto out; rc = target_check_scsi2_reservation_conflict(cmd); if (rc == 1) goto out; - else if (rc < 0) { - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - ret = -EINVAL; - goto out; - } + if (rc < 0) + return TCM_RESERVATION_CONFLICT; - ret = 0; spin_lock(&dev->dev_reservation_lock); if (!dev->dev_reserved_node_acl || !sess) goto out_unlock; @@ -216,25 +213,24 @@ int target_scsi2_reservation_release(struct se_cmd *cmd) out_unlock: spin_unlock(&dev->dev_reservation_lock); out: - if (!ret) - target_complete_cmd(cmd, GOOD); - return ret; + target_complete_cmd(cmd, GOOD); + return 0; } -int target_scsi2_reservation_reserve(struct se_cmd *cmd) +sense_reason_t +target_scsi2_reservation_reserve(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_session *sess = cmd->se_sess; struct se_portal_group *tpg; - int ret = 0, rc; + sense_reason_t ret = 0; + int rc; if ((cmd->t_task_cdb[1] & 0x01) && (cmd->t_task_cdb[1] & 0x02)) { pr_err("LongIO and Obselete Bits set, returning" " ILLEGAL_REQUEST\n"); - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; - ret = -EINVAL; - goto out; + return TCM_UNSUPPORTED_SCSI_OPCODE; } /* * This is currently the case for target_core_mod passthrough struct se_cmd @@ -245,13 +241,10 @@ int target_scsi2_reservation_reserve(struct se_cmd *cmd) rc = target_check_scsi2_reservation_conflict(cmd); if (rc == 1) goto out; - else if (rc < 0) { - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - ret = -EINVAL; - goto out; - } - ret = 0; + if (rc < 0) + return TCM_RESERVATION_CONFLICT; + tpg = sess->se_tpg; spin_lock(&dev->dev_reservation_lock); if (dev->dev_reserved_node_acl && @@ -265,8 +258,7 @@ int target_scsi2_reservation_reserve(struct se_cmd *cmd) " from %s \n", cmd->se_lun->unpacked_lun, cmd->se_deve->mapped_lun, sess->se_node_acl->initiatorname); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - ret = -EINVAL; + ret = TCM_RESERVATION_CONFLICT; goto out_unlock; } @@ -536,7 +528,8 @@ static int core_scsi3_pr_seq_non_holder( return 1; /* Conflict by default */ } -static int target_scsi3_pr_reservation_check(struct se_cmd *cmd) +static sense_reason_t +target_scsi3_pr_reservation_check(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_session *sess = cmd->se_sess; @@ -562,7 +555,7 @@ static int target_scsi3_pr_reservation_check(struct se_cmd *cmd) check_nonholder: if (core_scsi3_pr_seq_non_holder(cmd, pr_reg_type)) - return -EBUSY; + return TCM_RESERVATION_CONFLICT; return 0; } @@ -1435,7 +1428,8 @@ static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *se_deve) smp_mb__after_atomic_dec(); } -static int core_scsi3_decode_spec_i_port( +static sense_reason_t +core_scsi3_decode_spec_i_port( struct se_cmd *cmd, struct se_portal_group *tpg, unsigned char *l_isid, @@ -1457,8 +1451,9 @@ static int core_scsi3_decode_spec_i_port( unsigned char *buf; unsigned char *ptr, *i_str = NULL, proto_ident, tmp_proto_ident; char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN]; + sense_reason_t ret; u32 tpdl, tid_len = 0; - int ret, dest_local_nexus, prf_isid; + int dest_local_nexus, prf_isid; u32 dest_rtpi = 0; memset(dest_iport, 0, 64); @@ -1473,8 +1468,7 @@ static int core_scsi3_decode_spec_i_port( tidh_new = kzalloc(sizeof(struct pr_transport_id_holder), GFP_KERNEL); if (!tidh_new) { pr_err("Unable to allocate tidh_new\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } INIT_LIST_HEAD(&tidh_new->dest_list); tidh_new->dest_tpg = tpg; @@ -1486,8 +1480,7 @@ static int core_scsi3_decode_spec_i_port( sa_res_key, all_tg_pt, aptpl); if (!local_pr_reg) { kfree(tidh_new); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -ENOMEM; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } tidh_new->dest_pr_reg = local_pr_reg; /* @@ -1501,12 +1494,16 @@ static int core_scsi3_decode_spec_i_port( if (cmd->data_length < 28) { pr_warn("SPC-PR: Received PR OUT parameter list" " length too small: %u\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } buf = transport_kmap_data_sg(cmd); + if (!buf) { + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out; + } + /* * For a PERSISTENT RESERVE OUT specify initiator ports payload, * first extract TransportID Parameter Data Length, and make sure @@ -1521,9 +1518,8 @@ static int core_scsi3_decode_spec_i_port( pr_err("SPC-3 PR: Illegal tpdl: %u + 28 byte header" " does not equal CDB data_length: %u\n", tpdl, cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_unmap; } /* * Start processing the received transport IDs using the @@ -1566,16 +1562,13 @@ static int core_scsi3_decode_spec_i_port( smp_mb__after_atomic_inc(); spin_unlock(&dev->se_port_lock); - ret = core_scsi3_tpg_depend_item(tmp_tpg); - if (ret != 0) { + if (core_scsi3_tpg_depend_item(tmp_tpg)) { pr_err(" core_scsi3_tpg_depend_item()" " for tmp_tpg\n"); atomic_dec(&tmp_tpg->tpg_pr_ref_count); smp_mb__after_atomic_dec(); - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - ret = -EINVAL; - goto out; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_unmap; } /* * Locate the destination initiator ACL to be registered @@ -1597,17 +1590,14 @@ static int core_scsi3_decode_spec_i_port( continue; } - ret = core_scsi3_nodeacl_depend_item(dest_node_acl); - if (ret != 0) { + if (core_scsi3_nodeacl_depend_item(dest_node_acl)) { pr_err("configfs_depend_item() failed" " for dest_node_acl->acl_group\n"); atomic_dec(&dest_node_acl->acl_pr_ref_count); smp_mb__after_atomic_dec(); core_scsi3_tpg_undepend_item(tmp_tpg); - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - ret = -EINVAL; - goto out; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_unmap; } dest_tpg = tmp_tpg; @@ -1624,9 +1614,8 @@ static int core_scsi3_decode_spec_i_port( if (!dest_tpg) { pr_err("SPC-3 PR SPEC_I_PT: Unable to locate" " dest_tpg\n"); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_unmap; } pr_debug("SPC-3 PR SPEC_I_PT: Got %s data_length: %u tpdl: %u" @@ -1639,9 +1628,8 @@ static int core_scsi3_decode_spec_i_port( " %u for Transport ID: %s\n", tid_len, ptr); core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_tpg); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_unmap; } /* * Locate the desintation struct se_dev_entry pointer for matching @@ -1658,23 +1646,19 @@ static int core_scsi3_decode_spec_i_port( core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_tpg); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_unmap; } - ret = core_scsi3_lunacl_depend_item(dest_se_deve); - if (ret < 0) { + if (core_scsi3_lunacl_depend_item(dest_se_deve)) { pr_err("core_scsi3_lunacl_depend_item()" " failed\n"); atomic_dec(&dest_se_deve->pr_ref_count); smp_mb__after_atomic_dec(); core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_tpg); - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - ret = -EINVAL; - goto out; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_unmap; } pr_debug("SPC-3 PR SPEC_I_PT: Located %s Node: %s" @@ -1710,10 +1694,8 @@ static int core_scsi3_decode_spec_i_port( core_scsi3_lunacl_undepend_item(dest_se_deve); core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_tpg); - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - ret = -ENOMEM; - goto out; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_unmap; } INIT_LIST_HEAD(&tidh_new->dest_list); tidh_new->dest_tpg = dest_tpg; @@ -1744,9 +1726,8 @@ static int core_scsi3_decode_spec_i_port( core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_tpg); kfree(tidh_new); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_unmap; } tidh_new->dest_pr_reg = dest_pr_reg; list_add_tail(&tidh_new->dest_list, &tid_dest_list); @@ -1804,8 +1785,9 @@ static int core_scsi3_decode_spec_i_port( } return 0; -out: +out_unmap: transport_kunmap_data_sg(cmd); +out: /* * For the failure case, release everything from tid_dest_list * including *dest_pr_reg and the configfs dependances.. @@ -2020,14 +2002,15 @@ static int __core_scsi3_write_aptpl_to_file( return 0; } -static int core_scsi3_update_and_write_aptpl( - struct se_device *dev, - unsigned char *in_buf, - u32 in_pr_aptpl_buf_len) +static int +core_scsi3_update_and_write_aptpl(struct se_device *dev, unsigned char *in_buf, + u32 in_pr_aptpl_buf_len) { unsigned char null_buf[64], *buf; u32 pr_aptpl_buf_len; - int ret, clear_aptpl_metadata = 0; + int clear_aptpl_metadata = 0; + int ret; + /* * Can be called with a NULL pointer from PROUT service action CLEAR */ @@ -2049,25 +2032,17 @@ static int core_scsi3_update_and_write_aptpl( clear_aptpl_metadata); if (ret != 0) return ret; + /* * __core_scsi3_write_aptpl_to_file() will call strlen() * on the passed buf to determine pr_aptpl_buf_len. */ - ret = __core_scsi3_write_aptpl_to_file(dev, buf, 0); - if (ret != 0) - return ret; - - return ret; + return __core_scsi3_write_aptpl_to_file(dev, buf, 0); } -static int core_scsi3_emulate_pro_register( - struct se_cmd *cmd, - u64 res_key, - u64 sa_res_key, - int aptpl, - int all_tg_pt, - int spec_i_pt, - int ignore_key) +static sense_reason_t +core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, + int aptpl, int all_tg_pt, int spec_i_pt, int ignore_key) { struct se_session *se_sess = cmd->se_sess; struct se_device *dev = cmd->se_dev; @@ -2079,12 +2054,12 @@ static int core_scsi3_emulate_pro_register( /* Used for APTPL metadata w/ UNREGISTER */ unsigned char *pr_aptpl_buf = NULL; unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL; - int pr_holder = 0, ret = 0, type; + sense_reason_t ret; + int pr_holder = 0, type; if (!se_sess || !se_lun) { pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } se_tpg = se_sess->se_tpg; se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun]; @@ -2103,8 +2078,7 @@ static int core_scsi3_emulate_pro_register( if (res_key) { pr_warn("SPC-3 PR: Reservation Key non-zero" " for SA REGISTER, returning CONFLICT\n"); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + return TCM_RESERVATION_CONFLICT; } /* * Do nothing but return GOOD status. @@ -2118,15 +2092,13 @@ static int core_scsi3_emulate_pro_register( * Port Endpoint that the PRO was received from on the * Logical Unit of the SCSI device server. */ - ret = core_scsi3_alloc_registration(cmd->se_dev, + if (core_scsi3_alloc_registration(cmd->se_dev, se_sess->se_node_acl, se_deve, isid_ptr, sa_res_key, all_tg_pt, aptpl, - ignore_key, 0); - if (ret != 0) { + ignore_key, 0)) { pr_err("Unable to allocate" " struct t10_pr_registration\n"); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + return TCM_INVALID_PARAMETER_LIST; } } else { /* @@ -2160,201 +2132,192 @@ static int core_scsi3_emulate_pro_register( pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl, se_sess); - ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, + if (core_scsi3_update_and_write_aptpl(cmd->se_dev, &pr_reg->pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) { + pr_tmpl->pr_aptpl_buf_len)) { pr_tmpl->pr_aptpl_active = 1; pr_debug("SPC-3 PR: Set APTPL Bit Activated for REGISTER\n"); } - core_scsi3_put_pr_reg(pr_reg); - return ret; - } else { - /* - * Locate the existing *pr_reg via struct se_node_acl pointers - */ - pr_reg = pr_reg_e; - type = pr_reg->pr_res_type; - - if (!ignore_key) { - if (res_key != pr_reg->pr_res_key) { - pr_err("SPC-3 PR REGISTER: Received" - " res_key: 0x%016Lx does not match" - " existing SA REGISTER res_key:" - " 0x%016Lx\n", res_key, - pr_reg->pr_res_key); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; - } + goto out_put_pr_reg; + } + + /* + * Locate the existing *pr_reg via struct se_node_acl pointers + */ + pr_reg = pr_reg_e; + type = pr_reg->pr_res_type; + + if (!ignore_key) { + if (res_key != pr_reg->pr_res_key) { + pr_err("SPC-3 PR REGISTER: Received" + " res_key: 0x%016Lx does not match" + " existing SA REGISTER res_key:" + " 0x%016Lx\n", res_key, + pr_reg->pr_res_key); + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } - if (spec_i_pt) { - pr_err("SPC-3 PR UNREGISTER: SPEC_I_PT" - " set while sa_res_key=0\n"); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + } + + if (spec_i_pt) { + pr_err("SPC-3 PR UNREGISTER: SPEC_I_PT" + " set while sa_res_key=0\n"); + ret = TCM_INVALID_PARAMETER_LIST; + goto out_put_pr_reg; + } + + /* + * An existing ALL_TG_PT=1 registration being released + * must also set ALL_TG_PT=1 in the incoming PROUT. + */ + if (pr_reg->pr_reg_all_tg_pt && !(all_tg_pt)) { + pr_err("SPC-3 PR UNREGISTER: ALL_TG_PT=1" + " registration exists, but ALL_TG_PT=1 bit not" + " present in received PROUT\n"); + ret = TCM_INVALID_CDB_FIELD; + goto out_put_pr_reg; + } + + /* + * Allocate APTPL metadata buffer used for UNREGISTER ops + */ + if (aptpl) { + pr_aptpl_buf = kzalloc(pr_tmpl->pr_aptpl_buf_len, + GFP_KERNEL); + if (!pr_aptpl_buf) { + pr_err("Unable to allocate" + " pr_aptpl_buf\n"); + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_put_pr_reg; } - /* - * An existing ALL_TG_PT=1 registration being released - * must also set ALL_TG_PT=1 in the incoming PROUT. - */ - if (pr_reg->pr_reg_all_tg_pt && !(all_tg_pt)) { - pr_err("SPC-3 PR UNREGISTER: ALL_TG_PT=1" - " registration exists, but ALL_TG_PT=1 bit not" - " present in received PROUT\n"); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + } + + /* + * sa_res_key=0 Unregister Reservation Key for registered I_T + * Nexus sa_res_key=1 Change Reservation Key for registered I_T + * Nexus. + */ + if (!sa_res_key) { + pr_holder = core_scsi3_check_implict_release( + cmd->se_dev, pr_reg); + if (pr_holder < 0) { + kfree(pr_aptpl_buf); + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } + + spin_lock(&pr_tmpl->registration_lock); /* - * Allocate APTPL metadata buffer used for UNREGISTER ops + * Release all ALL_TG_PT=1 for the matching SCSI Initiator Port + * and matching pr_res_key. */ - if (aptpl) { - pr_aptpl_buf = kzalloc(pr_tmpl->pr_aptpl_buf_len, - GFP_KERNEL); - if (!pr_aptpl_buf) { - pr_err("Unable to allocate" - " pr_aptpl_buf\n"); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + if (pr_reg->pr_reg_all_tg_pt) { + list_for_each_entry_safe(pr_reg_p, pr_reg_tmp, + &pr_tmpl->registration_list, + pr_reg_list) { + + if (!pr_reg_p->pr_reg_all_tg_pt) + continue; + if (pr_reg_p->pr_res_key != res_key) + continue; + if (pr_reg == pr_reg_p) + continue; + if (strcmp(pr_reg->pr_reg_nacl->initiatorname, + pr_reg_p->pr_reg_nacl->initiatorname)) + continue; + + __core_scsi3_free_registration(dev, + pr_reg_p, NULL, 0); } } + /* - * sa_res_key=0 Unregister Reservation Key for registered I_T - * Nexus sa_res_key=1 Change Reservation Key for registered I_T - * Nexus. + * Release the calling I_T Nexus registration now.. */ - if (!sa_res_key) { - pr_holder = core_scsi3_check_implict_release( - cmd->se_dev, pr_reg); - if (pr_holder < 0) { - kfree(pr_aptpl_buf); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; - } - - spin_lock(&pr_tmpl->registration_lock); - /* - * Release all ALL_TG_PT=1 for the matching SCSI Initiator Port - * and matching pr_res_key. - */ - if (pr_reg->pr_reg_all_tg_pt) { - list_for_each_entry_safe(pr_reg_p, pr_reg_tmp, - &pr_tmpl->registration_list, - pr_reg_list) { - - if (!pr_reg_p->pr_reg_all_tg_pt) - continue; + __core_scsi3_free_registration(cmd->se_dev, pr_reg, NULL, 1); - if (pr_reg_p->pr_res_key != res_key) - continue; - - if (pr_reg == pr_reg_p) - continue; - - if (strcmp(pr_reg->pr_reg_nacl->initiatorname, - pr_reg_p->pr_reg_nacl->initiatorname)) - continue; - - __core_scsi3_free_registration(dev, - pr_reg_p, NULL, 0); - } - } - /* - * Release the calling I_T Nexus registration now.. - */ - __core_scsi3_free_registration(cmd->se_dev, pr_reg, - NULL, 1); - /* - * From spc4r17, section 5.7.11.3 Unregistering - * - * If the persistent reservation is a registrants only - * type, the device server shall establish a unit - * attention condition for the initiator port associated - * with every registered I_T nexus except for the I_T - * nexus on which the PERSISTENT RESERVE OUT command was - * received, with the additional sense code set to - * RESERVATIONS RELEASED. - */ - if (pr_holder && - ((type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY) || - (type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY))) { - list_for_each_entry(pr_reg_p, - &pr_tmpl->registration_list, - pr_reg_list) { - - core_scsi3_ua_allocate( - pr_reg_p->pr_reg_nacl, - pr_reg_p->pr_res_mapped_lun, - 0x2A, - ASCQ_2AH_RESERVATIONS_RELEASED); - } + /* + * From spc4r17, section 5.7.11.3 Unregistering + * + * If the persistent reservation is a registrants only + * type, the device server shall establish a unit + * attention condition for the initiator port associated + * with every registered I_T nexus except for the I_T + * nexus on which the PERSISTENT RESERVE OUT command was + * received, with the additional sense code set to + * RESERVATIONS RELEASED. + */ + if (pr_holder && + (type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY || + type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY)) { + list_for_each_entry(pr_reg_p, + &pr_tmpl->registration_list, + pr_reg_list) { + + core_scsi3_ua_allocate( + pr_reg_p->pr_reg_nacl, + pr_reg_p->pr_res_mapped_lun, + 0x2A, + ASCQ_2AH_RESERVATIONS_RELEASED); } - spin_unlock(&pr_tmpl->registration_lock); + } + spin_unlock(&pr_tmpl->registration_lock); - if (!aptpl) { - pr_tmpl->pr_aptpl_active = 0; - core_scsi3_update_and_write_aptpl(dev, NULL, 0); - pr_debug("SPC-3 PR: Set APTPL Bit Deactivated" - " for UNREGISTER\n"); - return 0; - } + if (!aptpl) { + pr_tmpl->pr_aptpl_active = 0; + core_scsi3_update_and_write_aptpl(dev, NULL, 0); + pr_debug("SPC-3 PR: Set APTPL Bit Deactivated" + " for UNREGISTER\n"); + return 0; + } - ret = core_scsi3_update_and_write_aptpl(dev, - &pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) { - pr_tmpl->pr_aptpl_active = 1; - pr_debug("SPC-3 PR: Set APTPL Bit Activated" - " for UNREGISTER\n"); - } + if (!core_scsi3_update_and_write_aptpl(dev, &pr_aptpl_buf[0], + pr_tmpl->pr_aptpl_buf_len)) { + pr_tmpl->pr_aptpl_active = 1; + pr_debug("SPC-3 PR: Set APTPL Bit Activated" + " for UNREGISTER\n"); + } - kfree(pr_aptpl_buf); - return ret; - } else { - /* - * Increment PRgeneration counter for struct se_device" - * upon a successful REGISTER, see spc4r17 section 6.3.2 - * READ_KEYS service action. - */ - pr_reg->pr_res_generation = core_scsi3_pr_generation( - cmd->se_dev); - pr_reg->pr_res_key = sa_res_key; - pr_debug("SPC-3 PR [%s] REGISTER%s: Changed Reservation" - " Key for %s to: 0x%016Lx PRgeneration:" - " 0x%08x\n", cmd->se_tfo->get_fabric_name(), - (ignore_key) ? "_AND_IGNORE_EXISTING_KEY" : "", - pr_reg->pr_reg_nacl->initiatorname, - pr_reg->pr_res_key, pr_reg->pr_res_generation); - - if (!aptpl) { - pr_tmpl->pr_aptpl_active = 0; - core_scsi3_update_and_write_aptpl(dev, NULL, 0); - core_scsi3_put_pr_reg(pr_reg); - pr_debug("SPC-3 PR: Set APTPL Bit Deactivated" - " for REGISTER\n"); - return 0; - } + goto out_free_aptpl_buf; + } - ret = core_scsi3_update_and_write_aptpl(dev, - &pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) { - pr_tmpl->pr_aptpl_active = 1; - pr_debug("SPC-3 PR: Set APTPL Bit Activated" - " for REGISTER\n"); - } + /* + * Increment PRgeneration counter for struct se_device" + * upon a successful REGISTER, see spc4r17 section 6.3.2 + * READ_KEYS service action. + */ + pr_reg->pr_res_generation = core_scsi3_pr_generation(cmd->se_dev); + pr_reg->pr_res_key = sa_res_key; + pr_debug("SPC-3 PR [%s] REGISTER%s: Changed Reservation" + " Key for %s to: 0x%016Lx PRgeneration:" + " 0x%08x\n", cmd->se_tfo->get_fabric_name(), + (ignore_key) ? "_AND_IGNORE_EXISTING_KEY" : "", + pr_reg->pr_reg_nacl->initiatorname, + pr_reg->pr_res_key, pr_reg->pr_res_generation); - kfree(pr_aptpl_buf); - core_scsi3_put_pr_reg(pr_reg); - } + if (!aptpl) { + pr_tmpl->pr_aptpl_active = 0; + core_scsi3_update_and_write_aptpl(dev, NULL, 0); + pr_debug("SPC-3 PR: Set APTPL Bit Deactivated" + " for REGISTER\n"); + ret = 0; + goto out_put_pr_reg; } - return 0; + + if (!core_scsi3_update_and_write_aptpl(dev, &pr_aptpl_buf[0], + pr_tmpl->pr_aptpl_buf_len)) { + pr_tmpl->pr_aptpl_active = 1; + pr_debug("SPC-3 PR: Set APTPL Bit Activated" + " for REGISTER\n"); + } + +out_free_aptpl_buf: + kfree(pr_aptpl_buf); + ret = 0; +out_put_pr_reg: + core_scsi3_put_pr_reg(pr_reg); + return ret; } unsigned char *core_scsi3_pr_dump_type(int type) @@ -2379,26 +2342,23 @@ unsigned char *core_scsi3_pr_dump_type(int type) return "Unknown SPC-3 PR Type"; } -static int core_scsi3_pro_reserve( - struct se_cmd *cmd, - struct se_device *dev, - int type, - int scope, - u64 res_key) +static sense_reason_t +core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key) { + struct se_device *dev = cmd->se_dev; struct se_session *se_sess = cmd->se_sess; struct se_lun *se_lun = cmd->se_lun; struct t10_pr_registration *pr_reg, *pr_res_holder; struct t10_reservation *pr_tmpl = &dev->t10_pr; char i_buf[PR_REG_ISID_ID_LEN]; - int ret, prf_isid; + sense_reason_t ret; + int prf_isid; memset(i_buf, 0, PR_REG_ISID_ID_LEN); if (!se_sess || !se_lun) { pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } /* * Locate the existing *pr_reg via struct se_node_acl pointers @@ -2408,8 +2368,7 @@ static int core_scsi3_pro_reserve( if (!pr_reg) { pr_err("SPC-3 PR: Unable to locate" " PR_REGISTERED *pr_reg for RESERVE\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } /* * From spc4r17 Section 5.7.9: Reserving: @@ -2424,9 +2383,8 @@ static int core_scsi3_pro_reserve( pr_err("SPC-3 PR RESERVE: Received res_key: 0x%016Lx" " does not match existing SA REGISTER res_key:" " 0x%016Lx\n", res_key, pr_reg->pr_res_key); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } /* * From spc4r17 Section 5.7.9: Reserving: @@ -2440,9 +2398,8 @@ static int core_scsi3_pro_reserve( */ if (scope != PR_SCOPE_LU_SCOPE) { pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_put_pr_reg; } /* * See if we have an existing PR reservation holder pointer at @@ -2473,9 +2430,8 @@ static int core_scsi3_pro_reserve( pr_res_holder->pr_reg_nacl->initiatorname); spin_unlock(&dev->dev_reservation_lock); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } /* * From spc4r17 Section 5.7.9: Reserving: @@ -2497,9 +2453,8 @@ static int core_scsi3_pro_reserve( pr_res_holder->pr_reg_nacl->initiatorname); spin_unlock(&dev->dev_reservation_lock); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } /* * From spc4r17 Section 5.7.9: Reserving: @@ -2512,8 +2467,8 @@ static int core_scsi3_pro_reserve( * shall completethe command with GOOD status. */ spin_unlock(&dev->dev_reservation_lock); - core_scsi3_put_pr_reg(pr_reg); - return 0; + ret = 0; + goto out_put_pr_reg; } /* * Otherwise, our *pr_reg becomes the PR reservation holder for said @@ -2537,27 +2492,24 @@ static int core_scsi3_pro_reserve( spin_unlock(&dev->dev_reservation_lock); if (pr_tmpl->pr_aptpl_active) { - ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, + if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, &pr_reg->pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) + pr_tmpl->pr_aptpl_buf_len)) { pr_debug("SPC-3 PR: Updated APTPL metadata" " for RESERVE\n"); + } } + ret = 0; +out_put_pr_reg: core_scsi3_put_pr_reg(pr_reg); - return 0; + return ret; } -static int core_scsi3_emulate_pro_reserve( - struct se_cmd *cmd, - int type, - int scope, - u64 res_key) +static sense_reason_t +core_scsi3_emulate_pro_reserve(struct se_cmd *cmd, int type, int scope, + u64 res_key) { - struct se_device *dev = cmd->se_dev; - int ret = 0; - switch (type) { case PR_TYPE_WRITE_EXCLUSIVE: case PR_TYPE_EXCLUSIVE_ACCESS: @@ -2565,16 +2517,12 @@ static int core_scsi3_emulate_pro_reserve( case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY: case PR_TYPE_WRITE_EXCLUSIVE_ALLREG: case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG: - ret = core_scsi3_pro_reserve(cmd, dev, type, scope, res_key); - break; + return core_scsi3_pro_reserve(cmd, type, scope, res_key); default: pr_err("SPC-3 PR: Unknown Service Action RESERVE Type:" " 0x%02x\n", type); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } - - return ret; } /* @@ -2612,23 +2560,21 @@ static void __core_scsi3_complete_pro_release( pr_reg->pr_res_holder = pr_reg->pr_res_type = pr_reg->pr_res_scope = 0; } -static int core_scsi3_emulate_pro_release( - struct se_cmd *cmd, - int type, - int scope, - u64 res_key) +static sense_reason_t +core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope, + u64 res_key) { struct se_device *dev = cmd->se_dev; struct se_session *se_sess = cmd->se_sess; struct se_lun *se_lun = cmd->se_lun; struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_res_holder; struct t10_reservation *pr_tmpl = &dev->t10_pr; - int ret, all_reg = 0; + int all_reg = 0; + sense_reason_t ret = 0; if (!se_sess || !se_lun) { pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } /* * Locate the existing *pr_reg via struct se_node_acl pointers @@ -2637,8 +2583,7 @@ static int core_scsi3_emulate_pro_release( if (!pr_reg) { pr_err("SPC-3 PR: Unable to locate" " PR_REGISTERED *pr_reg for RELEASE\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } /* * From spc4r17 Section 5.7.11.2 Releasing: @@ -2659,7 +2604,6 @@ static int core_scsi3_emulate_pro_release( * No persistent reservation, return GOOD status. */ spin_unlock(&dev->dev_reservation_lock); - core_scsi3_put_pr_reg(pr_reg); return 0; } if ((pr_res_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) || @@ -2673,9 +2617,9 @@ static int core_scsi3_emulate_pro_release( * persistent reservation holder. return GOOD status. */ spin_unlock(&dev->dev_reservation_lock); - core_scsi3_put_pr_reg(pr_reg); - return 0; + goto out_put_pr_reg; } + /* * From spc4r17 Section 5.7.11.2 Releasing: * @@ -2695,9 +2639,8 @@ static int core_scsi3_emulate_pro_release( " does not match existing SA REGISTER res_key:" " 0x%016Lx\n", res_key, pr_reg->pr_res_key); spin_unlock(&dev->dev_reservation_lock); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } /* * From spc4r17 Section 5.7.11.2 Releasing and above: @@ -2718,9 +2661,8 @@ static int core_scsi3_emulate_pro_release( pr_res_holder->pr_reg_nacl->initiatorname); spin_unlock(&dev->dev_reservation_lock); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } /* * In response to a persistent reservation release request from the @@ -2773,20 +2715,18 @@ static int core_scsi3_emulate_pro_release( write_aptpl: if (pr_tmpl->pr_aptpl_active) { - ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, - &pr_reg->pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) + if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, + &pr_reg->pr_aptpl_buf[0], pr_tmpl->pr_aptpl_buf_len)) { pr_debug("SPC-3 PR: Updated APTPL metadata for RELEASE\n"); + } } - +out_put_pr_reg: core_scsi3_put_pr_reg(pr_reg); - return 0; + return ret; } -static int core_scsi3_emulate_pro_clear( - struct se_cmd *cmd, - u64 res_key) +static sense_reason_t +core_scsi3_emulate_pro_clear(struct se_cmd *cmd, u64 res_key) { struct se_device *dev = cmd->se_dev; struct se_node_acl *pr_reg_nacl; @@ -2803,8 +2743,7 @@ static int core_scsi3_emulate_pro_clear( if (!pr_reg_n) { pr_err("SPC-3 PR: Unable to locate" " PR_REGISTERED *pr_reg for CLEAR\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } /* * From spc4r17 section 5.7.11.6, Clearing: @@ -2823,8 +2762,7 @@ static int core_scsi3_emulate_pro_clear( " existing SA REGISTER res_key:" " 0x%016Lx\n", res_key, pr_reg_n->pr_res_key); core_scsi3_put_pr_reg(pr_reg_n); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + return TCM_RESERVATION_CONFLICT; } /* * a) Release the persistent reservation, if any; @@ -2948,13 +2886,9 @@ static void core_scsi3_release_preempt_and_abort( } } -static int core_scsi3_pro_preempt( - struct se_cmd *cmd, - int type, - int scope, - u64 res_key, - u64 sa_res_key, - int abort) +static sense_reason_t +core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, + u64 sa_res_key, int abort) { struct se_device *dev = cmd->se_dev; struct se_node_acl *pr_reg_nacl; @@ -2964,12 +2898,10 @@ static int core_scsi3_pro_preempt( struct t10_reservation *pr_tmpl = &dev->t10_pr; u32 pr_res_mapped_lun = 0; int all_reg = 0, calling_it_nexus = 0, released_regs = 0; - int prh_type = 0, prh_scope = 0, ret; + int prh_type = 0, prh_scope = 0; - if (!se_sess) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; - } + if (!se_sess) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; pr_reg_n = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl, se_sess); @@ -2977,19 +2909,16 @@ static int core_scsi3_pro_preempt( pr_err("SPC-3 PR: Unable to locate" " PR_REGISTERED *pr_reg for PREEMPT%s\n", (abort) ? "_AND_ABORT" : ""); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + return TCM_RESERVATION_CONFLICT; } if (pr_reg_n->pr_res_key != res_key) { core_scsi3_put_pr_reg(pr_reg_n); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + return TCM_RESERVATION_CONFLICT; } if (scope != PR_SCOPE_LU_SCOPE) { pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope); core_scsi3_put_pr_reg(pr_reg_n); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + return TCM_INVALID_PARAMETER_LIST; } spin_lock(&dev->dev_reservation_lock); @@ -3002,8 +2931,7 @@ static int core_scsi3_pro_preempt( if (!all_reg && !sa_res_key) { spin_unlock(&dev->dev_reservation_lock); core_scsi3_put_pr_reg(pr_reg_n); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + return TCM_INVALID_PARAMETER_LIST; } /* * From spc4r17, section 5.7.11.4.4 Removing Registrations: @@ -3097,8 +3025,7 @@ static int core_scsi3_pro_preempt( if (!released_regs) { spin_unlock(&dev->dev_reservation_lock); core_scsi3_put_pr_reg(pr_reg_n); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + return TCM_RESERVATION_CONFLICT; } /* * For an existing all registrants type reservation @@ -3117,13 +3044,13 @@ static int core_scsi3_pro_preempt( spin_unlock(&dev->dev_reservation_lock); if (pr_tmpl->pr_aptpl_active) { - ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, + if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, &pr_reg_n->pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) + pr_tmpl->pr_aptpl_buf_len)) { pr_debug("SPC-3 PR: Updated APTPL" " metadata for PREEMPT%s\n", (abort) ? "_AND_ABORT" : ""); + } } core_scsi3_put_pr_reg(pr_reg_n); @@ -3253,12 +3180,12 @@ static int core_scsi3_pro_preempt( } if (pr_tmpl->pr_aptpl_active) { - ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, + if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, &pr_reg_n->pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) + pr_tmpl->pr_aptpl_buf_len)) { pr_debug("SPC-3 PR: Updated APTPL metadata for PREEMPT" - "%s\n", (abort) ? "_AND_ABORT" : ""); + "%s\n", abort ? "_AND_ABORT" : ""); + } } core_scsi3_put_pr_reg(pr_reg_n); @@ -3266,16 +3193,10 @@ static int core_scsi3_pro_preempt( return 0; } -static int core_scsi3_emulate_pro_preempt( - struct se_cmd *cmd, - int type, - int scope, - u64 res_key, - u64 sa_res_key, - int abort) +static sense_reason_t +core_scsi3_emulate_pro_preempt(struct se_cmd *cmd, int type, int scope, + u64 res_key, u64 sa_res_key, int abort) { - int ret = 0; - switch (type) { case PR_TYPE_WRITE_EXCLUSIVE: case PR_TYPE_EXCLUSIVE_ACCESS: @@ -3283,26 +3204,19 @@ static int core_scsi3_emulate_pro_preempt( case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY: case PR_TYPE_WRITE_EXCLUSIVE_ALLREG: case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG: - ret = core_scsi3_pro_preempt(cmd, type, scope, - res_key, sa_res_key, abort); - break; + return core_scsi3_pro_preempt(cmd, type, scope, res_key, + sa_res_key, abort); default: pr_err("SPC-3 PR: Unknown Service Action PREEMPT%s" " Type: 0x%02x\n", (abort) ? "_AND_ABORT" : "", type); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } - - return ret; } -static int core_scsi3_emulate_pro_register_and_move( - struct se_cmd *cmd, - u64 res_key, - u64 sa_res_key, - int aptpl, - int unreg) +static sense_reason_t +core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key, + u64 sa_res_key, int aptpl, int unreg) { struct se_session *se_sess = cmd->se_sess; struct se_device *dev = cmd->se_dev; @@ -3318,15 +3232,16 @@ static int core_scsi3_emulate_pro_register_and_move( unsigned char *initiator_str; char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN]; u32 tid_len, tmp_tid_len; - int new_reg = 0, type, scope, ret, matching_iname, prf_isid; + int new_reg = 0, type, scope, matching_iname, prf_isid; + sense_reason_t ret; unsigned short rtpi; unsigned char proto_ident; if (!se_sess || !se_lun) { pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } + memset(dest_iport, 0, 64); memset(i_buf, 0, PR_REG_ISID_ID_LEN); se_tpg = se_sess->se_tpg; @@ -3342,8 +3257,7 @@ static int core_scsi3_emulate_pro_register_and_move( if (!pr_reg) { pr_err("SPC-3 PR: Unable to locate PR_REGISTERED" " *pr_reg for REGISTER_AND_MOVE\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } /* * The provided reservation key much match the existing reservation key @@ -3353,9 +3267,8 @@ static int core_scsi3_emulate_pro_register_and_move( pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received" " res_key: 0x%016Lx does not match existing SA REGISTER" " res_key: 0x%016Lx\n", res_key, pr_reg->pr_res_key); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + ret = TCM_RESERVATION_CONFLICT; + goto out_put_pr_reg; } /* * The service active reservation key needs to be non zero @@ -3363,9 +3276,8 @@ static int core_scsi3_emulate_pro_register_and_move( if (!sa_res_key) { pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received zero" " sa_res_key\n"); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_put_pr_reg; } /* @@ -3374,6 +3286,11 @@ static int core_scsi3_emulate_pro_register_and_move( * information. */ buf = transport_kmap_data_sg(cmd); + if (!buf) { + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_put_pr_reg; + } + rtpi = (buf[18] & 0xff) << 8; rtpi |= buf[19] & 0xff; tid_len = (buf[20] & 0xff) << 24; @@ -3387,9 +3304,8 @@ static int core_scsi3_emulate_pro_register_and_move( pr_err("SPC-3 PR: Illegal tid_len: %u + 24 byte header" " does not equal CDB data_length: %u\n", tid_len, cmd->data_length); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_put_pr_reg; } spin_lock(&dev->se_port_lock); @@ -3407,15 +3323,13 @@ static int core_scsi3_emulate_pro_register_and_move( smp_mb__after_atomic_inc(); spin_unlock(&dev->se_port_lock); - ret = core_scsi3_tpg_depend_item(dest_se_tpg); - if (ret != 0) { + if (core_scsi3_tpg_depend_item(dest_se_tpg)) { pr_err("core_scsi3_tpg_depend_item() failed" " for dest_se_tpg\n"); atomic_dec(&dest_se_tpg->tpg_pr_ref_count); smp_mb__after_atomic_dec(); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_put_pr_reg; } spin_lock(&dev->se_port_lock); @@ -3427,12 +3341,15 @@ static int core_scsi3_emulate_pro_register_and_move( pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate" " fabric ops from Relative Target Port Identifier:" " %hu\n", rtpi); - core_scsi3_put_pr_reg(pr_reg); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - return -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; + goto out_put_pr_reg; } buf = transport_kmap_data_sg(cmd); + if (!buf) { + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto out_put_pr_reg; + } proto_ident = (buf[24] & 0x0f); pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:" @@ -3444,16 +3361,14 @@ static int core_scsi3_emulate_pro_register_and_move( " from fabric: %s\n", proto_ident, dest_tf_ops->get_fabric_proto_ident(dest_se_tpg), dest_tf_ops->get_fabric_name()); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } if (dest_tf_ops->tpg_parse_pr_out_transport_id == NULL) { pr_err("SPC-3 PR REGISTER_AND_MOVE: Fabric does not" " containg a valid tpg_parse_pr_out_transport_id" " function pointer\n"); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - ret = -EINVAL; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; goto out; } initiator_str = dest_tf_ops->tpg_parse_pr_out_transport_id(dest_se_tpg, @@ -3461,8 +3376,7 @@ static int core_scsi3_emulate_pro_register_and_move( if (!initiator_str) { pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate" " initiator_str from Transport ID\n"); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } @@ -3491,8 +3405,7 @@ static int core_scsi3_emulate_pro_register_and_move( pr_err("SPC-3 PR REGISTER_AND_MOVE: TransportID: %s" " matches: %s on received I_T Nexus\n", initiator_str, pr_reg_nacl->initiatorname); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } if (!strcmp(iport_ptr, pr_reg->pr_reg_isid)) { @@ -3500,8 +3413,7 @@ static int core_scsi3_emulate_pro_register_and_move( " matches: %s %s on received I_T Nexus\n", initiator_str, iport_ptr, pr_reg_nacl->initiatorname, pr_reg->pr_reg_isid); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } after_iport_check: @@ -3521,19 +3433,17 @@ after_iport_check: pr_err("Unable to locate %s dest_node_acl for" " TransportID%s\n", dest_tf_ops->get_fabric_name(), initiator_str); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } - ret = core_scsi3_nodeacl_depend_item(dest_node_acl); - if (ret != 0) { + + if (core_scsi3_nodeacl_depend_item(dest_node_acl)) { pr_err("core_scsi3_nodeacl_depend_item() for" " dest_node_acl\n"); atomic_dec(&dest_node_acl->acl_pr_ref_count); smp_mb__after_atomic_dec(); dest_node_acl = NULL; - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } @@ -3549,19 +3459,16 @@ after_iport_check: if (!dest_se_deve) { pr_err("Unable to locate %s dest_se_deve from RTPI:" " %hu\n", dest_tf_ops->get_fabric_name(), rtpi); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } - ret = core_scsi3_lunacl_depend_item(dest_se_deve); - if (ret < 0) { + if (core_scsi3_lunacl_depend_item(dest_se_deve)) { pr_err("core_scsi3_lunacl_depend_item() failed\n"); atomic_dec(&dest_se_deve->pr_ref_count); smp_mb__after_atomic_dec(); dest_se_deve = NULL; - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - ret = -EINVAL; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; goto out; } @@ -3580,8 +3487,7 @@ after_iport_check: pr_warn("SPC-3 PR REGISTER_AND_MOVE: No reservation" " currently held\n"); spin_unlock(&dev->dev_reservation_lock); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - ret = -EINVAL; + ret = TCM_INVALID_CDB_FIELD; goto out; } /* @@ -3594,8 +3500,7 @@ after_iport_check: pr_warn("SPC-3 PR REGISTER_AND_MOVE: Calling I_T" " Nexus is not reservation holder\n"); spin_unlock(&dev->dev_reservation_lock); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - ret = -EINVAL; + ret = TCM_RESERVATION_CONFLICT; goto out; } /* @@ -3613,8 +3518,7 @@ after_iport_check: " reservation for type: %s\n", core_scsi3_pr_dump_type(pr_res_holder->pr_res_type)); spin_unlock(&dev->dev_reservation_lock); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - ret = -EINVAL; + ret = TCM_RESERVATION_CONFLICT; goto out; } pr_res_nacl = pr_res_holder->pr_reg_nacl; @@ -3646,13 +3550,11 @@ after_iport_check: dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl, iport_ptr); if (!dest_pr_reg) { - ret = core_scsi3_alloc_registration(cmd->se_dev, + if (core_scsi3_alloc_registration(cmd->se_dev, dest_node_acl, dest_se_deve, iport_ptr, - sa_res_key, 0, aptpl, 2, 1); - if (ret != 0) { + sa_res_key, 0, aptpl, 2, 1)) { spin_unlock(&dev->dev_reservation_lock); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; + ret = TCM_INVALID_PARAMETER_LIST; goto out; } dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl, @@ -3723,12 +3625,12 @@ after_iport_check: " REGISTER_AND_MOVE\n"); } else { pr_tmpl->pr_aptpl_active = 1; - ret = core_scsi3_update_and_write_aptpl(cmd->se_dev, + if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, &dest_pr_reg->pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len); - if (!ret) + pr_tmpl->pr_aptpl_buf_len)) { pr_debug("SPC-3 PR: Set APTPL Bit Activated for" " REGISTER_AND_MOVE\n"); + } } transport_kunmap_data_sg(cmd); @@ -3743,6 +3645,8 @@ out: if (dest_node_acl) core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_se_tpg); + +out_put_pr_reg: core_scsi3_put_pr_reg(pr_reg); return ret; } @@ -3760,14 +3664,15 @@ static unsigned long long core_scsi3_extract_reservation_key(unsigned char *cdb) /* * See spc4r17 section 6.14 Table 170 */ -int target_scsi3_emulate_pr_out(struct se_cmd *cmd) +sense_reason_t +target_scsi3_emulate_pr_out(struct se_cmd *cmd) { unsigned char *cdb = &cmd->t_task_cdb[0]; unsigned char *buf; u64 res_key, sa_res_key; int sa, scope, type, aptpl; int spec_i_pt = 0, all_tg_pt = 0, unreg = 0; - int ret; + sense_reason_t ret; /* * Following spc2r20 5.5.1 Reservations overview: @@ -3782,28 +3687,22 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) pr_err("Received PERSISTENT_RESERVE CDB while legacy" " SPC-2 reservation is held, returning" " RESERVATION_CONFLICT\n"); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - ret = -EINVAL; - goto out; + return TCM_RESERVATION_CONFLICT; } /* * FIXME: A NULL struct se_session pointer means an this is not coming from * a $FABRIC_MOD's nexus, but from internal passthrough ops. */ - if (!cmd->se_sess) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - ret = -EINVAL; - goto out; - } + if (!cmd->se_sess) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; if (cmd->data_length < 24) { pr_warn("SPC-PR: Received PR OUT parameter list" " length too small: %u\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; + return TCM_INVALID_PARAMETER_LIST; } + /* * From the PERSISTENT_RESERVE_OUT command descriptor block (CDB) */ @@ -3812,6 +3711,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) type = (cdb[2] & 0x0f); buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + /* * From PERSISTENT_RESERVE_OUT parameter list (payload) */ @@ -3835,11 +3737,8 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) /* * SPEC_I_PT=1 is only valid for Service action: REGISTER */ - if (spec_i_pt && ((cdb[1] & 0x1f) != PRO_REGISTER)) { - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; - } + if (spec_i_pt && ((cdb[1] & 0x1f) != PRO_REGISTER)) + return TCM_INVALID_PARAMETER_LIST; /* * From spc4r17 section 6.14: @@ -3854,10 +3753,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) (cmd->data_length != 24)) { pr_warn("SPC-PR: Received PR OUT illegal parameter" " list length: %u\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - goto out; + return TCM_INVALID_PARAMETER_LIST; } + /* * (core_scsi3_emulate_pro_* function parameters * are defined by spc4r17 Table 174: @@ -3896,12 +3794,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd) default: pr_err("Unknown PERSISTENT_RESERVE_OUT service" " action: 0x%02x\n", cdb[1] & 0x1f); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - ret = -EINVAL; - break; + return TCM_INVALID_CDB_FIELD; } -out: if (!ret) target_complete_cmd(cmd, GOOD); return ret; @@ -3912,7 +3807,8 @@ out: * * See spc4r17 section 5.7.6.2 and section 6.13.2, Table 160 */ -static int core_scsi3_pri_read_keys(struct se_cmd *cmd) +static sense_reason_t +core_scsi3_pri_read_keys(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct t10_pr_registration *pr_reg; @@ -3922,11 +3818,13 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd) if (cmd->data_length < 8) { pr_err("PRIN SA READ_KEYS SCSI Data Length: %u" " too small\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); @@ -3970,7 +3868,8 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd) * * See spc4r17 section 5.7.6.3 and section 6.13.3.2 Table 161 and 162 */ -static int core_scsi3_pri_read_reservation(struct se_cmd *cmd) +static sense_reason_t +core_scsi3_pri_read_reservation(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct t10_pr_registration *pr_reg; @@ -3981,11 +3880,13 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd) if (cmd->data_length < 8) { pr_err("PRIN SA READ_RESERVATIONS SCSI Data Length: %u" " too small\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); @@ -4054,7 +3955,8 @@ err: * * See spc4r17 section 6.13.4 Table 165 */ -static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd) +static sense_reason_t +core_scsi3_pri_report_capabilities(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct t10_reservation *pr_tmpl = &dev->t10_pr; @@ -4064,11 +3966,12 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd) if (cmd->data_length < 6) { pr_err("PRIN SA REPORT_CAPABILITIES SCSI Data Length:" " %u too small\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; buf[0] = ((add_len << 8) & 0xff); buf[1] = (add_len & 0xff); @@ -4110,7 +4013,8 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd) * * See spc4r17 section 6.13.5 Table 168 and 169 */ -static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) +static sense_reason_t +core_scsi3_pri_read_full_status(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_node_acl *se_nacl; @@ -4125,11 +4029,12 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) if (cmd->data_length < 8) { pr_err("PRIN SA READ_FULL_STATUS SCSI Data Length: %u" " too small\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff); buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff); @@ -4255,9 +4160,10 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) return 0; } -int target_scsi3_emulate_pr_in(struct se_cmd *cmd) +sense_reason_t +target_scsi3_emulate_pr_in(struct se_cmd *cmd) { - int ret; + sense_reason_t ret; /* * Following spc2r20 5.5.1 Reservations overview: @@ -4272,8 +4178,7 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd) pr_err("Received PERSISTENT_RESERVE CDB while legacy" " SPC-2 reservation is held, returning" " RESERVATION_CONFLICT\n"); - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - return -EINVAL; + return TCM_RESERVATION_CONFLICT; } switch (cmd->t_task_cdb[1] & 0x1f) { @@ -4292,9 +4197,7 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd) default: pr_err("Unknown PERSISTENT_RESERVE_IN service" " action: 0x%02x\n", cmd->t_task_cdb[1] & 0x1f); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - ret = -EINVAL; - break; + return TCM_INVALID_CDB_FIELD; } if (!ret) @@ -4302,10 +4205,11 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd) return ret; } -int target_check_reservation(struct se_cmd *cmd) +sense_reason_t +target_check_reservation(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; - int ret; + sense_reason_t ret; if (!cmd->se_sess) return 0; diff --git a/drivers/target/target_core_pr.h b/drivers/target/target_core_pr.h index 7616f2690ca0..b4a004247ab2 100644 --- a/drivers/target/target_core_pr.h +++ b/drivers/target/target_core_pr.h @@ -47,8 +47,8 @@ extern struct kmem_cache *t10_pr_reg_cache; extern int core_pr_dump_initiator_port(struct t10_pr_registration *, char *, u32); -extern int target_scsi2_reservation_release(struct se_cmd *); -extern int target_scsi2_reservation_reserve(struct se_cmd *); +extern sense_reason_t target_scsi2_reservation_release(struct se_cmd *); +extern sense_reason_t target_scsi2_reservation_reserve(struct se_cmd *); extern int core_scsi3_alloc_aptpl_registration( struct t10_reservation *, u64, unsigned char *, unsigned char *, u32, @@ -61,8 +61,8 @@ extern void core_scsi3_free_pr_reg_from_nacl(struct se_device *, extern void core_scsi3_free_all_registrations(struct se_device *); extern unsigned char *core_scsi3_pr_dump_type(int); -extern int target_scsi3_emulate_pr_in(struct se_cmd *); -extern int target_scsi3_emulate_pr_out(struct se_cmd *); -extern int target_check_reservation(struct se_cmd *cmd); +extern sense_reason_t target_scsi3_emulate_pr_in(struct se_cmd *); +extern sense_reason_t target_scsi3_emulate_pr_out(struct se_cmd *); +extern sense_reason_t target_check_reservation(struct se_cmd *); #endif /* TARGET_CORE_PR_H */ diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index aa3e80a2f8db..b5c722bdd993 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -60,7 +60,7 @@ static inline struct pscsi_dev_virt *PSCSI_DEV(struct se_device *dev) static struct se_subsystem_api pscsi_template; -static int pscsi_execute_cmd(struct se_cmd *cmd); +static sense_reason_t pscsi_execute_cmd(struct se_cmd *cmd); static void pscsi_req_done(struct request *, int); /* pscsi_attach_hba(): @@ -642,7 +642,11 @@ static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, if (((cdb[0] == MODE_SENSE) || (cdb[0] == MODE_SENSE_10)) && (status_byte(result) << 1) == SAM_STAT_GOOD) { if (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) { - unsigned char *buf = transport_kmap_data_sg(cmd); + unsigned char *buf; + + buf = transport_kmap_data_sg(cmd); + if (!buf) + ; /* XXX: TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE */ if (cdb[0] == MODE_SENSE_10) { if (!(buf[3] & 0x80)) @@ -856,9 +860,9 @@ static inline struct bio *pscsi_get_bio(int sg_num) return bio; } -static int pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, - u32 sgl_nents, enum dma_data_direction data_direction, - struct bio **hbio) +static sense_reason_t +pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, + enum dma_data_direction data_direction, struct bio **hbio) { struct pscsi_dev_virt *pdv = PSCSI_DEV(cmd->se_dev); struct bio *bio = NULL, *tbio = NULL; @@ -946,7 +950,7 @@ static int pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, } } - return sgl_nents; + return 0; fail: while (*hbio) { bio = *hbio; @@ -954,8 +958,7 @@ fail: bio->bi_next = NULL; bio_endio(bio, 0); /* XXX: should be error */ } - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -ENOMEM; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } /* @@ -982,15 +985,13 @@ static inline void pscsi_clear_cdb_lun(unsigned char *cdb) } } -static int pscsi_parse_cdb(struct se_cmd *cmd) +static sense_reason_t +pscsi_parse_cdb(struct se_cmd *cmd) { unsigned char *cdb = cmd->t_task_cdb; - if (cmd->se_cmd_flags & SCF_BIDI) { - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; - return -EINVAL; - } + if (cmd->se_cmd_flags & SCF_BIDI) + return TCM_UNSUPPORTED_SCSI_OPCODE; pscsi_clear_cdb_lun(cdb); @@ -1020,7 +1021,8 @@ static int pscsi_parse_cdb(struct se_cmd *cmd) } } -static int pscsi_execute_cmd(struct se_cmd *cmd) +static sense_reason_t +pscsi_execute_cmd(struct se_cmd *cmd) { struct scatterlist *sgl = cmd->t_data_sg; u32 sgl_nents = cmd->t_data_nents; @@ -1029,7 +1031,7 @@ static int pscsi_execute_cmd(struct se_cmd *cmd) struct pscsi_plugin_task *pt; struct request *req; struct bio *hbio; - int ret; + sense_reason_t ret; /* * Dynamically alloc cdb space, since it may be larger than @@ -1037,8 +1039,7 @@ static int pscsi_execute_cmd(struct se_cmd *cmd) */ pt = kzalloc(sizeof(*pt) + scsi_command_size(cmd->t_task_cdb), GFP_KERNEL); if (!pt) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -ENOMEM; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } cmd->priv = pt; @@ -1052,24 +1053,21 @@ static int pscsi_execute_cmd(struct se_cmd *cmd) if (!req || IS_ERR(req)) { pr_err("PSCSI: blk_get_request() failed: %ld\n", req ? IS_ERR(req) : -ENOMEM); - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; goto fail; } } else { BUG_ON(!cmd->data_length); ret = pscsi_map_sg(cmd, sgl, sgl_nents, data_direction, &hbio); - if (ret < 0) { - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + if (ret) goto fail; - } req = blk_make_request(pdv->pdv_sd->request_queue, hbio, GFP_KERNEL); if (IS_ERR(req)) { pr_err("pSCSI: blk_make_request() failed\n"); + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; goto fail_free_bio; } } @@ -1100,10 +1098,10 @@ fail_free_bio: bio->bi_next = NULL; bio_endio(bio, 0); /* XXX: should be error */ } - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; fail: kfree(pt); - return -ENOMEM; + return ret; } /* pscsi_get_device_type(): @@ -1152,7 +1150,6 @@ static void pscsi_req_done(struct request *req, int uptodate) pr_debug("PSCSI Host Byte exception at cmd: %p CDB:" " 0x%02x Result: 0x%08x\n", cmd, pt->pscsi_cdb[0], pt->pscsi_result); - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION); break; } diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c index 92b1307a9931..126529cd5325 100644 --- a/drivers/target/target_core_rd.c +++ b/drivers/target/target_core_rd.c @@ -275,7 +275,8 @@ static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page) return NULL; } -static int rd_execute_rw(struct se_cmd *cmd) +static sense_reason_t +rd_execute_rw(struct se_cmd *cmd) { struct scatterlist *sgl = cmd->t_data_sg; u32 sgl_nents = cmd->t_data_nents; @@ -298,7 +299,7 @@ static int rd_execute_rw(struct se_cmd *cmd) table = rd_get_sg_table(dev, rd_page); if (!table) - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; rd_sg = &table->sg_table[rd_page - table->page_start_offset]; @@ -348,7 +349,7 @@ static int rd_execute_rw(struct se_cmd *cmd) table = rd_get_sg_table(dev, rd_page); if (!table) { sg_miter_stop(&m); - return -EINVAL; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } /* since we increment, the first sg entry is correct */ @@ -431,7 +432,8 @@ static struct sbc_ops rd_sbc_ops = { .execute_rw = rd_execute_rw, }; -static int rd_parse_cdb(struct se_cmd *cmd) +static sense_reason_t +rd_parse_cdb(struct se_cmd *cmd) { return sbc_parse_cdb(cmd, &rd_sbc_ops); } diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index a4eb9c553654..3929fa201088 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -37,7 +37,8 @@ #include "target_core_ua.h" -static int sbc_emulate_readcapacity(struct se_cmd *cmd) +static sense_reason_t +sbc_emulate_readcapacity(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; unsigned long long blocks_long = dev->transport->get_blocks(dev); @@ -60,16 +61,18 @@ static int sbc_emulate_readcapacity(struct se_cmd *cmd) buf[7] = dev->dev_attrib.block_size & 0xff; rbuf = transport_kmap_data_sg(cmd); - if (rbuf) { - memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); - transport_kunmap_data_sg(cmd); - } + if (!rbuf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + + memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); + transport_kunmap_data_sg(cmd); target_complete_cmd(cmd, GOOD); return 0; } -static int sbc_emulate_readcapacity_16(struct se_cmd *cmd) +static sense_reason_t +sbc_emulate_readcapacity_16(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; unsigned char *rbuf; @@ -97,10 +100,11 @@ static int sbc_emulate_readcapacity_16(struct se_cmd *cmd) buf[14] = 0x80; rbuf = transport_kmap_data_sg(cmd); - if (rbuf) { - memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); - transport_kunmap_data_sg(cmd); - } + if (!rbuf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + + memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); + transport_kunmap_data_sg(cmd); target_complete_cmd(cmd, GOOD); return 0; @@ -129,7 +133,8 @@ int spc_get_write_same_sectors(struct se_cmd *cmd) } EXPORT_SYMBOL(spc_get_write_same_sectors); -static int sbc_emulate_verify(struct se_cmd *cmd) +static sense_reason_t +sbc_emulate_verify(struct se_cmd *cmd) { target_complete_cmd(cmd, GOOD); return 0; @@ -313,13 +318,14 @@ out: kfree(buf); } -int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) +sense_reason_t +sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) { struct se_device *dev = cmd->se_dev; unsigned char *cdb = cmd->t_task_cdb; unsigned int size; u32 sectors = 0; - int ret; + sense_reason_t ret; switch (cdb[0]) { case READ_6: @@ -378,9 +384,9 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) cmd->execute_cmd = ops->execute_rw; break; case XDWRITEREAD_10: - if ((cmd->data_direction != DMA_TO_DEVICE) || + if (cmd->data_direction != DMA_TO_DEVICE || !(cmd->se_cmd_flags & SCF_BIDI)) - goto out_invalid_cdb_field; + return TCM_INVALID_CDB_FIELD; sectors = transport_get_sectors_10(cdb); cmd->t_task_lba = transport_lba_32(cdb); @@ -419,26 +425,26 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) break; case WRITE_SAME_32: if (!ops->execute_write_same) - goto out_unsupported_cdb; + return TCM_UNSUPPORTED_SCSI_OPCODE; sectors = transport_get_sectors_32(cdb); if (!sectors) { pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not" " supported\n"); - goto out_invalid_cdb_field; + return TCM_INVALID_CDB_FIELD; } size = sbc_get_size(cmd, 1); cmd->t_task_lba = get_unaligned_be64(&cdb[12]); if (sbc_write_same_supported(dev, &cdb[10]) < 0) - goto out_unsupported_cdb; + return TCM_UNSUPPORTED_SCSI_OPCODE; cmd->execute_cmd = ops->execute_write_same; break; default: pr_err("VARIABLE_LENGTH_CMD service action" " 0x%04x not supported\n", service_action); - goto out_unsupported_cdb; + return TCM_UNSUPPORTED_SCSI_OPCODE; } break; } @@ -454,7 +460,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) default: pr_err("Unsupported SA: 0x%02x\n", cmd->t_task_cdb[1] & 0x1f); - goto out_invalid_cdb_field; + return TCM_INVALID_CDB_FIELD; } size = (cdb[10] << 24) | (cdb[11] << 16) | (cdb[12] << 8) | cdb[13]; @@ -462,7 +468,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) case SYNCHRONIZE_CACHE: case SYNCHRONIZE_CACHE_16: if (!ops->execute_sync_cache) - goto out_unsupported_cdb; + return TCM_UNSUPPORTED_SCSI_OPCODE; /* * Extract LBA and range to be flushed for emulated SYNCHRONIZE_CACHE @@ -483,42 +489,42 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) */ if (cmd->t_task_lba || sectors) { if (sbc_check_valid_sectors(cmd) < 0) - goto out_invalid_cdb_field; + return TCM_INVALID_CDB_FIELD; } cmd->execute_cmd = ops->execute_sync_cache; break; case UNMAP: if (!ops->execute_unmap) - goto out_unsupported_cdb; + return TCM_UNSUPPORTED_SCSI_OPCODE; size = get_unaligned_be16(&cdb[7]); cmd->execute_cmd = ops->execute_unmap; break; case WRITE_SAME_16: if (!ops->execute_write_same) - goto out_unsupported_cdb; + return TCM_UNSUPPORTED_SCSI_OPCODE; sectors = transport_get_sectors_16(cdb); if (!sectors) { pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n"); - goto out_invalid_cdb_field; + return TCM_INVALID_CDB_FIELD; } size = sbc_get_size(cmd, 1); cmd->t_task_lba = get_unaligned_be64(&cdb[2]); if (sbc_write_same_supported(dev, &cdb[1]) < 0) - goto out_unsupported_cdb; + return TCM_UNSUPPORTED_SCSI_OPCODE; cmd->execute_cmd = ops->execute_write_same; break; case WRITE_SAME: if (!ops->execute_write_same) - goto out_unsupported_cdb; + return TCM_UNSUPPORTED_SCSI_OPCODE; sectors = transport_get_sectors_10(cdb); if (!sectors) { pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n"); - goto out_invalid_cdb_field; + return TCM_INVALID_CDB_FIELD; } size = sbc_get_size(cmd, 1); @@ -529,7 +535,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) * of byte 1 bit 3 UNMAP instead of original reserved field */ if (sbc_write_same_supported(dev, &cdb[1]) < 0) - goto out_unsupported_cdb; + return TCM_UNSUPPORTED_SCSI_OPCODE; cmd->execute_cmd = ops->execute_write_same; break; case VERIFY: @@ -556,7 +562,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) /* reject any command that we don't have a handler for */ if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && !cmd->execute_cmd) - goto out_unsupported_cdb; + return TCM_UNSUPPORTED_SCSI_OPCODE; if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) { unsigned long long end_lba; @@ -566,14 +572,14 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) " big sectors %u exceeds fabric_max_sectors:" " %u\n", cdb[0], sectors, dev->dev_attrib.fabric_max_sectors); - goto out_invalid_cdb_field; + return TCM_INVALID_CDB_FIELD; } if (sectors > dev->dev_attrib.hw_max_sectors) { printk_ratelimited(KERN_ERR "SCSI OP %02xh with too" " big sectors %u exceeds backend hw_max_sectors:" " %u\n", cdb[0], sectors, dev->dev_attrib.hw_max_sectors); - goto out_invalid_cdb_field; + return TCM_INVALID_CDB_FIELD; } end_lba = dev->transport->get_blocks(dev) + 1; @@ -581,26 +587,13 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) pr_err("cmd exceeds last lba %llu " "(lba %llu, sectors %u)\n", end_lba, cmd->t_task_lba, sectors); - goto out_invalid_cdb_field; + return TCM_INVALID_CDB_FIELD; } size = sbc_get_size(cmd, sectors); } - ret = target_cmd_size_check(cmd, size); - if (ret < 0) - return ret; - - return 0; - -out_unsupported_cdb: - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; - return -EINVAL; -out_invalid_cdb_field: - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return target_cmd_size_check(cmd, size); } EXPORT_SYMBOL(sbc_parse_cdb); diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index f9c2bd02043c..4b3c18305ec8 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -69,7 +69,8 @@ static void spc_fill_alua_data(struct se_port *port, unsigned char *buf) spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); } -static int spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf) +static sense_reason_t +spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf) { struct se_lun *lun = cmd->se_lun; struct se_device *dev = cmd->se_dev; @@ -108,7 +109,8 @@ static int spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf) } /* unit serial number */ -static int spc_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf) +static sense_reason_t +spc_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf) { struct se_device *dev = cmd->se_dev; u16 len = 0; @@ -161,7 +163,8 @@ static void spc_parse_naa_6h_vendor_specific(struct se_device *dev, * Device identification VPD, for a complete list of * DESIGNATOR TYPEs see spc4r17 Table 459. */ -static int spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf) +static sense_reason_t +spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf) { struct se_device *dev = cmd->se_dev; struct se_lun *lun = cmd->se_lun; @@ -406,7 +409,8 @@ check_scsi_name: } /* Extended INQUIRY Data VPD Page */ -static int spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf) +static sense_reason_t +spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf) { buf[3] = 0x3c; /* Set HEADSUP, ORDSUP, SIMPSUP */ @@ -419,7 +423,8 @@ static int spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf) } /* Block Limits VPD page */ -static int spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) +static sense_reason_t +spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) { struct se_device *dev = cmd->se_dev; u32 max_sectors; @@ -490,7 +495,8 @@ static int spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) } /* Block Device Characteristics VPD page */ -static int spc_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf) +static sense_reason_t +spc_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf) { struct se_device *dev = cmd->se_dev; @@ -502,7 +508,8 @@ static int spc_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf) } /* Thin Provisioning VPD */ -static int spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf) +static sense_reason_t +spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf) { struct se_device *dev = cmd->se_dev; @@ -552,11 +559,12 @@ static int spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf) return 0; } -static int spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf); +static sense_reason_t +spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf); static struct { uint8_t page; - int (*emulate)(struct se_cmd *, unsigned char *); + sense_reason_t (*emulate)(struct se_cmd *, unsigned char *); } evpd_handlers[] = { { .page = 0x00, .emulate = spc_emulate_evpd_00 }, { .page = 0x80, .emulate = spc_emulate_evpd_80 }, @@ -568,7 +576,8 @@ static struct { }; /* supported vital product data pages */ -static int spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf) +static sense_reason_t +spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf) { int p; @@ -586,14 +595,16 @@ static int spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf) return 0; } -static int spc_emulate_inquiry(struct se_cmd *cmd) +static sense_reason_t +spc_emulate_inquiry(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg; unsigned char *rbuf; unsigned char *cdb = cmd->t_task_cdb; unsigned char buf[SE_INQUIRY_BUF]; - int p, ret; + sense_reason_t ret; + int p; memset(buf, 0, SE_INQUIRY_BUF); @@ -606,8 +617,7 @@ static int spc_emulate_inquiry(struct se_cmd *cmd) if (cdb[2]) { pr_err("INQUIRY with EVPD==0 but PAGE CODE=%02x\n", cdb[2]); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - ret = -EINVAL; + ret = TCM_INVALID_CDB_FIELD; goto out; } @@ -624,15 +634,15 @@ static int spc_emulate_inquiry(struct se_cmd *cmd) } pr_err("Unknown VPD Code: 0x%02x\n", cdb[2]); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - ret = -EINVAL; + ret = TCM_INVALID_CDB_FIELD; out: rbuf = transport_kmap_data_sg(cmd); - if (rbuf) { - memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); - transport_kunmap_data_sg(cmd); - } + if (!rbuf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + + memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); + transport_kunmap_data_sg(cmd); if (!ret) target_complete_cmd(cmd, GOOD); @@ -834,7 +844,7 @@ static int spc_modesense_long_blockdesc(unsigned char *buf, u64 blocks, u32 bloc return 17; } -static int spc_emulate_modesense(struct se_cmd *cmd) +static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; char *cdb = cmd->t_task_cdb; @@ -851,7 +861,8 @@ static int spc_emulate_modesense(struct se_cmd *cmd) int i; map_buf = transport_kmap_data_sg(cmd); - + if (!map_buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; /* * If SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC is not set, then we * know we actually allocated a full page. Otherwise, if the @@ -864,8 +875,7 @@ static int spc_emulate_modesense(struct se_cmd *cmd) buf = kzalloc(SE_MODE_PAGE_BUF, GFP_KERNEL); if (!buf) { transport_kunmap_data_sg(cmd); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -ENOMEM; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } } else { buf = map_buf; @@ -920,9 +930,10 @@ static int spc_emulate_modesense(struct se_cmd *cmd) if (page == 0x3f) { if (subpage != 0x00 && subpage != 0xff) { - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - length = -EINVAL; - goto out; + pr_warn("MODE_SENSE: Invalid subpage code: 0x%02x\n", subpage); + kfree(buf); + transport_kunmap_data_sg(cmd); + return TCM_INVALID_CDB_FIELD; } for (i = 0; i < ARRAY_SIZE(modesense_handlers); ++i) { @@ -958,8 +969,8 @@ static int spc_emulate_modesense(struct se_cmd *cmd) pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n", page, subpage); - cmd->scsi_sense_reason = TCM_UNKNOWN_MODE_PAGE; - return -EINVAL; + transport_kunmap_data_sg(cmd); + return TCM_UNKNOWN_MODE_PAGE; set_length: if (ten) @@ -967,7 +978,6 @@ set_length: else buf[0] = length - 1; -out: if (buf != map_buf) { memcpy(map_buf, buf, cmd->data_length); kfree(buf); @@ -978,7 +988,7 @@ out: return 0; } -static int spc_emulate_modeselect(struct se_cmd *cmd) +static sense_reason_t spc_emulate_modeselect(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; char *cdb = cmd->t_task_cdb; @@ -993,10 +1003,11 @@ static int spc_emulate_modeselect(struct se_cmd *cmd) int i; buf = transport_kmap_data_sg(cmd); + if (!buf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; if (!pf) { - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - ret = -EINVAL; + ret = TCM_INVALID_CDB_FIELD; goto out; } @@ -1011,15 +1022,12 @@ static int spc_emulate_modeselect(struct se_cmd *cmd) goto check_contents; } - cmd->scsi_sense_reason = TCM_UNKNOWN_MODE_PAGE; - ret = -EINVAL; + ret = TCM_UNKNOWN_MODE_PAGE; goto out; check_contents: - if (memcmp(buf + off, tbuf, length)) { - cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; - ret = -EINVAL; - } + if (memcmp(buf + off, tbuf, length)) + ret = TCM_INVALID_PARAMETER_LIST; out: transport_kunmap_data_sg(cmd); @@ -1029,7 +1037,7 @@ out: return ret; } -static int spc_emulate_request_sense(struct se_cmd *cmd) +static sense_reason_t spc_emulate_request_sense(struct se_cmd *cmd) { unsigned char *cdb = cmd->t_task_cdb; unsigned char *rbuf; @@ -1041,19 +1049,14 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) if (cdb[1] & 0x01) { pr_err("REQUEST_SENSE description emulation not" " supported\n"); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -ENOSYS; + return TCM_INVALID_CDB_FIELD; } rbuf = transport_kmap_data_sg(cmd); - if (cmd->scsi_sense_reason != 0) { - /* - * Out of memory. We will fail with CHECK CONDITION, so - * we must not clear the unit attention condition. - */ - target_complete_cmd(cmd, CHECK_CONDITION); - return 0; - } else if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) { + if (!rbuf) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + + if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) { /* * CURRENT ERROR, UNIT ATTENTION */ @@ -1080,16 +1083,14 @@ static int spc_emulate_request_sense(struct se_cmd *cmd) buf[7] = 0x0A; } - if (rbuf) { - memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); - transport_kunmap_data_sg(cmd); - } + memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); + transport_kunmap_data_sg(cmd); target_complete_cmd(cmd, GOOD); return 0; } -int spc_emulate_report_luns(struct se_cmd *cmd) +sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd) { struct se_dev_entry *deve; struct se_session *sess = cmd->se_sess; @@ -1099,13 +1100,12 @@ int spc_emulate_report_luns(struct se_cmd *cmd) if (cmd->data_length < 16) { pr_warn("REPORT LUNS allocation length %u too small\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } buf = transport_kmap_data_sg(cmd); if (!buf) - return -ENOMEM; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; /* * If no struct se_session pointer is present, this struct se_cmd is @@ -1153,13 +1153,15 @@ done: } EXPORT_SYMBOL(spc_emulate_report_luns); -static int spc_emulate_testunitready(struct se_cmd *cmd) +static sense_reason_t +spc_emulate_testunitready(struct se_cmd *cmd) { target_complete_cmd(cmd, GOOD); return 0; } -int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) +sense_reason_t +spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) { struct se_device *dev = cmd->se_dev; unsigned char *cdb = cmd->t_task_cdb; @@ -1300,9 +1302,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) pr_warn("TARGET_CORE[%s]: Unsupported SCSI Opcode" " 0x%02x, sending CHECK_CONDITION.\n", cmd->se_tfo->get_fabric_name(), cdb[0]); - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; - return -EINVAL; + return TCM_UNSUPPORTED_SCSI_OPCODE; } return 0; diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index c4c931b525d2..98044bf1da08 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -557,7 +557,8 @@ static void target_complete_failure_work(struct work_struct *work) { struct se_cmd *cmd = container_of(work, struct se_cmd, work); - transport_generic_request_failure(cmd); + transport_generic_request_failure(cmd, + TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE); } /* @@ -625,7 +626,6 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) complete(&cmd->t_transport_stop_comp); return; } else if (cmd->transport_state & CMD_T_FAILED) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; INIT_WORK(&cmd->work, target_complete_failure_work); } else { INIT_WORK(&cmd->work, target_complete_ok_work); @@ -976,7 +976,8 @@ transport_set_vpd_ident(struct t10_vpd *vpd, unsigned char *page_83) } EXPORT_SYMBOL(transport_set_vpd_ident); -int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) +sense_reason_t +target_cmd_size_check(struct se_cmd *cmd, unsigned int size) { struct se_device *dev = cmd->se_dev; @@ -991,7 +992,7 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) if (cmd->data_direction == DMA_TO_DEVICE) { pr_err("Rejecting underflow/overflow" " WRITE data\n"); - goto out_invalid_cdb_field; + return TCM_INVALID_CDB_FIELD; } /* * Reject READ_* or WRITE_* with overflow/underflow for @@ -1002,7 +1003,7 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) " CDB on non 512-byte sector setup subsystem" " plugin: %s\n", dev->transport->name); /* Returns CHECK_CONDITION + INVALID_CDB_FIELD */ - goto out_invalid_cdb_field; + return TCM_INVALID_CDB_FIELD; } /* * For the overflow case keep the existing fabric provided @@ -1022,10 +1023,6 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) return 0; -out_invalid_cdb_field: - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; } /* @@ -1065,7 +1062,8 @@ void transport_init_se_cmd( } EXPORT_SYMBOL(transport_init_se_cmd); -static int transport_check_alloc_task_attr(struct se_cmd *cmd) +static sense_reason_t +transport_check_alloc_task_attr(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; @@ -1079,7 +1077,7 @@ static int transport_check_alloc_task_attr(struct se_cmd *cmd) if (cmd->sam_task_attr == MSG_ACA_TAG) { pr_debug("SAM Task Attribute ACA" " emulation is not supported\n"); - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } /* * Used to determine when ORDERED commands should go from @@ -1093,17 +1091,12 @@ static int transport_check_alloc_task_attr(struct se_cmd *cmd) return 0; } -/* target_setup_cmd_from_cdb(): - * - * Called from fabric RX Thread. - */ -int target_setup_cmd_from_cdb( - struct se_cmd *cmd, - unsigned char *cdb) +sense_reason_t +target_setup_cmd_from_cdb(struct se_cmd *cmd, unsigned char *cdb) { struct se_device *dev = cmd->se_dev; unsigned long flags; - int ret; + sense_reason_t ret; /* * Ensure that the received CDB is less than the max (252 + 8) bytes @@ -1113,9 +1106,7 @@ int target_setup_cmd_from_cdb( pr_err("Received SCSI CDB with command_size: %d that" " exceeds SCSI_MAX_VARLEN_CDB_SIZE: %d\n", scsi_command_size(cdb), SCSI_MAX_VARLEN_CDB_SIZE); - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + return TCM_INVALID_CDB_FIELD; } /* * If the received CDB is larger than TCM_MAX_COMMAND_SIZE, @@ -1130,10 +1121,7 @@ int target_setup_cmd_from_cdb( " %u > sizeof(cmd->__t_task_cdb): %lu ops\n", scsi_command_size(cdb), (unsigned long)sizeof(cmd->__t_task_cdb)); - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -ENOMEM; + return TCM_OUT_OF_RESOURCES; } } else cmd->t_task_cdb = &cmd->__t_task_cdb[0]; @@ -1145,50 +1133,30 @@ int target_setup_cmd_from_cdb( /* * Check for an existing UNIT ATTENTION condition */ - if (core_scsi3_ua_check(cmd, cdb) < 0) { - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_CHECK_CONDITION_UNIT_ATTENTION; - return -EINVAL; - } + ret = target_scsi3_ua_check(cmd); + if (ret) + return ret; ret = target_alua_state_check(cmd); - if (ret) { - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - if (ret > 0) - cmd->scsi_sense_reason = TCM_CHECK_CONDITION_NOT_READY; - else - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; - } + if (ret) + return ret; - /* - * Check status for SPC-3 Persistent Reservations - */ ret = target_check_reservation(cmd); - if (ret) { - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT; - cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT; - cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; + if (ret) return ret; - } ret = dev->transport->parse_cdb(cmd); - if (ret < 0) + if (ret) + return ret; + + ret = transport_check_alloc_task_attr(cmd); + if (ret) return ret; spin_lock_irqsave(&cmd->t_state_lock, flags); cmd->se_cmd_flags |= SCF_SUPPORTED_SAM_OPCODE; spin_unlock_irqrestore(&cmd->t_state_lock, flags); - /* - * Check for SAM Task Attribute Emulation - */ - if (transport_check_alloc_task_attr(cmd) < 0) { - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; - } spin_lock(&cmd->se_lun->lun_sep_lock); if (cmd->se_lun->lun_sep) cmd->se_lun->lun_sep->sep_stats.cmd_pdus++; @@ -1204,7 +1172,7 @@ EXPORT_SYMBOL(target_setup_cmd_from_cdb); int transport_handle_cdb_direct( struct se_cmd *cmd) { - int ret; + sense_reason_t ret; if (!cmd->se_lun) { dump_stack(); @@ -1234,13 +1202,41 @@ int transport_handle_cdb_direct( * and call transport_generic_request_failure() if necessary.. */ ret = transport_generic_new_cmd(cmd); - if (ret < 0) - transport_generic_request_failure(cmd); - + if (ret) + transport_generic_request_failure(cmd, ret); return 0; } EXPORT_SYMBOL(transport_handle_cdb_direct); +static sense_reason_t +transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *sgl, + u32 sgl_count, struct scatterlist *sgl_bidi, u32 sgl_bidi_count) +{ + if (!sgl || !sgl_count) + return 0; + + /* + * Reject SCSI data overflow with map_mem_to_cmd() as incoming + * scatterlists already have been set to follow what the fabric + * passes for the original expected data transfer length. + */ + if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT) { + pr_warn("Rejecting SCSI DATA overflow for fabric using" + " SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC\n"); + return TCM_INVALID_CDB_FIELD; + } + + cmd->t_data_sg = sgl; + cmd->t_data_nents = sgl_count; + + if (sgl_bidi && sgl_bidi_count) { + cmd->t_bidi_data_sg = sgl_bidi; + cmd->t_bidi_data_nents = sgl_bidi_count; + } + cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC; + return 0; +} + /* * target_submit_cmd_map_sgls - lookup unpacked lun and submit uninitialized * se_cmd + use pre-allocated SGL memory. @@ -1273,7 +1269,8 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess struct scatterlist *sgl_bidi, u32 sgl_bidi_count) { struct se_portal_group *se_tpg; - int rc; + sense_reason_t rc; + int ret; se_tpg = se_sess->se_tpg; BUG_ON(!se_tpg); @@ -1294,9 +1291,9 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess * for fabrics using TARGET_SCF_ACK_KREF that expect a second * kref_put() to happen during fabric packet acknowledgement. */ - rc = target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF)); - if (rc) - return rc; + ret = target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF)); + if (ret) + return ret; /* * Signal bidirectional data payloads to target-core */ @@ -1305,16 +1302,16 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess /* * Locate se_lun pointer and attach it to struct se_cmd */ - if (transport_lookup_cmd_lun(se_cmd, unpacked_lun) < 0) { - transport_send_check_condition_and_sense(se_cmd, - se_cmd->scsi_sense_reason, 0); + rc = transport_lookup_cmd_lun(se_cmd, unpacked_lun); + if (rc) { + transport_send_check_condition_and_sense(se_cmd, rc, 0); target_put_sess_cmd(se_sess, se_cmd); return 0; } rc = target_setup_cmd_from_cdb(se_cmd, cdb); if (rc != 0) { - transport_generic_request_failure(se_cmd); + transport_generic_request_failure(se_cmd, rc); return 0; } /* @@ -1349,7 +1346,7 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess rc = transport_generic_map_mem_to_cmd(se_cmd, sgl, sgl_count, sgl_bidi, sgl_bidi_count); if (rc != 0) { - transport_generic_request_failure(se_cmd); + transport_generic_request_failure(se_cmd, rc); return 0; } } @@ -1495,16 +1492,17 @@ bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags) /* * Handle SAM-esque emulation for generic transport request failures. */ -void transport_generic_request_failure(struct se_cmd *cmd) +void transport_generic_request_failure(struct se_cmd *cmd, + sense_reason_t sense_reason) { int ret = 0; pr_debug("-----[ Storage Engine Exception for cmd: %p ITT: 0x%08x" " CDB: 0x%02x\n", cmd, cmd->se_tfo->get_task_tag(cmd), cmd->t_task_cdb[0]); - pr_debug("-----[ i_state: %d t_state: %d scsi_sense_reason: %d\n", + pr_debug("-----[ i_state: %d t_state: %d sense_reason: %d\n", cmd->se_tfo->get_cmd_state(cmd), - cmd->t_state, cmd->scsi_sense_reason); + cmd->t_state, sense_reason); pr_debug("-----[ CMD_T_ACTIVE: %d CMD_T_STOP: %d CMD_T_SENT: %d\n", (cmd->transport_state & CMD_T_ACTIVE) != 0, (cmd->transport_state & CMD_T_STOP) != 0, @@ -1515,7 +1513,7 @@ void transport_generic_request_failure(struct se_cmd *cmd) */ transport_complete_task_attr(cmd); - switch (cmd->scsi_sense_reason) { + switch (sense_reason) { case TCM_NON_EXISTENT_LUN: case TCM_UNSUPPORTED_SCSI_OPCODE: case TCM_INVALID_CDB_FIELD: @@ -1528,6 +1526,9 @@ void transport_generic_request_failure(struct se_cmd *cmd) case TCM_CHECK_CONDITION_UNIT_ATTENTION: case TCM_CHECK_CONDITION_NOT_READY: break; + case TCM_OUT_OF_RESOURCES: + sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + break; case TCM_RESERVATION_CONFLICT: /* * No SENSE Data payload for this case, set SCSI Status @@ -1555,13 +1556,12 @@ void transport_generic_request_failure(struct se_cmd *cmd) goto check_stop; default: pr_err("Unknown transport error for CDB 0x%02x: %d\n", - cmd->t_task_cdb[0], cmd->scsi_sense_reason); - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; + cmd->t_task_cdb[0], sense_reason); + sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; break; } - ret = transport_send_check_condition_and_sense(cmd, - cmd->scsi_sense_reason, 0); + ret = transport_send_check_condition_and_sense(cmd, sense_reason, 0); if (ret == -EAGAIN || ret == -ENOMEM) goto queue_full; @@ -1579,21 +1579,21 @@ EXPORT_SYMBOL(transport_generic_request_failure); static void __target_execute_cmd(struct se_cmd *cmd) { - int error = 0; + sense_reason_t ret; spin_lock_irq(&cmd->t_state_lock); cmd->transport_state |= (CMD_T_BUSY|CMD_T_SENT); spin_unlock_irq(&cmd->t_state_lock); - if (cmd->execute_cmd) - error = cmd->execute_cmd(cmd); - - if (error) { - spin_lock_irq(&cmd->t_state_lock); - cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT); - spin_unlock_irq(&cmd->t_state_lock); + if (cmd->execute_cmd) { + ret = cmd->execute_cmd(cmd); + if (ret) { + spin_lock_irq(&cmd->t_state_lock); + cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT); + spin_unlock_irq(&cmd->t_state_lock); - transport_generic_request_failure(cmd); + transport_generic_request_failure(cmd, ret); + } } } @@ -1987,53 +1987,6 @@ out_busy: spin_unlock_irqrestore(&cmd->t_state_lock, flags); } -/* - * transport_generic_map_mem_to_cmd - Use fabric-alloced pages instead of - * allocating in the core. - * @cmd: Associated se_cmd descriptor - * @mem: SGL style memory for TCM WRITE / READ - * @sg_mem_num: Number of SGL elements - * @mem_bidi_in: SGL style memory for TCM BIDI READ - * @sg_mem_bidi_num: Number of BIDI READ SGL elements - * - * Return: nonzero return cmd was rejected for -ENOMEM or inproper usage - * of parameters. - */ -int transport_generic_map_mem_to_cmd( - struct se_cmd *cmd, - struct scatterlist *sgl, - u32 sgl_count, - struct scatterlist *sgl_bidi, - u32 sgl_bidi_count) -{ - if (!sgl || !sgl_count) - return 0; - - /* - * Reject SCSI data overflow with map_mem_to_cmd() as incoming - * scatterlists already have been set to follow what the fabric - * passes for the original expected data transfer length. - */ - if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT) { - pr_warn("Rejecting SCSI DATA overflow for fabric using" - " SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC\n"); - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; - } - - cmd->t_data_sg = sgl; - cmd->t_data_nents = sgl_count; - - if (sgl_bidi && sgl_bidi_count) { - cmd->t_bidi_data_sg = sgl_bidi; - cmd->t_bidi_data_nents = sgl_bidi_count; - } - cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC; - return 0; -} -EXPORT_SYMBOL(transport_generic_map_mem_to_cmd); - void *transport_kmap_data_sg(struct se_cmd *cmd) { struct scatterlist *sg = cmd->t_data_sg; @@ -2054,10 +2007,8 @@ void *transport_kmap_data_sg(struct se_cmd *cmd) /* >1 page. use vmap */ pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL); - if (!pages) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + if (!pages) return NULL; - } /* convert sg[] to pages[] */ for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) { @@ -2066,10 +2017,8 @@ void *transport_kmap_data_sg(struct se_cmd *cmd) cmd->t_data_vmap = vmap(pages, cmd->t_data_nents, VM_MAP, PAGE_KERNEL); kfree(pages); - if (!cmd->t_data_vmap) { - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + if (!cmd->t_data_vmap) return NULL; - } return cmd->t_data_vmap + cmd->t_data_sg[0].offset; } @@ -2135,7 +2084,8 @@ out: * might not have the payload yet, so notify the fabric via a call to * ->write_pending instead. Otherwise place it on the execution queue. */ -int transport_generic_new_cmd(struct se_cmd *cmd) +sense_reason_t +transport_generic_new_cmd(struct se_cmd *cmd) { int ret = 0; @@ -2148,7 +2098,7 @@ int transport_generic_new_cmd(struct se_cmd *cmd) cmd->data_length) { ret = transport_generic_get_mem(cmd); if (ret < 0) - goto out_fail; + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } atomic_inc(&cmd->t_fe_count); @@ -2174,14 +2124,11 @@ int transport_generic_new_cmd(struct se_cmd *cmd) if (ret == -EAGAIN || ret == -ENOMEM) goto queue_full; - if (ret < 0) - return ret; - return 1; + /* fabric drivers should only return -EAGAIN or -ENOMEM as error */ + WARN_ON(ret); + + return 0; -out_fail: - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; queue_full: pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd); cmd->t_state = TRANSPORT_COMPLETE_QF_WP; @@ -2625,10 +2572,9 @@ static int transport_get_sense_codes( return 0; } -int transport_send_check_condition_and_sense( - struct se_cmd *cmd, - u8 reason, - int from_transport) +int +transport_send_check_condition_and_sense(struct se_cmd *cmd, + sense_reason_t reason, int from_transport) { unsigned char *buffer = cmd->sense_buffer; unsigned long flags; diff --git a/drivers/target/target_core_ua.c b/drivers/target/target_core_ua.c index 59c95ee14749..60c8f41b9f1c 100644 --- a/drivers/target/target_core_ua.c +++ b/drivers/target/target_core_ua.c @@ -38,9 +38,8 @@ #include "target_core_pr.h" #include "target_core_ua.h" -int core_scsi3_ua_check( - struct se_cmd *cmd, - unsigned char *cdb) +sense_reason_t +target_scsi3_ua_check(struct se_cmd *cmd) { struct se_dev_entry *deve; struct se_session *sess = cmd->se_sess; @@ -71,16 +70,14 @@ int core_scsi3_ua_check( * was received, then the device server shall process the command * and either: */ - switch (cdb[0]) { + switch (cmd->t_task_cdb[0]) { case INQUIRY: case REPORT_LUNS: case REQUEST_SENSE: return 0; default: - return -EINVAL; + return TCM_CHECK_CONDITION_UNIT_ATTENTION; } - - return -EINVAL; } int core_scsi3_ua_allocate( diff --git a/drivers/target/target_core_ua.h b/drivers/target/target_core_ua.h index 6e6b03460a1a..0204952fe4d3 100644 --- a/drivers/target/target_core_ua.h +++ b/drivers/target/target_core_ua.h @@ -26,7 +26,7 @@ extern struct kmem_cache *se_ua_cache; -extern int core_scsi3_ua_check(struct se_cmd *, unsigned char *); +extern sense_reason_t target_scsi3_ua_check(struct se_cmd *); extern int core_scsi3_ua_allocate(struct se_node_acl *, u32, u8, u8); extern void core_scsi3_ua_release_all(struct se_dev_entry *); extern void core_scsi3_ua_for_check_condition(struct se_cmd *, u8 *, u8 *); diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c index aa31692064dd..6a69bf55aea9 100644 --- a/drivers/vhost/tcm_vhost.c +++ b/drivers/vhost/tcm_vhost.c @@ -541,10 +541,6 @@ static void tcm_vhost_submission_work(struct work_struct *work) if (tv_cmd->tvc_sgl_count) { sg_ptr = tv_cmd->tvc_sgl; - /* - * For BIDI commands, pass in the extra READ buffer - * to transport_generic_map_mem_to_cmd() below.. - */ /* FIXME: Fix BIDI operation in tcm_vhost_submission_work() */ #if 0 if (se_cmd->se_cmd_flags & SCF_BIDI) { diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index e57f738f04f9..aa868090b9ab 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -31,17 +31,17 @@ struct se_subsystem_api { struct scatterlist *, unsigned char *); - int (*parse_cdb)(struct se_cmd *cmd); + sense_reason_t (*parse_cdb)(struct se_cmd *cmd); u32 (*get_device_type)(struct se_device *); sector_t (*get_blocks)(struct se_device *); unsigned char *(*get_sense_buffer)(struct se_cmd *); }; struct sbc_ops { - int (*execute_rw)(struct se_cmd *cmd); - int (*execute_sync_cache)(struct se_cmd *cmd); - int (*execute_write_same)(struct se_cmd *cmd); - int (*execute_unmap)(struct se_cmd *cmd); + sense_reason_t (*execute_rw)(struct se_cmd *cmd); + sense_reason_t (*execute_sync_cache)(struct se_cmd *cmd); + sense_reason_t (*execute_write_same)(struct se_cmd *cmd); + sense_reason_t (*execute_unmap)(struct se_cmd *cmd); }; int transport_subsystem_register(struct se_subsystem_api *); @@ -49,11 +49,11 @@ void transport_subsystem_release(struct se_subsystem_api *); void target_complete_cmd(struct se_cmd *, u8); -int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size); -int spc_emulate_report_luns(struct se_cmd *cmd); +sense_reason_t spc_parse_cdb(struct se_cmd *cmd, unsigned int *size); +sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd); int spc_get_write_same_sectors(struct se_cmd *cmd); -int sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops); +sense_reason_t sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops); u32 sbc_get_device_rev(struct se_device *dev); u32 sbc_get_device_type(struct se_device *dev); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 11b0a68dc765..5350f6e580f0 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -144,8 +144,6 @@ enum se_cmd_flags_table { SCF_EMULATED_TASK_SENSE = 0x00000004, SCF_SCSI_DATA_CDB = 0x00000008, SCF_SCSI_TMR_CDB = 0x00000010, - SCF_SCSI_CDB_EXCEPTION = 0x00000020, - SCF_SCSI_RESERVATION_CONFLICT = 0x00000040, SCF_FUA = 0x00000080, SCF_SE_LUN_CMD = 0x00000100, SCF_BIDI = 0x00000400, @@ -167,27 +165,32 @@ enum transport_lunflags_table { }; /* - * Used by transport_send_check_condition_and_sense() and se_cmd->scsi_sense_reason + * Used by transport_send_check_condition_and_sense() * to signal which ASC/ASCQ sense payload should be built. */ +typedef unsigned __bitwise__ sense_reason_t; + enum tcm_sense_reason_table { - TCM_NON_EXISTENT_LUN = 0x01, - TCM_UNSUPPORTED_SCSI_OPCODE = 0x02, - TCM_INCORRECT_AMOUNT_OF_DATA = 0x03, - TCM_UNEXPECTED_UNSOLICITED_DATA = 0x04, - TCM_SERVICE_CRC_ERROR = 0x05, - TCM_SNACK_REJECTED = 0x06, - TCM_SECTOR_COUNT_TOO_MANY = 0x07, - TCM_INVALID_CDB_FIELD = 0x08, - TCM_INVALID_PARAMETER_LIST = 0x09, - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE = 0x0a, - TCM_UNKNOWN_MODE_PAGE = 0x0b, - TCM_WRITE_PROTECTED = 0x0c, - TCM_CHECK_CONDITION_ABORT_CMD = 0x0d, - TCM_CHECK_CONDITION_UNIT_ATTENTION = 0x0e, - TCM_CHECK_CONDITION_NOT_READY = 0x0f, - TCM_RESERVATION_CONFLICT = 0x10, - TCM_ADDRESS_OUT_OF_RANGE = 0x11, +#define R(x) (__force sense_reason_t )(x) + TCM_NON_EXISTENT_LUN = R(0x01), + TCM_UNSUPPORTED_SCSI_OPCODE = R(0x02), + TCM_INCORRECT_AMOUNT_OF_DATA = R(0x03), + TCM_UNEXPECTED_UNSOLICITED_DATA = R(0x04), + TCM_SERVICE_CRC_ERROR = R(0x05), + TCM_SNACK_REJECTED = R(0x06), + TCM_SECTOR_COUNT_TOO_MANY = R(0x07), + TCM_INVALID_CDB_FIELD = R(0x08), + TCM_INVALID_PARAMETER_LIST = R(0x09), + TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE = R(0x0a), + TCM_UNKNOWN_MODE_PAGE = R(0x0b), + TCM_WRITE_PROTECTED = R(0x0c), + TCM_CHECK_CONDITION_ABORT_CMD = R(0x0d), + TCM_CHECK_CONDITION_UNIT_ATTENTION = R(0x0e), + TCM_CHECK_CONDITION_NOT_READY = R(0x0f), + TCM_RESERVATION_CONFLICT = R(0x10), + TCM_ADDRESS_OUT_OF_RANGE = R(0x11), + TCM_OUT_OF_RESOURCES = R(0x12), +#undef R }; enum target_sc_flags_table { @@ -407,7 +410,6 @@ struct se_cmd { u8 scsi_status; u8 scsi_asc; u8 scsi_ascq; - u8 scsi_sense_reason; u16 scsi_sense_length; /* Delay for ALUA Active/NonOptimized state access in milliseconds */ int alua_nonop_delay; @@ -445,7 +447,7 @@ struct se_cmd { struct completion cmd_wait_comp; struct kref cmd_kref; struct target_core_fabric_ops *se_tfo; - int (*execute_cmd)(struct se_cmd *); + sense_reason_t (*execute_cmd)(struct se_cmd *); void (*transport_complete_callback)(struct se_cmd *); unsigned char *t_task_cdb; diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h index 81ddb4ae6c3f..9087b200e552 100644 --- a/include/target/target_core_fabric.h +++ b/include/target/target_core_fabric.h @@ -98,8 +98,8 @@ void transport_deregister_session(struct se_session *); void transport_init_se_cmd(struct se_cmd *, struct target_core_fabric_ops *, struct se_session *, u32, int, int, unsigned char *); -int transport_lookup_cmd_lun(struct se_cmd *, u32); -int target_setup_cmd_from_cdb(struct se_cmd *, unsigned char *); +sense_reason_t transport_lookup_cmd_lun(struct se_cmd *, u32); +sense_reason_t target_setup_cmd_from_cdb(struct se_cmd *, unsigned char *); int target_submit_cmd_map_sgls(struct se_cmd *, struct se_session *, unsigned char *, unsigned char *, u32, u32, int, int, int, struct scatterlist *, u32, struct scatterlist *, u32); @@ -110,9 +110,7 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess, void *fabric_tmr_ptr, unsigned char tm_type, gfp_t, unsigned int, int); int transport_handle_cdb_direct(struct se_cmd *); -int transport_generic_map_mem_to_cmd(struct se_cmd *cmd, - struct scatterlist *, u32, struct scatterlist *, u32); -int transport_generic_new_cmd(struct se_cmd *); +sense_reason_t transport_generic_new_cmd(struct se_cmd *); void target_execute_cmd(struct se_cmd *cmd); @@ -120,7 +118,8 @@ void transport_generic_free_cmd(struct se_cmd *, int); bool transport_wait_for_tasks(struct se_cmd *); int transport_check_aborted_status(struct se_cmd *, int); -int transport_send_check_condition_and_sense(struct se_cmd *, u8, int); +int transport_send_check_condition_and_sense(struct se_cmd *, + sense_reason_t, int); int target_put_sess_cmd(struct se_session *, struct se_cmd *); void target_sess_cmd_list_set_waiting(struct se_session *); @@ -131,7 +130,7 @@ int core_alua_check_nonop_delay(struct se_cmd *); int core_tmr_alloc_req(struct se_cmd *, void *, u8, gfp_t); void core_tmr_release_req(struct se_tmr_req *); int transport_generic_handle_tmr(struct se_cmd *); -void transport_generic_request_failure(struct se_cmd *); +void transport_generic_request_failure(struct se_cmd *, sense_reason_t); int transport_lookup_tmr_lun(struct se_cmd *, u32); struct se_node_acl *core_tpg_check_initiator_node_acl(struct se_portal_group *, -- cgit v1.2.3 From cd063bef414c51d79b9c6ea7a8ef8f9d319529bc Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 7 Nov 2012 20:01:10 -0800 Subject: target/sbc: Seperate WRITE_SAME based on UNMAP flag in sbc_ops This patch adds a new sbc_ops->execute_write_same_unmap() caller for use with WRITE_SAME w/ UNMAP=1, and performs the ->execute_cmd() setup based this bit within sbc_setup_write_same() code. Also, makes the changes in sbc_parse_cdb() to handle a sense_reason_t return from sbc_setup_write_same() on error. Reported-by: Christoph Hellwig Cc: Martin K. Petersen Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_sbc.c | 51 ++++++++++++++++-------------------- include/target/target_core_backend.h | 1 + 2 files changed, 24 insertions(+), 28 deletions(-) (limited to 'include') diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index b8024219cd4f..a5a8f463004b 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -235,26 +235,30 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb) return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32; } -static int sbc_write_same_supported(struct se_device *dev, - unsigned char *flags) +static sense_reason_t +sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *ops) { if ((flags[0] & 0x04) || (flags[0] & 0x02)) { pr_err("WRITE_SAME PBDATA and LBDATA" " bits not supported for Block Discard" " Emulation\n"); - return -ENOSYS; + return TCM_UNSUPPORTED_SCSI_OPCODE; } - /* - * Currently for the emulated case we only accept - * tpws with the UNMAP=1 bit set. + * Special case for WRITE_SAME w/ UNMAP=1 that ends up getting + * translated into block discard requests within backend code. */ - if (!(flags[0] & 0x08)) { - pr_err("WRITE_SAME w/o UNMAP bit not" - " supported for Block Discard Emulation\n"); - return -ENOSYS; + if (flags[0] & 0x08) { + if (!ops->execute_write_same_unmap) + return TCM_UNSUPPORTED_SCSI_OPCODE; + + cmd->execute_cmd = ops->execute_write_same_unmap; + return 0; } + if (!ops->execute_write_same) + return TCM_UNSUPPORTED_SCSI_OPCODE; + cmd->execute_cmd = ops->execute_write_same; return 0; } @@ -418,9 +422,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) cmd->se_cmd_flags |= SCF_FUA; break; case WRITE_SAME_32: - if (!ops->execute_write_same) - return TCM_UNSUPPORTED_SCSI_OPCODE; - sectors = transport_get_sectors_32(cdb); if (!sectors) { pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not" @@ -431,9 +432,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) size = sbc_get_size(cmd, 1); cmd->t_task_lba = get_unaligned_be64(&cdb[12]); - if (sbc_write_same_supported(dev, &cdb[10]) < 0) - return TCM_UNSUPPORTED_SCSI_OPCODE; - cmd->execute_cmd = ops->execute_write_same; + ret = sbc_setup_write_same(cmd, &cdb[10], ops); + if (ret < 0) + return ret; break; default: pr_err("VARIABLE_LENGTH_CMD service action" @@ -495,9 +496,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) cmd->execute_cmd = ops->execute_unmap; break; case WRITE_SAME_16: - if (!ops->execute_write_same) - return TCM_UNSUPPORTED_SCSI_OPCODE; - sectors = transport_get_sectors_16(cdb); if (!sectors) { pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n"); @@ -507,14 +505,11 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) size = sbc_get_size(cmd, 1); cmd->t_task_lba = get_unaligned_be64(&cdb[2]); - if (sbc_write_same_supported(dev, &cdb[1]) < 0) - return TCM_UNSUPPORTED_SCSI_OPCODE; - cmd->execute_cmd = ops->execute_write_same; + ret = sbc_setup_write_same(cmd, &cdb[1], ops); + if (ret < 0) + return ret; break; case WRITE_SAME: - if (!ops->execute_write_same) - return TCM_UNSUPPORTED_SCSI_OPCODE; - sectors = transport_get_sectors_10(cdb); if (!sectors) { pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n"); @@ -528,9 +523,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) * Follow sbcr26 with WRITE_SAME (10) and check for the existence * of byte 1 bit 3 UNMAP instead of original reserved field */ - if (sbc_write_same_supported(dev, &cdb[1]) < 0) - return TCM_UNSUPPORTED_SCSI_OPCODE; - cmd->execute_cmd = ops->execute_write_same; + ret = sbc_setup_write_same(cmd, &cdb[1], ops); + if (ret < 0) + return ret; break; case VERIFY: size = 0; diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index aa868090b9ab..3393ab10766c 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -41,6 +41,7 @@ struct sbc_ops { sense_reason_t (*execute_rw)(struct se_cmd *cmd); sense_reason_t (*execute_sync_cache)(struct se_cmd *cmd); sense_reason_t (*execute_write_same)(struct se_cmd *cmd); + sense_reason_t (*execute_write_same_unmap)(struct se_cmd *cmd); sense_reason_t (*execute_unmap)(struct se_cmd *cmd); }; -- cgit v1.2.3 From 773cbaf7460aa58c67d4dca83c3f8bca10323bbe Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 15 Nov 2012 11:02:49 -0800 Subject: target: Add/check max_write_same_len device attribute + update block limits VPD This patch adds a new max_write_same_len device attribute for use with WRITE_SAME w/ UNMAP=0 backend emulation. This can be useful for lowering the default backend value (IBLOCK uses 0xFFFF). Also, update block limits VPD emulation code in spc_emulate_evpd_b0() to report MAXIMUM WRITE SAME LENGTH, and enforce max_write_same_len during sbc_parse() -> sbc_setup_write_same() CDB sanity checking for all emulated WRITE_SAME w/ UNMAP=0 cases. (Robert: Move max_write_same_len check in sbc_setup_write_same() to check both WRITE_SAME w/ UNMAP=1 and w/ UNMAP=0 cases) Cc: Christoph Hellwig Cc: Martin K. Petersen Cc: Robert Elliott Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_configfs.c | 4 ++++ drivers/target/target_core_device.c | 11 +++++++++++ drivers/target/target_core_internal.h | 1 + drivers/target/target_core_sbc.c | 7 +++++++ drivers/target/target_core_spc.c | 8 +++++++- include/target/target_core_base.h | 3 +++ 6 files changed, 33 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 7b473b66da7b..2b141643f06e 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -676,6 +676,9 @@ SE_DEV_ATTR(unmap_granularity, S_IRUGO | S_IWUSR); DEF_DEV_ATTRIB(unmap_granularity_alignment); SE_DEV_ATTR(unmap_granularity_alignment, S_IRUGO | S_IWUSR); +DEF_DEV_ATTRIB(max_write_same_len); +SE_DEV_ATTR(max_write_same_len, S_IRUGO | S_IWUSR); + CONFIGFS_EATTR_OPS(target_core_dev_attrib, se_dev_attrib, da_group); static struct configfs_attribute *target_core_dev_attrib_attrs[] = { @@ -701,6 +704,7 @@ static struct configfs_attribute *target_core_dev_attrib_attrs[] = { &target_core_dev_attrib_max_unmap_block_desc_count.attr, &target_core_dev_attrib_unmap_granularity.attr, &target_core_dev_attrib_unmap_granularity_alignment.attr, + &target_core_dev_attrib_max_write_same_len.attr, NULL, }; diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 599374e6d245..54439bc42dab 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -706,6 +706,16 @@ int se_dev_set_unmap_granularity_alignment( return 0; } +int se_dev_set_max_write_same_len( + struct se_device *dev, + u32 max_write_same_len) +{ + dev->dev_attrib.max_write_same_len = max_write_same_len; + pr_debug("dev[%p]: Set max_write_same_len: %u\n", + dev, dev->dev_attrib.max_write_same_len); + return 0; +} + int se_dev_set_emulate_dpo(struct se_device *dev, int flag) { if (flag != 0 && flag != 1) { @@ -1393,6 +1403,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) dev->dev_attrib.unmap_granularity = DA_UNMAP_GRANULARITY_DEFAULT; dev->dev_attrib.unmap_granularity_alignment = DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT; + dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN; dev->dev_attrib.fabric_max_sectors = DA_FABRIC_MAX_SECTORS; dev->dev_attrib.optimal_sectors = DA_FABRIC_MAX_SECTORS; diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index bc9c52284845..93e9c1f580b0 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -24,6 +24,7 @@ int se_dev_set_max_unmap_lba_count(struct se_device *, u32); int se_dev_set_max_unmap_block_desc_count(struct se_device *, u32); int se_dev_set_unmap_granularity(struct se_device *, u32); int se_dev_set_unmap_granularity_alignment(struct se_device *, u32); +int se_dev_set_max_write_same_len(struct se_device *, u32); int se_dev_set_emulate_dpo(struct se_device *, int); int se_dev_set_emulate_fua_write(struct se_device *, int); int se_dev_set_emulate_fua_read(struct se_device *, int); diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index a5a8f463004b..45e11d0e38c4 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -238,12 +238,19 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb) static sense_reason_t sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *ops) { + unsigned int sectors = spc_get_write_same_sectors(cmd); + if ((flags[0] & 0x04) || (flags[0] & 0x02)) { pr_err("WRITE_SAME PBDATA and LBDATA" " bits not supported for Block Discard" " Emulation\n"); return TCM_UNSUPPORTED_SCSI_OPCODE; } + if (sectors > cmd->se_dev->dev_attrib.max_write_same_len) { + pr_warn("WRITE_SAME sectors: %u exceeds max_write_same_len: %u\n", + sectors, cmd->se_dev->dev_attrib.max_write_same_len); + return TCM_INVALID_CDB_FIELD; + } /* * Special case for WRITE_SAME w/ UNMAP=1 that ends up getting * translated into block discard requests within backend code. diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 4b3c18305ec8..cf1b8bb310c4 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -465,7 +465,7 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) * Exit now if we don't support TP. */ if (!have_tp) - return 0; + goto max_write_same; /* * Set MAXIMUM UNMAP LBA COUNT @@ -491,6 +491,12 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) if (dev->dev_attrib.unmap_granularity_alignment != 0) buf[32] |= 0x80; /* Set the UGAVALID bit */ + /* + * MAXIMUM WRITE SAME LENGTH + */ +max_write_same: + put_unaligned_be64(dev->dev_attrib.max_write_same_len, &buf[36]); + return 0; } diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 5350f6e580f0..645d90ac6097 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -71,6 +71,8 @@ #define DA_UNMAP_GRANULARITY_DEFAULT 0 /* Default unmap_granularity_alignment */ #define DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT 0 +/* Default max_write_same_len, disabled by default */ +#define DA_MAX_WRITE_SAME_LEN 0 /* Default max transfer length */ #define DA_FABRIC_MAX_SECTORS 8192 /* Emulation for Direct Page Out */ @@ -609,6 +611,7 @@ struct se_dev_attrib { u32 max_unmap_block_desc_count; u32 unmap_granularity; u32 unmap_granularity_alignment; + u32 max_write_same_len; struct se_device *da_dev; struct config_group da_group; }; -- cgit v1.2.3 From ffe0067544f93c0e71c793d7f17240486d091a3c Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Tue, 27 Nov 2012 19:07:52 -0800 Subject: target: Make spc_get_write_same_sectors return sector_t We already expect TFO->get_blocks() to return sector_t for zero value case when doing WRITE_SAME to the end of the backend device, so go ahead and return sector_t from spc_get_write_same_sectors() to handle this case properly. Also, update the single iblock_execute_write_same() caller of this code. Cc: Christoph Hellwig Cc: Martin K. Petersen Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_iblock.c | 2 +- drivers/target/target_core_sbc.c | 2 +- include/target/target_core_backend.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 34f258b4d37f..b526d23dcd4f 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -481,7 +481,7 @@ iblock_execute_write_same(struct se_cmd *cmd) struct bio *bio; struct bio_list list; sector_t block_lba = cmd->t_task_lba; - unsigned int sectors = spc_get_write_same_sectors(cmd); + sector_t sectors = spc_get_write_same_sectors(cmd); sg = &cmd->t_data_sg[0]; diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 94fd004ea3fc..26a6d183ccb1 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -107,7 +107,7 @@ sbc_emulate_readcapacity_16(struct se_cmd *cmd) return 0; } -int spc_get_write_same_sectors(struct se_cmd *cmd) +sector_t spc_get_write_same_sectors(struct se_cmd *cmd) { u32 num_blocks; diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index 3393ab10766c..507910992c59 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -52,7 +52,7 @@ void target_complete_cmd(struct se_cmd *, u8); sense_reason_t spc_parse_cdb(struct se_cmd *cmd, unsigned int *size); sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd); -int spc_get_write_same_sectors(struct se_cmd *cmd); +sector_t spc_get_write_same_sectors(struct se_cmd *cmd); sense_reason_t sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops); u32 sbc_get_device_rev(struct se_device *dev); -- cgit v1.2.3 From 0ff8754981261a80f4b77db2536dfea92c2d4539 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Tue, 4 Dec 2012 23:43:57 -0800 Subject: target: Add link_magic for fabric allow_link destination target_items This patch adds [dev,lun]_link_magic value assignment + checks within generic target_fabric_port_link() and target_fabric_mappedlun_link() code to ensure destination config_item *target_item sent from configfs_symlink() -> config_item_operations->allow_link() is the underlying se_device->dev_group and se_lun->lun_group that we expect to symlink. Reported-by: Sebastian Andrzej Siewior Cc: Sebastian Andrzej Siewior Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_device.c | 1 + drivers/target/target_core_fabric_configfs.c | 12 ++++++++++++ drivers/target/target_core_tpg.c | 1 + include/target/target_core_base.h | 4 ++++ 4 files changed, 18 insertions(+) (limited to 'include') diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 3f604393d89c..e2695101bb99 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -1352,6 +1352,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) if (!dev) return NULL; + dev->dev_link_magic = SE_DEV_LINK_MAGIC; dev->se_hba = hba; dev->transport = hba->transport; diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index 9c6791734ee8..810263dfa4a1 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -70,6 +70,12 @@ static int target_fabric_mappedlun_link( struct se_portal_group *se_tpg; struct config_item *nacl_ci, *tpg_ci, *tpg_ci_s, *wwn_ci, *wwn_ci_s; int ret = 0, lun_access; + + if (lun->lun_link_magic != SE_LUN_LINK_MAGIC) { + pr_err("Bad lun->lun_link_magic, not a valid lun_ci pointer:" + " %p to struct lun: %p\n", lun_ci, lun); + return -EFAULT; + } /* * Ensure that the source port exists */ @@ -742,6 +748,12 @@ static int target_fabric_port_link( struct target_fabric_configfs *tf; int ret; + if (dev->dev_link_magic != SE_DEV_LINK_MAGIC) { + pr_err("Bad dev->dev_link_magic, not a valid se_dev_ci pointer:" + " %p to struct se_device: %p\n", se_dev_ci, dev); + return -EFAULT; + } + tpg_ci = &lun_ci->ci_parent->ci_group->cg_item; se_tpg = container_of(to_config_group(tpg_ci), struct se_portal_group, tpg_group); diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index d84cc0a8739e..0163309e2aba 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c @@ -669,6 +669,7 @@ int core_tpg_register( for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { lun = se_tpg->tpg_lun_list[i]; lun->unpacked_lun = i; + lun->lun_link_magic = SE_LUN_LINK_MAGIC; lun->lun_status = TRANSPORT_LUN_STATUS_FREE; atomic_set(&lun->lun_acl_count, 0); init_completion(&lun->lun_shutdown_comp); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 645d90ac6097..1346ee04db5e 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -624,6 +624,8 @@ struct se_dev_stat_grps { }; struct se_device { +#define SE_DEV_LINK_MAGIC 0xfeeddeef + u32 dev_link_magic; /* RELATIVE TARGET PORT IDENTIFER Counter */ u16 dev_rpti_counter; /* Used for SAM Task Attribute ordering */ @@ -722,6 +724,8 @@ struct se_port_stat_grps { }; struct se_lun { +#define SE_LUN_LINK_MAGIC 0xffff7771 + u32 lun_link_magic; /* See transport_lun_status_table */ enum transport_lun_status_table lun_status; u32 lun_access; -- cgit v1.2.3 From 79e62fc3827bd437c304c1810f36896fc1e717b1 Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Tue, 11 Dec 2012 16:30:53 -0800 Subject: target/iscsi_target: Add NodeACL tags for initiator group support Thanks for reviews, looking a lot better. ---- 8< ---- Initiator access config could be easier. The way other storage vendors have addressed this is to support initiator groups: the admin adds initiator WWNs to the group, and then LUN permissions can be granted for the entire group at once. Instead of changing ktarget's configfs interface, this patch keeps the configfs interface per-initiator-wwn and just adds a 'tag' field for each. This should be enough for user tools like targetcli to group initiator ACLs and sync their configurations. acl_tag is not used internally, but needs to be kept in configfs so that all user tools can avoid dependencies on each other. Code tested to work, although userspace pieces still to be implemented. Signed-off-by: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_configfs.c | 24 ++++++++++++++++++++++++ drivers/target/target_core_tpg.c | 23 +++++++++++++++++++++++ include/target/target_core_base.h | 2 ++ include/target/target_core_fabric.h | 2 ++ 4 files changed, 51 insertions(+) (limited to 'include') diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index 542641c504a6..5201d5ef9700 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -754,9 +754,33 @@ static ssize_t lio_target_nacl_store_cmdsn_depth( TF_NACL_BASE_ATTR(lio_target, cmdsn_depth, S_IRUGO | S_IWUSR); +static ssize_t lio_target_nacl_show_tag( + struct se_node_acl *se_nacl, + char *page) +{ + return snprintf(page, PAGE_SIZE, "%s", se_nacl->acl_tag); +} + +static ssize_t lio_target_nacl_store_tag( + struct se_node_acl *se_nacl, + const char *page, + size_t count) +{ + int ret; + + ret = core_tpg_set_initiator_node_tag(se_nacl->se_tpg, se_nacl, page); + + if (ret < 0) + return ret; + return count; +} + +TF_NACL_BASE_ATTR(lio_target, tag, S_IRUGO | S_IWUSR); + static struct configfs_attribute *lio_target_initiator_attrs[] = { &lio_target_nacl_info.attr, &lio_target_nacl_cmdsn_depth.attr, + &lio_target_nacl_tag.attr, NULL, }; diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index 0163309e2aba..5192ac0337f7 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c @@ -616,6 +616,29 @@ int core_tpg_set_initiator_node_queue_depth( } EXPORT_SYMBOL(core_tpg_set_initiator_node_queue_depth); +/* core_tpg_set_initiator_node_tag(): + * + * Initiator nodeacl tags are not used internally, but may be used by + * userspace to emulate aliases or groups. + * Returns length of newly-set tag or -EINVAL. + */ +int core_tpg_set_initiator_node_tag( + struct se_portal_group *tpg, + struct se_node_acl *acl, + const char *new_tag) +{ + if (strlen(new_tag) >= MAX_ACL_TAG_SIZE) + return -EINVAL; + + if (!strncmp("NULL", new_tag, 4)) { + acl->acl_tag[0] = '\0'; + return 0; + } + + return snprintf(acl->acl_tag, MAX_ACL_TAG_SIZE, "%s", new_tag); +} +EXPORT_SYMBOL(core_tpg_set_initiator_node_tag); + static int core_tpg_setup_virtual_lun0(struct se_portal_group *se_tpg) { /* Set in core_dev_setup_virtual_lun0() */ diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 1346ee04db5e..7cae2360221e 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -507,6 +507,8 @@ struct se_node_acl { bool acl_stop:1; u32 queue_depth; u32 acl_index; +#define MAX_ACL_TAG_SIZE 64 + char acl_tag[MAX_ACL_TAG_SIZE]; u64 num_cmds; u64 read_bytes; u64 write_bytes; diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h index 9087b200e552..aaa1ee6ab391 100644 --- a/include/target/target_core_fabric.h +++ b/include/target/target_core_fabric.h @@ -142,6 +142,8 @@ int core_tpg_del_initiator_node_acl(struct se_portal_group *, struct se_node_acl *, int); int core_tpg_set_initiator_node_queue_depth(struct se_portal_group *, unsigned char *, u32, int); +int core_tpg_set_initiator_node_tag(struct se_portal_group *, + struct se_node_acl *, const char *); int core_tpg_register(struct target_core_fabric_ops *, struct se_wwn *, struct se_portal_group *, void *, int); int core_tpg_deregister(struct se_portal_group *); -- cgit v1.2.3