target_core_ua.c revision de103c93aff0bed0ae984274e5dc8b95899badab
1/******************************************************************************* 2 * Filename: target_core_ua.c 3 * 4 * This file contains logic for SPC-3 Unit Attention emulation 5 * 6 * Copyright (c) 2009,2010 Rising Tide Systems 7 * Copyright (c) 2009,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 27#include <linux/slab.h> 28#include <linux/spinlock.h> 29#include <scsi/scsi.h> 30#include <scsi/scsi_cmnd.h> 31 32#include <target/target_core_base.h> 33#include <target/target_core_fabric.h> 34#include <target/target_core_configfs.h> 35 36#include "target_core_internal.h" 37#include "target_core_alua.h" 38#include "target_core_pr.h" 39#include "target_core_ua.h" 40 41sense_reason_t 42target_scsi3_ua_check(struct se_cmd *cmd) 43{ 44 struct se_dev_entry *deve; 45 struct se_session *sess = cmd->se_sess; 46 struct se_node_acl *nacl; 47 48 if (!sess) 49 return 0; 50 51 nacl = sess->se_node_acl; 52 if (!nacl) 53 return 0; 54 55 deve = nacl->device_list[cmd->orig_fe_lun]; 56 if (!atomic_read(&deve->ua_count)) 57 return 0; 58 /* 59 * From sam4r14, section 5.14 Unit attention condition: 60 * 61 * a) if an INQUIRY command enters the enabled command state, the 62 * device server shall process the INQUIRY command and shall neither 63 * report nor clear any unit attention condition; 64 * b) if a REPORT LUNS command enters the enabled command state, the 65 * device server shall process the REPORT LUNS command and shall not 66 * report any unit attention condition; 67 * e) if a REQUEST SENSE command enters the enabled command state while 68 * a unit attention condition exists for the SCSI initiator port 69 * associated with the I_T nexus on which the REQUEST SENSE command 70 * was received, then the device server shall process the command 71 * and either: 72 */ 73 switch (cmd->t_task_cdb[0]) { 74 case INQUIRY: 75 case REPORT_LUNS: 76 case REQUEST_SENSE: 77 return 0; 78 default: 79 return TCM_CHECK_CONDITION_UNIT_ATTENTION; 80 } 81} 82 83int core_scsi3_ua_allocate( 84 struct se_node_acl *nacl, 85 u32 unpacked_lun, 86 u8 asc, 87 u8 ascq) 88{ 89 struct se_dev_entry *deve; 90 struct se_ua *ua, *ua_p, *ua_tmp; 91 /* 92 * PASSTHROUGH OPS 93 */ 94 if (!nacl) 95 return -EINVAL; 96 97 ua = kmem_cache_zalloc(se_ua_cache, GFP_ATOMIC); 98 if (!ua) { 99 pr_err("Unable to allocate struct se_ua\n"); 100 return -ENOMEM; 101 } 102 INIT_LIST_HEAD(&ua->ua_dev_list); 103 INIT_LIST_HEAD(&ua->ua_nacl_list); 104 105 ua->ua_nacl = nacl; 106 ua->ua_asc = asc; 107 ua->ua_ascq = ascq; 108 109 spin_lock_irq(&nacl->device_list_lock); 110 deve = nacl->device_list[unpacked_lun]; 111 112 spin_lock(&deve->ua_lock); 113 list_for_each_entry_safe(ua_p, ua_tmp, &deve->ua_list, ua_nacl_list) { 114 /* 115 * Do not report the same UNIT ATTENTION twice.. 116 */ 117 if ((ua_p->ua_asc == asc) && (ua_p->ua_ascq == ascq)) { 118 spin_unlock(&deve->ua_lock); 119 spin_unlock_irq(&nacl->device_list_lock); 120 kmem_cache_free(se_ua_cache, ua); 121 return 0; 122 } 123 /* 124 * Attach the highest priority Unit Attention to 125 * the head of the list following sam4r14, 126 * Section 5.14 Unit Attention Condition: 127 * 128 * POWER ON, RESET, OR BUS DEVICE RESET OCCURRED highest 129 * POWER ON OCCURRED or 130 * DEVICE INTERNAL RESET 131 * SCSI BUS RESET OCCURRED or 132 * MICROCODE HAS BEEN CHANGED or 133 * protocol specific 134 * BUS DEVICE RESET FUNCTION OCCURRED 135 * I_T NEXUS LOSS OCCURRED 136 * COMMANDS CLEARED BY POWER LOSS NOTIFICATION 137 * all others Lowest 138 * 139 * Each of the ASCQ codes listed above are defined in 140 * the 29h ASC family, see spc4r17 Table D.1 141 */ 142 if (ua_p->ua_asc == 0x29) { 143 if ((asc == 0x29) && (ascq > ua_p->ua_ascq)) 144 list_add(&ua->ua_nacl_list, 145 &deve->ua_list); 146 else 147 list_add_tail(&ua->ua_nacl_list, 148 &deve->ua_list); 149 } else if (ua_p->ua_asc == 0x2a) { 150 /* 151 * Incoming Family 29h ASCQ codes will override 152 * Family 2AHh ASCQ codes for Unit Attention condition. 153 */ 154 if ((asc == 0x29) || (ascq > ua_p->ua_asc)) 155 list_add(&ua->ua_nacl_list, 156 &deve->ua_list); 157 else 158 list_add_tail(&ua->ua_nacl_list, 159 &deve->ua_list); 160 } else 161 list_add_tail(&ua->ua_nacl_list, 162 &deve->ua_list); 163 spin_unlock(&deve->ua_lock); 164 spin_unlock_irq(&nacl->device_list_lock); 165 166 atomic_inc(&deve->ua_count); 167 smp_mb__after_atomic_inc(); 168 return 0; 169 } 170 list_add_tail(&ua->ua_nacl_list, &deve->ua_list); 171 spin_unlock(&deve->ua_lock); 172 spin_unlock_irq(&nacl->device_list_lock); 173 174 pr_debug("[%s]: Allocated UNIT ATTENTION, mapped LUN: %u, ASC:" 175 " 0x%02x, ASCQ: 0x%02x\n", 176 nacl->se_tpg->se_tpg_tfo->get_fabric_name(), unpacked_lun, 177 asc, ascq); 178 179 atomic_inc(&deve->ua_count); 180 smp_mb__after_atomic_inc(); 181 return 0; 182} 183 184void core_scsi3_ua_release_all( 185 struct se_dev_entry *deve) 186{ 187 struct se_ua *ua, *ua_p; 188 189 spin_lock(&deve->ua_lock); 190 list_for_each_entry_safe(ua, ua_p, &deve->ua_list, ua_nacl_list) { 191 list_del(&ua->ua_nacl_list); 192 kmem_cache_free(se_ua_cache, ua); 193 194 atomic_dec(&deve->ua_count); 195 smp_mb__after_atomic_dec(); 196 } 197 spin_unlock(&deve->ua_lock); 198} 199 200void core_scsi3_ua_for_check_condition( 201 struct se_cmd *cmd, 202 u8 *asc, 203 u8 *ascq) 204{ 205 struct se_device *dev = cmd->se_dev; 206 struct se_dev_entry *deve; 207 struct se_session *sess = cmd->se_sess; 208 struct se_node_acl *nacl; 209 struct se_ua *ua = NULL, *ua_p; 210 int head = 1; 211 212 if (!sess) 213 return; 214 215 nacl = sess->se_node_acl; 216 if (!nacl) 217 return; 218 219 spin_lock_irq(&nacl->device_list_lock); 220 deve = nacl->device_list[cmd->orig_fe_lun]; 221 if (!atomic_read(&deve->ua_count)) { 222 spin_unlock_irq(&nacl->device_list_lock); 223 return; 224 } 225 /* 226 * The highest priority Unit Attentions are placed at the head of the 227 * struct se_dev_entry->ua_list, and will be returned in CHECK_CONDITION + 228 * sense data for the received CDB. 229 */ 230 spin_lock(&deve->ua_lock); 231 list_for_each_entry_safe(ua, ua_p, &deve->ua_list, ua_nacl_list) { 232 /* 233 * For ua_intlck_ctrl code not equal to 00b, only report the 234 * highest priority UNIT_ATTENTION and ASC/ASCQ without 235 * clearing it. 236 */ 237 if (dev->dev_attrib.emulate_ua_intlck_ctrl != 0) { 238 *asc = ua->ua_asc; 239 *ascq = ua->ua_ascq; 240 break; 241 } 242 /* 243 * Otherwise for the default 00b, release the UNIT ATTENTION 244 * condition. Return the ASC/ASCQ of the highest priority UA 245 * (head of the list) in the outgoing CHECK_CONDITION + sense. 246 */ 247 if (head) { 248 *asc = ua->ua_asc; 249 *ascq = ua->ua_ascq; 250 head = 0; 251 } 252 list_del(&ua->ua_nacl_list); 253 kmem_cache_free(se_ua_cache, ua); 254 255 atomic_dec(&deve->ua_count); 256 smp_mb__after_atomic_dec(); 257 } 258 spin_unlock(&deve->ua_lock); 259 spin_unlock_irq(&nacl->device_list_lock); 260 261 pr_debug("[%s]: %s UNIT ATTENTION condition with" 262 " INTLCK_CTRL: %d, mapped LUN: %u, got CDB: 0x%02x" 263 " reported ASC: 0x%02x, ASCQ: 0x%02x\n", 264 nacl->se_tpg->se_tpg_tfo->get_fabric_name(), 265 (dev->dev_attrib.emulate_ua_intlck_ctrl != 0) ? "Reporting" : 266 "Releasing", dev->dev_attrib.emulate_ua_intlck_ctrl, 267 cmd->orig_fe_lun, cmd->t_task_cdb[0], *asc, *ascq); 268} 269 270int core_scsi3_ua_clear_for_request_sense( 271 struct se_cmd *cmd, 272 u8 *asc, 273 u8 *ascq) 274{ 275 struct se_dev_entry *deve; 276 struct se_session *sess = cmd->se_sess; 277 struct se_node_acl *nacl; 278 struct se_ua *ua = NULL, *ua_p; 279 int head = 1; 280 281 if (!sess) 282 return -EINVAL; 283 284 nacl = sess->se_node_acl; 285 if (!nacl) 286 return -EINVAL; 287 288 spin_lock_irq(&nacl->device_list_lock); 289 deve = nacl->device_list[cmd->orig_fe_lun]; 290 if (!atomic_read(&deve->ua_count)) { 291 spin_unlock_irq(&nacl->device_list_lock); 292 return -EPERM; 293 } 294 /* 295 * The highest priority Unit Attentions are placed at the head of the 296 * struct se_dev_entry->ua_list. The First (and hence highest priority) 297 * ASC/ASCQ will be returned in REQUEST_SENSE payload data for the 298 * matching struct se_lun. 299 * 300 * Once the returning ASC/ASCQ values are set, we go ahead and 301 * release all of the Unit Attention conditions for the associated 302 * struct se_lun. 303 */ 304 spin_lock(&deve->ua_lock); 305 list_for_each_entry_safe(ua, ua_p, &deve->ua_list, ua_nacl_list) { 306 if (head) { 307 *asc = ua->ua_asc; 308 *ascq = ua->ua_ascq; 309 head = 0; 310 } 311 list_del(&ua->ua_nacl_list); 312 kmem_cache_free(se_ua_cache, ua); 313 314 atomic_dec(&deve->ua_count); 315 smp_mb__after_atomic_dec(); 316 } 317 spin_unlock(&deve->ua_lock); 318 spin_unlock_irq(&nacl->device_list_lock); 319 320 pr_debug("[%s]: Released UNIT ATTENTION condition, mapped" 321 " LUN: %u, got REQUEST_SENSE reported ASC: 0x%02x," 322 " ASCQ: 0x%02x\n", nacl->se_tpg->se_tpg_tfo->get_fabric_name(), 323 cmd->orig_fe_lun, *asc, *ascq); 324 325 return (head) ? -EPERM : 0; 326} 327