aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2012-05-20 11:59:13 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2012-07-16 20:25:56 -0400
commit88455ec4be02c395820b1ff57656b0844ec03ac3 (patch)
tree3f8a7feda6180fea2e0aa832014d743dee853441 /drivers/target
parent9b3b804101db067c3889948f57031f852186ea11 (diff)
target: split parsing of SPC commands into a separate helper
(nab: Add EXPORT_SYMBOL usage for spc_parse_cdb) Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/Makefile1
-rw-r--r--drivers/target/target_core_internal.h3
-rw-r--r--drivers/target/target_core_spc.c169
-rw-r--r--drivers/target/target_core_transport.c112
4 files changed, 176 insertions, 109 deletions
diff --git a/drivers/target/Makefile b/drivers/target/Makefile
index 61648d84fbb6..70cab2a138d1 100644
--- a/drivers/target/Makefile
+++ b/drivers/target/Makefile
@@ -10,6 +10,7 @@ target_core_mod-y := target_core_configfs.o \
10 target_core_tpg.o \ 10 target_core_tpg.o \
11 target_core_transport.o \ 11 target_core_transport.o \
12 target_core_cdb.o \ 12 target_core_cdb.o \
13 target_core_spc.o \
13 target_core_ua.o \ 14 target_core_ua.o \
14 target_core_rd.o \ 15 target_core_rd.o \
15 target_core_stat.o 16 target_core_stat.o
diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h
index 165e82429687..6bbf18dc9e0d 100644
--- a/drivers/target/target_core_internal.h
+++ b/drivers/target/target_core_internal.h
@@ -96,6 +96,9 @@ int core_tpg_post_addlun(struct se_portal_group *, struct se_lun *,
96struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32 unpacked_lun); 96struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32 unpacked_lun);
97int core_tpg_post_dellun(struct se_portal_group *, struct se_lun *); 97int core_tpg_post_dellun(struct se_portal_group *, struct se_lun *);
98 98
99/* target_core_spc.c */
100int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size, bool passthrough);
101
99/* target_core_transport.c */ 102/* target_core_transport.c */
100extern struct kmem_cache *se_tmr_req_cache; 103extern struct kmem_cache *se_tmr_req_cache;
101 104
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
new file mode 100644
index 000000000000..ec2108667d65
--- /dev/null
+++ b/drivers/target/target_core_spc.c
@@ -0,0 +1,169 @@
1/*
2 * SCSI Primary Commands (SPC) parsing and emulation.
3 *
4 * Copyright (c) 2002, 2003, 2004, 2005 PyX Technologies, Inc.
5 * Copyright (c) 2005, 2006, 2007 SBE, Inc.
6 * Copyright (c) 2007-2010 Rising Tide Systems
7 * Copyright (c) 2008-2010 Linux-iSCSI.org
8 *
9 * Nicholas A. Bellinger <nab@kernel.org>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 */
25
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <asm/unaligned.h>
29
30#include <scsi/scsi.h>
31#include <scsi/scsi_tcq.h>
32
33#include <target/target_core_base.h>
34#include <target/target_core_backend.h>
35#include <target/target_core_fabric.h>
36
37#include "target_core_internal.h"
38#include "target_core_pr.h"
39#include "target_core_ua.h"
40
41
42int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size, bool passthrough)
43{
44 struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev;
45 unsigned char *cdb = cmd->t_task_cdb;
46
47 switch (cdb[0]) {
48 case MODE_SELECT:
49 *size = cdb[4];
50 break;
51 case MODE_SELECT_10:
52 *size = (cdb[7] << 8) + cdb[8];
53 break;
54 case MODE_SENSE:
55 *size = cdb[4];
56 if (!passthrough)
57 cmd->execute_cmd = target_emulate_modesense;
58 break;
59 case MODE_SENSE_10:
60 *size = (cdb[7] << 8) + cdb[8];
61 if (!passthrough)
62 cmd->execute_cmd = target_emulate_modesense;
63 break;
64 case LOG_SELECT:
65 case LOG_SENSE:
66 *size = (cdb[7] << 8) + cdb[8];
67 break;
68 case PERSISTENT_RESERVE_IN:
69 if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS)
70 cmd->execute_cmd = target_scsi3_emulate_pr_in;
71 *size = (cdb[7] << 8) + cdb[8];
72 break;
73 case PERSISTENT_RESERVE_OUT:
74 if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS)
75 cmd->execute_cmd = target_scsi3_emulate_pr_out;
76 *size = (cdb[7] << 8) + cdb[8];
77 break;
78 case RELEASE:
79 case RELEASE_10:
80 if (cdb[0] == RELEASE_10)
81 *size = (cdb[7] << 8) | cdb[8];
82 else
83 *size = cmd->data_length;
84
85 if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH)
86 cmd->execute_cmd = target_scsi2_reservation_release;
87 break;
88 case RESERVE:
89 case RESERVE_10:
90 /*
91 * The SPC-2 RESERVE does not contain a size in the SCSI CDB.
92 * Assume the passthrough or $FABRIC_MOD will tell us about it.
93 */
94 if (cdb[0] == RESERVE_10)
95 *size = (cdb[7] << 8) | cdb[8];
96 else
97 *size = cmd->data_length;
98
99 /*
100 * Setup the legacy emulated handler for SPC-2 and
101 * >= SPC-3 compatible reservation handling (CRH=1)
102 * Otherwise, we assume the underlying SCSI logic is
103 * is running in SPC_PASSTHROUGH, and wants reservations
104 * emulation disabled.
105 */
106 if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH)
107 cmd->execute_cmd = target_scsi2_reservation_reserve;
108 break;
109 case REQUEST_SENSE:
110 *size = cdb[4];
111 if (!passthrough)
112 cmd->execute_cmd = target_emulate_request_sense;
113 break;
114 case INQUIRY:
115 *size = (cdb[3] << 8) + cdb[4];
116
117 /*
118 * Do implict HEAD_OF_QUEUE processing for INQUIRY.
119 * See spc4r17 section 5.3
120 */
121 if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
122 cmd->sam_task_attr = MSG_HEAD_TAG;
123 if (!passthrough)
124 cmd->execute_cmd = target_emulate_inquiry;
125 break;
126 case SECURITY_PROTOCOL_IN:
127 case SECURITY_PROTOCOL_OUT:
128 *size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
129 break;
130 case EXTENDED_COPY:
131 case READ_ATTRIBUTE:
132 case RECEIVE_COPY_RESULTS:
133 case WRITE_ATTRIBUTE:
134 *size = (cdb[10] << 24) | (cdb[11] << 16) |
135 (cdb[12] << 8) | cdb[13];
136 break;
137 case RECEIVE_DIAGNOSTIC:
138 case SEND_DIAGNOSTIC:
139 *size = (cdb[3] << 8) | cdb[4];
140 break;
141 case WRITE_BUFFER:
142 *size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8];
143 break;
144 case REPORT_LUNS:
145 cmd->execute_cmd = target_report_luns;
146 *size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
147 /*
148 * Do implict HEAD_OF_QUEUE processing for REPORT_LUNS
149 * See spc4r17 section 5.3
150 */
151 if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
152 cmd->sam_task_attr = MSG_HEAD_TAG;
153 break;
154 case TEST_UNIT_READY:
155 if (!passthrough)
156 cmd->execute_cmd = target_emulate_noop;
157 break;
158 default:
159 pr_warn("TARGET_CORE[%s]: Unsupported SCSI Opcode"
160 " 0x%02x, sending CHECK_CONDITION.\n",
161 cmd->se_tfo->get_fabric_name(), cdb[0]);
162 cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
163 cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
164 return -EINVAL;
165 }
166
167 return 0;
168}
169EXPORT_SYMBOL(spc_parse_cdb);
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 23657a027666..a8a3d1544e65 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -2658,26 +2658,8 @@ static int transport_generic_cmd_sequencer(
2658 size = (cdb[8] << 8) + cdb[9]; 2658 size = (cdb[8] << 8) + cdb[9];
2659 } 2659 }
2660 break; 2660 break;
2661 case MODE_SELECT:
2662 size = cdb[4];
2663 break;
2664 case MODE_SELECT_10:
2665 size = (cdb[7] << 8) + cdb[8];
2666 break;
2667 case MODE_SENSE:
2668 size = cdb[4];
2669 if (!passthrough)
2670 cmd->execute_cmd = target_emulate_modesense;
2671 break;
2672 case MODE_SENSE_10:
2673 size = (cdb[7] << 8) + cdb[8];
2674 if (!passthrough)
2675 cmd->execute_cmd = target_emulate_modesense;
2676 break;
2677 case GPCMD_READ_BUFFER_CAPACITY: 2661 case GPCMD_READ_BUFFER_CAPACITY:
2678 case GPCMD_SEND_OPC: 2662 case GPCMD_SEND_OPC:
2679 case LOG_SELECT:
2680 case LOG_SENSE:
2681 size = (cdb[7] << 8) + cdb[8]; 2663 size = (cdb[7] << 8) + cdb[8];
2682 break; 2664 break;
2683 case READ_BLOCK_LIMITS: 2665 case READ_BLOCK_LIMITS:
@@ -2689,16 +2671,6 @@ static int transport_generic_cmd_sequencer(
2689 case GPCMD_READ_TRACK_RZONE_INFO: 2671 case GPCMD_READ_TRACK_RZONE_INFO:
2690 size = (cdb[7] << 8) + cdb[8]; 2672 size = (cdb[7] << 8) + cdb[8];
2691 break; 2673 break;
2692 case PERSISTENT_RESERVE_IN:
2693 if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS)
2694 cmd->execute_cmd = target_scsi3_emulate_pr_in;
2695 size = (cdb[7] << 8) + cdb[8];
2696 break;
2697 case PERSISTENT_RESERVE_OUT:
2698 if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS)
2699 cmd->execute_cmd = target_scsi3_emulate_pr_out;
2700 size = (cdb[7] << 8) + cdb[8];
2701 break;
2702 case GPCMD_MECHANISM_STATUS: 2674 case GPCMD_MECHANISM_STATUS:
2703 case GPCMD_READ_DVD_STRUCTURE: 2675 case GPCMD_READ_DVD_STRUCTURE:
2704 size = (cdb[8] << 8) + cdb[9]; 2676 size = (cdb[8] << 8) + cdb[9];
@@ -2725,17 +2697,6 @@ static int transport_generic_cmd_sequencer(
2725 size = (cdb[8] << 8) + cdb[9]; 2697 size = (cdb[8] << 8) + cdb[9];
2726 } 2698 }
2727 break; 2699 break;
2728 case INQUIRY:
2729 size = (cdb[3] << 8) + cdb[4];
2730 /*
2731 * Do implict HEAD_OF_QUEUE processing for INQUIRY.
2732 * See spc4r17 section 5.3
2733 */
2734 if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
2735 cmd->sam_task_attr = MSG_HEAD_TAG;
2736 if (!passthrough)
2737 cmd->execute_cmd = target_emulate_inquiry;
2738 break;
2739 case READ_BUFFER: 2700 case READ_BUFFER:
2740 size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8]; 2701 size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8];
2741 break; 2702 break;
@@ -2745,10 +2706,6 @@ static int transport_generic_cmd_sequencer(
2745 cmd->execute_cmd = target_emulate_readcapacity; 2706 cmd->execute_cmd = target_emulate_readcapacity;
2746 break; 2707 break;
2747 case READ_MEDIA_SERIAL_NUMBER: 2708 case READ_MEDIA_SERIAL_NUMBER:
2748 case SECURITY_PROTOCOL_IN:
2749 case SECURITY_PROTOCOL_OUT:
2750 size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
2751 break;
2752 case SERVICE_ACTION_IN: 2709 case SERVICE_ACTION_IN:
2753 switch (cmd->t_task_cdb[1] & 0x1f) { 2710 switch (cmd->t_task_cdb[1] & 0x1f) {
2754 case SAI_READ_CAPACITY_16: 2711 case SAI_READ_CAPACITY_16:
@@ -2767,17 +2724,9 @@ static int transport_generic_cmd_sequencer(
2767 /*FALLTHROUGH*/ 2724 /*FALLTHROUGH*/
2768 case ACCESS_CONTROL_IN: 2725 case ACCESS_CONTROL_IN:
2769 case ACCESS_CONTROL_OUT: 2726 case ACCESS_CONTROL_OUT:
2770 case EXTENDED_COPY:
2771 case READ_ATTRIBUTE:
2772 case RECEIVE_COPY_RESULTS:
2773 case WRITE_ATTRIBUTE:
2774 size = (cdb[10] << 24) | (cdb[11] << 16) | 2727 size = (cdb[10] << 24) | (cdb[11] << 16) |
2775 (cdb[12] << 8) | cdb[13]; 2728 (cdb[12] << 8) | cdb[13];
2776 break; 2729 break;
2777 case RECEIVE_DIAGNOSTIC:
2778 case SEND_DIAGNOSTIC:
2779 size = (cdb[3] << 8) | cdb[4];
2780 break;
2781/* #warning FIXME: Figure out correct GPCMD_READ_CD blocksize. */ 2730/* #warning FIXME: Figure out correct GPCMD_READ_CD blocksize. */
2782#if 0 2731#if 0
2783 case GPCMD_READ_CD: 2732 case GPCMD_READ_CD:
@@ -2788,52 +2737,9 @@ static int transport_generic_cmd_sequencer(
2788 case READ_TOC: 2737 case READ_TOC:
2789 size = cdb[8]; 2738 size = cdb[8];
2790 break; 2739 break;
2791 case REQUEST_SENSE:
2792 size = cdb[4];
2793 if (!passthrough)
2794 cmd->execute_cmd = target_emulate_request_sense;
2795 break;
2796 case READ_ELEMENT_STATUS: 2740 case READ_ELEMENT_STATUS:
2797 size = 65536 * cdb[7] + 256 * cdb[8] + cdb[9]; 2741 size = 65536 * cdb[7] + 256 * cdb[8] + cdb[9];
2798 break; 2742 break;
2799 case WRITE_BUFFER:
2800 size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8];
2801 break;
2802 case RESERVE:
2803 case RESERVE_10:
2804 /*
2805 * The SPC-2 RESERVE does not contain a size in the SCSI CDB.
2806 * Assume the passthrough or $FABRIC_MOD will tell us about it.
2807 */
2808 if (cdb[0] == RESERVE_10)
2809 size = (cdb[7] << 8) | cdb[8];
2810 else
2811 size = cmd->data_length;
2812
2813 /*
2814 * Setup the legacy emulated handler for SPC-2 and
2815 * >= SPC-3 compatible reservation handling (CRH=1)
2816 * Otherwise, we assume the underlying SCSI logic is
2817 * is running in SPC_PASSTHROUGH, and wants reservations
2818 * emulation disabled.
2819 */
2820 if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH)
2821 cmd->execute_cmd = target_scsi2_reservation_reserve;
2822 break;
2823 case RELEASE:
2824 case RELEASE_10:
2825 /*
2826 * The SPC-2 RELEASE does not contain a size in the SCSI CDB.
2827 * Assume the passthrough or $FABRIC_MOD will tell us about it.
2828 */
2829 if (cdb[0] == RELEASE_10)
2830 size = (cdb[7] << 8) | cdb[8];
2831 else
2832 size = cmd->data_length;
2833
2834 if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH)
2835 cmd->execute_cmd = target_scsi2_reservation_release;
2836 break;
2837 case SYNCHRONIZE_CACHE: 2743 case SYNCHRONIZE_CACHE:
2838 case SYNCHRONIZE_CACHE_16: 2744 case SYNCHRONIZE_CACHE_16:
2839 /* 2745 /*
@@ -2916,7 +2822,6 @@ static int transport_generic_cmd_sequencer(
2916 case SEEK_10: 2822 case SEEK_10:
2917 case SPACE: 2823 case SPACE:
2918 case START_STOP: 2824 case START_STOP:
2919 case TEST_UNIT_READY:
2920 case VERIFY: 2825 case VERIFY:
2921 case WRITE_FILEMARKS: 2826 case WRITE_FILEMARKS:
2922 if (!passthrough) 2827 if (!passthrough)
@@ -2928,16 +2833,6 @@ static int transport_generic_cmd_sequencer(
2928 case GPCMD_SET_SPEED: 2833 case GPCMD_SET_SPEED:
2929 case MOVE_MEDIUM: 2834 case MOVE_MEDIUM:
2930 break; 2835 break;
2931 case REPORT_LUNS:
2932 cmd->execute_cmd = target_report_luns;
2933 size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
2934 /*
2935 * Do implict HEAD_OF_QUEUE processing for REPORT_LUNS
2936 * See spc4r17 section 5.3
2937 */
2938 if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
2939 cmd->sam_task_attr = MSG_HEAD_TAG;
2940 break;
2941 case GET_EVENT_STATUS_NOTIFICATION: 2836 case GET_EVENT_STATUS_NOTIFICATION:
2942 size = (cdb[7] << 8) | cdb[8]; 2837 size = (cdb[7] << 8) | cdb[8];
2943 break; 2838 break;
@@ -2973,10 +2868,9 @@ static int transport_generic_cmd_sequencer(
2973 } 2868 }
2974 break; 2869 break;
2975 default: 2870 default:
2976 pr_warn("TARGET_CORE[%s]: Unsupported SCSI Opcode" 2871 ret = spc_parse_cdb(cmd, &size, passthrough);
2977 " 0x%02x, sending CHECK_CONDITION.\n", 2872 if (ret)
2978 cmd->se_tfo->get_fabric_name(), cdb[0]); 2873 return ret;
2979 goto out_unsupported_cdb;
2980 } 2874 }
2981 2875
2982 ret = target_cmd_size_check(cmd, size); 2876 ret = target_cmd_size_check(cmd, size);