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 #ifndef SPDK_SCSI_INTERNAL_H 36 #define SPDK_SCSI_INTERNAL_H 37 38 #include "spdk/stdinc.h" 39 40 #include "spdk/bdev.h" 41 #include "spdk/scsi.h" 42 #include "spdk/scsi_spec.h" 43 #include "spdk/trace.h" 44 #include "spdk/dif.h" 45 46 #include "spdk/log.h" 47 48 #define SPDK_SCSI_DEV_MAX_LUN 256 49 50 enum { 51 SPDK_SCSI_TASK_UNKNOWN = -1, 52 SPDK_SCSI_TASK_COMPLETE, 53 SPDK_SCSI_TASK_PENDING, 54 }; 55 56 struct spdk_scsi_port { 57 uint8_t is_used; 58 uint64_t id; 59 uint16_t index; 60 uint16_t transport_id_len; 61 char transport_id[SPDK_SCSI_MAX_TRANSPORT_ID_LENGTH]; 62 char name[SPDK_SCSI_PORT_MAX_NAME_LENGTH]; 63 }; 64 65 /* Registrant with I_T nextus */ 66 struct spdk_scsi_pr_registrant { 67 uint64_t rkey; 68 uint16_t relative_target_port_id; 69 uint16_t transport_id_len; 70 char transport_id[SPDK_SCSI_MAX_TRANSPORT_ID_LENGTH]; 71 char initiator_port_name[SPDK_SCSI_PORT_MAX_NAME_LENGTH]; 72 char target_port_name[SPDK_SCSI_PORT_MAX_NAME_LENGTH]; 73 struct spdk_scsi_port *initiator_port; 74 struct spdk_scsi_port *target_port; 75 TAILQ_ENTRY(spdk_scsi_pr_registrant) link; 76 }; 77 78 #define SCSI_SPC2_RESERVE 0x00000001U 79 80 /* Reservation with LU_SCOPE */ 81 struct spdk_scsi_pr_reservation { 82 uint32_t flags; 83 struct spdk_scsi_pr_registrant *holder; 84 enum spdk_scsi_pr_type_code rtype; 85 uint64_t crkey; 86 }; 87 88 struct spdk_scsi_dev { 89 int id; 90 int is_allocated; 91 bool removed; 92 spdk_scsi_dev_destruct_cb_t remove_cb; 93 void *remove_ctx; 94 95 char name[SPDK_SCSI_DEV_MAX_NAME + 1]; 96 97 TAILQ_HEAD(, spdk_scsi_lun) luns; 98 99 int num_ports; 100 struct spdk_scsi_port port[SPDK_SCSI_DEV_MAX_PORTS]; 101 102 uint8_t protocol_id; 103 }; 104 105 struct spdk_scsi_lun_desc { 106 struct spdk_scsi_lun *lun; 107 spdk_scsi_lun_remove_cb_t hotremove_cb; 108 void *hotremove_ctx; 109 TAILQ_ENTRY(spdk_scsi_lun_desc) link; 110 }; 111 112 struct spdk_scsi_lun { 113 /** LUN id for this logical unit. */ 114 int id; 115 116 /** Pointer to the SCSI device containing this LUN. */ 117 struct spdk_scsi_dev *dev; 118 119 /** The bdev associated with this LUN. */ 120 struct spdk_bdev *bdev; 121 122 /** Descriptor for opened block device. */ 123 struct spdk_bdev_desc *bdev_desc; 124 125 /** The thread which opens this LUN. */ 126 struct spdk_thread *thread; 127 128 /** I/O channel for the bdev associated with this LUN. */ 129 struct spdk_io_channel *io_channel; 130 131 /** The reference number for this LUN, thus we can correctly free the io_channel */ 132 uint32_t ref; 133 134 /** Poller to release the resource of the lun when it is hot removed */ 135 struct spdk_poller *hotremove_poller; 136 137 /** The LUN is removed */ 138 bool removed; 139 140 /** Callback to be fired when LUN removal is first triggered. */ 141 void (*hotremove_cb)(const struct spdk_scsi_lun *lun, void *arg); 142 143 /** Argument for hotremove_cb */ 144 void *hotremove_ctx; 145 146 /** Callback to be fired when the bdev size of related LUN has changed. */ 147 void (*resize_cb)(const struct spdk_scsi_lun *, void *); 148 149 /** Argument for resize_cb */ 150 void *resize_ctx; 151 152 /** Registrant head for I_T nexus */ 153 TAILQ_HEAD(, spdk_scsi_pr_registrant) reg_head; 154 /** Persistent Reservation Generation */ 155 uint32_t pr_generation; 156 /** Reservation for the LUN */ 157 struct spdk_scsi_pr_reservation reservation; 158 /** Reservation holder for SPC2 RESERVE(6) and RESERVE(10) */ 159 struct spdk_scsi_pr_registrant scsi2_holder; 160 161 /** List of open descriptors for this LUN. */ 162 TAILQ_HEAD(, spdk_scsi_lun_desc) open_descs; 163 164 /** submitted tasks */ 165 TAILQ_HEAD(tasks, spdk_scsi_task) tasks; 166 167 /** pending tasks */ 168 TAILQ_HEAD(pending_tasks, spdk_scsi_task) pending_tasks; 169 170 /** submitted management tasks */ 171 TAILQ_HEAD(mgmt_tasks, spdk_scsi_task) mgmt_tasks; 172 173 /** pending management tasks */ 174 TAILQ_HEAD(pending_mgmt_tasks, spdk_scsi_task) pending_mgmt_tasks; 175 176 /** poller to check completion of tasks prior to reset */ 177 struct spdk_poller *reset_poller; 178 179 /** A structure to connect LUNs in a list. */ 180 TAILQ_ENTRY(spdk_scsi_lun) tailq; 181 }; 182 183 struct spdk_scsi_lun *scsi_lun_construct(const char *bdev_name, 184 void (*resize_cb)(const struct spdk_scsi_lun *, void *), 185 void *resize_ctx, 186 void (*hotremove_cb)(const struct spdk_scsi_lun *, void *), 187 void *hotremove_ctx); 188 void scsi_lun_destruct(struct spdk_scsi_lun *lun); 189 190 void scsi_lun_execute_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task); 191 void scsi_lun_execute_mgmt_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task); 192 bool scsi_lun_has_pending_mgmt_tasks(const struct spdk_scsi_lun *lun, 193 const struct spdk_scsi_port *initiator_port); 194 void scsi_lun_complete_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task); 195 void scsi_lun_complete_reset_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task); 196 bool scsi_lun_has_pending_tasks(const struct spdk_scsi_lun *lun, 197 const struct spdk_scsi_port *initiator_port); 198 int scsi_lun_allocate_io_channel(struct spdk_scsi_lun *lun); 199 void scsi_lun_free_io_channel(struct spdk_scsi_lun *lun); 200 201 struct spdk_scsi_dev *scsi_dev_get_list(void); 202 203 int scsi_port_construct(struct spdk_scsi_port *port, uint64_t id, 204 uint16_t index, const char *name); 205 void scsi_port_destruct(struct spdk_scsi_port *port); 206 207 int bdev_scsi_execute(struct spdk_scsi_task *task); 208 void bdev_scsi_reset(struct spdk_scsi_task *task); 209 210 bool bdev_scsi_get_dif_ctx(struct spdk_bdev *bdev, struct spdk_scsi_task *task, 211 struct spdk_dif_ctx *dif_ctx); 212 213 int scsi_pr_out(struct spdk_scsi_task *task, uint8_t *cdb, uint8_t *data, uint16_t data_len); 214 int scsi_pr_in(struct spdk_scsi_task *task, uint8_t *cdb, uint8_t *data, uint16_t data_len); 215 int scsi_pr_check(struct spdk_scsi_task *task); 216 217 int scsi2_reserve(struct spdk_scsi_task *task, uint8_t *cdb); 218 int scsi2_release(struct spdk_scsi_task *task); 219 int scsi2_reserve_check(struct spdk_scsi_task *task); 220 221 #endif /* SPDK_SCSI_INTERNAL_H */ 222