diff options
Diffstat (limited to 'drivers/target')
45 files changed, 993 insertions, 1061 deletions
diff --git a/drivers/target/iscsi/Kconfig b/drivers/target/iscsi/Kconfig index 922484ea4e30..70d76f3dd693 100644 --- a/drivers/target/iscsi/Kconfig +++ b/drivers/target/iscsi/Kconfig @@ -1,12 +1,15 @@ # SPDX-License-Identifier: GPL-2.0-only config ISCSI_TARGET - tristate "Linux-iSCSI.org iSCSI Target Mode Stack" + tristate "SCSI Target Mode Stack" depends on INET + select CRC32 select CRYPTO - select CRYPTO_CRC32C - select CRYPTO_CRC32C_INTEL if X86 + select CRYPTO_HASH help - Say M here to enable the ConfigFS enabled Linux-iSCSI.org iSCSI - Target Mode Stack. + Say M to enable the SCSI target mode stack. A SCSI target mode stack + is software that makes local storage available over a storage network + to a SCSI initiator system. The supported storage network technologies + include iSCSI, Fibre Channel and the SCSI RDMA Protocol (SRP). + Configuration of the SCSI target mode stack happens through configfs. source "drivers/target/iscsi/cxgbit/Kconfig" diff --git a/drivers/target/iscsi/cxgbit/cxgbit_target.c b/drivers/target/iscsi/cxgbit/cxgbit_target.c index acfc39683c87..3698f2eb097e 100644 --- a/drivers/target/iscsi/cxgbit/cxgbit_target.c +++ b/drivers/target/iscsi/cxgbit/cxgbit_target.c @@ -7,7 +7,7 @@ #include <linux/kthread.h> #include <linux/sched/signal.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <net/tcp.h> #include <target/target_core_base.h> #include <target/target_core_fabric.h> diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index b516c2893420..a2dde08c8a62 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -8,7 +8,7 @@ * ******************************************************************************/ -#include <crypto/hash.h> +#include <linux/crc32c.h> #include <linux/string.h> #include <linux/kthread.h> #include <linux/completion.h> @@ -17,7 +17,7 @@ #include <linux/idr.h> #include <linux/delay.h> #include <linux/sched/signal.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <linux/inet.h> #include <net/ipv6.h> #include <scsi/scsi_proto.h> @@ -490,8 +490,8 @@ void iscsit_aborted_task(struct iscsit_conn *conn, struct iscsit_cmd *cmd) } EXPORT_SYMBOL(iscsit_aborted_task); -static void iscsit_do_crypto_hash_buf(struct ahash_request *, const void *, - u32, u32, const void *, void *); +static u32 iscsit_crc_buf(const void *buf, u32 payload_length, + u32 padding, const void *pad_bytes); static void iscsit_tx_thread_wait_for_tcp(struct iscsit_conn *); static int @@ -510,9 +510,7 @@ iscsit_xmit_nondatain_pdu(struct iscsit_conn *conn, struct iscsit_cmd *cmd, if (conn->conn_ops->HeaderDigest) { u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; - iscsit_do_crypto_hash_buf(conn->conn_tx_hash, hdr, - ISCSI_HDR_LEN, 0, NULL, - header_digest); + *header_digest = iscsit_crc_buf(hdr, ISCSI_HDR_LEN, 0, NULL); iov[0].iov_len += ISCSI_CRC_LEN; tx_size += ISCSI_CRC_LEN; @@ -537,11 +535,9 @@ iscsit_xmit_nondatain_pdu(struct iscsit_conn *conn, struct iscsit_cmd *cmd, } if (conn->conn_ops->DataDigest) { - iscsit_do_crypto_hash_buf(conn->conn_tx_hash, - data_buf, data_buf_len, - padding, &cmd->pad_bytes, - &cmd->data_crc); - + cmd->data_crc = iscsit_crc_buf(data_buf, data_buf_len, + padding, + &cmd->pad_bytes); iov[niov].iov_base = &cmd->data_crc; iov[niov++].iov_len = ISCSI_CRC_LEN; tx_size += ISCSI_CRC_LEN; @@ -566,8 +562,8 @@ iscsit_xmit_nondatain_pdu(struct iscsit_conn *conn, struct iscsit_cmd *cmd, static int iscsit_map_iovec(struct iscsit_cmd *cmd, struct kvec *iov, int nvec, u32 data_offset, u32 data_length); static void iscsit_unmap_iovec(struct iscsit_cmd *); -static u32 iscsit_do_crypto_hash_sg(struct ahash_request *, struct iscsit_cmd *, - u32, u32, u32, u8 *); +static u32 iscsit_crc_sglist(const struct iscsit_cmd *cmd, u32 data_length, + u32 padding, const u8 *pad_bytes); static int iscsit_xmit_datain_pdu(struct iscsit_conn *conn, struct iscsit_cmd *cmd, const struct iscsi_datain *datain) @@ -584,10 +580,8 @@ iscsit_xmit_datain_pdu(struct iscsit_conn *conn, struct iscsit_cmd *cmd, if (conn->conn_ops->HeaderDigest) { u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; - iscsit_do_crypto_hash_buf(conn->conn_tx_hash, cmd->pdu, - ISCSI_HDR_LEN, 0, NULL, - header_digest); - + *header_digest = iscsit_crc_buf(cmd->pdu, ISCSI_HDR_LEN, 0, + NULL); iov[0].iov_len += ISCSI_CRC_LEN; tx_size += ISCSI_CRC_LEN; @@ -614,12 +608,8 @@ iscsit_xmit_datain_pdu(struct iscsit_conn *conn, struct iscsit_cmd *cmd, } if (conn->conn_ops->DataDigest) { - cmd->data_crc = iscsit_do_crypto_hash_sg(conn->conn_tx_hash, - cmd, datain->offset, - datain->length, - cmd->padding, - cmd->pad_bytes); - + cmd->data_crc = iscsit_crc_sglist(cmd, datain->length, + cmd->padding, cmd->pad_bytes); iov[iov_count].iov_base = &cmd->data_crc; iov[iov_count++].iov_len = ISCSI_CRC_LEN; tx_size += ISCSI_CRC_LEN; @@ -1234,12 +1224,6 @@ attach_cmd: spin_lock_bh(&conn->cmd_lock); list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list); spin_unlock_bh(&conn->cmd_lock); - /* - * Check if we need to delay processing because of ALUA - * Active/NonOptimized primary access state.. - */ - core_alua_check_nonop_delay(&cmd->se_cmd); - return 0; } EXPORT_SYMBOL(iscsit_setup_scsi_cmd); @@ -1410,77 +1394,45 @@ iscsit_handle_scsi_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd, return iscsit_get_immediate_data(cmd, hdr, dump_payload); } -static u32 iscsit_do_crypto_hash_sg( - struct ahash_request *hash, - struct iscsit_cmd *cmd, - u32 data_offset, - u32 data_length, - u32 padding, - u8 *pad_bytes) +static u32 iscsit_crc_sglist(const struct iscsit_cmd *cmd, u32 data_length, + u32 padding, const u8 *pad_bytes) { - u32 data_crc; - struct scatterlist *sg; - unsigned int page_off; - - crypto_ahash_init(hash); - - sg = cmd->first_data_sg; - page_off = cmd->first_data_sg_off; - - if (data_length && page_off) { - struct scatterlist first_sg; - u32 len = min_t(u32, data_length, sg->length - page_off); - - sg_init_table(&first_sg, 1); - sg_set_page(&first_sg, sg_page(sg), len, sg->offset + page_off); - - ahash_request_set_crypt(hash, &first_sg, NULL, len); - crypto_ahash_update(hash); - - data_length -= len; - sg = sg_next(sg); - } + struct scatterlist *sg = cmd->first_data_sg; + unsigned int page_off = cmd->first_data_sg_off; + u32 crc = ~0; while (data_length) { - u32 cur_len = min_t(u32, data_length, sg->length); + u32 cur_len = min_t(u32, data_length, sg->length - page_off); + const void *virt; - ahash_request_set_crypt(hash, sg, NULL, cur_len); - crypto_ahash_update(hash); + virt = kmap_local_page(sg_page(sg)) + sg->offset + page_off; + crc = crc32c(crc, virt, cur_len); + kunmap_local(virt); - data_length -= cur_len; /* iscsit_map_iovec has already checked for invalid sg pointers */ sg = sg_next(sg); - } - - if (padding) { - struct scatterlist pad_sg; - sg_init_one(&pad_sg, pad_bytes, padding); - ahash_request_set_crypt(hash, &pad_sg, (u8 *)&data_crc, - padding); - crypto_ahash_finup(hash); - } else { - ahash_request_set_crypt(hash, NULL, (u8 *)&data_crc, 0); - crypto_ahash_final(hash); + page_off = 0; + data_length -= cur_len; } - return data_crc; + if (padding) + crc = crc32c(crc, pad_bytes, padding); + + return ~crc; } -static void iscsit_do_crypto_hash_buf(struct ahash_request *hash, - const void *buf, u32 payload_length, u32 padding, - const void *pad_bytes, void *data_crc) +static u32 iscsit_crc_buf(const void *buf, u32 payload_length, + u32 padding, const void *pad_bytes) { - struct scatterlist sg[2]; + u32 crc = ~0; - sg_init_table(sg, ARRAY_SIZE(sg)); - sg_set_buf(sg, buf, payload_length); - if (padding) - sg_set_buf(sg + 1, pad_bytes, padding); + crc = crc32c(crc, buf, payload_length); - ahash_request_set_crypt(hash, sg, data_crc, payload_length + padding); + if (padding) + crc = crc32c(crc, pad_bytes, padding); - crypto_ahash_digest(hash); + return ~crc; } int @@ -1668,11 +1620,8 @@ iscsit_get_dataout(struct iscsit_conn *conn, struct iscsit_cmd *cmd, if (conn->conn_ops->DataDigest) { u32 data_crc; - data_crc = iscsit_do_crypto_hash_sg(conn->conn_rx_hash, cmd, - be32_to_cpu(hdr->offset), - payload_length, padding, - cmd->pad_bytes); - + data_crc = iscsit_crc_sglist(cmd, payload_length, padding, + cmd->pad_bytes); if (checksum != data_crc) { pr_err("ITT: 0x%08x, Offset: %u, Length: %u," " DataSN: 0x%08x, CRC32C DataDigest 0x%08x" @@ -1931,10 +1880,8 @@ static int iscsit_handle_nop_out(struct iscsit_conn *conn, struct iscsit_cmd *cm } if (conn->conn_ops->DataDigest) { - iscsit_do_crypto_hash_buf(conn->conn_rx_hash, ping_data, - payload_length, padding, - cmd->pad_bytes, &data_crc); - + data_crc = iscsit_crc_buf(ping_data, payload_length, + padding, cmd->pad_bytes); if (checksum != data_crc) { pr_err("Ping data CRC32C DataDigest" " 0x%08x does not match computed 0x%08x\n", @@ -2334,10 +2281,7 @@ iscsit_handle_text_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd, goto reject; if (conn->conn_ops->DataDigest) { - iscsit_do_crypto_hash_buf(conn->conn_rx_hash, - text_in, rx_size, 0, NULL, - &data_crc); - + data_crc = iscsit_crc_buf(text_in, rx_size, 0, NULL); if (checksum != data_crc) { pr_err("Text data CRC32C DataDigest" " 0x%08x does not match computed" @@ -2694,10 +2638,8 @@ static int iscsit_handle_immediate_data( if (conn->conn_ops->DataDigest) { u32 data_crc; - data_crc = iscsit_do_crypto_hash_sg(conn->conn_rx_hash, cmd, - cmd->write_data_done, length, padding, - cmd->pad_bytes); - + data_crc = iscsit_crc_sglist(cmd, length, padding, + cmd->pad_bytes); if (checksum != data_crc) { pr_err("ImmediateData CRC32C DataDigest 0x%08x" " does not match computed 0x%08x\n", checksum, @@ -3477,7 +3419,7 @@ iscsit_build_sendtargets_response(struct iscsit_cmd *cmd, } } - if (inet_addr_is_any((struct sockaddr *)&np->np_sockaddr)) + if (inet_addr_is_any(&np->np_sockaddr)) sockaddr = &conn->local_sockaddr; else sockaddr = &np->np_sockaddr; @@ -4122,10 +4064,8 @@ static void iscsit_get_rx_pdu(struct iscsit_conn *conn) break; } - iscsit_do_crypto_hash_buf(conn->conn_rx_hash, buffer, - ISCSI_HDR_LEN, 0, NULL, - &checksum); - + checksum = iscsit_crc_buf(buffer, ISCSI_HDR_LEN, 0, + NULL); if (digest != checksum) { pr_err("HeaderDigest CRC32C failed," " received 0x%08x, computed 0x%08x\n", @@ -4323,8 +4263,8 @@ int iscsit_close_connection( spin_unlock(&iscsit_global->ts_bitmap_lock); iscsit_stop_timers_for_cmds(conn); - iscsit_stop_nopin_response_timer(conn); iscsit_stop_nopin_timer(conn); + iscsit_stop_nopin_response_timer(conn); if (conn->conn_transport->iscsit_wait_conn) conn->conn_transport->iscsit_wait_conn(conn); @@ -4412,15 +4352,6 @@ int iscsit_close_connection( */ iscsit_check_conn_usage_count(conn); - ahash_request_free(conn->conn_tx_hash); - if (conn->conn_rx_hash) { - struct crypto_ahash *tfm; - - tfm = crypto_ahash_reqtfm(conn->conn_rx_hash); - ahash_request_free(conn->conn_rx_hash); - crypto_free_ahash(tfm); - } - if (conn->sock) sock_release(conn->sock); @@ -4733,21 +4664,6 @@ int iscsit_logout_post_handler( } EXPORT_SYMBOL(iscsit_logout_post_handler); -void iscsit_fail_session(struct iscsit_session *sess) -{ - struct iscsit_conn *conn; - - spin_lock_bh(&sess->conn_lock); - list_for_each_entry(conn, &sess->sess_conn_list, conn_list) { - pr_debug("Moving to TARG_CONN_STATE_CLEANUP_WAIT.\n"); - conn->conn_state = TARG_CONN_STATE_CLEANUP_WAIT; - } - spin_unlock_bh(&sess->conn_lock); - - pr_debug("Moving to TARG_SESS_STATE_FAILED.\n"); - sess->session_state = TARG_SESS_STATE_FAILED; -} - void iscsit_stop_session( struct iscsit_session *sess, int session_sleep, diff --git a/drivers/target/iscsi/iscsi_target.h b/drivers/target/iscsi/iscsi_target.h index 0c997a08adec..f4addae2aae4 100644 --- a/drivers/target/iscsi/iscsi_target.h +++ b/drivers/target/iscsi/iscsi_target.h @@ -15,7 +15,6 @@ struct kref; struct sockaddr_storage; extern struct iscsi_tiqn *iscsit_get_tiqn_for_login(unsigned char *); -extern struct iscsi_tiqn *iscsit_get_tiqn(unsigned char *, int); extern void iscsit_put_tiqn_for_login(struct iscsi_tiqn *); extern struct iscsi_tiqn *iscsit_add_tiqn(unsigned char *); extern void iscsit_del_tiqn(struct iscsi_tiqn *); @@ -35,14 +34,12 @@ extern void iscsit_set_unsolicited_dataout(struct iscsit_cmd *); extern int iscsit_logout_closesession(struct iscsit_cmd *, struct iscsit_conn *); extern int iscsit_logout_closeconnection(struct iscsit_cmd *, struct iscsit_conn *); extern int iscsit_logout_removeconnforrecovery(struct iscsit_cmd *, struct iscsit_conn *); -extern int iscsit_send_async_msg(struct iscsit_conn *, u16, u8, u8); extern int iscsit_build_r2ts_for_cmd(struct iscsit_conn *, struct iscsit_cmd *, bool recovery); extern void iscsit_thread_get_cpumask(struct iscsit_conn *); extern int iscsi_target_tx_thread(void *); extern int iscsi_target_rx_thread(void *); extern int iscsit_close_connection(struct iscsit_conn *); extern int iscsit_close_session(struct iscsit_session *, bool can_sleep); -extern void iscsit_fail_session(struct iscsit_session *); extern void iscsit_stop_session(struct iscsit_session *, int, int); extern int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *, int); diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index 5d0f51822414..efe8cdb20060 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -45,9 +45,9 @@ static ssize_t lio_target_np_driver_show(struct config_item *item, char *page, tpg_np_new = iscsit_tpg_locate_child_np(tpg_np, type); if (tpg_np_new) - rb = sprintf(page, "1\n"); + rb = sysfs_emit(page, "1\n"); else - rb = sprintf(page, "0\n"); + rb = sysfs_emit(page, "0\n"); return rb; } @@ -282,7 +282,7 @@ static ssize_t iscsi_nacl_attrib_##name##_show(struct config_item *item,\ { \ struct se_node_acl *se_nacl = attrib_to_nacl(item); \ struct iscsi_node_acl *nacl = to_iscsi_nacl(se_nacl); \ - return sprintf(page, "%u\n", nacl->node_attrib.name); \ + return sysfs_emit(page, "%u\n", nacl->node_attrib.name); \ } \ \ static ssize_t iscsi_nacl_attrib_##name##_store(struct config_item *item,\ @@ -320,7 +320,7 @@ static ssize_t iscsi_nacl_attrib_authentication_show(struct config_item *item, struct se_node_acl *se_nacl = attrib_to_nacl(item); struct iscsi_node_acl *nacl = to_iscsi_nacl(se_nacl); - return sprintf(page, "%d\n", nacl->node_attrib.authentication); + return sysfs_emit(page, "%d\n", nacl->node_attrib.authentication); } static ssize_t iscsi_nacl_attrib_authentication_store(struct config_item *item, @@ -533,102 +533,102 @@ static ssize_t lio_target_nacl_info_show(struct config_item *item, char *page) spin_lock_bh(&se_nacl->nacl_sess_lock); se_sess = se_nacl->nacl_sess; if (!se_sess) { - rb += sprintf(page+rb, "No active iSCSI Session for Initiator" + rb += sysfs_emit_at(page, rb, "No active iSCSI Session for Initiator" " Endpoint: %s\n", se_nacl->initiatorname); } else { sess = se_sess->fabric_sess_ptr; - rb += sprintf(page+rb, "InitiatorName: %s\n", + rb += sysfs_emit_at(page, rb, "InitiatorName: %s\n", sess->sess_ops->InitiatorName); - rb += sprintf(page+rb, "InitiatorAlias: %s\n", + rb += sysfs_emit_at(page, rb, "InitiatorAlias: %s\n", sess->sess_ops->InitiatorAlias); - rb += sprintf(page+rb, + rb += sysfs_emit_at(page, rb, "LIO Session ID: %u ISID: 0x%6ph TSIH: %hu ", sess->sid, sess->isid, sess->tsih); - rb += sprintf(page+rb, "SessionType: %s\n", + rb += sysfs_emit_at(page, rb, "SessionType: %s\n", (sess->sess_ops->SessionType) ? "Discovery" : "Normal"); - rb += sprintf(page+rb, "Session State: "); + rb += sysfs_emit_at(page, rb, "Session State: "); switch (sess->session_state) { case TARG_SESS_STATE_FREE: - rb += sprintf(page+rb, "TARG_SESS_FREE\n"); + rb += sysfs_emit_at(page, rb, "TARG_SESS_FREE\n"); break; case TARG_SESS_STATE_ACTIVE: - rb += sprintf(page+rb, "TARG_SESS_STATE_ACTIVE\n"); + rb += sysfs_emit_at(page, rb, "TARG_SESS_STATE_ACTIVE\n"); break; case TARG_SESS_STATE_LOGGED_IN: - rb += sprintf(page+rb, "TARG_SESS_STATE_LOGGED_IN\n"); + rb += sysfs_emit_at(page, rb, "TARG_SESS_STATE_LOGGED_IN\n"); break; case TARG_SESS_STATE_FAILED: - rb += sprintf(page+rb, "TARG_SESS_STATE_FAILED\n"); + rb += sysfs_emit_at(page, rb, "TARG_SESS_STATE_FAILED\n"); break; case TARG_SESS_STATE_IN_CONTINUE: - rb += sprintf(page+rb, "TARG_SESS_STATE_IN_CONTINUE\n"); + rb += sysfs_emit_at(page, rb, "TARG_SESS_STATE_IN_CONTINUE\n"); break; default: - rb += sprintf(page+rb, "ERROR: Unknown Session" + rb += sysfs_emit_at(page, rb, "ERROR: Unknown Session" " State!\n"); break; } - rb += sprintf(page+rb, "---------------------[iSCSI Session" + rb += sysfs_emit_at(page, rb, "---------------------[iSCSI Session" " Values]-----------------------\n"); - rb += sprintf(page+rb, " CmdSN/WR : CmdSN/WC : ExpCmdSN" + rb += sysfs_emit_at(page, rb, " CmdSN/WR : CmdSN/WC : ExpCmdSN" " : MaxCmdSN : ITT : TTT\n"); max_cmd_sn = (u32) atomic_read(&sess->max_cmd_sn); - rb += sprintf(page+rb, " 0x%08x 0x%08x 0x%08x 0x%08x" + rb += sysfs_emit_at(page, rb, " 0x%08x 0x%08x 0x%08x 0x%08x" " 0x%08x 0x%08x\n", sess->cmdsn_window, (max_cmd_sn - sess->exp_cmd_sn) + 1, sess->exp_cmd_sn, max_cmd_sn, sess->init_task_tag, sess->targ_xfer_tag); - rb += sprintf(page+rb, "----------------------[iSCSI" + rb += sysfs_emit_at(page, rb, "----------------------[iSCSI" " Connections]-------------------------\n"); spin_lock(&sess->conn_lock); list_for_each_entry(conn, &sess->sess_conn_list, conn_list) { - rb += sprintf(page+rb, "CID: %hu Connection" + rb += sysfs_emit_at(page, rb, "CID: %hu Connection" " State: ", conn->cid); switch (conn->conn_state) { case TARG_CONN_STATE_FREE: - rb += sprintf(page+rb, + rb += sysfs_emit_at(page, rb, "TARG_CONN_STATE_FREE\n"); break; case TARG_CONN_STATE_XPT_UP: - rb += sprintf(page+rb, + rb += sysfs_emit_at(page, rb, "TARG_CONN_STATE_XPT_UP\n"); break; case TARG_CONN_STATE_IN_LOGIN: - rb += sprintf(page+rb, + rb += sysfs_emit_at(page, rb, "TARG_CONN_STATE_IN_LOGIN\n"); break; case TARG_CONN_STATE_LOGGED_IN: - rb += sprintf(page+rb, + rb += sysfs_emit_at(page, rb, "TARG_CONN_STATE_LOGGED_IN\n"); break; case TARG_CONN_STATE_IN_LOGOUT: - rb += sprintf(page+rb, + rb += sysfs_emit_at(page, rb, "TARG_CONN_STATE_IN_LOGOUT\n"); break; case TARG_CONN_STATE_LOGOUT_REQUESTED: - rb += sprintf(page+rb, + rb += sysfs_emit_at(page, rb, "TARG_CONN_STATE_LOGOUT_REQUESTED\n"); break; case TARG_CONN_STATE_CLEANUP_WAIT: - rb += sprintf(page+rb, + rb += sysfs_emit_at(page, rb, "TARG_CONN_STATE_CLEANUP_WAIT\n"); break; default: - rb += sprintf(page+rb, + rb += sysfs_emit_at(page, rb, "ERROR: Unknown Connection State!\n"); break; } - rb += sprintf(page+rb, " Address %pISc %s", &conn->login_sockaddr, + rb += sysfs_emit_at(page, rb, " Address %pISc %s", &conn->login_sockaddr, (conn->network_transport == ISCSI_TCP) ? "TCP" : "SCTP"); - rb += sprintf(page+rb, " StatSN: 0x%08x\n", + rb += sysfs_emit_at(page, rb, " StatSN: 0x%08x\n", conn->stat_sn); } spin_unlock(&sess->conn_lock); @@ -641,7 +641,7 @@ static ssize_t lio_target_nacl_info_show(struct config_item *item, char *page) static ssize_t lio_target_nacl_cmdsn_depth_show(struct config_item *item, char *page) { - return sprintf(page, "%u\n", acl_to_nacl(item)->queue_depth); + return sysfs_emit(page, "%u\n", acl_to_nacl(item)->queue_depth); } static ssize_t lio_target_nacl_cmdsn_depth_store(struct config_item *item, @@ -665,7 +665,7 @@ static ssize_t lio_target_nacl_cmdsn_depth_store(struct config_item *item, } acl_ci = &se_nacl->acl_group.cg_item; if (!acl_ci) { - pr_err("Unable to locatel acl_ci\n"); + pr_err("Unable to locate acl_ci\n"); return -EINVAL; } tpg_ci = &acl_ci->ci_parent->ci_group->cg_item; @@ -684,7 +684,7 @@ static ssize_t lio_target_nacl_cmdsn_depth_store(struct config_item *item, ret = core_tpg_set_initiator_node_queue_depth(se_nacl, cmdsn_depth); - pr_debug("LIO_Target_ConfigFS: %s/%s Set CmdSN Window: %u for" + pr_debug("LIO_Target_ConfigFS: %s/%s Set CmdSN Window: %u for " "InitiatorName: %s\n", config_item_name(wwn_ci), config_item_name(tpg_ci), cmdsn_depth, config_item_name(acl_ci)); @@ -750,7 +750,7 @@ static ssize_t iscsi_tpg_attrib_##name##_show(struct config_item *item, \ if (iscsit_get_tpg(tpg) < 0) \ return -EINVAL; \ \ - rb = sprintf(page, "%u\n", tpg->tpg_attrib.name); \ + rb = sysfs_emit(page, "%u\n", tpg->tpg_attrib.name); \ iscsit_put_tpg(tpg); \ return rb; \ } \ @@ -783,7 +783,6 @@ CONFIGFS_ATTR(iscsi_tpg_attrib_, name) DEF_TPG_ATTRIB(authentication); DEF_TPG_ATTRIB(login_timeout); -DEF_TPG_ATTRIB(netif_timeout); DEF_TPG_ATTRIB(generate_node_acls); DEF_TPG_ATTRIB(default_cmdsn_depth); DEF_TPG_ATTRIB(cache_dynamic_acls); @@ -799,7 +798,6 @@ DEF_TPG_ATTRIB(login_keys_workaround); static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = { &iscsi_tpg_attrib_attr_authentication, &iscsi_tpg_attrib_attr_login_timeout, - &iscsi_tpg_attrib_attr_netif_timeout, &iscsi_tpg_attrib_attr_generate_node_acls, &iscsi_tpg_attrib_attr_default_cmdsn_depth, &iscsi_tpg_attrib_attr_cache_dynamic_acls, @@ -1133,12 +1131,12 @@ static void lio_target_tiqn_deltpg(struct se_portal_group *se_tpg) /* End items for lio_target_tiqn_cit */ -/* Start LIO-Target TIQN struct contig_item lio_target_cit */ +/* Start LIO-Target TIQN struct config_item lio_target_cit */ static ssize_t lio_target_wwn_lio_version_show(struct config_item *item, char *page) { - return sprintf(page, "Datera Inc. iSCSI Target "ISCSIT_VERSION"\n"); + return sysfs_emit(page, "Datera Inc. iSCSI Target %s\n", ISCSIT_VERSION); } CONFIGFS_ATTR_RO(lio_target_wwn_, lio_version); @@ -1146,7 +1144,7 @@ CONFIGFS_ATTR_RO(lio_target_wwn_, lio_version); static ssize_t lio_target_wwn_cpus_allowed_list_show( struct config_item *item, char *page) { - return sprintf(page, "%*pbl\n", + return sysfs_emit(page, "%*pbl\n", cpumask_pr_args(iscsit_global->allowed_cpumask)); } @@ -1283,7 +1281,7 @@ static ssize_t iscsi_disc_enforce_discovery_auth_show(struct config_item *item, { struct iscsi_node_auth *discovery_auth = &iscsit_global->discovery_acl.node_auth; - return sprintf(page, "%d\n", discovery_auth->enforce_discovery_auth); + return sysfs_emit(page, "%d\n", discovery_auth->enforce_discovery_auth); } static ssize_t iscsi_disc_enforce_discovery_auth_store(struct config_item *item, @@ -1591,5 +1589,8 @@ const struct target_core_fabric_ops iscsi_ops = { .tfc_tpg_nacl_auth_attrs = lio_target_nacl_auth_attrs, .tfc_tpg_nacl_param_attrs = lio_target_nacl_param_attrs, - .write_pending_must_be_called = true, + .write_pending_must_be_called = 1, + + .default_submit_type = TARGET_DIRECT_SUBMIT, + .direct_submit_supp = 1, }; diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c index 07e9cf431edd..24db6b07493e 100644 --- a/drivers/target/iscsi/iscsi_target_erl0.c +++ b/drivers/target/iscsi/iscsi_target_erl0.c @@ -743,7 +743,8 @@ int iscsit_check_post_dataout( void iscsit_handle_time2retain_timeout(struct timer_list *t) { - struct iscsit_session *sess = from_timer(sess, t, time2retain_timer); + struct iscsit_session *sess = timer_container_of(sess, t, + time2retain_timer); struct iscsi_portal_group *tpg = sess->tpg; struct se_portal_group *se_tpg = &tpg->tpg_se_tpg; @@ -810,7 +811,7 @@ int iscsit_stop_time2retain_timer(struct iscsit_session *sess) sess->time2retain_timer_flags |= ISCSI_TF_STOP; spin_unlock(&se_tpg->session_lock); - del_timer_sync(&sess->time2retain_timer); + timer_delete_sync(&sess->time2retain_timer); spin_lock(&se_tpg->session_lock); sess->time2retain_timer_flags &= ~ISCSI_TF_RUNNING; diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c index f460a66c0e7c..d8ca06e697d6 100644 --- a/drivers/target/iscsi/iscsi_target_erl1.c +++ b/drivers/target/iscsi/iscsi_target_erl1.c @@ -583,7 +583,7 @@ int iscsit_dataout_datapduinorder_no_fbit( struct iscsi_pdu *pdu) { int i, send_recovery_r2t = 0, recovery = 0; - u32 length = 0, offset = 0, pdu_count = 0, xfer_len = 0; + u32 length = 0, offset = 0, pdu_count = 0; struct iscsit_conn *conn = cmd->conn; struct iscsi_pdu *first_pdu = NULL; @@ -596,7 +596,6 @@ int iscsit_dataout_datapduinorder_no_fbit( if (cmd->pdu_list[i].seq_no == pdu->seq_no) { if (!first_pdu) first_pdu = &cmd->pdu_list[i]; - xfer_len += cmd->pdu_list[i].length; pdu_count++; } else if (pdu_count) break; @@ -948,7 +947,7 @@ int iscsit_execute_cmd(struct iscsit_cmd *cmd, int ooo) iscsit_set_unsolicited_dataout(cmd); } - return transport_handle_cdb_direct(&cmd->se_cmd); + return target_submit(&cmd->se_cmd); case ISCSI_OP_NOOP_OUT: case ISCSI_OP_TEXT: @@ -1095,7 +1094,7 @@ void iscsit_handle_dataout_timeout(struct timer_list *t) { u32 pdu_length = 0, pdu_offset = 0; u32 r2t_length = 0, r2t_offset = 0; - struct iscsit_cmd *cmd = from_timer(cmd, t, dataout_timer); + struct iscsit_cmd *cmd = timer_container_of(cmd, t, dataout_timer); struct iscsit_conn *conn = cmd->conn; struct iscsit_session *sess = NULL; struct iscsi_node_attrib *na; @@ -1228,7 +1227,7 @@ void iscsit_stop_dataout_timer(struct iscsit_cmd *cmd) cmd->dataout_timer_flags |= ISCSI_TF_STOP; spin_unlock_bh(&cmd->dataout_timeout_lock); - del_timer_sync(&cmd->dataout_timer); + timer_delete_sync(&cmd->dataout_timer); spin_lock_bh(&cmd->dataout_timeout_lock); cmd->dataout_timer_flags &= ~ISCSI_TF_RUNNING; diff --git a/drivers/target/iscsi/iscsi_target_erl2.c b/drivers/target/iscsi/iscsi_target_erl2.c index 18e88d2ea5fd..56d78af7cec7 100644 --- a/drivers/target/iscsi/iscsi_target_erl2.c +++ b/drivers/target/iscsi/iscsi_target_erl2.c @@ -25,54 +25,6 @@ /* * FIXME: Does RData SNACK apply here as well? */ -void iscsit_create_conn_recovery_datain_values( - struct iscsit_cmd *cmd, - __be32 exp_data_sn) -{ - u32 data_sn = 0; - struct iscsit_conn *conn = cmd->conn; - - cmd->next_burst_len = 0; - cmd->read_data_done = 0; - - while (be32_to_cpu(exp_data_sn) > data_sn) { - if ((cmd->next_burst_len + - conn->conn_ops->MaxRecvDataSegmentLength) < - conn->sess->sess_ops->MaxBurstLength) { - cmd->read_data_done += - conn->conn_ops->MaxRecvDataSegmentLength; - cmd->next_burst_len += - conn->conn_ops->MaxRecvDataSegmentLength; - } else { - cmd->read_data_done += - (conn->sess->sess_ops->MaxBurstLength - - cmd->next_burst_len); - cmd->next_burst_len = 0; - } - data_sn++; - } -} - -void iscsit_create_conn_recovery_dataout_values( - struct iscsit_cmd *cmd) -{ - u32 write_data_done = 0; - struct iscsit_conn *conn = cmd->conn; - - cmd->data_sn = 0; - cmd->next_burst_len = 0; - - while (cmd->write_data_done > write_data_done) { - if ((write_data_done + conn->sess->sess_ops->MaxBurstLength) <= - cmd->write_data_done) - write_data_done += conn->sess->sess_ops->MaxBurstLength; - else - break; - } - - cmd->write_data_done = write_data_done; -} - static int iscsit_attach_active_connection_recovery_entry( struct iscsit_session *sess, struct iscsi_conn_recovery *cr) diff --git a/drivers/target/iscsi/iscsi_target_erl2.h b/drivers/target/iscsi/iscsi_target_erl2.h index 6655e4bcf893..9064c74eef7a 100644 --- a/drivers/target/iscsi/iscsi_target_erl2.h +++ b/drivers/target/iscsi/iscsi_target_erl2.h @@ -9,8 +9,6 @@ struct iscsit_conn; struct iscsi_conn_recovery; struct iscsit_session; -extern void iscsit_create_conn_recovery_datain_values(struct iscsit_cmd *, __be32); -extern void iscsit_create_conn_recovery_dataout_values(struct iscsit_cmd *); extern struct iscsi_conn_recovery *iscsit_get_inactive_connection_recovery_entry( struct iscsit_session *, u16); extern void iscsit_free_connection_recovery_entries(struct iscsit_session *); diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 90b870f234f0..53aca059dc16 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -8,7 +8,6 @@ * ******************************************************************************/ -#include <crypto/hash.h> #include <linux/module.h> #include <linux/string.h> #include <linux/kthread.h> @@ -71,46 +70,6 @@ out_login: return NULL; } -/* - * Used by iscsi_target_nego.c:iscsi_target_locate_portal() to setup - * per struct iscsit_conn libcrypto contexts for crc32c and crc32-intel - */ -int iscsi_login_setup_crypto(struct iscsit_conn *conn) -{ - struct crypto_ahash *tfm; - - /* - * Setup slicing by CRC32C algorithm for RX and TX libcrypto contexts - * which will default to crc32c_intel.ko for cpu_has_xmm4_2, or fallback - * to software 1x8 byte slicing from crc32c.ko - */ - tfm = crypto_alloc_ahash("crc32c", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm)) { - pr_err("crypto_alloc_ahash() failed\n"); - return -ENOMEM; - } - - conn->conn_rx_hash = ahash_request_alloc(tfm, GFP_KERNEL); - if (!conn->conn_rx_hash) { - pr_err("ahash_request_alloc() failed for conn_rx_hash\n"); - crypto_free_ahash(tfm); - return -ENOMEM; - } - ahash_request_set_callback(conn->conn_rx_hash, 0, NULL, NULL); - - conn->conn_tx_hash = ahash_request_alloc(tfm, GFP_KERNEL); - if (!conn->conn_tx_hash) { - pr_err("ahash_request_alloc() failed for conn_tx_hash\n"); - ahash_request_free(conn->conn_rx_hash); - conn->conn_rx_hash = NULL; - crypto_free_ahash(tfm); - return -ENOMEM; - } - ahash_request_set_callback(conn->conn_tx_hash, 0, NULL, NULL); - - return 0; -} - static int iscsi_login_check_initiator_version( struct iscsit_conn *conn, u8 version_max, @@ -863,7 +822,7 @@ int iscsit_setup_np( sock_set_reuseaddr(sock->sk); ip_sock_set_freebind(sock->sk); - ret = kernel_bind(sock, (struct sockaddr *)&np->np_sockaddr, len); + ret = kernel_bind(sock, (struct sockaddr_unsized *)&np->np_sockaddr, len); if (ret < 0) { pr_err("kernel_bind() failed: %d\n", ret); goto fail; @@ -1165,15 +1124,6 @@ old_sess_out: iscsit_dec_session_usage_count(conn->sess); } - ahash_request_free(conn->conn_tx_hash); - if (conn->conn_rx_hash) { - struct crypto_ahash *tfm; - - tfm = crypto_ahash_reqtfm(conn->conn_rx_hash); - ahash_request_free(conn->conn_rx_hash); - crypto_free_ahash(tfm); - } - if (conn->param_list) { iscsi_release_param_list(conn->param_list); conn->param_list = NULL; diff --git a/drivers/target/iscsi/iscsi_target_login.h b/drivers/target/iscsi/iscsi_target_login.h index 3ca2f232b387..03c7d695d58f 100644 --- a/drivers/target/iscsi/iscsi_target_login.h +++ b/drivers/target/iscsi/iscsi_target_login.h @@ -9,7 +9,6 @@ struct iscsi_login; struct iscsi_np; struct sockaddr_storage; -extern int iscsi_login_setup_crypto(struct iscsit_conn *); extern int iscsi_check_for_session_reinstatement(struct iscsit_conn *); extern int iscsi_login_post_auth_non_zero_tsih(struct iscsit_conn *, u16, u32); extern int iscsit_setup_np(struct iscsi_np *, @@ -24,6 +23,5 @@ extern int iscsit_start_kthreads(struct iscsit_conn *); extern void iscsi_post_login_handler(struct iscsi_np *, struct iscsit_conn *, u8); extern void iscsi_target_login_sess_out(struct iscsit_conn *, bool, bool); extern int iscsi_target_login_thread(void *); -extern void iscsi_handle_login_thread_timeout(struct timer_list *t); #endif /*** ISCSI_TARGET_LOGIN_H ***/ diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index fa3fb5f4e6bc..832588f21f91 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c @@ -212,7 +212,7 @@ int iscsi_target_check_login_request( if ((login_req->max_version != login->version_max) || (login_req->min_version != login->version_min)) { - pr_err("Login request changed Version Max/Nin" + pr_err("Login request changed Version Max/Min" " unexpectedly to 0x%02x/0x%02x, protocol error\n", login_req->max_version, login_req->min_version); iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, @@ -557,7 +557,7 @@ static void iscsi_target_do_login_rx(struct work_struct *work) * before initial PDU processing in iscsi_target_start_negotiation() * has completed, go ahead and retry until it's cleared. * - * Otherwise if the TCP connection drops while this is occuring, + * Otherwise if the TCP connection drops while this is occurring, * iscsi_target_start_negotiation() will detect the failure, call * cancel_delayed_work_sync(&conn->login_work), and cleanup the * remaining iscsi connection resources from iscsi_np process context. @@ -1050,7 +1050,7 @@ static int iscsi_target_do_login(struct iscsit_conn *conn, struct iscsi_login *l /* * Check to make sure the TCP connection has not * dropped asynchronously while session reinstatement - * was occuring in this kthread context, before + * was occurring in this kthread context, before * transitioning to full feature phase operation. */ if (iscsi_target_sk_check_close(conn)) @@ -1194,14 +1194,7 @@ int iscsi_target_locate_portal( goto get_target; sess->sess_ops->SessionType = 1; - /* - * Setup crc32c modules from libcrypto - */ - if (iscsi_login_setup_crypto(conn) < 0) { - pr_err("iscsi_login_setup_crypto() failed\n"); - ret = -1; - goto out; - } + /* * Serialize access across the discovery struct iscsi_portal_group to * process login attempt. @@ -1258,17 +1251,7 @@ get_target: } conn->tpg_np = tpg_np; pr_debug("Located Portal Group Object: %hu\n", conn->tpg->tpgt); - /* - * Setup crc32c modules from libcrypto - */ - if (iscsi_login_setup_crypto(conn) < 0) { - pr_err("iscsi_login_setup_crypto() failed\n"); - kref_put(&tpg_np->tpg_np_kref, iscsit_login_kref_put); - iscsit_put_tiqn_for_login(tiqn); - conn->tpg = NULL; - ret = -1; - goto out; - } + /* * Serialize access across the struct iscsi_portal_group to * process login attempt. diff --git a/drivers/target/iscsi/iscsi_target_nego.h b/drivers/target/iscsi/iscsi_target_nego.h index 41c3db3ddeaa..e60a46d34835 100644 --- a/drivers/target/iscsi/iscsi_target_nego.h +++ b/drivers/target/iscsi/iscsi_target_nego.h @@ -15,8 +15,6 @@ extern int extract_param(const char *, const char *, unsigned int, char *, unsigned char *); extern int iscsi_target_check_login_request(struct iscsit_conn *, struct iscsi_login *); -extern int iscsi_target_get_initial_payload(struct iscsit_conn *, - struct iscsi_login *); extern int iscsi_target_locate_portal(struct iscsi_np *, struct iscsit_conn *, struct iscsi_login *); extern int iscsi_target_start_negotiation( diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c index 5b90c22ee3dc..1d4e1788e073 100644 --- a/drivers/target/iscsi/iscsi_target_parameters.c +++ b/drivers/target/iscsi/iscsi_target_parameters.c @@ -67,54 +67,6 @@ int iscsi_login_tx_data( return 0; } -void iscsi_dump_conn_ops(struct iscsi_conn_ops *conn_ops) -{ - pr_debug("HeaderDigest: %s\n", (conn_ops->HeaderDigest) ? - "CRC32C" : "None"); - pr_debug("DataDigest: %s\n", (conn_ops->DataDigest) ? - "CRC32C" : "None"); - pr_debug("MaxRecvDataSegmentLength: %u\n", - conn_ops->MaxRecvDataSegmentLength); -} - -void iscsi_dump_sess_ops(struct iscsi_sess_ops *sess_ops) -{ - pr_debug("InitiatorName: %s\n", sess_ops->InitiatorName); - pr_debug("InitiatorAlias: %s\n", sess_ops->InitiatorAlias); - pr_debug("TargetName: %s\n", sess_ops->TargetName); - pr_debug("TargetAlias: %s\n", sess_ops->TargetAlias); - pr_debug("TargetPortalGroupTag: %hu\n", - sess_ops->TargetPortalGroupTag); - pr_debug("MaxConnections: %hu\n", sess_ops->MaxConnections); - pr_debug("InitialR2T: %s\n", - (sess_ops->InitialR2T) ? "Yes" : "No"); - pr_debug("ImmediateData: %s\n", (sess_ops->ImmediateData) ? - "Yes" : "No"); - pr_debug("MaxBurstLength: %u\n", sess_ops->MaxBurstLength); - pr_debug("FirstBurstLength: %u\n", sess_ops->FirstBurstLength); - pr_debug("DefaultTime2Wait: %hu\n", sess_ops->DefaultTime2Wait); - pr_debug("DefaultTime2Retain: %hu\n", - sess_ops->DefaultTime2Retain); - pr_debug("MaxOutstandingR2T: %hu\n", - sess_ops->MaxOutstandingR2T); - pr_debug("DataPDUInOrder: %s\n", - (sess_ops->DataPDUInOrder) ? "Yes" : "No"); - pr_debug("DataSequenceInOrder: %s\n", - (sess_ops->DataSequenceInOrder) ? "Yes" : "No"); - pr_debug("ErrorRecoveryLevel: %hu\n", - sess_ops->ErrorRecoveryLevel); - pr_debug("SessionType: %s\n", (sess_ops->SessionType) ? - "Discovery" : "Normal"); -} - -void iscsi_print_params(struct iscsi_param_list *param_list) -{ - struct iscsi_param *param; - - list_for_each_entry(param, ¶m_list->param_list, p_list) - pr_debug("%s: %s\n", param->name, param->value); -} - static struct iscsi_param *iscsi_set_default_param(struct iscsi_param_list *param_list, char *name, char *value, u8 phase, u8 scope, u8 sender, u16 type_range, u8 use) diff --git a/drivers/target/iscsi/iscsi_target_parameters.h b/drivers/target/iscsi/iscsi_target_parameters.h index 00fbbebb8c75..c672a971fcb7 100644 --- a/drivers/target/iscsi/iscsi_target_parameters.h +++ b/drivers/target/iscsi/iscsi_target_parameters.h @@ -32,9 +32,6 @@ struct iscsi_sess_ops; extern int iscsi_login_rx_data(struct iscsit_conn *, char *, int); extern int iscsi_login_tx_data(struct iscsit_conn *, char *, char *, int); -extern void iscsi_dump_conn_ops(struct iscsi_conn_ops *); -extern void iscsi_dump_sess_ops(struct iscsi_sess_ops *); -extern void iscsi_print_params(struct iscsi_param_list *); extern int iscsi_create_default_params(struct iscsi_param_list **); extern int iscsi_set_keys_to_negotiate(struct iscsi_param_list *, bool); extern int iscsi_set_keys_irrelevant_for_discovery(struct iscsi_param_list *); diff --git a/drivers/target/iscsi/iscsi_target_tmr.c b/drivers/target/iscsi/iscsi_target_tmr.c index afc801f255f5..620de3910599 100644 --- a/drivers/target/iscsi/iscsi_target_tmr.c +++ b/drivers/target/iscsi/iscsi_target_tmr.c @@ -8,7 +8,7 @@ * ******************************************************************************/ -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <scsi/scsi_proto.h> #include <scsi/iscsi_proto.h> #include <target/target_core_base.h> @@ -112,7 +112,8 @@ u8 iscsit_tmr_task_reassign( struct iscsi_tmr_req *tmr_req = cmd->tmr_req; struct se_tmr_req *se_tmr = cmd->se_cmd.se_tmr_req; struct iscsi_tm *hdr = (struct iscsi_tm *) buf; - u64 ret, ref_lun; + u64 ref_lun; + int ret; pr_debug("Got TASK_REASSIGN TMR ITT: 0x%08x," " RefTaskTag: 0x%08x, ExpDataSN: 0x%08x, CID: %hu\n", @@ -318,7 +319,7 @@ static int iscsit_task_reassign_complete_read( pr_debug("READ ITT: 0x%08x: t_state: %d never sent to" " transport\n", cmd->init_task_tag, cmd->se_cmd.t_state); - transport_handle_cdb_direct(se_cmd); + target_submit(se_cmd); return 0; } diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c index 3cac1aafef68..bf06cfdfb012 100644 --- a/drivers/target/iscsi/iscsi_target_tpg.c +++ b/drivers/target/iscsi/iscsi_target_tpg.c @@ -200,18 +200,12 @@ static void iscsit_clear_tpg_np_login_threads( spin_unlock(&tpg->tpg_np_lock); } -void iscsit_tpg_dump_params(struct iscsi_portal_group *tpg) -{ - iscsi_print_params(tpg->param_list); -} - static void iscsit_set_default_tpg_attribs(struct iscsi_portal_group *tpg) { struct iscsi_tpg_attrib *a = &tpg->tpg_attrib; a->authentication = TA_AUTHENTICATION; a->login_timeout = TA_LOGIN_TIMEOUT; - a->netif_timeout = TA_NETIF_TIMEOUT; a->default_cmdsn_depth = TA_DEFAULT_CMDSN_DEPTH; a->generate_node_acls = TA_GENERATE_NODE_ACLS; a->cache_dynamic_acls = TA_CACHE_DYNAMIC_ACLS; @@ -666,31 +660,6 @@ int iscsit_ta_login_timeout( return 0; } -int iscsit_ta_netif_timeout( - struct iscsi_portal_group *tpg, - u32 netif_timeout) -{ - struct iscsi_tpg_attrib *a = &tpg->tpg_attrib; - - if (netif_timeout > TA_NETIF_TIMEOUT_MAX) { - pr_err("Requested Network Interface Timeout %u larger" - " than maximum %u\n", netif_timeout, - TA_NETIF_TIMEOUT_MAX); - return -EINVAL; - } else if (netif_timeout < TA_NETIF_TIMEOUT_MIN) { - pr_err("Requested Network Interface Timeout %u smaller" - " than minimum %u\n", netif_timeout, - TA_NETIF_TIMEOUT_MIN); - return -EINVAL; - } - - a->netif_timeout = netif_timeout; - pr_debug("Set Network Interface Timeout to %u for" - " Target Portal Group %hu\n", a->netif_timeout, tpg->tpgt); - - return 0; -} - int iscsit_ta_generate_node_acls( struct iscsi_portal_group *tpg, u32 flag) diff --git a/drivers/target/iscsi/iscsi_target_tpg.h b/drivers/target/iscsi/iscsi_target_tpg.h index 839e45362776..1155b7b3164a 100644 --- a/drivers/target/iscsi/iscsi_target_tpg.h +++ b/drivers/target/iscsi/iscsi_target_tpg.h @@ -18,18 +18,12 @@ extern struct iscsi_portal_group *iscsit_get_tpg_from_np(struct iscsi_tiqn *, struct iscsi_np *, struct iscsi_tpg_np **); extern int iscsit_get_tpg(struct iscsi_portal_group *); extern void iscsit_put_tpg(struct iscsi_portal_group *); -extern void iscsit_tpg_dump_params(struct iscsi_portal_group *); extern int iscsit_tpg_add_portal_group(struct iscsi_tiqn *, struct iscsi_portal_group *); extern int iscsit_tpg_del_portal_group(struct iscsi_tiqn *, struct iscsi_portal_group *, int); extern int iscsit_tpg_enable_portal_group(struct iscsi_portal_group *); extern int iscsit_tpg_disable_portal_group(struct iscsi_portal_group *, int); -extern struct iscsi_node_acl *iscsit_tpg_add_initiator_node_acl( - struct iscsi_portal_group *, const char *, u32); -extern void iscsit_tpg_del_initiator_node_acl(struct iscsi_portal_group *, - struct se_node_acl *); extern struct iscsi_node_attrib *iscsit_tpg_get_node_attrib(struct iscsit_session *); -extern void iscsit_tpg_del_external_nps(struct iscsi_tpg_np *); extern struct iscsi_tpg_np *iscsit_tpg_locate_child_np(struct iscsi_tpg_np *, int); extern struct iscsi_tpg_np *iscsit_tpg_add_network_portal(struct iscsi_portal_group *, struct sockaddr_storage *, struct iscsi_tpg_np *, @@ -38,7 +32,6 @@ extern int iscsit_tpg_del_network_portal(struct iscsi_portal_group *, struct iscsi_tpg_np *); extern int iscsit_ta_authentication(struct iscsi_portal_group *, u32); extern int iscsit_ta_login_timeout(struct iscsi_portal_group *, u32); -extern int iscsit_ta_netif_timeout(struct iscsi_portal_group *, u32); extern int iscsit_ta_generate_node_acls(struct iscsi_portal_group *, u32); extern int iscsit_ta_default_cmdsn_depth(struct iscsi_portal_group *, u32); extern int iscsit_ta_cache_dynamic_acls(struct iscsi_portal_group *, u32); diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 91a75a4a7cc1..5e6cf34929b5 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -333,50 +333,6 @@ int iscsit_sequence_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd, } EXPORT_SYMBOL(iscsit_sequence_cmd); -int iscsit_check_unsolicited_dataout(struct iscsit_cmd *cmd, unsigned char *buf) -{ - struct iscsit_conn *conn = cmd->conn; - struct se_cmd *se_cmd = &cmd->se_cmd; - struct iscsi_data *hdr = (struct iscsi_data *) buf; - u32 payload_length = ntoh24(hdr->dlength); - - if (conn->sess->sess_ops->InitialR2T) { - pr_err("Received unexpected unsolicited data" - " while InitialR2T=Yes, protocol error.\n"); - transport_send_check_condition_and_sense(se_cmd, - TCM_UNEXPECTED_UNSOLICITED_DATA, 0); - return -1; - } - - if ((cmd->first_burst_len + payload_length) > - conn->sess->sess_ops->FirstBurstLength) { - pr_err("Total %u bytes exceeds FirstBurstLength: %u" - " for this Unsolicited DataOut Burst.\n", - (cmd->first_burst_len + payload_length), - conn->sess->sess_ops->FirstBurstLength); - transport_send_check_condition_and_sense(se_cmd, - TCM_INCORRECT_AMOUNT_OF_DATA, 0); - return -1; - } - - if (!(hdr->flags & ISCSI_FLAG_CMD_FINAL)) - return 0; - - if (((cmd->first_burst_len + payload_length) != cmd->se_cmd.data_length) && - ((cmd->first_burst_len + payload_length) != - conn->sess->sess_ops->FirstBurstLength)) { - pr_err("Unsolicited non-immediate data received %u" - " does not equal FirstBurstLength: %u, and does" - " not equal ExpXferLen %u.\n", - (cmd->first_burst_len + payload_length), - conn->sess->sess_ops->FirstBurstLength, cmd->se_cmd.data_length); - transport_send_check_condition_and_sense(se_cmd, - TCM_INCORRECT_AMOUNT_OF_DATA, 0); - return -1; - } - return 0; -} - struct iscsit_cmd *iscsit_find_cmd_from_itt( struct iscsit_conn *conn, itt_t init_task_tag) @@ -895,7 +851,8 @@ static int iscsit_add_nopin(struct iscsit_conn *conn, int want_response) void iscsit_handle_nopin_response_timeout(struct timer_list *t) { - struct iscsit_conn *conn = from_timer(conn, t, nopin_response_timer); + struct iscsit_conn *conn = timer_container_of(conn, t, + nopin_response_timer); struct iscsit_session *sess = conn->sess; iscsit_inc_conn_usage_count(conn); @@ -966,7 +923,7 @@ void iscsit_stop_nopin_response_timer(struct iscsit_conn *conn) conn->nopin_response_timer_flags |= ISCSI_TF_STOP; spin_unlock_bh(&conn->nopin_timer_lock); - del_timer_sync(&conn->nopin_response_timer); + timer_delete_sync(&conn->nopin_response_timer); spin_lock_bh(&conn->nopin_timer_lock); conn->nopin_response_timer_flags &= ~ISCSI_TF_RUNNING; @@ -975,7 +932,7 @@ void iscsit_stop_nopin_response_timer(struct iscsit_conn *conn) void iscsit_handle_nopin_timeout(struct timer_list *t) { - struct iscsit_conn *conn = from_timer(conn, t, nopin_timer); + struct iscsit_conn *conn = timer_container_of(conn, t, nopin_timer); iscsit_inc_conn_usage_count(conn); @@ -1033,7 +990,7 @@ void iscsit_stop_nopin_timer(struct iscsit_conn *conn) conn->nopin_timer_flags |= ISCSI_TF_STOP; spin_unlock_bh(&conn->nopin_timer_lock); - del_timer_sync(&conn->nopin_timer); + timer_delete_sync(&conn->nopin_timer); spin_lock_bh(&conn->nopin_timer_lock); conn->nopin_timer_flags &= ~ISCSI_TF_RUNNING; @@ -1042,7 +999,7 @@ void iscsit_stop_nopin_timer(struct iscsit_conn *conn) void iscsit_login_timeout(struct timer_list *t) { - struct iscsit_conn *conn = from_timer(conn, t, login_timer); + struct iscsit_conn *conn = timer_container_of(conn, t, login_timer); struct iscsi_login *login = conn->login; pr_debug("Entering iscsi_target_login_timeout >>>>>>>>>>>>>>>>>>>\n"); @@ -1252,20 +1209,6 @@ int iscsit_tx_login_rsp(struct iscsit_conn *conn, u8 status_class, u8 status_det return conn->conn_transport->iscsit_put_login_tx(conn, login, 0); } -void iscsit_print_session_params(struct iscsit_session *sess) -{ - struct iscsit_conn *conn; - - pr_debug("-----------------------------[Session Params for" - " SID: %u]-----------------------------\n", sess->sid); - spin_lock_bh(&sess->conn_lock); - list_for_each_entry(conn, &sess->sess_conn_list, conn_list) - iscsi_dump_conn_ops(conn->conn_ops); - spin_unlock_bh(&sess->conn_lock); - - iscsi_dump_sess_ops(sess->sess_ops); -} - int rx_data( struct iscsit_conn *conn, struct kvec *iov, diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h index 24b8e577575a..7ae48a8a5cbf 100644 --- a/drivers/target/iscsi/iscsi_target_util.h +++ b/drivers/target/iscsi/iscsi_target_util.h @@ -17,14 +17,12 @@ extern struct iscsi_r2t *iscsit_get_r2t_for_eos(struct iscsit_cmd *, u32, u32); extern struct iscsi_r2t *iscsit_get_r2t_from_list(struct iscsit_cmd *); extern void iscsit_free_r2t(struct iscsi_r2t *, struct iscsit_cmd *); extern void iscsit_free_r2ts_from_list(struct iscsit_cmd *); -extern struct iscsit_cmd *iscsit_alloc_cmd(struct iscsit_conn *, gfp_t); extern struct iscsit_cmd *iscsit_allocate_cmd(struct iscsit_conn *, int); extern struct iscsi_seq *iscsit_get_seq_holder_for_datain(struct iscsit_cmd *, u32); extern struct iscsi_seq *iscsit_get_seq_holder_for_r2t(struct iscsit_cmd *); extern struct iscsi_r2t *iscsit_get_holder_for_r2tsn(struct iscsit_cmd *, u32); extern int iscsit_sequence_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd, unsigned char * ,__be32 cmdsn); -extern int iscsit_check_unsolicited_dataout(struct iscsit_cmd *, unsigned char *); extern struct iscsit_cmd *iscsit_find_cmd_from_itt_or_dump(struct iscsit_conn *, itt_t, u32); extern struct iscsit_cmd *iscsit_find_cmd_from_ttt(struct iscsit_conn *, u32); @@ -34,7 +32,6 @@ extern void iscsit_add_cmd_to_immediate_queue(struct iscsit_cmd *, struct iscsit extern struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsit_conn *); extern int iscsit_add_cmd_to_response_queue(struct iscsit_cmd *, struct iscsit_conn *, u8); extern struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsit_conn *); -extern void iscsit_remove_cmd_from_tx_queues(struct iscsit_cmd *, struct iscsit_conn *); extern bool iscsit_conn_all_queues_empty(struct iscsit_conn *); extern void iscsit_free_queue_reqs_for_conn(struct iscsit_conn *); extern void iscsit_release_cmd(struct iscsit_cmd *); @@ -63,10 +60,6 @@ extern int iscsit_set_login_timer_kworker(struct iscsit_conn *, struct task_stru extern int iscsit_send_tx_data(struct iscsit_cmd *, struct iscsit_conn *, int); extern int iscsit_fe_sendpage_sg(struct iscsit_cmd *, struct iscsit_conn *); extern int iscsit_tx_login_rsp(struct iscsit_conn *, u8, u8); -extern void iscsit_print_session_params(struct iscsit_session *); -extern int iscsit_print_dev_to_proc(char *, char **, off_t, int); -extern int iscsit_print_sessions_to_proc(char *, char **, off_t, int); -extern int iscsit_print_tpg_to_proc(char *, char **, off_t, int); extern int rx_data(struct iscsit_conn *, struct kvec *, int, int); extern int tx_data(struct iscsit_conn *, struct kvec *, int, int); extern void iscsit_collect_login_stats(struct iscsit_conn *, u8, u8); diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index 4ec99a55ac30..01a8e349dc4d 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c @@ -83,7 +83,7 @@ static int tcm_loop_show_info(struct seq_file *m, struct Scsi_Host *host) static int tcm_loop_driver_probe(struct device *); static void tcm_loop_driver_remove(struct device *); -static struct bus_type tcm_loop_lld_bus = { +static const struct bus_type tcm_loop_lld_bus = { .name = "tcm_loop_bus", .probe = tcm_loop_driver_probe, .remove = tcm_loop_driver_remove, @@ -154,7 +154,7 @@ static void tcm_loop_target_queue_cmd(struct tcm_loop_cmd *tl_cmd) GFP_ATOMIC)) return; - target_queue_submission(se_cmd); + target_submit(se_cmd); return; out_done: @@ -176,7 +176,7 @@ static int tcm_loop_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc) memset(tl_cmd, 0, sizeof(*tl_cmd)); tl_cmd->sc = sc; - tl_cmd->sc_cmd_tag = scsi_cmd_to_rq(sc)->tag; + tl_cmd->sc_cmd_tag = blk_mq_unique_tag(scsi_cmd_to_rq(sc)); tcm_loop_target_queue_cmd(tl_cmd); return 0; @@ -242,7 +242,8 @@ static int tcm_loop_abort_task(struct scsi_cmnd *sc) tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host); tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id]; ret = tcm_loop_issue_tmr(tl_tpg, sc->device->lun, - scsi_cmd_to_rq(sc)->tag, TMR_ABORT_TASK); + blk_mq_unique_tag(scsi_cmd_to_rq(sc)), + TMR_ABORT_TASK); return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED; } @@ -893,6 +894,9 @@ static ssize_t tcm_loop_tpg_address_show(struct config_item *item, struct tcm_loop_tpg, tl_se_tpg); struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba; + if (!tl_hba->sh) + return -ENODEV; + return snprintf(page, PAGE_SIZE, "%d:0:%d\n", tl_hba->sh->host_no, tl_tpg->tl_tpgt); } @@ -1102,6 +1106,8 @@ static const struct target_core_fabric_ops loop_ops = { .tfc_wwn_attrs = tcm_loop_wwn_attrs, .tfc_tpg_base_attrs = tcm_loop_tpg_attrs, .tfc_tpg_attrib_attrs = tcm_loop_tpg_attrib_attrs, + .default_submit_type = TARGET_QUEUE_SUBMIT, + .direct_submit_supp = 0, }; static int __init tcm_loop_fabric_init(void) diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c index 2a761bc09193..b8457477cee9 100644 --- a/drivers/target/sbp/sbp_target.c +++ b/drivers/target/sbp/sbp_target.c @@ -23,7 +23,7 @@ #include <target/target_core_base.h> #include <target/target_core_backend.h> #include <target/target_core_fabric.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include "sbp_target.h" @@ -730,7 +730,7 @@ static int tgt_agent_rw_orb_pointer(struct fw_card *card, int tcode, void *data, pr_debug("tgt_agent ORB_POINTER write: 0x%llx\n", agent->orb_pointer); - queue_work(system_unbound_wq, &agent->work); + queue_work(system_dfl_wq, &agent->work); return RCODE_COMPLETE; @@ -764,7 +764,7 @@ static int tgt_agent_rw_doorbell(struct fw_card *card, int tcode, void *data, pr_debug("tgt_agent DOORBELL\n"); - queue_work(system_unbound_wq, &agent->work); + queue_work(system_dfl_wq, &agent->work); return RCODE_COMPLETE; @@ -990,7 +990,7 @@ static void tgt_agent_fetch_work(struct work_struct *work) if (tgt_agent_check_active(agent) && !doorbell) { INIT_WORK(&req->work, tgt_agent_process_work); - queue_work(system_unbound_wq, &req->work); + queue_work(system_dfl_wq, &req->work); } else { /* don't process this request, just check next_ORB */ sbp_free_request(req); @@ -1618,7 +1618,7 @@ static void sbp_mgt_agent_rw(struct fw_card *card, agent->orb_offset = sbp2_pointer_to_addr(ptr); agent->request = req; - queue_work(system_unbound_wq, &agent->work); + queue_work(system_dfl_wq, &agent->work); rcode = RCODE_COMPLETE; } else if (tcode == TCODE_READ_BLOCK_REQUEST) { addr_to_sbp2_pointer(agent->orb_offset, ptr); @@ -2278,6 +2278,9 @@ static const struct target_core_fabric_ops sbp_ops = { .tfc_wwn_attrs = sbp_wwn_attrs, .tfc_tpg_base_attrs = sbp_tpg_base_attrs, .tfc_tpg_attrib_attrs = sbp_tpg_attrib_attrs, + + .default_submit_type = TARGET_DIRECT_SUBMIT, + .direct_submit_supp = 1, }; static int __init sbp_init(void) diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 3372856319f7..10250aca5a81 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -19,7 +19,7 @@ #include <linux/file.h> #include <linux/fs.h> #include <scsi/scsi_proto.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <target/target_core_base.h> #include <target/target_core_backend.h> @@ -850,7 +850,6 @@ int core_alua_check_nonop_delay( msleep_interruptible(cmd->alua_nonop_delay); return 0; } -EXPORT_SYMBOL(core_alua_check_nonop_delay); static int core_alua_write_tpg_metadata( const char *path, diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 936e5ff1b209..f7868b41c5e6 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -123,7 +123,7 @@ static ssize_t target_core_item_dbroot_store(struct config_item *item, goto unlock; } - read_bytes = snprintf(db_root_stage, DB_ROOT_LEN, "%s", page); + read_bytes = scnprintf(db_root_stage, DB_ROOT_LEN, "%s", page); if (!read_bytes) goto unlock; @@ -143,7 +143,7 @@ static ssize_t target_core_item_dbroot_store(struct config_item *item, } filp_close(fp, NULL); - strncpy(db_root, db_root_stage, read_bytes); + strscpy(db_root, db_root_stage); pr_debug("Target_Core_ConfigFS: db_root set to %s\n", db_root); r = read_bytes; @@ -577,6 +577,12 @@ DEF_CONFIGFS_ATTRIB_SHOW(unmap_granularity_alignment); DEF_CONFIGFS_ATTRIB_SHOW(unmap_zeroes_data); DEF_CONFIGFS_ATTRIB_SHOW(max_write_same_len); DEF_CONFIGFS_ATTRIB_SHOW(emulate_rsoc); +DEF_CONFIGFS_ATTRIB_SHOW(submit_type); +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_len); +DEF_CONFIGFS_ATTRIB_SHOW(atomic_alignment); +DEF_CONFIGFS_ATTRIB_SHOW(atomic_granularity); +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_with_boundary); +DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_boundary); #define DEF_CONFIGFS_ATTRIB_STORE_U32(_name) \ static ssize_t _name##_store(struct config_item *item, const char *page,\ @@ -672,12 +678,10 @@ static ssize_t emulate_model_alias_store(struct config_item *item, return ret; BUILD_BUG_ON(sizeof(dev->t10_wwn.model) != INQUIRY_MODEL_LEN + 1); - if (flag) { + if (flag) dev_set_t10_wwn_model_alias(dev); - } else { - strscpy(dev->t10_wwn.model, dev->transport->inquiry_prod, - sizeof(dev->t10_wwn.model)); - } + else + strscpy(dev->t10_wwn.model, dev->transport->inquiry_prod); da->emulate_model_alias = flag; return count; } @@ -758,6 +762,29 @@ static ssize_t emulate_tas_store(struct config_item *item, return count; } +static int target_try_configure_unmap(struct se_device *dev, + const char *config_opt) +{ + if (!dev->transport->configure_unmap) { + pr_err("Generic Block Discard not supported\n"); + return -ENOSYS; + } + + if (!target_dev_configured(dev)) { + pr_err("Generic Block Discard setup for %s requires device to be configured\n", + config_opt); + return -ENODEV; + } + + if (!dev->transport->configure_unmap(dev)) { + pr_err("Generic Block Discard setup for %s failed\n", + config_opt); + return -ENOSYS; + } + + return 0; +} + static ssize_t emulate_tpu_store(struct config_item *item, const char *page, size_t count) { @@ -775,11 +802,9 @@ static ssize_t emulate_tpu_store(struct config_item *item, * Discard supported is detected iblock_create_virtdevice(). */ if (flag && !da->max_unmap_block_desc_count) { - if (!dev->transport->configure_unmap || - !dev->transport->configure_unmap(dev)) { - pr_err("Generic Block Discard not supported\n"); - return -ENOSYS; - } + ret = target_try_configure_unmap(dev, "emulate_tpu"); + if (ret) + return ret; } da->emulate_tpu = flag; @@ -805,11 +830,9 @@ static ssize_t emulate_tpws_store(struct config_item *item, * Discard supported is detected iblock_create_virtdevice(). */ if (flag && !da->max_unmap_block_desc_count) { - if (!dev->transport->configure_unmap || - !dev->transport->configure_unmap(dev)) { - pr_err("Generic Block Discard not supported\n"); - return -ENOSYS; - } + ret = target_try_configure_unmap(dev, "emulate_tpws"); + if (ret) + return ret; } da->emulate_tpws = flag; @@ -1021,12 +1044,9 @@ static ssize_t unmap_zeroes_data_store(struct config_item *item, * Discard supported is detected iblock_configure_device(). */ if (flag && !da->max_unmap_block_desc_count) { - if (!dev->transport->configure_unmap || - !dev->transport->configure_unmap(dev)) { - pr_err("dev[%p]: Thin Provisioning LBPRZ will not be set because max_unmap_block_desc_count is zero\n", - da->da_dev); - return -ENOSYS; - } + ret = target_try_configure_unmap(dev, "unmap_zeroes_data"); + if (ret) + return ret; } da->unmap_zeroes_data = flag; pr_debug("dev[%p]: SE Device Thin Provisioning LBPRZ bit: %d\n", @@ -1231,6 +1251,24 @@ static ssize_t emulate_rsoc_store(struct config_item *item, return count; } +static ssize_t submit_type_store(struct config_item *item, const char *page, + size_t count) +{ + struct se_dev_attrib *da = to_attrib(item); + int ret; + u8 val; + + ret = kstrtou8(page, 0, &val); + if (ret < 0) + return ret; + + if (val > TARGET_QUEUE_SUBMIT) + return -EINVAL; + + da->submit_type = val; + return count; +} + CONFIGFS_ATTR(, emulate_model_alias); CONFIGFS_ATTR(, emulate_dpo); CONFIGFS_ATTR(, emulate_fua_write); @@ -1266,6 +1304,12 @@ CONFIGFS_ATTR(, unmap_zeroes_data); CONFIGFS_ATTR(, max_write_same_len); CONFIGFS_ATTR(, alua_support); CONFIGFS_ATTR(, pgr_support); +CONFIGFS_ATTR(, submit_type); +CONFIGFS_ATTR_RO(, atomic_max_len); +CONFIGFS_ATTR_RO(, atomic_alignment); +CONFIGFS_ATTR_RO(, atomic_granularity); +CONFIGFS_ATTR_RO(, atomic_max_with_boundary); +CONFIGFS_ATTR_RO(, atomic_max_boundary); /* * dev_attrib attributes for devices using the target core SBC/SPC @@ -1308,6 +1352,12 @@ struct configfs_attribute *sbc_attrib_attrs[] = { &attr_alua_support, &attr_pgr_support, &attr_emulate_rsoc, + &attr_submit_type, + &attr_atomic_alignment, + &attr_atomic_max_len, + &attr_atomic_granularity, + &attr_atomic_max_with_boundary, + &attr_atomic_max_boundary, NULL, }; EXPORT_SYMBOL(sbc_attrib_attrs); @@ -1325,6 +1375,7 @@ struct configfs_attribute *passthrough_attrib_attrs[] = { &attr_emulate_pr, &attr_alua_support, &attr_pgr_support, + &attr_submit_type, NULL, }; EXPORT_SYMBOL(passthrough_attrib_attrs); @@ -1392,16 +1443,16 @@ static ssize_t target_wwn_vendor_id_store(struct config_item *item, /* +2 to allow for a trailing (stripped) '\n' and null-terminator */ unsigned char buf[INQUIRY_VENDOR_LEN + 2]; char *stripped = NULL; - size_t len; + ssize_t len; ssize_t ret; - len = strlcpy(buf, page, sizeof(buf)); - if (len < sizeof(buf)) { + len = strscpy(buf, page); + if (len > 0) { /* Strip any newline added from userspace. */ stripped = strstrip(buf); len = strlen(stripped); } - if (len > INQUIRY_VENDOR_LEN) { + if (len < 0 || len > INQUIRY_VENDOR_LEN) { pr_err("Emulated T10 Vendor Identification exceeds" " INQUIRY_VENDOR_LEN: " __stringify(INQUIRY_VENDOR_LEN) "\n"); @@ -1426,7 +1477,7 @@ static ssize_t target_wwn_vendor_id_store(struct config_item *item, } BUILD_BUG_ON(sizeof(dev->t10_wwn.vendor) != INQUIRY_VENDOR_LEN + 1); - strscpy(dev->t10_wwn.vendor, stripped, sizeof(dev->t10_wwn.vendor)); + strscpy(dev->t10_wwn.vendor, stripped); pr_debug("Target_Core_ConfigFS: Set emulated T10 Vendor Identification:" " %s\n", dev->t10_wwn.vendor); @@ -1448,16 +1499,16 @@ static ssize_t target_wwn_product_id_store(struct config_item *item, /* +2 to allow for a trailing (stripped) '\n' and null-terminator */ unsigned char buf[INQUIRY_MODEL_LEN + 2]; char *stripped = NULL; - size_t len; + ssize_t len; ssize_t ret; - len = strlcpy(buf, page, sizeof(buf)); - if (len < sizeof(buf)) { + len = strscpy(buf, page); + if (len > 0) { /* Strip any newline added from userspace. */ stripped = strstrip(buf); len = strlen(stripped); } - if (len > INQUIRY_MODEL_LEN) { + if (len < 0 || len > INQUIRY_MODEL_LEN) { pr_err("Emulated T10 Vendor exceeds INQUIRY_MODEL_LEN: " __stringify(INQUIRY_MODEL_LEN) "\n"); @@ -1482,7 +1533,7 @@ static ssize_t target_wwn_product_id_store(struct config_item *item, } BUILD_BUG_ON(sizeof(dev->t10_wwn.model) != INQUIRY_MODEL_LEN + 1); - strscpy(dev->t10_wwn.model, stripped, sizeof(dev->t10_wwn.model)); + strscpy(dev->t10_wwn.model, stripped); pr_debug("Target_Core_ConfigFS: Set emulated T10 Model Identification: %s\n", dev->t10_wwn.model); @@ -1504,16 +1555,16 @@ static ssize_t target_wwn_revision_store(struct config_item *item, /* +2 to allow for a trailing (stripped) '\n' and null-terminator */ unsigned char buf[INQUIRY_REVISION_LEN + 2]; char *stripped = NULL; - size_t len; + ssize_t len; ssize_t ret; - len = strlcpy(buf, page, sizeof(buf)); - if (len < sizeof(buf)) { + len = strscpy(buf, page); + if (len > 0) { /* Strip any newline added from userspace. */ stripped = strstrip(buf); len = strlen(stripped); } - if (len > INQUIRY_REVISION_LEN) { + if (len < 0 || len > INQUIRY_REVISION_LEN) { pr_err("Emulated T10 Revision exceeds INQUIRY_REVISION_LEN: " __stringify(INQUIRY_REVISION_LEN) "\n"); @@ -1538,7 +1589,7 @@ static ssize_t target_wwn_revision_store(struct config_item *item, } BUILD_BUG_ON(sizeof(dev->t10_wwn.revision) != INQUIRY_REVISION_LEN + 1); - strscpy(dev->t10_wwn.revision, stripped, sizeof(dev->t10_wwn.revision)); + strscpy(dev->t10_wwn.revision, stripped); pr_debug("Target_Core_ConfigFS: Set emulated T10 Revision: %s\n", dev->t10_wwn.revision); @@ -2722,33 +2773,24 @@ static ssize_t target_lu_gp_lu_gp_id_store(struct config_item *item, static ssize_t target_lu_gp_members_show(struct config_item *item, char *page) { struct t10_alua_lu_gp *lu_gp = to_lu_gp(item); - struct se_device *dev; - struct se_hba *hba; struct t10_alua_lu_gp_member *lu_gp_mem; - ssize_t len = 0, cur_len; - unsigned char buf[LU_GROUP_NAME_BUF] = { }; + const char *const end = page + PAGE_SIZE; + char *cur = page; spin_lock(&lu_gp->lu_gp_lock); list_for_each_entry(lu_gp_mem, &lu_gp->lu_gp_mem_list, lu_gp_mem_list) { - dev = lu_gp_mem->lu_gp_mem_dev; - hba = dev->se_hba; + struct se_device *dev = lu_gp_mem->lu_gp_mem_dev; + struct se_hba *hba = dev->se_hba; - cur_len = snprintf(buf, LU_GROUP_NAME_BUF, "%s/%s\n", + cur += scnprintf(cur, end - cur, "%s/%s\n", config_item_name(&hba->hba_group.cg_item), config_item_name(&dev->dev_group.cg_item)); - cur_len++; /* Extra byte for NULL terminator */ - - if ((cur_len + len) > PAGE_SIZE) { - pr_warn("Ran out of lu_gp_show_attr" - "_members buffer\n"); + if (WARN_ON_ONCE(cur >= end)) break; - } - memcpy(page+len, buf, cur_len); - len += cur_len; } spin_unlock(&lu_gp->lu_gp_lock); - return len; + return cur - page; } CONFIGFS_ATTR(target_lu_gp_, lu_gp_id); @@ -3626,7 +3668,7 @@ static void target_init_dbroot(void) } filp_close(fp, NULL); - strncpy(db_root, db_root_stage, DB_ROOT_LEN); + strscpy(db_root, db_root_stage); pr_debug("Target_Core_ConfigFS: db_root set to %s\n", db_root); } @@ -3710,11 +3752,13 @@ static int __init target_core_init_configfs(void) if (ret < 0) goto out; - target_init_dbroot(); + scoped_with_kernel_creds() + target_init_dbroot(); return 0; out: + target_xcopy_release_pt(); configfs_unregister_subsystem(subsys); core_dev_release_virtual_lun0(); rd_module_exit(); diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index b7ac60f4a219..8ccb8541db1c 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -21,7 +21,7 @@ #include <linux/in.h> #include <linux/export.h> #include <linux/t10-pi.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <net/sock.h> #include <net/tcp.h> #include <scsi/scsi_common.h> @@ -37,7 +37,6 @@ #include "target_core_ua.h" static DEFINE_MUTEX(device_mutex); -static LIST_HEAD(device_list); static DEFINE_IDR(devices_idr); static struct se_hba *lun0_hba; @@ -56,14 +55,14 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd) rcu_read_lock(); deve = target_nacl_find_deve(nacl, se_cmd->orig_fe_lun); if (deve) { - atomic_long_inc(&deve->total_cmds); + this_cpu_inc(deve->stats->total_cmds); if (se_cmd->data_direction == DMA_TO_DEVICE) - atomic_long_add(se_cmd->data_length, - &deve->write_bytes); + this_cpu_add(deve->stats->write_bytes, + se_cmd->data_length); else if (se_cmd->data_direction == DMA_FROM_DEVICE) - atomic_long_add(se_cmd->data_length, - &deve->read_bytes); + this_cpu_add(deve->stats->read_bytes, + se_cmd->data_length); if ((se_cmd->data_direction == DMA_TO_DEVICE) && deve->lun_access_ro) { @@ -127,14 +126,14 @@ out_unlock: * target_core_fabric_configfs.c:target_fabric_port_release */ se_cmd->se_dev = rcu_dereference_raw(se_lun->lun_se_dev); - atomic_long_inc(&se_cmd->se_dev->num_cmds); + this_cpu_inc(se_cmd->se_dev->stats->total_cmds); if (se_cmd->data_direction == DMA_TO_DEVICE) - atomic_long_add(se_cmd->data_length, - &se_cmd->se_dev->write_bytes); + this_cpu_add(se_cmd->se_dev->stats->write_bytes, + se_cmd->data_length); else if (se_cmd->data_direction == DMA_FROM_DEVICE) - atomic_long_add(se_cmd->data_length, - &se_cmd->se_dev->read_bytes); + this_cpu_add(se_cmd->se_dev->stats->read_bytes, + se_cmd->data_length); return ret; } @@ -147,7 +146,6 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd) struct se_session *se_sess = se_cmd->se_sess; struct se_node_acl *nacl = se_sess->se_node_acl; struct se_tmr_req *se_tmr = se_cmd->se_tmr_req; - unsigned long flags; rcu_read_lock(); deve = target_nacl_find_deve(nacl, se_cmd->orig_fe_lun); @@ -178,10 +176,6 @@ out_unlock: se_cmd->se_dev = rcu_dereference_raw(se_lun->lun_se_dev); se_tmr->tmr_dev = rcu_dereference_raw(se_lun->lun_se_dev); - spin_lock_irqsave(&se_tmr->tmr_dev->se_tmr_lock, flags); - list_add_tail(&se_tmr->tmr_list, &se_tmr->tmr_dev->dev_tmr_list); - spin_unlock_irqrestore(&se_tmr->tmr_dev->se_tmr_lock, flags); - return 0; } EXPORT_SYMBOL(transport_lookup_tmr_lun); @@ -328,6 +322,7 @@ int core_enable_device_list_for_node( struct se_portal_group *tpg) { struct se_dev_entry *orig, *new; + int ret = 0; new = kzalloc(sizeof(*new), GFP_KERNEL); if (!new) { @@ -335,6 +330,12 @@ int core_enable_device_list_for_node( return -ENOMEM; } + new->stats = alloc_percpu(struct se_dev_entry_io_stats); + if (!new->stats) { + ret = -ENOMEM; + goto free_deve; + } + spin_lock_init(&new->ua_lock); INIT_LIST_HEAD(&new->ua_list); INIT_LIST_HEAD(&new->lun_link); @@ -357,8 +358,8 @@ int core_enable_device_list_for_node( " for dynamic -> explicit NodeACL conversion:" " %s\n", nacl->initiatorname); mutex_unlock(&nacl->lun_entry_mutex); - kfree(new); - return -EINVAL; + ret = -EINVAL; + goto free_stats; } if (orig->se_lun_acl != NULL) { pr_warn_ratelimited("Detected existing explicit" @@ -366,8 +367,8 @@ int core_enable_device_list_for_node( " mapped_lun: %llu, failing\n", nacl->initiatorname, mapped_lun); mutex_unlock(&nacl->lun_entry_mutex); - kfree(new); - return -EINVAL; + ret = -EINVAL; + goto free_stats; } new->se_lun = lun; @@ -400,6 +401,20 @@ int core_enable_device_list_for_node( target_luns_data_has_changed(nacl, new, true); return 0; + +free_stats: + free_percpu(new->stats); +free_deve: + kfree(new); + return ret; +} + +static void target_free_dev_entry(struct rcu_head *head) +{ + struct se_dev_entry *deve = container_of(head, struct se_dev_entry, + rcu_head); + free_percpu(deve->stats); + kfree(deve); } void core_disable_device_list_for_node( @@ -449,7 +464,7 @@ void core_disable_device_list_for_node( kref_put(&orig->pr_kref, target_pr_kref_release); wait_for_completion(&orig->pr_comp); - kfree_rcu(orig, rcu_head); + call_rcu(&orig->rcu_head, target_free_dev_entry); core_scsi3_free_pr_reg_from_nacl(dev, nacl); target_luns_data_has_changed(nacl, NULL, false); @@ -685,6 +700,18 @@ static void scsi_dump_inquiry(struct se_device *dev) pr_debug(" Type: %s ", scsi_device_type(device_type)); } +static void target_non_ordered_release(struct percpu_ref *ref) +{ + struct se_device *dev = container_of(ref, struct se_device, + non_ordered); + unsigned long flags; + + spin_lock_irqsave(&dev->delayed_cmd_lock, flags); + if (!list_empty(&dev->delayed_cmd_list)) + schedule_work(&dev->delayed_cmd_work); + spin_unlock_irqrestore(&dev->delayed_cmd_lock, flags); +} + struct se_device *target_alloc_device(struct se_hba *hba, const char *name) { struct se_device *dev; @@ -695,11 +722,13 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) if (!dev) return NULL; + dev->stats = alloc_percpu(struct se_dev_io_stats); + if (!dev->stats) + goto free_device; + dev->queues = kcalloc(nr_cpu_ids, sizeof(*dev->queues), GFP_KERNEL); - if (!dev->queues) { - dev->transport->free_device(dev); - return NULL; - } + if (!dev->queues) + goto free_stats; dev->queue_cnt = nr_cpu_ids; for (i = 0; i < dev->queue_cnt; i++) { @@ -713,6 +742,10 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) INIT_WORK(&q->sq.work, target_queued_submit_work); } + if (percpu_ref_init(&dev->non_ordered, target_non_ordered_release, + PERCPU_REF_ALLOW_REINIT, GFP_KERNEL)) + goto free_queues; + dev->se_hba = hba; dev->transport = hba->backend->ops; dev->transport_flags = dev->transport->transport_flags_default; @@ -779,7 +812,9 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) dev->dev_attrib.unmap_zeroes_data = DA_UNMAP_ZEROES_DATA_DEFAULT; dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN; + dev->dev_attrib.submit_type = TARGET_FABRIC_DEFAULT_SUBMIT; + /* Skip allocating lun_stats since we can't export them. */ xcopy_lun = &dev->xcopy_lun; rcu_assign_pointer(xcopy_lun->lun_se_dev, dev); init_completion(&xcopy_lun->lun_shutdown_comp); @@ -796,14 +831,39 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) sizeof(dev->t10_wwn.revision)); return dev; + +free_queues: + kfree(dev->queues); +free_stats: + free_percpu(dev->stats); +free_device: + hba->backend->ops->free_device(dev); + return NULL; } +void target_configure_write_atomic_from_bdev(struct se_dev_attrib *attrib, + struct block_device *bdev) +{ + struct request_queue *q = bdev_get_queue(bdev); + int block_size = bdev_logical_block_size(bdev); + + if (!bdev_can_atomic_write(bdev)) + return; + + attrib->atomic_max_len = queue_atomic_write_max_bytes(q) / block_size; + attrib->atomic_granularity = attrib->atomic_alignment = + queue_atomic_write_unit_min_bytes(q) / block_size; + attrib->atomic_max_with_boundary = 0; + attrib->atomic_max_boundary = 0; +} +EXPORT_SYMBOL_GPL(target_configure_write_atomic_from_bdev); + /* * Check if the underlying struct block_device supports discard and if yes * configure the UNMAP parameters. */ -bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib, - struct block_device *bdev) +bool target_configure_unmap_from_bdev(struct se_dev_attrib *attrib, + struct block_device *bdev) { int block_size = bdev_logical_block_size(bdev); @@ -821,7 +881,7 @@ bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib, bdev_discard_alignment(bdev) / block_size; return true; } -EXPORT_SYMBOL(target_configure_unmap_from_queue); +EXPORT_SYMBOL(target_configure_unmap_from_bdev); /* * Convert from blocksize advertised to the initiator to the 512 byte @@ -843,7 +903,6 @@ sector_t target_to_linux_sector(struct se_device *dev, sector_t lb) EXPORT_SYMBOL(target_to_linux_sector); struct devices_idr_iter { - struct config_item *prev_item; int (*fn)(struct se_device *dev, void *data); void *data; }; @@ -853,11 +912,9 @@ static int target_devices_idr_iter(int id, void *p, void *data) { struct devices_idr_iter *iter = data; struct se_device *dev = p; + struct config_item *item; int ret; - config_item_put(iter->prev_item); - iter->prev_item = NULL; - /* * We add the device early to the idr, so it can be used * by backend modules during configuration. We do not want @@ -867,12 +924,13 @@ static int target_devices_idr_iter(int id, void *p, void *data) if (!target_dev_configured(dev)) return 0; - iter->prev_item = config_item_get_unless_zero(&dev->dev_group.cg_item); - if (!iter->prev_item) + item = config_item_get_unless_zero(&dev->dev_group.cg_item); + if (!item) return 0; mutex_unlock(&device_mutex); ret = iter->fn(dev, iter->data); + config_item_put(item); mutex_lock(&device_mutex); return ret; @@ -895,7 +953,6 @@ int target_for_each_device(int (*fn)(struct se_device *dev, void *data), mutex_lock(&device_mutex); ret = idr_for_each(&devices_idr, target_devices_idr_iter, &iter); mutex_unlock(&device_mutex); - config_item_put(iter.prev_item); return ret; } @@ -988,6 +1045,9 @@ void target_free_device(struct se_device *dev) WARN_ON(!list_empty(&dev->dev_sep_list)); + percpu_ref_exit(&dev->non_ordered); + cancel_work_sync(&dev->delayed_cmd_work); + if (target_dev_configured(dev)) { dev->transport->destroy_device(dev); @@ -1009,6 +1069,7 @@ void target_free_device(struct se_device *dev) dev->transport->free_prot(dev); kfree(dev->queues); + free_percpu(dev->stats); dev->transport->free_device(dev); } @@ -1086,8 +1147,8 @@ passthrough_parse_cdb(struct se_cmd *cmd, if (!dev->dev_attrib.emulate_pr && ((cdb[0] == PERSISTENT_RESERVE_IN) || (cdb[0] == PERSISTENT_RESERVE_OUT) || - (cdb[0] == RELEASE || cdb[0] == RELEASE_10) || - (cdb[0] == RESERVE || cdb[0] == RESERVE_10))) { + (cdb[0] == RELEASE_6 || cdb[0] == RELEASE_10) || + (cdb[0] == RESERVE_6 || cdb[0] == RESERVE_10))) { return TCM_UNSUPPORTED_SCSI_OPCODE; } @@ -1109,7 +1170,7 @@ passthrough_parse_cdb(struct se_cmd *cmd, return target_cmd_size_check(cmd, size); } - if (cdb[0] == RELEASE || cdb[0] == RELEASE_10) { + if (cdb[0] == RELEASE_6 || cdb[0] == RELEASE_10) { cmd->execute_cmd = target_scsi2_reservation_release; if (cdb[0] == RELEASE_10) size = get_unaligned_be16(&cdb[7]); @@ -1117,7 +1178,7 @@ passthrough_parse_cdb(struct se_cmd *cmd, size = cmd->data_length; return target_cmd_size_check(cmd, size); } - if (cdb[0] == RESERVE || cdb[0] == RESERVE_10) { + if (cdb[0] == RESERVE_6 || cdb[0] == RESERVE_10) { cmd->execute_cmd = target_scsi2_reservation_reserve; if (cdb[0] == RESERVE_10) size = get_unaligned_be16(&cdb[7]); diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index b7c637644cd4..13159928e365 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -697,7 +697,7 @@ static void target_fabric_port_release(struct config_item *item) struct se_lun *lun = container_of(to_config_group(item), struct se_lun, lun_group); - kfree_rcu(lun, rcu_head); + call_rcu(&lun->rcu_head, target_tpg_free_lun); } static struct configfs_item_operations target_fabric_port_item_ops = { @@ -1065,8 +1065,32 @@ target_fabric_wwn_cmd_completion_affinity_store(struct config_item *item, } CONFIGFS_ATTR(target_fabric_wwn_, cmd_completion_affinity); +static ssize_t +target_fabric_wwn_default_submit_type_show(struct config_item *item, + char *page) +{ + struct se_wwn *wwn = container_of(to_config_group(item), struct se_wwn, + param_group); + return sysfs_emit(page, "%u\n", + wwn->wwn_tf->tf_ops->default_submit_type); +} +CONFIGFS_ATTR_RO(target_fabric_wwn_, default_submit_type); + +static ssize_t +target_fabric_wwn_direct_submit_supported_show(struct config_item *item, + char *page) +{ + struct se_wwn *wwn = container_of(to_config_group(item), struct se_wwn, + param_group); + return sysfs_emit(page, "%u\n", + wwn->wwn_tf->tf_ops->direct_submit_supp); +} +CONFIGFS_ATTR_RO(target_fabric_wwn_, direct_submit_supported); + static struct configfs_attribute *target_fabric_wwn_param_attrs[] = { &target_fabric_wwn_attr_cmd_completion_affinity, + &target_fabric_wwn_attr_default_submit_type, + &target_fabric_wwn_attr_direct_submit_supported, NULL, }; diff --git a/drivers/target/target_core_fabric_lib.c b/drivers/target/target_core_fabric_lib.c index 6600ae44f29d..ec7bc6e30228 100644 --- a/drivers/target/target_core_fabric_lib.c +++ b/drivers/target/target_core_fabric_lib.c @@ -21,7 +21,7 @@ #include <linux/ctype.h> #include <linux/spinlock.h> #include <linux/export.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <scsi/scsi_proto.h> @@ -257,11 +257,41 @@ static int iscsi_get_pr_transport_id_len( return len; } -static char *iscsi_parse_pr_out_transport_id( +static void sas_parse_pr_out_transport_id(char *buf, char *i_str) +{ + char hex[17] = {}; + + bin2hex(hex, buf + 4, 8); + snprintf(i_str, TRANSPORT_IQN_LEN, "naa.%s", hex); +} + +static void srp_parse_pr_out_transport_id(char *buf, char *i_str) +{ + char hex[33] = {}; + + bin2hex(hex, buf + 8, 16); + snprintf(i_str, TRANSPORT_IQN_LEN, "0x%s", hex); +} + +static void fcp_parse_pr_out_transport_id(char *buf, char *i_str) +{ + snprintf(i_str, TRANSPORT_IQN_LEN, "%8phC", buf + 8); +} + +static void sbp_parse_pr_out_transport_id(char *buf, char *i_str) +{ + char hex[17] = {}; + + bin2hex(hex, buf + 8, 8); + snprintf(i_str, TRANSPORT_IQN_LEN, "%s", hex); +} + +static bool iscsi_parse_pr_out_transport_id( struct se_portal_group *se_tpg, char *buf, u32 *out_tid_len, - char **port_nexus_ptr) + char **port_nexus_ptr, + char *i_str) { char *p; int i; @@ -282,7 +312,7 @@ static char *iscsi_parse_pr_out_transport_id( if ((format_code != 0x00) && (format_code != 0x40)) { pr_err("Illegal format code: 0x%02x for iSCSI" " Initiator Transport ID\n", format_code); - return NULL; + return false; } /* * If the caller wants the TransportID Length, we set that value for the @@ -306,7 +336,7 @@ static char *iscsi_parse_pr_out_transport_id( pr_err("Unable to locate \",i,0x\" separator" " for Initiator port identifier: %s\n", &buf[4]); - return NULL; + return false; } *p = '\0'; /* Terminate iSCSI Name */ p += 5; /* Skip over ",i,0x" separator */ @@ -339,7 +369,8 @@ static char *iscsi_parse_pr_out_transport_id( } else *port_nexus_ptr = NULL; - return &buf[4]; + strscpy(i_str, &buf[4], TRANSPORT_IQN_LEN); + return true; } int target_get_pr_transport_id_len(struct se_node_acl *nacl, @@ -387,33 +418,35 @@ int target_get_pr_transport_id(struct se_node_acl *nacl, } } -const char *target_parse_pr_out_transport_id(struct se_portal_group *tpg, - char *buf, u32 *out_tid_len, char **port_nexus_ptr) +bool target_parse_pr_out_transport_id(struct se_portal_group *tpg, + char *buf, u32 *out_tid_len, char **port_nexus_ptr, char *i_str) { - u32 offset; - switch (tpg->proto_id) { case SCSI_PROTOCOL_SAS: /* * Assume the FORMAT CODE 00b from spc4r17, 7.5.4.7 TransportID * for initiator ports using SCSI over SAS Serial SCSI Protocol. */ - offset = 4; + sas_parse_pr_out_transport_id(buf, i_str); break; - case SCSI_PROTOCOL_SBP: case SCSI_PROTOCOL_SRP: + srp_parse_pr_out_transport_id(buf, i_str); + break; case SCSI_PROTOCOL_FCP: - offset = 8; + fcp_parse_pr_out_transport_id(buf, i_str); + break; + case SCSI_PROTOCOL_SBP: + sbp_parse_pr_out_transport_id(buf, i_str); break; case SCSI_PROTOCOL_ISCSI: return iscsi_parse_pr_out_transport_id(tpg, buf, out_tid_len, - port_nexus_ptr); + port_nexus_ptr, i_str); default: pr_err("Unknown proto_id: 0x%02x\n", tpg->proto_id); - return NULL; + return false; } *port_nexus_ptr = NULL; *out_tid_len = 24; - return buf + offset; + return true; } diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 4d447520bab8..b2610073e8cc 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -22,7 +22,7 @@ #include <linux/uio.h> #include <linux/scatterlist.h> #include <scsi/scsi_proto.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <target/target_core_base.h> #include <target/target_core_backend.h> @@ -92,8 +92,8 @@ static bool fd_configure_unmap(struct se_device *dev) struct inode *inode = file->f_mapping->host; if (S_ISBLK(inode->i_mode)) - return target_configure_unmap_from_queue(&dev->dev_attrib, - I_BDEV(inode)); + return target_configure_unmap_from_bdev(&dev->dev_attrib, + I_BDEV(inode)); /* Limit UNMAP emulation to 8k Number of LBAs (NoLB) */ dev->dev_attrib.max_unmap_lba_count = 0x2000; @@ -299,9 +299,9 @@ fd_execute_rw_aio(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, aio_cmd->iocb.ki_flags |= IOCB_DSYNC; if (is_write) - ret = call_write_iter(file, &aio_cmd->iocb, &iter); + ret = file->f_op->write_iter(&aio_cmd->iocb, &iter); else - ret = call_read_iter(file, &aio_cmd->iocb, &iter); + ret = file->f_op->read_iter(&aio_cmd->iocb, &iter); if (ret != -EIOCBQUEUED) cmd_rw_aio_complete(&aio_cmd->iocb, ret); diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index a7050f63b7cc..8ec7b534ad76 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -26,7 +26,7 @@ #include <linux/pr.h> #include <scsi/scsi_proto.h> #include <scsi/scsi_common.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <target/target_core_base.h> #include <target/target_core_backend.h> @@ -64,6 +64,7 @@ static struct se_device *iblock_alloc_device(struct se_hba *hba, const char *nam pr_err("Unable to allocate struct iblock_dev\n"); return NULL; } + ib_dev->ibd_exclusive = true; ib_dev->ibd_plug = kcalloc(nr_cpu_ids, sizeof(*ib_dev->ibd_plug), GFP_KERNEL); @@ -83,17 +84,19 @@ static bool iblock_configure_unmap(struct se_device *dev) { struct iblock_dev *ib_dev = IBLOCK_DEV(dev); - return target_configure_unmap_from_queue(&dev->dev_attrib, - ib_dev->ibd_bd); + return target_configure_unmap_from_bdev(&dev->dev_attrib, + ib_dev->ibd_bd); } static int iblock_configure_device(struct se_device *dev) { struct iblock_dev *ib_dev = IBLOCK_DEV(dev); struct request_queue *q; - struct block_device *bd = NULL; + struct file *bdev_file; + struct block_device *bd; struct blk_integrity *bi; blk_mode_t mode = BLK_OPEN_READ; + void *holder = ib_dev; unsigned int max_write_zeroes_sectors; int ret; @@ -108,20 +111,25 @@ static int iblock_configure_device(struct se_device *dev) goto out; } - pr_debug( "IBLOCK: Claiming struct block_device: %s\n", - ib_dev->ibd_udev_path); + pr_debug("IBLOCK: Claiming struct block_device: %s: %d\n", + ib_dev->ibd_udev_path, ib_dev->ibd_exclusive); if (!ib_dev->ibd_readonly) mode |= BLK_OPEN_WRITE; else dev->dev_flags |= DF_READ_ONLY; - bd = blkdev_get_by_path(ib_dev->ibd_udev_path, mode, ib_dev, NULL); - if (IS_ERR(bd)) { - ret = PTR_ERR(bd); + if (!ib_dev->ibd_exclusive) + holder = NULL; + + bdev_file = bdev_file_open_by_path(ib_dev->ibd_udev_path, mode, holder, + NULL); + if (IS_ERR(bdev_file)) { + ret = PTR_ERR(bdev_file); goto out_free_bioset; } - ib_dev->ibd_bd = bd; + ib_dev->ibd_bdev_file = bdev_file; + ib_dev->ibd_bd = bd = file_bdev(bdev_file); q = bdev_get_queue(bd); @@ -144,40 +152,33 @@ static int iblock_configure_device(struct se_device *dev) if (bdev_nonrot(bd)) dev->dev_attrib.is_nonrot = 1; + target_configure_write_atomic_from_bdev(&dev->dev_attrib, bd); + bi = bdev_get_integrity(bd); - if (bi) { - struct bio_set *bs = &ib_dev->ibd_bio_set; - - if (!strcmp(bi->profile->name, "T10-DIF-TYPE3-IP") || - !strcmp(bi->profile->name, "T10-DIF-TYPE1-IP")) { - pr_err("IBLOCK export of blk_integrity: %s not" - " supported\n", bi->profile->name); - ret = -ENOSYS; - goto out_blkdev_put; - } + if (!bi) + return 0; - if (!strcmp(bi->profile->name, "T10-DIF-TYPE3-CRC")) { - dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE3_PROT; - } else if (!strcmp(bi->profile->name, "T10-DIF-TYPE1-CRC")) { + switch (bi->csum_type) { + case BLK_INTEGRITY_CSUM_IP: + pr_err("IBLOCK export of blk_integrity: %s not supported\n", + blk_integrity_profile_name(bi)); + ret = -ENOSYS; + goto out_blkdev_put; + case BLK_INTEGRITY_CSUM_CRC: + if (bi->flags & BLK_INTEGRITY_REF_TAG) dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE1_PROT; - } - - if (dev->dev_attrib.pi_prot_type) { - if (bioset_integrity_create(bs, IBLOCK_BIO_POOL_SIZE) < 0) { - pr_err("Unable to allocate bioset for PI\n"); - ret = -ENOMEM; - goto out_blkdev_put; - } - pr_debug("IBLOCK setup BIP bs->bio_integrity_pool: %p\n", - &bs->bio_integrity_pool); - } - dev->dev_attrib.hw_pi_prot_type = dev->dev_attrib.pi_prot_type; + else + dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE3_PROT; + break; + default: + break; } + dev->dev_attrib.hw_pi_prot_type = dev->dev_attrib.pi_prot_type; return 0; out_blkdev_put: - blkdev_put(ib_dev->ibd_bd, ib_dev); + fput(ib_dev->ibd_bdev_file); out_free_bioset: bioset_exit(&ib_dev->ibd_bio_set); out: @@ -202,8 +203,8 @@ static void iblock_destroy_device(struct se_device *dev) { struct iblock_dev *ib_dev = IBLOCK_DEV(dev); - if (ib_dev->ibd_bd != NULL) - blkdev_put(ib_dev->ibd_bd, ib_dev); + if (ib_dev->ibd_bdev_file) + fput(ib_dev->ibd_bdev_file); bioset_exit(&ib_dev->ibd_bio_set); } @@ -566,13 +567,14 @@ fail: } enum { - Opt_udev_path, Opt_readonly, Opt_force, Opt_err + Opt_udev_path, Opt_readonly, Opt_force, Opt_exclusive, Opt_err, }; static match_table_t tokens = { {Opt_udev_path, "udev_path=%s"}, {Opt_readonly, "readonly=%d"}, {Opt_force, "force=%d"}, + {Opt_exclusive, "exclusive=%d"}, {Opt_err, NULL} }; @@ -582,7 +584,7 @@ static ssize_t iblock_set_configfs_dev_params(struct se_device *dev, struct iblock_dev *ib_dev = IBLOCK_DEV(dev); char *orig, *ptr, *arg_p, *opts; substring_t args[MAX_OPT_ARGS]; - int ret = 0, token; + int ret = 0, token, tmp_exclusive; unsigned long tmp_readonly; opts = kstrdup(page, GFP_KERNEL); @@ -629,6 +631,22 @@ static ssize_t iblock_set_configfs_dev_params(struct se_device *dev, ib_dev->ibd_readonly = tmp_readonly; pr_debug("IBLOCK: readonly: %d\n", ib_dev->ibd_readonly); break; + case Opt_exclusive: + arg_p = match_strdup(&args[0]); + if (!arg_p) { + ret = -ENOMEM; + break; + } + ret = kstrtoint(arg_p, 0, &tmp_exclusive); + kfree(arg_p); + if (ret < 0) { + pr_err("kstrtoul() failed for exclusive=\n"); + goto out; + } + ib_dev->ibd_exclusive = tmp_exclusive; + pr_debug("IBLOCK: exclusive: %d\n", + ib_dev->ibd_exclusive); + break; case Opt_force: break; default: @@ -653,6 +671,7 @@ static ssize_t iblock_show_configfs_dev_params(struct se_device *dev, char *b) bl += sprintf(b + bl, " UDEV PATH: %s", ib_dev->ibd_udev_path); bl += sprintf(b + bl, " readonly: %d\n", ib_dev->ibd_readonly); + bl += sprintf(b + bl, " exclusive: %d\n", ib_dev->ibd_exclusive); bl += sprintf(b + bl, " "); if (bd) { @@ -739,11 +758,16 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, if (data_direction == DMA_TO_DEVICE) { struct iblock_dev *ib_dev = IBLOCK_DEV(dev); + + /* + * Set bits to indicate WRITE_ODIRECT so we are not throttled + * by WBT. + */ + opf = REQ_OP_WRITE | REQ_SYNC | REQ_IDLE; /* * Force writethrough using REQ_FUA if a volatile write cache * is not enabled, or if initiator set the Force Unit Access bit. */ - opf = REQ_OP_WRITE; miter_dir = SG_MITER_TO_SG; if (bdev_fua(ib_dev->ibd_bd)) { if (cmd->se_cmd_flags & SCF_FUA) @@ -751,6 +775,9 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, else if (!bdev_write_cache(ib_dev->ibd_bd)) opf |= REQ_FUA; } + + if (cmd->se_cmd_flags & SCF_ATOMIC) + opf |= REQ_ATOMIC; } else { opf = REQ_OP_READ; miter_dir = SG_MITER_FROM_SG; diff --git a/drivers/target/target_core_iblock.h b/drivers/target/target_core_iblock.h index 8c55375d2f75..e2f28a69a11c 100644 --- a/drivers/target/target_core_iblock.h +++ b/drivers/target/target_core_iblock.h @@ -32,7 +32,9 @@ struct iblock_dev { u32 ibd_flags; struct bio_set ibd_bio_set; struct block_device *ibd_bd; + struct file *ibd_bdev_file; bool ibd_readonly; + bool ibd_exclusive; struct iblock_dev_plug *ibd_plug; } ____cacheline_aligned; diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index 408be26d2e9b..763e6d26e187 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -103,8 +103,8 @@ int target_get_pr_transport_id_len(struct se_node_acl *nacl, int target_get_pr_transport_id(struct se_node_acl *nacl, struct t10_pr_registration *pr_reg, int *format_code, unsigned char *buf); -const char *target_parse_pr_out_transport_id(struct se_portal_group *tpg, - char *buf, u32 *out_tid_len, char **port_nexus_ptr); +bool target_parse_pr_out_transport_id(struct se_portal_group *tpg, + char *buf, u32 *out_tid_len, char **port_nexus_ptr, char *i_str); /* target_core_hba.c */ struct se_hba *core_alloc_hba(const char *, u32, u32); @@ -125,6 +125,7 @@ void core_tpg_add_node_to_devs(struct se_node_acl *, struct se_portal_group *, struct se_lun *); void core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *); struct se_lun *core_tpg_alloc_lun(struct se_portal_group *, u64); +void target_tpg_free_lun(struct rcu_head *head); int core_tpg_add_lun(struct se_portal_group *, struct se_lun *, bool, struct se_device *); void core_tpg_remove_lun(struct se_portal_group *, struct se_lun *); diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 49d9167bb263..83e172c92238 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -19,7 +19,7 @@ #include <linux/fcntl.h> #include <linux/fs.h> #include <scsi/scsi_proto.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <target/target_core_base.h> #include <target/target_core_backend.h> @@ -91,7 +91,7 @@ target_scsi2_reservation_check(struct se_cmd *cmd) switch (cmd->t_task_cdb[0]) { case INQUIRY: - case RELEASE: + case RELEASE_6: case RELEASE_10: return 0; default: @@ -418,12 +418,12 @@ static int core_scsi3_pr_seq_non_holder(struct se_cmd *cmd, u32 pr_reg_type, return -EINVAL; } break; - case RELEASE: + case RELEASE_6: case RELEASE_10: /* Handled by CRH=1 in target_scsi2_reservation_release() */ ret = 0; break; - case RESERVE: + case RESERVE_6: case RESERVE_10: /* Handled by CRH=1 in target_scsi2_reservation_reserve() */ ret = 0; @@ -470,6 +470,7 @@ static int core_scsi3_pr_seq_non_holder(struct se_cmd *cmd, u32 pr_reg_type, case INQUIRY: case LOG_SENSE: case SERVICE_ACTION_IN_12: + case READ_CAPACITY: case REPORT_LUNS: case REQUEST_SENSE: case PERSISTENT_RESERVE_IN: @@ -1477,11 +1478,12 @@ core_scsi3_decode_spec_i_port( LIST_HEAD(tid_dest_list); struct pr_transport_id_holder *tidh_new, *tidh, *tidh_tmp; unsigned char *buf, *ptr, proto_ident; - const unsigned char *i_str = NULL; + unsigned char i_str[TRANSPORT_IQN_LEN]; char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN]; sense_reason_t ret; u32 tpdl, tid_len = 0; u32 dest_rtpi = 0; + bool tid_found; /* * Allocate a struct pr_transport_id_holder and setup the @@ -1570,9 +1572,9 @@ core_scsi3_decode_spec_i_port( dest_rtpi = tmp_lun->lun_tpg->tpg_rtpi; iport_ptr = NULL; - i_str = target_parse_pr_out_transport_id(tmp_tpg, - ptr, &tid_len, &iport_ptr); - if (!i_str) + tid_found = target_parse_pr_out_transport_id(tmp_tpg, + ptr, &tid_len, &iport_ptr, i_str); + if (!tid_found) continue; /* * Determine if this SCSI device server requires that @@ -1841,7 +1843,9 @@ out: } kmem_cache_free(t10_pr_reg_cache, dest_pr_reg); - core_scsi3_lunacl_undepend_item(dest_se_deve); + + if (dest_se_deve) + core_scsi3_lunacl_undepend_item(dest_se_deve); if (is_local) continue; @@ -3150,13 +3154,14 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key, struct t10_pr_registration *pr_reg, *pr_res_holder, *dest_pr_reg; struct t10_reservation *pr_tmpl = &dev->t10_pr; unsigned char *buf; - const unsigned char *initiator_str; + unsigned char initiator_str[TRANSPORT_IQN_LEN]; char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN] = { }; u32 tid_len, tmp_tid_len; int new_reg = 0, type, scope, matching_iname; sense_reason_t ret; unsigned short rtpi; unsigned char proto_ident; + bool tid_found; if (!se_sess || !se_lun) { pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); @@ -3275,9 +3280,9 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key, ret = TCM_INVALID_PARAMETER_LIST; goto out; } - initiator_str = target_parse_pr_out_transport_id(dest_se_tpg, - &buf[24], &tmp_tid_len, &iport_ptr); - if (!initiator_str) { + tid_found = target_parse_pr_out_transport_id(dest_se_tpg, + &buf[24], &tmp_tid_len, &iport_ptr, initiator_str); + if (!tid_found) { pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate" " initiator_str from Transport ID\n"); ret = TCM_INVALID_PARAMETER_LIST; diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 0d4f09693ef4..db4e09042469 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -20,7 +20,7 @@ #include <linux/cdrom.h> #include <linux/ratelimit.h> #include <linux/module.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <scsi/scsi_device.h> #include <scsi/scsi_host.h> @@ -352,7 +352,7 @@ static int pscsi_create_type_disk(struct se_device *dev, struct scsi_device *sd) struct pscsi_hba_virt *phv = dev->se_hba->hba_ptr; struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); struct Scsi_Host *sh = sd->host; - struct block_device *bd; + struct file *bdev_file; int ret; if (scsi_device_get(sd)) { @@ -366,18 +366,18 @@ static int pscsi_create_type_disk(struct se_device *dev, struct scsi_device *sd) * Claim exclusive struct block_device access to struct scsi_device * for TYPE_DISK and TYPE_ZBC using supplied udev_path */ - bd = blkdev_get_by_path(dev->udev_path, BLK_OPEN_WRITE | BLK_OPEN_READ, - pdv, NULL); - if (IS_ERR(bd)) { - pr_err("pSCSI: blkdev_get_by_path() failed\n"); + bdev_file = bdev_file_open_by_path(dev->udev_path, + BLK_OPEN_WRITE | BLK_OPEN_READ, pdv, NULL); + if (IS_ERR(bdev_file)) { + pr_err("pSCSI: bdev_file_open_by_path() failed\n"); scsi_device_put(sd); - return PTR_ERR(bd); + return PTR_ERR(bdev_file); } - pdv->pdv_bd = bd; + pdv->pdv_bdev_file = bdev_file; ret = pscsi_add_device_to_list(dev, sd); if (ret) { - blkdev_put(pdv->pdv_bd, pdv); + fput(bdev_file); scsi_device_put(sd); return ret; } @@ -564,9 +564,9 @@ static void pscsi_destroy_device(struct se_device *dev) * from pscsi_create_type_disk() */ if ((sd->type == TYPE_DISK || sd->type == TYPE_ZBC) && - pdv->pdv_bd) { - blkdev_put(pdv->pdv_bd, pdv); - pdv->pdv_bd = NULL; + pdv->pdv_bdev_file) { + fput(pdv->pdv_bdev_file); + pdv->pdv_bdev_file = NULL; } /* * For HBA mode PHV_LLD_SCSI_HOST_NO, release the reference @@ -823,7 +823,6 @@ static sense_reason_t pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, struct request *req) { - struct pscsi_dev_virt *pdv = PSCSI_DEV(cmd->se_dev); struct bio *bio = NULL; struct page *page; struct scatterlist *sg; @@ -862,7 +861,7 @@ new_bio: bio = bio_kmalloc(nr_vecs, GFP_KERNEL); if (!bio) goto fail; - bio_init(bio, NULL, bio->bi_inline_vecs, nr_vecs, + bio_init_inline(bio, NULL, nr_vecs, rw ? REQ_OP_WRITE : REQ_OP_READ); bio->bi_end_io = pscsi_bi_endio; @@ -871,12 +870,11 @@ new_bio: (rw) ? "rw" : "r", nr_vecs); } - pr_debug("PSCSI: Calling bio_add_pc_page() i: %d" + pr_debug("PSCSI: Calling bio_add_page() i: %d" " bio: %p page: %p len: %d off: %d\n", i, bio, page, len, off); - rc = bio_add_pc_page(pdv->pdv_sd->request_queue, - bio, page, bytes, off); + rc = bio_add_page(bio, page, bytes, off); pr_debug("PSCSI: bio->bi_vcnt: %d nr_vecs: %d\n", bio_segments(bio), nr_vecs); if (rc != bytes) { @@ -907,12 +905,15 @@ new_bio: return 0; fail: - if (bio) - bio_put(bio); + if (bio) { + bio_uninit(bio); + kfree(bio); + } while (req->bio) { bio = req->bio; req->bio = bio->bi_next; - bio_put(bio); + bio_uninit(bio); + kfree(bio); } req->biotail = NULL; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; @@ -994,8 +995,8 @@ static sector_t pscsi_get_blocks(struct se_device *dev) { struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); - if (pdv->pdv_bd) - return bdev_nr_sectors(pdv->pdv_bd); + if (pdv->pdv_bdev_file) + return bdev_nr_sectors(file_bdev(pdv->pdv_bdev_file)); return 0; } diff --git a/drivers/target/target_core_pscsi.h b/drivers/target/target_core_pscsi.h index 23d9a6e340d4..9acaa21e4c78 100644 --- a/drivers/target/target_core_pscsi.h +++ b/drivers/target/target_core_pscsi.h @@ -37,7 +37,7 @@ struct pscsi_dev_virt { int pdv_channel_id; int pdv_target_id; int pdv_lun_id; - struct block_device *pdv_bd; + struct file *pdv_bdev_file; struct scsi_device *pdv_sd; struct Scsi_Host *pdv_lld_host; } ____cacheline_aligned; diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 6a02561cc20c..abe91dc8722e 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -12,7 +12,7 @@ #include <linux/ratelimit.h> #include <linux/crc-t10dif.h> #include <linux/t10-pi.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <scsi/scsi_proto.h> #include <scsi/scsi_tcq.h> @@ -764,6 +764,49 @@ sbc_check_dpofua(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb) return 0; } +static sense_reason_t +sbc_check_atomic(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb) +{ + struct se_dev_attrib *attrib = &dev->dev_attrib; + u16 boundary, transfer_len; + u64 lba; + + lba = transport_lba_64(cdb); + boundary = get_unaligned_be16(&cdb[10]); + transfer_len = get_unaligned_be16(&cdb[12]); + + if (!attrib->atomic_max_len) + return TCM_UNSUPPORTED_SCSI_OPCODE; + + if (boundary) { + if (transfer_len > attrib->atomic_max_with_boundary) + return TCM_INVALID_CDB_FIELD; + + if (boundary > attrib->atomic_max_boundary) + return TCM_INVALID_CDB_FIELD; + } else { + if (transfer_len > attrib->atomic_max_len) + return TCM_INVALID_CDB_FIELD; + } + + if (attrib->atomic_granularity) { + if (transfer_len % attrib->atomic_granularity) + return TCM_INVALID_CDB_FIELD; + + if (boundary && boundary % attrib->atomic_granularity) + return TCM_INVALID_CDB_FIELD; + } + + if (dev->dev_attrib.atomic_alignment) { + u64 _lba = lba; + + if (do_div(_lba, dev->dev_attrib.atomic_alignment)) + return TCM_INVALID_CDB_FIELD; + } + + return 0; +} + sense_reason_t sbc_parse_cdb(struct se_cmd *cmd, struct exec_cmd_ops *ops) { @@ -861,6 +904,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct exec_cmd_ops *ops) break; case WRITE_16: case WRITE_VERIFY_16: + case WRITE_ATOMIC_16: sectors = transport_get_sectors_16(cdb); cmd->t_task_lba = transport_lba_64(cdb); @@ -872,6 +916,13 @@ sbc_parse_cdb(struct se_cmd *cmd, struct exec_cmd_ops *ops) return ret; cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; + if (cdb[0] == WRITE_ATOMIC_16) { + cmd->se_cmd_flags |= SCF_ATOMIC; + + ret = sbc_check_atomic(dev, cmd, cdb); + if (ret) + return ret; + } cmd->execute_cmd = sbc_execute_rw; break; case VARIABLE_LENGTH_CMD: diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 50290abc07bc..fe2b888bcb43 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -9,7 +9,7 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <scsi/scsi_proto.h> #include <scsi/scsi_common.h> @@ -521,7 +521,6 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) have_tp = 1; buf[0] = dev->transport->get_device_type(dev); - buf[3] = have_tp ? 0x3c : 0x10; /* Set WSNZ to 1 */ buf[4] = 0x01; @@ -562,11 +561,10 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) else put_unaligned_be32(dev->dev_attrib.optimal_sectors, &buf[12]); - /* - * Exit now if we don't support TP. - */ + put_unaligned_be16(12, &buf[2]); + if (!have_tp) - goto max_write_same; + goto try_atomic; /* * Set MAXIMUM UNMAP LBA COUNT @@ -595,9 +593,29 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) /* * MAXIMUM WRITE SAME LENGTH */ -max_write_same: put_unaligned_be64(dev->dev_attrib.max_write_same_len, &buf[36]); + put_unaligned_be16(40, &buf[2]); + +try_atomic: + /* + * ATOMIC + */ + if (!dev->dev_attrib.atomic_max_len) + goto done; + + if (dev->dev_attrib.atomic_max_len < io_max_blocks) + put_unaligned_be32(dev->dev_attrib.atomic_max_len, &buf[44]); + else + put_unaligned_be32(io_max_blocks, &buf[44]); + + put_unaligned_be32(dev->dev_attrib.atomic_alignment, &buf[48]); + put_unaligned_be32(dev->dev_attrib.atomic_granularity, &buf[52]); + put_unaligned_be32(dev->dev_attrib.atomic_max_with_boundary, &buf[56]); + put_unaligned_be32(dev->dev_attrib.atomic_max_boundary, &buf[60]); + + put_unaligned_be16(60, &buf[2]); +done: return 0; } @@ -1325,7 +1343,7 @@ static void set_dpofua_usage_bits32(u8 *usage_bits, struct se_device *dev) usage_bits[10] |= 0x18; } -static struct target_opcode_descriptor tcm_opcode_read6 = { +static const struct target_opcode_descriptor tcm_opcode_read6 = { .support = SCSI_SUPPORT_FULL, .opcode = READ_6, .cdb_size = 6, @@ -1333,7 +1351,7 @@ static struct target_opcode_descriptor tcm_opcode_read6 = { 0xff, SCSI_CONTROL_MASK}, }; -static struct target_opcode_descriptor tcm_opcode_read10 = { +static const struct target_opcode_descriptor tcm_opcode_read10 = { .support = SCSI_SUPPORT_FULL, .opcode = READ_10, .cdb_size = 10, @@ -1343,7 +1361,7 @@ static struct target_opcode_descriptor tcm_opcode_read10 = { .update_usage_bits = set_dpofua_usage_bits, }; -static struct target_opcode_descriptor tcm_opcode_read12 = { +static const struct target_opcode_descriptor tcm_opcode_read12 = { .support = SCSI_SUPPORT_FULL, .opcode = READ_12, .cdb_size = 12, @@ -1353,7 +1371,7 @@ static struct target_opcode_descriptor tcm_opcode_read12 = { .update_usage_bits = set_dpofua_usage_bits, }; -static struct target_opcode_descriptor tcm_opcode_read16 = { +static const struct target_opcode_descriptor tcm_opcode_read16 = { .support = SCSI_SUPPORT_FULL, .opcode = READ_16, .cdb_size = 16, @@ -1364,7 +1382,7 @@ static struct target_opcode_descriptor tcm_opcode_read16 = { .update_usage_bits = set_dpofua_usage_bits, }; -static struct target_opcode_descriptor tcm_opcode_write6 = { +static const struct target_opcode_descriptor tcm_opcode_write6 = { .support = SCSI_SUPPORT_FULL, .opcode = WRITE_6, .cdb_size = 6, @@ -1372,7 +1390,7 @@ static struct target_opcode_descriptor tcm_opcode_write6 = { 0xff, SCSI_CONTROL_MASK}, }; -static struct target_opcode_descriptor tcm_opcode_write10 = { +static const struct target_opcode_descriptor tcm_opcode_write10 = { .support = SCSI_SUPPORT_FULL, .opcode = WRITE_10, .cdb_size = 10, @@ -1382,7 +1400,7 @@ static struct target_opcode_descriptor tcm_opcode_write10 = { .update_usage_bits = set_dpofua_usage_bits, }; -static struct target_opcode_descriptor tcm_opcode_write_verify10 = { +static const struct target_opcode_descriptor tcm_opcode_write_verify10 = { .support = SCSI_SUPPORT_FULL, .opcode = WRITE_VERIFY, .cdb_size = 10, @@ -1392,7 +1410,7 @@ static struct target_opcode_descriptor tcm_opcode_write_verify10 = { .update_usage_bits = set_dpofua_usage_bits, }; -static struct target_opcode_descriptor tcm_opcode_write12 = { +static const struct target_opcode_descriptor tcm_opcode_write12 = { .support = SCSI_SUPPORT_FULL, .opcode = WRITE_12, .cdb_size = 12, @@ -1402,7 +1420,7 @@ static struct target_opcode_descriptor tcm_opcode_write12 = { .update_usage_bits = set_dpofua_usage_bits, }; -static struct target_opcode_descriptor tcm_opcode_write16 = { +static const struct target_opcode_descriptor tcm_opcode_write16 = { .support = SCSI_SUPPORT_FULL, .opcode = WRITE_16, .cdb_size = 16, @@ -1413,7 +1431,7 @@ static struct target_opcode_descriptor tcm_opcode_write16 = { .update_usage_bits = set_dpofua_usage_bits, }; -static struct target_opcode_descriptor tcm_opcode_write_verify16 = { +static const struct target_opcode_descriptor tcm_opcode_write_verify16 = { .support = SCSI_SUPPORT_FULL, .opcode = WRITE_VERIFY_16, .cdb_size = 16, @@ -1424,7 +1442,7 @@ static struct target_opcode_descriptor tcm_opcode_write_verify16 = { .update_usage_bits = set_dpofua_usage_bits, }; -static bool tcm_is_ws_enabled(struct target_opcode_descriptor *descr, +static bool tcm_is_ws_enabled(const struct target_opcode_descriptor *descr, struct se_cmd *cmd) { struct exec_cmd_ops *ops = cmd->protocol_data; @@ -1434,7 +1452,7 @@ static bool tcm_is_ws_enabled(struct target_opcode_descriptor *descr, !!ops->execute_write_same; } -static struct target_opcode_descriptor tcm_opcode_write_same32 = { +static const struct target_opcode_descriptor tcm_opcode_write_same32 = { .support = SCSI_SUPPORT_FULL, .serv_action_valid = 1, .opcode = VARIABLE_LENGTH_CMD, @@ -1452,7 +1470,25 @@ static struct target_opcode_descriptor tcm_opcode_write_same32 = { .update_usage_bits = set_dpofua_usage_bits32, }; -static bool tcm_is_caw_enabled(struct target_opcode_descriptor *descr, +static bool tcm_is_atomic_enabled(const struct target_opcode_descriptor *descr, + struct se_cmd *cmd) +{ + return cmd->se_dev->dev_attrib.atomic_max_len; +} + +static struct target_opcode_descriptor tcm_opcode_write_atomic16 = { + .support = SCSI_SUPPORT_FULL, + .opcode = WRITE_ATOMIC_16, + .cdb_size = 16, + .usage_bits = {WRITE_ATOMIC_16, 0xf8, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK}, + .enabled = tcm_is_atomic_enabled, + .update_usage_bits = set_dpofua_usage_bits, +}; + +static bool tcm_is_caw_enabled(const struct target_opcode_descriptor *descr, struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; @@ -1460,7 +1496,7 @@ static bool tcm_is_caw_enabled(struct target_opcode_descriptor *descr, return dev->dev_attrib.emulate_caw; } -static struct target_opcode_descriptor tcm_opcode_compare_write = { +static const struct target_opcode_descriptor tcm_opcode_compare_write = { .support = SCSI_SUPPORT_FULL, .opcode = COMPARE_AND_WRITE, .cdb_size = 16, @@ -1472,7 +1508,7 @@ static struct target_opcode_descriptor tcm_opcode_compare_write = { .update_usage_bits = set_dpofua_usage_bits, }; -static struct target_opcode_descriptor tcm_opcode_read_capacity = { +static const struct target_opcode_descriptor tcm_opcode_read_capacity = { .support = SCSI_SUPPORT_FULL, .opcode = READ_CAPACITY, .cdb_size = 10, @@ -1481,7 +1517,7 @@ static struct target_opcode_descriptor tcm_opcode_read_capacity = { 0x01, SCSI_CONTROL_MASK}, }; -static struct target_opcode_descriptor tcm_opcode_read_capacity16 = { +static const struct target_opcode_descriptor tcm_opcode_read_capacity16 = { .support = SCSI_SUPPORT_FULL, .serv_action_valid = 1, .opcode = SERVICE_ACTION_IN_16, @@ -1493,7 +1529,7 @@ static struct target_opcode_descriptor tcm_opcode_read_capacity16 = { 0xff, 0xff, 0x00, SCSI_CONTROL_MASK}, }; -static bool tcm_is_rep_ref_enabled(struct target_opcode_descriptor *descr, +static bool tcm_is_rep_ref_enabled(const struct target_opcode_descriptor *descr, struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; @@ -1507,7 +1543,7 @@ static bool tcm_is_rep_ref_enabled(struct target_opcode_descriptor *descr, return true; } -static struct target_opcode_descriptor tcm_opcode_read_report_refferals = { +static const struct target_opcode_descriptor tcm_opcode_read_report_refferals = { .support = SCSI_SUPPORT_FULL, .serv_action_valid = 1, .opcode = SERVICE_ACTION_IN_16, @@ -1520,7 +1556,7 @@ static struct target_opcode_descriptor tcm_opcode_read_report_refferals = { .enabled = tcm_is_rep_ref_enabled, }; -static struct target_opcode_descriptor tcm_opcode_sync_cache = { +static const struct target_opcode_descriptor tcm_opcode_sync_cache = { .support = SCSI_SUPPORT_FULL, .opcode = SYNCHRONIZE_CACHE, .cdb_size = 10, @@ -1529,7 +1565,7 @@ static struct target_opcode_descriptor tcm_opcode_sync_cache = { 0xff, SCSI_CONTROL_MASK}, }; -static struct target_opcode_descriptor tcm_opcode_sync_cache16 = { +static const struct target_opcode_descriptor tcm_opcode_sync_cache16 = { .support = SCSI_SUPPORT_FULL, .opcode = SYNCHRONIZE_CACHE_16, .cdb_size = 16, @@ -1539,7 +1575,7 @@ static struct target_opcode_descriptor tcm_opcode_sync_cache16 = { 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK}, }; -static bool tcm_is_unmap_enabled(struct target_opcode_descriptor *descr, +static bool tcm_is_unmap_enabled(const struct target_opcode_descriptor *descr, struct se_cmd *cmd) { struct exec_cmd_ops *ops = cmd->protocol_data; @@ -1548,7 +1584,7 @@ static bool tcm_is_unmap_enabled(struct target_opcode_descriptor *descr, return ops->execute_unmap && dev->dev_attrib.emulate_tpu; } -static struct target_opcode_descriptor tcm_opcode_unmap = { +static const struct target_opcode_descriptor tcm_opcode_unmap = { .support = SCSI_SUPPORT_FULL, .opcode = UNMAP, .cdb_size = 10, @@ -1558,7 +1594,7 @@ static struct target_opcode_descriptor tcm_opcode_unmap = { .enabled = tcm_is_unmap_enabled, }; -static struct target_opcode_descriptor tcm_opcode_write_same = { +static const struct target_opcode_descriptor tcm_opcode_write_same = { .support = SCSI_SUPPORT_FULL, .opcode = WRITE_SAME, .cdb_size = 10, @@ -1568,7 +1604,7 @@ static struct target_opcode_descriptor tcm_opcode_write_same = { .enabled = tcm_is_ws_enabled, }; -static struct target_opcode_descriptor tcm_opcode_write_same16 = { +static const struct target_opcode_descriptor tcm_opcode_write_same16 = { .support = SCSI_SUPPORT_FULL, .opcode = WRITE_SAME_16, .cdb_size = 16, @@ -1579,7 +1615,7 @@ static struct target_opcode_descriptor tcm_opcode_write_same16 = { .enabled = tcm_is_ws_enabled, }; -static struct target_opcode_descriptor tcm_opcode_verify = { +static const struct target_opcode_descriptor tcm_opcode_verify = { .support = SCSI_SUPPORT_FULL, .opcode = VERIFY, .cdb_size = 10, @@ -1588,7 +1624,7 @@ static struct target_opcode_descriptor tcm_opcode_verify = { 0xff, SCSI_CONTROL_MASK}, }; -static struct target_opcode_descriptor tcm_opcode_verify16 = { +static const struct target_opcode_descriptor tcm_opcode_verify16 = { .support = SCSI_SUPPORT_FULL, .opcode = VERIFY_16, .cdb_size = 16, @@ -1598,7 +1634,7 @@ static struct target_opcode_descriptor tcm_opcode_verify16 = { 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK}, }; -static struct target_opcode_descriptor tcm_opcode_start_stop = { +static const struct target_opcode_descriptor tcm_opcode_start_stop = { .support = SCSI_SUPPORT_FULL, .opcode = START_STOP, .cdb_size = 6, @@ -1606,7 +1642,7 @@ static struct target_opcode_descriptor tcm_opcode_start_stop = { 0x01, SCSI_CONTROL_MASK}, }; -static struct target_opcode_descriptor tcm_opcode_mode_select = { +static const struct target_opcode_descriptor tcm_opcode_mode_select = { .support = SCSI_SUPPORT_FULL, .opcode = MODE_SELECT, .cdb_size = 6, @@ -1614,7 +1650,7 @@ static struct target_opcode_descriptor tcm_opcode_mode_select = { 0xff, SCSI_CONTROL_MASK}, }; -static struct target_opcode_descriptor tcm_opcode_mode_select10 = { +static const struct target_opcode_descriptor tcm_opcode_mode_select10 = { .support = SCSI_SUPPORT_FULL, .opcode = MODE_SELECT_10, .cdb_size = 10, @@ -1623,7 +1659,7 @@ static struct target_opcode_descriptor tcm_opcode_mode_select10 = { 0xff, SCSI_CONTROL_MASK}, }; -static struct target_opcode_descriptor tcm_opcode_mode_sense = { +static const struct target_opcode_descriptor tcm_opcode_mode_sense = { .support = SCSI_SUPPORT_FULL, .opcode = MODE_SENSE, .cdb_size = 6, @@ -1631,7 +1667,7 @@ static struct target_opcode_descriptor tcm_opcode_mode_sense = { 0xff, SCSI_CONTROL_MASK}, }; -static struct target_opcode_descriptor tcm_opcode_mode_sense10 = { +static const struct target_opcode_descriptor tcm_opcode_mode_sense10 = { .support = SCSI_SUPPORT_FULL, .opcode = MODE_SENSE_10, .cdb_size = 10, @@ -1640,7 +1676,7 @@ static struct target_opcode_descriptor tcm_opcode_mode_sense10 = { 0xff, SCSI_CONTROL_MASK}, }; -static struct target_opcode_descriptor tcm_opcode_pri_read_keys = { +static const struct target_opcode_descriptor tcm_opcode_pri_read_keys = { .support = SCSI_SUPPORT_FULL, .serv_action_valid = 1, .opcode = PERSISTENT_RESERVE_IN, @@ -1651,7 +1687,7 @@ static struct target_opcode_descriptor tcm_opcode_pri_read_keys = { 0xff, SCSI_CONTROL_MASK}, }; -static struct target_opcode_descriptor tcm_opcode_pri_read_resrv = { +static const struct target_opcode_descriptor tcm_opcode_pri_read_resrv = { .support = SCSI_SUPPORT_FULL, .serv_action_valid = 1, .opcode = PERSISTENT_RESERVE_IN, @@ -1662,7 +1698,7 @@ static struct target_opcode_descriptor tcm_opcode_pri_read_resrv = { 0xff, SCSI_CONTROL_MASK}, }; -static bool tcm_is_pr_enabled(struct target_opcode_descriptor *descr, +static bool tcm_is_pr_enabled(const struct target_opcode_descriptor *descr, struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; @@ -1674,9 +1710,9 @@ static bool tcm_is_pr_enabled(struct target_opcode_descriptor *descr, return true; switch (descr->opcode) { - case RESERVE: + case RESERVE_6: case RESERVE_10: - case RELEASE: + case RELEASE_6: case RELEASE_10: /* * The pr_ops which are used by the backend modules don't @@ -1704,7 +1740,7 @@ static bool tcm_is_pr_enabled(struct target_opcode_descriptor *descr, return true; } -static struct target_opcode_descriptor tcm_opcode_pri_read_caps = { +static const struct target_opcode_descriptor tcm_opcode_pri_read_caps = { .support = SCSI_SUPPORT_FULL, .serv_action_valid = 1, .opcode = PERSISTENT_RESERVE_IN, @@ -1716,7 +1752,7 @@ static struct target_opcode_descriptor tcm_opcode_pri_read_caps = { .enabled = tcm_is_pr_enabled, }; -static struct target_opcode_descriptor tcm_opcode_pri_read_full_status = { +static const struct target_opcode_descriptor tcm_opcode_pri_read_full_status = { .support = SCSI_SUPPORT_FULL, .serv_action_valid = 1, .opcode = PERSISTENT_RESERVE_IN, @@ -1728,7 +1764,7 @@ static struct target_opcode_descriptor tcm_opcode_pri_read_full_status = { .enabled = tcm_is_pr_enabled, }; -static struct target_opcode_descriptor tcm_opcode_pro_register = { +static const struct target_opcode_descriptor tcm_opcode_pro_register = { .support = SCSI_SUPPORT_FULL, .serv_action_valid = 1, .opcode = PERSISTENT_RESERVE_OUT, @@ -1740,7 +1776,7 @@ static struct target_opcode_descriptor tcm_opcode_pro_register = { .enabled = tcm_is_pr_enabled, }; -static struct target_opcode_descriptor tcm_opcode_pro_reserve = { +static const struct target_opcode_descriptor tcm_opcode_pro_reserve = { .support = SCSI_SUPPORT_FULL, .serv_action_valid = 1, .opcode = PERSISTENT_RESERVE_OUT, @@ -1752,7 +1788,7 @@ static struct target_opcode_descriptor tcm_opcode_pro_reserve = { .enabled = tcm_is_pr_enabled, }; -static struct target_opcode_descriptor tcm_opcode_pro_release = { +static const struct target_opcode_descriptor tcm_opcode_pro_release = { .support = SCSI_SUPPORT_FULL, .serv_action_valid = 1, .opcode = PERSISTENT_RESERVE_OUT, @@ -1764,7 +1800,7 @@ static struct target_opcode_descriptor tcm_opcode_pro_release = { .enabled = tcm_is_pr_enabled, }; -static struct target_opcode_descriptor tcm_opcode_pro_clear = { +static const struct target_opcode_descriptor tcm_opcode_pro_clear = { .support = SCSI_SUPPORT_FULL, .serv_action_valid = 1, .opcode = PERSISTENT_RESERVE_OUT, @@ -1776,7 +1812,7 @@ static struct target_opcode_descriptor tcm_opcode_pro_clear = { .enabled = tcm_is_pr_enabled, }; -static struct target_opcode_descriptor tcm_opcode_pro_preempt = { +static const struct target_opcode_descriptor tcm_opcode_pro_preempt = { .support = SCSI_SUPPORT_FULL, .serv_action_valid = 1, .opcode = PERSISTENT_RESERVE_OUT, @@ -1788,7 +1824,7 @@ static struct target_opcode_descriptor tcm_opcode_pro_preempt = { .enabled = tcm_is_pr_enabled, }; -static struct target_opcode_descriptor tcm_opcode_pro_preempt_abort = { +static const struct target_opcode_descriptor tcm_opcode_pro_preempt_abort = { .support = SCSI_SUPPORT_FULL, .serv_action_valid = 1, .opcode = PERSISTENT_RESERVE_OUT, @@ -1800,7 +1836,7 @@ static struct target_opcode_descriptor tcm_opcode_pro_preempt_abort = { .enabled = tcm_is_pr_enabled, }; -static struct target_opcode_descriptor tcm_opcode_pro_reg_ign_exist = { +static const struct target_opcode_descriptor tcm_opcode_pro_reg_ign_exist = { .support = SCSI_SUPPORT_FULL, .serv_action_valid = 1, .opcode = PERSISTENT_RESERVE_OUT, @@ -1814,7 +1850,7 @@ static struct target_opcode_descriptor tcm_opcode_pro_reg_ign_exist = { .enabled = tcm_is_pr_enabled, }; -static struct target_opcode_descriptor tcm_opcode_pro_register_move = { +static const struct target_opcode_descriptor tcm_opcode_pro_register_move = { .support = SCSI_SUPPORT_FULL, .serv_action_valid = 1, .opcode = PERSISTENT_RESERVE_OUT, @@ -1826,16 +1862,16 @@ static struct target_opcode_descriptor tcm_opcode_pro_register_move = { .enabled = tcm_is_pr_enabled, }; -static struct target_opcode_descriptor tcm_opcode_release = { +static const struct target_opcode_descriptor tcm_opcode_release = { .support = SCSI_SUPPORT_FULL, - .opcode = RELEASE, + .opcode = RELEASE_6, .cdb_size = 6, - .usage_bits = {RELEASE, 0x00, 0x00, 0x00, + .usage_bits = {RELEASE_6, 0x00, 0x00, 0x00, 0x00, SCSI_CONTROL_MASK}, .enabled = tcm_is_pr_enabled, }; -static struct target_opcode_descriptor tcm_opcode_release10 = { +static const struct target_opcode_descriptor tcm_opcode_release10 = { .support = SCSI_SUPPORT_FULL, .opcode = RELEASE_10, .cdb_size = 10, @@ -1845,16 +1881,16 @@ static struct target_opcode_descriptor tcm_opcode_release10 = { .enabled = tcm_is_pr_enabled, }; -static struct target_opcode_descriptor tcm_opcode_reserve = { +static const struct target_opcode_descriptor tcm_opcode_reserve = { .support = SCSI_SUPPORT_FULL, - .opcode = RESERVE, + .opcode = RESERVE_6, .cdb_size = 6, - .usage_bits = {RESERVE, 0x00, 0x00, 0x00, + .usage_bits = {RESERVE_6, 0x00, 0x00, 0x00, 0x00, SCSI_CONTROL_MASK}, .enabled = tcm_is_pr_enabled, }; -static struct target_opcode_descriptor tcm_opcode_reserve10 = { +static const struct target_opcode_descriptor tcm_opcode_reserve10 = { .support = SCSI_SUPPORT_FULL, .opcode = RESERVE_10, .cdb_size = 10, @@ -1864,7 +1900,7 @@ static struct target_opcode_descriptor tcm_opcode_reserve10 = { .enabled = tcm_is_pr_enabled, }; -static struct target_opcode_descriptor tcm_opcode_request_sense = { +static const struct target_opcode_descriptor tcm_opcode_request_sense = { .support = SCSI_SUPPORT_FULL, .opcode = REQUEST_SENSE, .cdb_size = 6, @@ -1872,7 +1908,7 @@ static struct target_opcode_descriptor tcm_opcode_request_sense = { 0xff, SCSI_CONTROL_MASK}, }; -static struct target_opcode_descriptor tcm_opcode_inquiry = { +static const struct target_opcode_descriptor tcm_opcode_inquiry = { .support = SCSI_SUPPORT_FULL, .opcode = INQUIRY, .cdb_size = 6, @@ -1880,7 +1916,7 @@ static struct target_opcode_descriptor tcm_opcode_inquiry = { 0xff, SCSI_CONTROL_MASK}, }; -static bool tcm_is_3pc_enabled(struct target_opcode_descriptor *descr, +static bool tcm_is_3pc_enabled(const struct target_opcode_descriptor *descr, struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; @@ -1888,7 +1924,7 @@ static bool tcm_is_3pc_enabled(struct target_opcode_descriptor *descr, return dev->dev_attrib.emulate_3pc; } -static struct target_opcode_descriptor tcm_opcode_extended_copy_lid1 = { +static const struct target_opcode_descriptor tcm_opcode_extended_copy_lid1 = { .support = SCSI_SUPPORT_FULL, .serv_action_valid = 1, .opcode = EXTENDED_COPY, @@ -1900,7 +1936,7 @@ static struct target_opcode_descriptor tcm_opcode_extended_copy_lid1 = { .enabled = tcm_is_3pc_enabled, }; -static struct target_opcode_descriptor tcm_opcode_rcv_copy_res_op_params = { +static const struct target_opcode_descriptor tcm_opcode_rcv_copy_res_op_params = { .support = SCSI_SUPPORT_FULL, .serv_action_valid = 1, .opcode = RECEIVE_COPY_RESULTS, @@ -1914,7 +1950,7 @@ static struct target_opcode_descriptor tcm_opcode_rcv_copy_res_op_params = { .enabled = tcm_is_3pc_enabled, }; -static struct target_opcode_descriptor tcm_opcode_report_luns = { +static const struct target_opcode_descriptor tcm_opcode_report_luns = { .support = SCSI_SUPPORT_FULL, .opcode = REPORT_LUNS, .cdb_size = 12, @@ -1923,7 +1959,7 @@ static struct target_opcode_descriptor tcm_opcode_report_luns = { 0xff, 0xff, 0x00, SCSI_CONTROL_MASK}, }; -static struct target_opcode_descriptor tcm_opcode_test_unit_ready = { +static const struct target_opcode_descriptor tcm_opcode_test_unit_ready = { .support = SCSI_SUPPORT_FULL, .opcode = TEST_UNIT_READY, .cdb_size = 6, @@ -1931,7 +1967,7 @@ static struct target_opcode_descriptor tcm_opcode_test_unit_ready = { 0x00, SCSI_CONTROL_MASK}, }; -static struct target_opcode_descriptor tcm_opcode_report_target_pgs = { +static const struct target_opcode_descriptor tcm_opcode_report_target_pgs = { .support = SCSI_SUPPORT_FULL, .serv_action_valid = 1, .opcode = MAINTENANCE_IN, @@ -1942,7 +1978,7 @@ static struct target_opcode_descriptor tcm_opcode_report_target_pgs = { 0xff, 0xff, 0x00, SCSI_CONTROL_MASK}, }; -static bool spc_rsoc_enabled(struct target_opcode_descriptor *descr, +static bool spc_rsoc_enabled(const struct target_opcode_descriptor *descr, struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; @@ -1950,7 +1986,7 @@ static bool spc_rsoc_enabled(struct target_opcode_descriptor *descr, return dev->dev_attrib.emulate_rsoc; } -static struct target_opcode_descriptor tcm_opcode_report_supp_opcodes = { +static const struct target_opcode_descriptor tcm_opcode_report_supp_opcodes = { .support = SCSI_SUPPORT_FULL, .serv_action_valid = 1, .opcode = MAINTENANCE_IN, @@ -1963,7 +1999,7 @@ static struct target_opcode_descriptor tcm_opcode_report_supp_opcodes = { .enabled = spc_rsoc_enabled, }; -static bool tcm_is_set_tpg_enabled(struct target_opcode_descriptor *descr, +static bool tcm_is_set_tpg_enabled(const struct target_opcode_descriptor *descr, struct se_cmd *cmd) { struct t10_alua_tg_pt_gp *l_tg_pt_gp; @@ -1984,7 +2020,7 @@ static bool tcm_is_set_tpg_enabled(struct target_opcode_descriptor *descr, return true; } -static struct target_opcode_descriptor tcm_opcode_set_tpg = { +static const struct target_opcode_descriptor tcm_opcode_set_tpg = { .support = SCSI_SUPPORT_FULL, .serv_action_valid = 1, .opcode = MAINTENANCE_OUT, @@ -1996,7 +2032,7 @@ static struct target_opcode_descriptor tcm_opcode_set_tpg = { .enabled = tcm_is_set_tpg_enabled, }; -static struct target_opcode_descriptor *tcm_supported_opcodes[] = { +static const struct target_opcode_descriptor *tcm_supported_opcodes[] = { &tcm_opcode_read6, &tcm_opcode_read10, &tcm_opcode_read12, @@ -2008,6 +2044,7 @@ static struct target_opcode_descriptor *tcm_supported_opcodes[] = { &tcm_opcode_write16, &tcm_opcode_write_verify16, &tcm_opcode_write_same32, + &tcm_opcode_write_atomic16, &tcm_opcode_compare_write, &tcm_opcode_read_capacity, &tcm_opcode_read_capacity16, @@ -2053,7 +2090,7 @@ static struct target_opcode_descriptor *tcm_supported_opcodes[] = { static int spc_rsoc_encode_command_timeouts_descriptor(unsigned char *buf, u8 ctdp, - struct target_opcode_descriptor *descr) + const struct target_opcode_descriptor *descr) { if (!ctdp) return 0; @@ -2068,7 +2105,7 @@ spc_rsoc_encode_command_timeouts_descriptor(unsigned char *buf, u8 ctdp, static int spc_rsoc_encode_command_descriptor(unsigned char *buf, u8 ctdp, - struct target_opcode_descriptor *descr) + const struct target_opcode_descriptor *descr) { int td_size = 0; @@ -2087,7 +2124,7 @@ spc_rsoc_encode_command_descriptor(unsigned char *buf, u8 ctdp, static int spc_rsoc_encode_one_command_descriptor(unsigned char *buf, u8 ctdp, - struct target_opcode_descriptor *descr, + const struct target_opcode_descriptor *descr, struct se_device *dev) { int td_size = 0; @@ -2110,9 +2147,9 @@ spc_rsoc_encode_one_command_descriptor(unsigned char *buf, u8 ctdp, } static sense_reason_t -spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode) +spc_rsoc_get_descr(struct se_cmd *cmd, const struct target_opcode_descriptor **opcode) { - struct target_opcode_descriptor *descr; + const struct target_opcode_descriptor *descr; struct se_session *sess = cmd->se_sess; unsigned char *cdb = cmd->t_task_cdb; u8 opts = cdb[2] & 0x3; @@ -2151,8 +2188,10 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode) if (descr->serv_action_valid) return TCM_INVALID_CDB_FIELD; - if (!descr->enabled || descr->enabled(descr, cmd)) + if (!descr->enabled || descr->enabled(descr, cmd)) { *opcode = descr; + return TCM_NO_SENSE; + } break; case 0x2: /* @@ -2166,8 +2205,10 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode) if (descr->serv_action_valid && descr->service_action == requested_sa) { if (!descr->enabled || descr->enabled(descr, - cmd)) + cmd)) { *opcode = descr; + return TCM_NO_SENSE; + } } else if (!descr->serv_action_valid) return TCM_INVALID_CDB_FIELD; break; @@ -2180,20 +2221,22 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode) */ if (descr->service_action == requested_sa) if (!descr->enabled || descr->enabled(descr, - cmd)) + cmd)) { *opcode = descr; + return TCM_NO_SENSE; + } break; } } - return 0; + return TCM_NO_SENSE; } static sense_reason_t spc_emulate_report_supp_op_codes(struct se_cmd *cmd) { int descr_num = ARRAY_SIZE(tcm_supported_opcodes); - struct target_opcode_descriptor *descr = NULL; + const struct target_opcode_descriptor *descr = NULL; unsigned char *cdb = cmd->t_task_cdb; u8 rctd = (cdb[2] >> 7) & 0x1; unsigned char *buf = NULL; @@ -2243,7 +2286,7 @@ spc_emulate_report_supp_op_codes(struct se_cmd *cmd) response_length += spc_rsoc_encode_command_descriptor( &buf[response_length], rctd, descr); } - put_unaligned_be32(response_length - 3, buf); + put_unaligned_be32(response_length - 4, buf); } else { response_length = spc_rsoc_encode_one_command_descriptor( &buf[response_length], rctd, descr, @@ -2267,9 +2310,9 @@ spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) unsigned char *cdb = cmd->t_task_cdb; switch (cdb[0]) { - case RESERVE: + case RESERVE_6: case RESERVE_10: - case RELEASE: + case RELEASE_6: case RELEASE_10: if (!dev->dev_attrib.emulate_pr) return TCM_UNSUPPORTED_SCSI_OPCODE; @@ -2313,7 +2356,7 @@ spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) *size = get_unaligned_be32(&cdb[5]); cmd->execute_cmd = target_scsi3_emulate_pr_out; break; - case RELEASE: + case RELEASE_6: case RELEASE_10: if (cdb[0] == RELEASE_10) *size = get_unaligned_be16(&cdb[7]); @@ -2322,7 +2365,7 @@ spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) cmd->execute_cmd = target_scsi2_reservation_release; break; - case RESERVE: + case RESERVE_6: case RESERVE_10: /* * The SPC-2 RESERVE does not contain a size in the SCSI CDB. diff --git a/drivers/target/target_core_stat.c b/drivers/target/target_core_stat.c index c42cbde8a31b..083205052be2 100644 --- a/drivers/target/target_core_stat.c +++ b/drivers/target/target_core_stat.c @@ -117,9 +117,9 @@ static ssize_t target_stat_tgt_status_show(struct config_item *item, char *page) { if (to_stat_tgt_dev(item)->export_count) - return snprintf(page, PAGE_SIZE, "activated"); + return snprintf(page, PAGE_SIZE, "activated\n"); else - return snprintf(page, PAGE_SIZE, "deactivated"); + return snprintf(page, PAGE_SIZE, "deactivated\n"); } static ssize_t target_stat_tgt_non_access_lus_show(struct config_item *item, @@ -276,35 +276,39 @@ static ssize_t target_stat_lu_state_bit_show(struct config_item *item, return snprintf(page, PAGE_SIZE, "exposed\n"); } -static ssize_t target_stat_lu_num_cmds_show(struct config_item *item, - char *page) -{ - struct se_device *dev = to_stat_lu_dev(item); - - /* scsiLuNumCommands */ - return snprintf(page, PAGE_SIZE, "%lu\n", - atomic_long_read(&dev->num_cmds)); -} - -static ssize_t target_stat_lu_read_mbytes_show(struct config_item *item, - char *page) -{ - struct se_device *dev = to_stat_lu_dev(item); - - /* scsiLuReadMegaBytes */ - return snprintf(page, PAGE_SIZE, "%lu\n", - atomic_long_read(&dev->read_bytes) >> 20); -} - -static ssize_t target_stat_lu_write_mbytes_show(struct config_item *item, - char *page) -{ - struct se_device *dev = to_stat_lu_dev(item); - - /* scsiLuWrittenMegaBytes */ - return snprintf(page, PAGE_SIZE, "%lu\n", - atomic_long_read(&dev->write_bytes) >> 20); -} +#define per_cpu_stat_snprintf(stats_struct, prefix, field, shift) \ +static ssize_t \ +per_cpu_stat_##prefix##_snprintf(struct stats_struct __percpu *per_cpu_stats, \ + char *page) \ +{ \ + struct stats_struct *stats; \ + unsigned int cpu; \ + u64 sum = 0; \ + \ + for_each_possible_cpu(cpu) { \ + stats = per_cpu_ptr(per_cpu_stats, cpu); \ + sum += stats->field; \ + } \ + \ + return snprintf(page, PAGE_SIZE, "%llu\n", sum >> shift); \ +} + +#define lu_show_per_cpu_stat(prefix, field, shift) \ +per_cpu_stat_snprintf(se_dev_io_stats, prefix, field, shift); \ +static ssize_t \ +target_stat_##prefix##_show(struct config_item *item, char *page) \ +{ \ + struct se_device *dev = to_stat_lu_dev(item); \ + \ + return per_cpu_stat_##prefix##_snprintf(dev->stats, page); \ +} \ + +/* scsiLuNumCommands */ +lu_show_per_cpu_stat(lu_num_cmds, total_cmds, 0); +/* scsiLuReadMegaBytes */ +lu_show_per_cpu_stat(lu_read_mbytes, read_bytes, 20); +/* scsiLuWrittenMegaBytes */ +lu_show_per_cpu_stat(lu_write_mbytes, write_bytes, 20); static ssize_t target_stat_lu_resets_show(struct config_item *item, char *page) { @@ -602,53 +606,30 @@ static ssize_t target_stat_tgt_port_port_index_show(struct config_item *item, return ret; } -static ssize_t target_stat_tgt_port_in_cmds_show(struct config_item *item, - char *page) -{ - struct se_lun *lun = to_stat_tgt_port(item); - struct se_device *dev; - ssize_t ret = -ENODEV; - - rcu_read_lock(); - dev = rcu_dereference(lun->lun_se_dev); - if (dev) - ret = snprintf(page, PAGE_SIZE, "%lu\n", - atomic_long_read(&lun->lun_stats.cmd_pdus)); - rcu_read_unlock(); - return ret; -} - -static ssize_t target_stat_tgt_port_write_mbytes_show(struct config_item *item, - char *page) -{ - struct se_lun *lun = to_stat_tgt_port(item); - struct se_device *dev; - ssize_t ret = -ENODEV; - - rcu_read_lock(); - dev = rcu_dereference(lun->lun_se_dev); - if (dev) - ret = snprintf(page, PAGE_SIZE, "%u\n", - (u32)(atomic_long_read(&lun->lun_stats.rx_data_octets) >> 20)); - rcu_read_unlock(); - return ret; -} - -static ssize_t target_stat_tgt_port_read_mbytes_show(struct config_item *item, - char *page) -{ - struct se_lun *lun = to_stat_tgt_port(item); - struct se_device *dev; - ssize_t ret = -ENODEV; - - rcu_read_lock(); - dev = rcu_dereference(lun->lun_se_dev); - if (dev) - ret = snprintf(page, PAGE_SIZE, "%u\n", - (u32)(atomic_long_read(&lun->lun_stats.tx_data_octets) >> 20)); - rcu_read_unlock(); - return ret; -} +#define tgt_port_show_per_cpu_stat(prefix, field, shift) \ +per_cpu_stat_snprintf(scsi_port_stats, prefix, field, shift); \ +static ssize_t \ +target_stat_##prefix##_show(struct config_item *item, char *page) \ +{ \ + struct se_lun *lun = to_stat_tgt_port(item); \ + struct se_device *dev; \ + int ret; \ + \ + rcu_read_lock(); \ + dev = rcu_dereference(lun->lun_se_dev); \ + if (!dev) { \ + rcu_read_unlock(); \ + return -ENODEV; \ + } \ + \ + ret = per_cpu_stat_##prefix##_snprintf(lun->lun_stats, page); \ + rcu_read_unlock(); \ + return ret; \ +} + +tgt_port_show_per_cpu_stat(tgt_port_in_cmds, cmd_pdus, 0); +tgt_port_show_per_cpu_stat(tgt_port_write_mbytes, rx_data_octets, 20); +tgt_port_show_per_cpu_stat(tgt_port_read_mbytes, tx_data_octets, 20); static ssize_t target_stat_tgt_port_hs_in_cmds_show(struct config_item *item, char *page) @@ -1014,68 +995,34 @@ static ssize_t target_stat_auth_att_count_show(struct config_item *item, return ret; } -static ssize_t target_stat_auth_num_cmds_show(struct config_item *item, - char *page) -{ - struct se_lun_acl *lacl = auth_to_lacl(item); - struct se_node_acl *nacl = lacl->se_lun_nacl; - struct se_dev_entry *deve; - ssize_t ret; - - rcu_read_lock(); - deve = target_nacl_find_deve(nacl, lacl->mapped_lun); - if (!deve) { - rcu_read_unlock(); - return -ENODEV; - } - /* scsiAuthIntrOutCommands */ - ret = snprintf(page, PAGE_SIZE, "%lu\n", - atomic_long_read(&deve->total_cmds)); - rcu_read_unlock(); - return ret; -} - -static ssize_t target_stat_auth_read_mbytes_show(struct config_item *item, - char *page) -{ - struct se_lun_acl *lacl = auth_to_lacl(item); - struct se_node_acl *nacl = lacl->se_lun_nacl; - struct se_dev_entry *deve; - ssize_t ret; - - rcu_read_lock(); - deve = target_nacl_find_deve(nacl, lacl->mapped_lun); - if (!deve) { - rcu_read_unlock(); - return -ENODEV; - } - /* scsiAuthIntrReadMegaBytes */ - ret = snprintf(page, PAGE_SIZE, "%u\n", - (u32)(atomic_long_read(&deve->read_bytes) >> 20)); - rcu_read_unlock(); - return ret; -} - -static ssize_t target_stat_auth_write_mbytes_show(struct config_item *item, - char *page) -{ - struct se_lun_acl *lacl = auth_to_lacl(item); - struct se_node_acl *nacl = lacl->se_lun_nacl; - struct se_dev_entry *deve; - ssize_t ret; - - rcu_read_lock(); - deve = target_nacl_find_deve(nacl, lacl->mapped_lun); - if (!deve) { - rcu_read_unlock(); - return -ENODEV; - } - /* scsiAuthIntrWrittenMegaBytes */ - ret = snprintf(page, PAGE_SIZE, "%u\n", - (u32)(atomic_long_read(&deve->write_bytes) >> 20)); - rcu_read_unlock(); - return ret; -} +#define auth_show_per_cpu_stat(prefix, field, shift) \ +per_cpu_stat_snprintf(se_dev_entry_io_stats, prefix, field, shift); \ +static ssize_t \ +target_stat_##prefix##_show(struct config_item *item, char *page) \ +{ \ + struct se_lun_acl *lacl = auth_to_lacl(item); \ + struct se_node_acl *nacl = lacl->se_lun_nacl; \ + struct se_dev_entry *deve; \ + int ret; \ + \ + rcu_read_lock(); \ + deve = target_nacl_find_deve(nacl, lacl->mapped_lun); \ + if (!deve) { \ + rcu_read_unlock(); \ + return -ENODEV; \ + } \ + \ + ret = per_cpu_stat_##prefix##_snprintf(deve->stats, page); \ + rcu_read_unlock(); \ + return ret; \ +} + +/* scsiAuthIntrOutCommands */ +auth_show_per_cpu_stat(auth_num_cmds, total_cmds, 0); +/* scsiAuthIntrReadMegaBytes */ +auth_show_per_cpu_stat(auth_read_mbytes, read_bytes, 20); +/* scsiAuthIntrWrittenMegaBytes */ +auth_show_per_cpu_stat(auth_write_mbytes, write_bytes, 20); static ssize_t target_stat_auth_hs_num_cmds_show(struct config_item *item, char *page) diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index c0e429e5ef31..8b5ad50baa43 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c @@ -548,7 +548,7 @@ int core_tpg_register( ret = core_tpg_add_lun(se_tpg, se_tpg->tpg_virt_lun0, true, g_lun0_dev); if (ret < 0) { - kfree(se_tpg->tpg_virt_lun0); + target_tpg_free_lun(&se_tpg->tpg_virt_lun0->rcu_head); return ret; } } @@ -595,7 +595,7 @@ int core_tpg_deregister(struct se_portal_group *se_tpg) if (se_tpg->proto_id >= 0) { core_tpg_remove_lun(se_tpg, se_tpg->tpg_virt_lun0); - kfree_rcu(se_tpg->tpg_virt_lun0, rcu_head); + call_rcu(&se_tpg->tpg_virt_lun0->rcu_head, target_tpg_free_lun); } target_tpg_deregister_rtpi(se_tpg); @@ -615,6 +615,13 @@ struct se_lun *core_tpg_alloc_lun( pr_err("Unable to allocate se_lun memory\n"); return ERR_PTR(-ENOMEM); } + + lun->lun_stats = alloc_percpu(struct scsi_port_stats); + if (!lun->lun_stats) { + pr_err("Unable to allocate se_lun stats memory\n"); + goto free_lun; + } + lun->unpacked_lun = unpacked_lun; atomic_set(&lun->lun_acl_count, 0); init_completion(&lun->lun_shutdown_comp); @@ -628,6 +635,18 @@ struct se_lun *core_tpg_alloc_lun( lun->lun_tpg = tpg; return lun; + +free_lun: + kfree(lun); + return ERR_PTR(-ENOMEM); +} + +void target_tpg_free_lun(struct rcu_head *head) +{ + struct se_lun *lun = container_of(head, struct se_lun, rcu_head); + + free_percpu(lun->lun_stats); + kfree(lun); } int core_tpg_add_lun( diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 687adc9e086c..e8b7955d40f2 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -22,7 +22,7 @@ #include <linux/module.h> #include <linux/ratelimit.h> #include <linux/vmalloc.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <net/sock.h> #include <net/tcp.h> #include <scsi/scsi_proto.h> @@ -126,12 +126,12 @@ int init_se_kmem_caches(void) } target_completion_wq = alloc_workqueue("target_completion", - WQ_MEM_RECLAIM, 0); + WQ_MEM_RECLAIM | WQ_PERCPU, 0); if (!target_completion_wq) goto out_free_lba_map_mem_cache; target_submission_wq = alloc_workqueue("target_submission", - WQ_MEM_RECLAIM, 0); + WQ_MEM_RECLAIM | WQ_PERCPU, 0); if (!target_submission_wq) goto out_free_completion_wq; @@ -264,6 +264,7 @@ void target_free_cmd_counter(struct target_cmd_counter *cmd_cnt) percpu_ref_put(&cmd_cnt->refcnt); percpu_ref_exit(&cmd_cnt->refcnt); + kfree(cmd_cnt); } EXPORT_SYMBOL_GPL(target_free_cmd_counter); @@ -1570,22 +1571,49 @@ target_cmd_parse_cdb(struct se_cmd *cmd) return ret; cmd->se_cmd_flags |= SCF_SUPPORTED_SAM_OPCODE; - atomic_long_inc(&cmd->se_lun->lun_stats.cmd_pdus); + /* + * If this is the xcopy_lun then we won't have lun_stats since we + * can't export them. + */ + if (cmd->se_lun->lun_stats) + this_cpu_inc(cmd->se_lun->lun_stats->cmd_pdus); return 0; } EXPORT_SYMBOL(target_cmd_parse_cdb); -/* - * Used by fabric module frontends to queue tasks directly. - * May only be used from process context. - */ -int transport_handle_cdb_direct( - struct se_cmd *cmd) +static int __target_submit(struct se_cmd *cmd) { sense_reason_t ret; might_sleep(); + /* + * Check if we need to delay processing because of ALUA + * Active/NonOptimized primary access state.. + */ + core_alua_check_nonop_delay(cmd); + + if (cmd->t_data_nents != 0) { + /* + * This is primarily a hack for udev and tcm loop which sends + * INQUIRYs with a single page and expects the data to be + * cleared. + */ + if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && + cmd->data_direction == DMA_FROM_DEVICE) { + struct scatterlist *sgl = cmd->t_data_sg; + unsigned char *buf = NULL; + + BUG_ON(!sgl); + + buf = kmap_local_page(sg_page(sgl)); + if (buf) { + memset(buf + sgl->offset, 0, sgl->length); + kunmap_local(buf); + } + } + } + if (!cmd->se_lun) { dump_stack(); pr_err("cmd->se_lun is NULL\n"); @@ -1613,7 +1641,6 @@ int transport_handle_cdb_direct( transport_generic_request_failure(cmd, ret); return 0; } -EXPORT_SYMBOL(transport_handle_cdb_direct); sense_reason_t transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *sgl, @@ -1781,53 +1808,6 @@ generic_fail: EXPORT_SYMBOL_GPL(target_submit_prep); /** - * target_submit - perform final initialization and submit cmd to LIO core - * @se_cmd: command descriptor to submit - * - * target_submit_prep must have been called on the cmd, and this must be - * called from process context. - */ -void target_submit(struct se_cmd *se_cmd) -{ - struct scatterlist *sgl = se_cmd->t_data_sg; - unsigned char *buf = NULL; - - might_sleep(); - - if (se_cmd->t_data_nents != 0) { - BUG_ON(!sgl); - /* - * A work-around for tcm_loop as some userspace code via - * scsi-generic do not memset their associated read buffers, - * so go ahead and do that here for type non-data CDBs. Also - * note that this is currently guaranteed to be a single SGL - * for this case by target core in target_setup_cmd_from_cdb() - * -> transport_generic_cmd_sequencer(). - */ - if (!(se_cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && - se_cmd->data_direction == DMA_FROM_DEVICE) { - if (sgl) - buf = kmap(sg_page(sgl)) + sgl->offset; - - if (buf) { - memset(buf, 0, sgl->length); - kunmap(sg_page(sgl)); - } - } - - } - - /* - * Check if we need to delay processing because of ALUA - * Active/NonOptimized primary access state.. - */ - core_alua_check_nonop_delay(se_cmd); - - transport_handle_cdb_direct(se_cmd); -} -EXPORT_SYMBOL_GPL(target_submit); - -/** * target_submit_cmd - lookup unpacked lun and submit uninitialized se_cmd * * @se_cmd: command descriptor to submit @@ -1922,7 +1902,7 @@ void target_queued_submit_work(struct work_struct *work) se_plug = target_plug_device(se_dev); } - target_submit(se_cmd); + __target_submit(se_cmd); } if (se_plug) @@ -1933,7 +1913,7 @@ void target_queued_submit_work(struct work_struct *work) * target_queue_submission - queue the cmd to run on the LIO workqueue * @se_cmd: command descriptor to submit */ -void target_queue_submission(struct se_cmd *se_cmd) +static void target_queue_submission(struct se_cmd *se_cmd) { struct se_device *se_dev = se_cmd->se_dev; int cpu = se_cmd->cpuid; @@ -1943,7 +1923,35 @@ void target_queue_submission(struct se_cmd *se_cmd) llist_add(&se_cmd->se_cmd_list, &sq->cmd_list); queue_work_on(cpu, target_submission_wq, &sq->work); } -EXPORT_SYMBOL_GPL(target_queue_submission); + +/** + * target_submit - perform final initialization and submit cmd to LIO core + * @se_cmd: command descriptor to submit + * + * target_submit_prep or something similar must have been called on the cmd, + * and this must be called from process context. + */ +int target_submit(struct se_cmd *se_cmd) +{ + const struct target_core_fabric_ops *tfo = se_cmd->se_sess->se_tpg->se_tpg_tfo; + struct se_dev_attrib *da = &se_cmd->se_dev->dev_attrib; + u8 submit_type; + + if (da->submit_type == TARGET_FABRIC_DEFAULT_SUBMIT) + submit_type = tfo->default_submit_type; + else if (da->submit_type == TARGET_DIRECT_SUBMIT && + tfo->direct_submit_supp) + submit_type = TARGET_DIRECT_SUBMIT; + else + submit_type = TARGET_QUEUE_SUBMIT; + + if (submit_type == TARGET_DIRECT_SUBMIT) + return __target_submit(se_cmd); + + target_queue_submission(se_cmd); + return 0; +} +EXPORT_SYMBOL_GPL(target_submit); static void target_complete_tmr_failure(struct work_struct *work) { @@ -2210,6 +2218,7 @@ static int target_write_prot_action(struct se_cmd *cmd) static bool target_handle_task_attr(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; + unsigned long flags; if (dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH) return false; @@ -2222,13 +2231,10 @@ static bool target_handle_task_attr(struct se_cmd *cmd) */ switch (cmd->sam_task_attr) { case TCM_HEAD_TAG: - atomic_inc_mb(&dev->non_ordered); pr_debug("Added HEAD_OF_QUEUE for CDB: 0x%02x\n", cmd->t_task_cdb[0]); return false; case TCM_ORDERED_TAG: - atomic_inc_mb(&dev->delayed_cmd_count); - pr_debug("Added ORDERED for CDB: 0x%02x to ordered list\n", cmd->t_task_cdb[0]); break; @@ -2236,29 +2242,29 @@ static bool target_handle_task_attr(struct se_cmd *cmd) /* * For SIMPLE and UNTAGGED Task Attribute commands */ - atomic_inc_mb(&dev->non_ordered); - - if (atomic_read(&dev->delayed_cmd_count) == 0) +retry: + if (percpu_ref_tryget_live(&dev->non_ordered)) return false; + break; } - if (cmd->sam_task_attr != TCM_ORDERED_TAG) { - atomic_inc_mb(&dev->delayed_cmd_count); - /* - * We will account for this when we dequeue from the delayed - * list. - */ - atomic_dec_mb(&dev->non_ordered); + spin_lock_irqsave(&dev->delayed_cmd_lock, flags); + if (cmd->sam_task_attr == TCM_SIMPLE_TAG && + !percpu_ref_is_dying(&dev->non_ordered)) { + spin_unlock_irqrestore(&dev->delayed_cmd_lock, flags); + /* We raced with the last ordered completion so retry. */ + goto retry; + } else if (!percpu_ref_is_dying(&dev->non_ordered)) { + percpu_ref_kill(&dev->non_ordered); } - spin_lock_irq(&cmd->t_state_lock); + spin_lock(&cmd->t_state_lock); cmd->transport_state &= ~CMD_T_SENT; - spin_unlock_irq(&cmd->t_state_lock); + spin_unlock(&cmd->t_state_lock); - spin_lock(&dev->delayed_cmd_lock); list_add_tail(&cmd->se_delayed_node, &dev->delayed_cmd_list); - spin_unlock(&dev->delayed_cmd_lock); + spin_unlock_irqrestore(&dev->delayed_cmd_lock, flags); pr_debug("Added CDB: 0x%02x Task Attr: 0x%02x to delayed CMD listn", cmd->t_task_cdb[0], cmd->sam_task_attr); @@ -2310,41 +2316,52 @@ void target_do_delayed_work(struct work_struct *work) while (!dev->ordered_sync_in_progress) { struct se_cmd *cmd; - if (list_empty(&dev->delayed_cmd_list)) + /* + * We can be woken up early/late due to races or the + * extra wake up we do when adding commands to the list. + * We check for both cases here. + */ + if (list_empty(&dev->delayed_cmd_list) || + !percpu_ref_is_zero(&dev->non_ordered)) break; cmd = list_entry(dev->delayed_cmd_list.next, struct se_cmd, se_delayed_node); + cmd->se_cmd_flags |= SCF_TASK_ORDERED_SYNC; + cmd->transport_state |= CMD_T_SENT; - if (cmd->sam_task_attr == TCM_ORDERED_TAG) { - /* - * Check if we started with: - * [ordered] [simple] [ordered] - * and we are now at the last ordered so we have to wait - * for the simple cmd. - */ - if (atomic_read(&dev->non_ordered) > 0) - break; - - dev->ordered_sync_in_progress = true; - } + dev->ordered_sync_in_progress = true; list_del(&cmd->se_delayed_node); - atomic_dec_mb(&dev->delayed_cmd_count); spin_unlock(&dev->delayed_cmd_lock); - if (cmd->sam_task_attr != TCM_ORDERED_TAG) - atomic_inc_mb(&dev->non_ordered); - - cmd->transport_state |= CMD_T_SENT; - __target_execute_cmd(cmd, true); - spin_lock(&dev->delayed_cmd_lock); } spin_unlock(&dev->delayed_cmd_lock); } +static void transport_complete_ordered_sync(struct se_cmd *cmd) +{ + struct se_device *dev = cmd->se_dev; + unsigned long flags; + + spin_lock_irqsave(&dev->delayed_cmd_lock, flags); + dev->dev_cur_ordered_id++; + + pr_debug("Incremented dev_cur_ordered_id: %u for type %d\n", + dev->dev_cur_ordered_id, cmd->sam_task_attr); + + dev->ordered_sync_in_progress = false; + + if (list_empty(&dev->delayed_cmd_list)) + percpu_ref_resurrect(&dev->non_ordered); + else + schedule_work(&dev->delayed_cmd_work); + + spin_unlock_irqrestore(&dev->delayed_cmd_lock, flags); +} + /* * Called from I/O completion to determine which dormant/delayed * and ordered cmds need to have their tasks added to the execution queue. @@ -2357,30 +2374,24 @@ static void transport_complete_task_attr(struct se_cmd *cmd) return; if (!(cmd->se_cmd_flags & SCF_TASK_ATTR_SET)) - goto restart; - - if (cmd->sam_task_attr == TCM_SIMPLE_TAG) { - atomic_dec_mb(&dev->non_ordered); - dev->dev_cur_ordered_id++; - } else if (cmd->sam_task_attr == TCM_HEAD_TAG) { - atomic_dec_mb(&dev->non_ordered); - dev->dev_cur_ordered_id++; - pr_debug("Incremented dev_cur_ordered_id: %u for HEAD_OF_QUEUE\n", - dev->dev_cur_ordered_id); - } else if (cmd->sam_task_attr == TCM_ORDERED_TAG) { - spin_lock(&dev->delayed_cmd_lock); - dev->ordered_sync_in_progress = false; - spin_unlock(&dev->delayed_cmd_lock); + return; - dev->dev_cur_ordered_id++; - pr_debug("Incremented dev_cur_ordered_id: %u for ORDERED\n", - dev->dev_cur_ordered_id); - } cmd->se_cmd_flags &= ~SCF_TASK_ATTR_SET; -restart: - if (atomic_read(&dev->delayed_cmd_count) > 0) - schedule_work(&dev->delayed_cmd_work); + if (cmd->se_cmd_flags & SCF_TASK_ORDERED_SYNC) { + transport_complete_ordered_sync(cmd); + return; + } + + switch (cmd->sam_task_attr) { + case TCM_SIMPLE_TAG: + percpu_ref_put(&dev->non_ordered); + break; + case TCM_ORDERED_TAG: + /* All ordered should have been executed as sync */ + WARN_ON(1); + break; + } } static void transport_complete_qf(struct se_cmd *cmd) @@ -2591,8 +2602,9 @@ queue_rsp: !(cmd->se_cmd_flags & SCF_TREAT_READ_AS_NORMAL)) goto queue_status; - atomic_long_add(cmd->data_length, - &cmd->se_lun->lun_stats.tx_data_octets); + if (cmd->se_lun->lun_stats) + this_cpu_add(cmd->se_lun->lun_stats->tx_data_octets, + cmd->data_length); /* * Perform READ_STRIP of PI using software emulation when * backend had PI enabled, if the transport will not be @@ -2615,14 +2627,16 @@ queue_rsp: goto queue_full; break; case DMA_TO_DEVICE: - atomic_long_add(cmd->data_length, - &cmd->se_lun->lun_stats.rx_data_octets); + if (cmd->se_lun->lun_stats) + this_cpu_add(cmd->se_lun->lun_stats->rx_data_octets, + cmd->data_length); /* * Check if we need to send READ payload for BIDI-COMMAND */ if (cmd->se_cmd_flags & SCF_BIDI) { - atomic_long_add(cmd->data_length, - &cmd->se_lun->lun_stats.tx_data_octets); + if (cmd->se_lun->lun_stats) + this_cpu_add(cmd->se_lun->lun_stats->tx_data_octets, + cmd->data_length); ret = cmd->se_tfo->queue_data_in(cmd); if (ret) goto queue_full; @@ -3626,6 +3640,10 @@ int transport_generic_handle_tmr( unsigned long flags; bool aborted = false; + spin_lock_irqsave(&cmd->se_dev->se_tmr_lock, flags); + list_add_tail(&cmd->se_tmr_req->tmr_list, &cmd->se_dev->dev_tmr_list); + spin_unlock_irqrestore(&cmd->se_dev->se_tmr_lock, flags); + spin_lock_irqsave(&cmd->t_state_lock, flags); if (cmd->transport_state & CMD_T_ABORTED) { aborted = true; diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index 22cc6cac0ba2..3fd963612775 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -201,7 +201,7 @@ struct tcmu_tmr { uint8_t tmr_type; uint32_t tmr_cmd_cnt; - int16_t tmr_cmd_ids[]; + int16_t tmr_cmd_ids[] __counted_by(tmr_cmd_cnt); }; /* @@ -361,7 +361,7 @@ static const struct genl_multicast_group tcmu_mcgrps[] = { [TCMU_MCGRP_CONFIG] = { .name = "config", }, }; -static struct nla_policy tcmu_attr_policy[TCMU_ATTR_MAX+1] = { +static const struct nla_policy tcmu_attr_policy[TCMU_ATTR_MAX + 1] = { [TCMU_ATTR_DEVICE] = { .type = NLA_STRING }, [TCMU_ATTR_MINOR] = { .type = NLA_U32 }, [TCMU_ATTR_CMD_STATUS] = { .type = NLA_S32 }, @@ -1232,7 +1232,7 @@ static void tcmu_set_next_deadline(struct list_head *queue, cmd = list_first_entry(queue, struct tcmu_cmd, queue_entry); mod_timer(timer, cmd->deadline); } else - del_timer(timer); + timer_delete(timer); } static int @@ -1564,7 +1564,7 @@ static void tcmu_device_timedout(struct tcmu_dev *udev) static void tcmu_cmd_timedout(struct timer_list *t) { - struct tcmu_dev *udev = from_timer(udev, t, cmd_timer); + struct tcmu_dev *udev = timer_container_of(udev, t, cmd_timer); pr_debug("%s cmd timeout has expired\n", udev->name); tcmu_device_timedout(udev); @@ -1572,7 +1572,7 @@ static void tcmu_cmd_timedout(struct timer_list *t) static void tcmu_qfull_timedout(struct timer_list *t) { - struct tcmu_dev *udev = from_timer(udev, t, qfull_timer); + struct tcmu_dev *udev = timer_container_of(udev, t, qfull_timer); pr_debug("%s qfull timeout has expired\n", udev->name); tcmu_device_timedout(udev); @@ -2130,7 +2130,7 @@ static int tcmu_netlink_event_send(struct tcmu_dev *udev, } ret = genlmsg_multicast_allns(&tcmu_genl_family, skb, 0, - TCMU_MCGRP_CONFIG, GFP_KERNEL); + TCMU_MCGRP_CONFIG); /* Wait during an add as the listener may not be up yet */ if (ret == 0 || @@ -2321,8 +2321,8 @@ static void tcmu_destroy_device(struct se_device *dev) { struct tcmu_dev *udev = TCMU_DEV(dev); - del_timer_sync(&udev->cmd_timer); - del_timer_sync(&udev->qfull_timer); + timer_delete_sync(&udev->cmd_timer); + timer_delete_sync(&udev->qfull_timer); mutex_lock(&root_udev_mutex); list_del(&udev->node); @@ -2408,7 +2408,7 @@ static void tcmu_reset_ring(struct tcmu_dev *udev, u8 err_level) tcmu_flush_dcache_range(mb, sizeof(*mb)); clear_bit(TCMU_DEV_BIT_BROKEN, &udev->flags); - del_timer(&udev->cmd_timer); + timer_delete(&udev->cmd_timer); /* * ring is empty and qfull queue never contains aborted commands. @@ -2430,7 +2430,7 @@ enum { Opt_cmd_ring_size_mb, Opt_err, }; -static match_table_t tokens = { +static const match_table_t tokens = { {Opt_dev_config, "dev_config=%s"}, {Opt_dev_size, "dev_size=%s"}, {Opt_hw_block_size, "hw_block_size=%d"}, diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c index 91ed015b588c..93534a6e14b7 100644 --- a/drivers/target/target_core_xcopy.c +++ b/drivers/target/target_core_xcopy.c @@ -15,10 +15,11 @@ #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/list.h> +#include <linux/rculist.h> #include <linux/configfs.h> #include <linux/ratelimit.h> #include <scsi/scsi_proto.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <target/target_core_base.h> #include <target/target_core_backend.h> @@ -461,7 +462,7 @@ static const struct target_core_fabric_ops xcopy_pt_tfo = { int target_xcopy_setup_pt(void) { - xcopy_wq = alloc_workqueue("xcopy_wq", WQ_MEM_RECLAIM, 0); + xcopy_wq = alloc_workqueue("xcopy_wq", WQ_MEM_RECLAIM | WQ_PERCPU, 0); if (!xcopy_wq) { pr_err("Unable to allocate xcopy_wq\n"); return -ENOMEM; diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index 21783cd71c15..34ab628809e8 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -16,7 +16,7 @@ #include <linux/configfs.h> #include <linux/ctype.h> #include <linux/hash.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <scsi/scsi_tcq.h> #include <scsi/libfc.h> diff --git a/drivers/target/tcm_fc/tfc_conf.c b/drivers/target/tcm_fc/tfc_conf.c index 6ac3fc1a7d39..f686d95d3273 100644 --- a/drivers/target/tcm_fc/tfc_conf.c +++ b/drivers/target/tcm_fc/tfc_conf.c @@ -25,7 +25,7 @@ #include <linux/configfs.h> #include <linux/kernel.h> #include <linux/ctype.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <scsi/libfc.h> #include <target/target_core_base.h> @@ -250,7 +250,7 @@ static struct se_portal_group *ft_add_tpg(struct se_wwn *wwn, const char *name) tpg->lport_wwn = ft_wwn; INIT_LIST_HEAD(&tpg->lun_list); - wq = alloc_workqueue("tcm_fc", 0, 1); + wq = alloc_workqueue("tcm_fc", WQ_PERCPU, 1); if (!wq) { kfree(tpg); return NULL; @@ -432,6 +432,9 @@ static const struct target_core_fabric_ops ft_fabric_ops = { .tfc_wwn_attrs = ft_wwn_attrs, .tfc_tpg_nacl_base_attrs = ft_nacl_base_attrs, + + .default_submit_type = TARGET_DIRECT_SUBMIT, + .direct_submit_supp = 1, }; static struct notifier_block ft_notifier = { diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c index bbe2e29612fa..45329284f52f 100644 --- a/drivers/target/tcm_fc/tfc_io.c +++ b/drivers/target/tcm_fc/tfc_io.c @@ -26,7 +26,7 @@ #include <linux/ctype.h> #include <linux/hash.h> #include <linux/ratelimit.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <scsi/libfc.h> #include <target/target_core_base.h> diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c index 593540da9346..d6afaba52ea5 100644 --- a/drivers/target/tcm_fc/tfc_sess.c +++ b/drivers/target/tcm_fc/tfc_sess.c @@ -19,7 +19,7 @@ #include <linux/rcupdate.h> #include <linux/rculist.h> #include <linux/kref.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <scsi/libfc.h> #include <target/target_core_base.h> |
