1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>. 5 * Copyright (c) Intel Corporation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * * Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * * Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * * Neither the name of Intel Corporation nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include "scsi_internal.h" 36 #include "spdk/endian.h" 37 #include "spdk/env.h" 38 #include "spdk/io_channel.h" 39 #include "spdk/event.h" 40 #include "spdk/util.h" 41 42 void 43 spdk_scsi_lun_complete_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task) 44 { 45 if (lun) { 46 if (task->type == SPDK_SCSI_TASK_TYPE_CMD) { 47 TAILQ_REMOVE(&lun->tasks, task, scsi_link); 48 } 49 spdk_trace_record(TRACE_SCSI_TASK_DONE, lun->dev->id, 0, (uintptr_t)task, 0); 50 } 51 spdk_event_call(task->cb_event); 52 } 53 54 void 55 spdk_scsi_lun_clear_all(struct spdk_scsi_lun *lun) 56 { 57 struct spdk_scsi_task *task, *task_tmp; 58 59 /* 60 * This function is called from one location, after the backend LUN 61 * device was reset. Can assume are no active tasks in the 62 * backend that need to be terminated. Just need to queue all tasks 63 * back to frontend for any final processing and cleanup. 64 * 65 * Queue the tasks back roughly in the order they were received 66 * ('cleanup' = oldest, 'tasks' = current, and 'pending' = newest) 67 */ 68 69 TAILQ_FOREACH_SAFE(task, &lun->tasks, scsi_link, task_tmp) { 70 spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION, 71 SPDK_SCSI_SENSE_ABORTED_COMMAND, 72 SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE, 73 SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE); 74 spdk_scsi_lun_complete_task(lun, task); 75 } 76 77 TAILQ_FOREACH_SAFE(task, &lun->pending_tasks, scsi_link, task_tmp) { 78 TAILQ_REMOVE(&lun->pending_tasks, task, scsi_link); 79 TAILQ_INSERT_TAIL(&lun->tasks, task, scsi_link); 80 spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION, 81 SPDK_SCSI_SENSE_ABORTED_COMMAND, 82 SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE, 83 SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE); 84 spdk_scsi_lun_complete_task(lun, task); 85 } 86 } 87 88 static int 89 spdk_scsi_lun_abort_all(struct spdk_scsi_task *mtask, 90 struct spdk_scsi_lun *lun, 91 struct spdk_scsi_port *initiator_port) 92 { 93 if (!lun) { 94 mtask->response = SPDK_SCSI_TASK_MGMT_RESP_INVALID_LUN; 95 return -1; 96 } 97 98 mtask->response = SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED; 99 return -1; 100 } 101 102 static int 103 spdk_scsi_lun_abort_task(struct spdk_scsi_task *mtask, 104 struct spdk_scsi_lun *lun, 105 struct spdk_scsi_port *initiator_port, 106 uint32_t task_tag) 107 { 108 if (!lun) { 109 /* LUN does not exist */ 110 mtask->response = SPDK_SCSI_TASK_MGMT_RESP_INVALID_LUN; 111 return -1; 112 } 113 114 mtask->response = SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED; 115 return -1; 116 } 117 118 static int 119 spdk_scsi_lun_reset(struct spdk_scsi_task *mtask, struct spdk_scsi_lun *lun) 120 { 121 if (!lun) { 122 /* LUN does not exist */ 123 mtask->response = SPDK_SCSI_TASK_MGMT_RESP_INVALID_LUN; 124 spdk_scsi_lun_complete_task(NULL, mtask); 125 return -1; 126 } 127 128 spdk_bdev_scsi_reset(lun->bdev, mtask); 129 return 0; 130 } 131 132 int 133 spdk_scsi_lun_task_mgmt_execute(struct spdk_scsi_task *task) 134 { 135 int rc; 136 137 if (!task) { 138 return -1; 139 } 140 141 switch (task->function) { 142 case SPDK_SCSI_TASK_FUNC_ABORT_TASK: 143 rc = spdk_scsi_lun_abort_task(task, task->lun, 144 task->initiator_port, 145 task->abort_id); 146 if (rc < 0) { 147 SPDK_ERRLOG("ABORT_TASK failed\n"); 148 } 149 150 break; 151 152 case SPDK_SCSI_TASK_FUNC_ABORT_TASK_SET: 153 rc = spdk_scsi_lun_abort_all(task, task->lun, 154 task->initiator_port); 155 if (rc < 0) { 156 SPDK_ERRLOG("ABORT_TASK_SET failed\n"); 157 } 158 159 break; 160 161 case SPDK_SCSI_TASK_FUNC_LUN_RESET: 162 rc = spdk_scsi_lun_reset(task, task->lun); 163 if (rc < 0) { 164 SPDK_ERRLOG("LUN_RESET failed\n"); 165 } 166 return rc; 167 168 default: 169 SPDK_ERRLOG("Unknown Task Management Function!\n"); 170 /* 171 * Task management functions other than those above should never 172 * reach this point having been filtered by the frontend. Reject 173 * the task as being unsupported. 174 */ 175 task->response = SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED; 176 rc = -1; 177 break; 178 } 179 180 spdk_scsi_lun_complete_task(task->lun, task); 181 182 return rc; 183 } 184 185 void 186 spdk_scsi_task_process_null_lun(struct spdk_scsi_task *task) 187 { 188 uint8_t buffer[36]; 189 uint32_t allocation_len; 190 uint32_t data_len; 191 192 task->length = task->transfer_len; 193 if (task->cdb[0] == SPDK_SPC_INQUIRY) { 194 /* 195 * SPC-4 states that INQUIRY commands to an unsupported LUN 196 * must be served with PERIPHERAL QUALIFIER = 0x3 and 197 * PERIPHERAL DEVICE TYPE = 0x1F. 198 */ 199 data_len = sizeof(buffer); 200 201 memset(buffer, 0, data_len); 202 /* PERIPHERAL QUALIFIER(7-5) PERIPHERAL DEVICE TYPE(4-0) */ 203 buffer[0] = 0x03 << 5 | 0x1f; 204 /* ADDITIONAL LENGTH */ 205 buffer[4] = data_len - 5; 206 207 allocation_len = from_be16(&task->cdb[3]); 208 if (spdk_scsi_task_scatter_data(task, buffer, spdk_min(allocation_len, data_len)) >= 0) { 209 task->data_transferred = data_len; 210 task->status = SPDK_SCSI_STATUS_GOOD; 211 } 212 } else { 213 /* LOGICAL UNIT NOT SUPPORTED */ 214 spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION, 215 SPDK_SCSI_SENSE_ILLEGAL_REQUEST, 216 SPDK_SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED, 217 SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE); 218 task->data_transferred = 0; 219 } 220 } 221 222 int 223 spdk_scsi_lun_append_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task) 224 { 225 TAILQ_INSERT_TAIL(&lun->pending_tasks, task, scsi_link); 226 return 0; 227 } 228 229 void 230 spdk_scsi_lun_execute_tasks(struct spdk_scsi_lun *lun) 231 { 232 struct spdk_scsi_task *task, *task_tmp; 233 int rc; 234 235 TAILQ_FOREACH_SAFE(task, &lun->pending_tasks, scsi_link, task_tmp) { 236 task->status = SPDK_SCSI_STATUS_GOOD; 237 task->ch = lun->io_channel; 238 spdk_trace_record(TRACE_SCSI_TASK_START, lun->dev->id, task->length, (uintptr_t)task, 0); 239 TAILQ_REMOVE(&lun->pending_tasks, task, scsi_link); 240 TAILQ_INSERT_TAIL(&lun->tasks, task, scsi_link); 241 if (!lun->removed) { 242 rc = spdk_bdev_scsi_execute(lun->bdev, task); 243 } else { 244 spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION, 245 SPDK_SCSI_SENSE_ABORTED_COMMAND, 246 SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE, 247 SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE); 248 rc = SPDK_SCSI_TASK_COMPLETE; 249 } 250 251 switch (rc) { 252 case SPDK_SCSI_TASK_PENDING: 253 break; 254 255 case SPDK_SCSI_TASK_COMPLETE: 256 spdk_scsi_lun_complete_task(lun, task); 257 break; 258 259 default: 260 abort(); 261 } 262 } 263 } 264 265 static void 266 spdk_scsi_lun_hotplug(void *arg) 267 { 268 struct spdk_scsi_lun *lun = (struct spdk_scsi_lun *)arg; 269 270 if (TAILQ_EMPTY(&lun->pending_tasks) && TAILQ_EMPTY(&lun->tasks)) { 271 spdk_scsi_lun_free_io_channel(lun); 272 spdk_scsi_lun_delete(lun->name); 273 } 274 } 275 276 static void spdk_scsi_lun_hot_remove(void *remove_ctx) 277 { 278 struct spdk_scsi_lun *lun = (struct spdk_scsi_lun *)remove_ctx; 279 280 lun->removed = true; 281 spdk_poller_register(&lun->hotplug_poller, spdk_scsi_lun_hotplug, lun, 282 lun->lcore, 0); 283 } 284 285 /** 286 * \brief Constructs a new spdk_scsi_lun object based on the provided parameters. 287 * 288 * \param name Name for the SCSI LUN. 289 * \param blockdev Blockdev associated with this LUN 290 * 291 * \return NULL if blockdev == NULL 292 * \return pointer to the new spdk_scsi_lun object otherwise 293 */ 294 _spdk_scsi_lun * 295 spdk_scsi_lun_construct(const char *name, struct spdk_bdev *bdev) 296 { 297 struct spdk_scsi_lun *lun; 298 int rc; 299 300 if (bdev == NULL) { 301 SPDK_ERRLOG("blockdev must be non-NULL\n"); 302 return NULL; 303 } 304 305 lun = spdk_lun_db_get_lun(name); 306 if (lun) { 307 SPDK_ERRLOG("LUN %s already created\n", lun->name); 308 return NULL; 309 } 310 311 lun = calloc(1, sizeof(*lun)); 312 if (lun == NULL) { 313 SPDK_ERRLOG("could not allocate lun\n"); 314 return NULL; 315 } 316 317 if (!spdk_bdev_claim(bdev, spdk_scsi_lun_hot_remove, lun)) { 318 SPDK_ERRLOG("LUN %s: bdev %s is already claimed\n", name, bdev->name); 319 free(lun); 320 return NULL; 321 } 322 323 TAILQ_INIT(&lun->tasks); 324 TAILQ_INIT(&lun->pending_tasks); 325 326 lun->bdev = bdev; 327 snprintf(lun->name, sizeof(lun->name), "%s", name); 328 329 rc = spdk_scsi_lun_db_add(lun); 330 if (rc < 0) { 331 SPDK_ERRLOG("Unable to add LUN %s to DB\n", lun->name); 332 spdk_bdev_unclaim(bdev); 333 free(lun); 334 return NULL; 335 } 336 337 return lun; 338 } 339 340 int 341 spdk_scsi_lun_destruct(struct spdk_scsi_lun *lun) 342 { 343 spdk_bdev_unclaim(lun->bdev); 344 spdk_poller_unregister(&lun->hotplug_poller, NULL); 345 spdk_scsi_lun_db_delete(lun); 346 347 free(lun); 348 349 return 0; 350 } 351 352 int 353 spdk_scsi_lun_claim(struct spdk_scsi_lun *lun) 354 { 355 assert(spdk_lun_db_get_lun(lun->name) != NULL); 356 357 if (lun->claimed != false) { 358 return -1; 359 } 360 361 lun->claimed = true; 362 return 0; 363 } 364 365 int 366 spdk_scsi_lun_unclaim(struct spdk_scsi_lun *lun) 367 { 368 assert(spdk_lun_db_get_lun(lun->name) != NULL); 369 assert(lun->claimed == true); 370 lun->claimed = false; 371 lun->dev = NULL; 372 373 return 0; 374 } 375 376 int 377 spdk_scsi_lun_delete(const char *lun_name) 378 { 379 struct spdk_scsi_lun *lun; 380 struct spdk_scsi_dev *dev; 381 382 pthread_mutex_lock(&g_spdk_scsi.mutex); 383 lun = spdk_lun_db_get_lun(lun_name); 384 if (lun == NULL) { 385 SPDK_ERRLOG("LUN '%s' not found", lun_name); 386 pthread_mutex_unlock(&g_spdk_scsi.mutex); 387 return -1; 388 } 389 390 dev = lun->dev; 391 392 /* Remove the LUN from the device */ 393 if (dev != NULL) { 394 spdk_scsi_dev_delete_lun(dev, lun); 395 } 396 397 /* Destroy this lun */ 398 spdk_scsi_lun_destruct(lun); 399 pthread_mutex_unlock(&g_spdk_scsi.mutex); 400 return 0; 401 } 402 403 int spdk_scsi_lun_allocate_io_channel(struct spdk_scsi_lun *lun) 404 { 405 if (lun->io_channel != NULL) { 406 if (pthread_self() == lun->thread_id) { 407 lun->ref++; 408 return 0; 409 } 410 SPDK_ERRLOG("io_channel already allocated for lun %s\n", lun->name); 411 return -1; 412 } 413 414 lun->lcore = spdk_env_get_current_core(); 415 416 lun->io_channel = spdk_bdev_get_io_channel(lun->bdev, SPDK_IO_PRIORITY_DEFAULT); 417 if (lun->io_channel == NULL) { 418 return -1; 419 } 420 lun->thread_id = pthread_self(); 421 lun->ref = 1; 422 return 0; 423 } 424 425 void spdk_scsi_lun_free_io_channel(struct spdk_scsi_lun *lun) 426 { 427 if (lun->io_channel != NULL) { 428 lun->ref--; 429 if (lun->ref == 0) { 430 spdk_put_io_channel(lun->io_channel); 431 lun->io_channel = NULL; 432 } 433 } 434 } 435 436 int 437 spdk_scsi_lun_get_id(const struct spdk_scsi_lun *lun) 438 { 439 return lun->id; 440 } 441 442 const char * 443 spdk_scsi_lun_get_name(const struct spdk_scsi_lun *lun) 444 { 445 return lun->name; 446 } 447