1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #ifndef FTL_IO_H 35 #define FTL_IO_H 36 37 #include "spdk/stdinc.h" 38 #include "spdk/nvme.h" 39 #include "spdk/ftl.h" 40 41 #include "ftl_ppa.h" 42 #include "ftl_trace.h" 43 44 struct spdk_ftl_dev; 45 struct ftl_rwb_batch; 46 struct ftl_band; 47 struct ftl_io; 48 struct ftl_md; 49 50 typedef int (*ftl_md_pack_fn)(struct spdk_ftl_dev *, struct ftl_md *, void *); 51 52 /* IO flags */ 53 enum ftl_io_flags { 54 /* Indicates whether IO is already initialized */ 55 FTL_IO_INITIALIZED = (1 << 0), 56 /* Keep the IO when done with the request */ 57 FTL_IO_KEEP_ALIVE = (1 << 1), 58 /* Internal based IO (defrag, metadata etc.) */ 59 FTL_IO_INTERNAL = (1 << 2), 60 /* Indicates that the IO should not go through if there's */ 61 /* already another one scheduled to the same LBA */ 62 FTL_IO_WEAK = (1 << 3), 63 /* Indicates that the IO is used for padding */ 64 FTL_IO_PAD = (1 << 4), 65 /* The IO operates on metadata */ 66 FTL_IO_MD = (1 << 5), 67 /* Using PPA instead of LBA */ 68 FTL_IO_PPA_MODE = (1 << 6), 69 /* Indicates that IO contains noncontiguous LBAs */ 70 FTL_IO_VECTOR_LBA = (1 << 7), 71 /* Indicates that IO is being retried */ 72 FTL_IO_RETRY = (1 << 8), 73 }; 74 75 enum ftl_io_type { 76 FTL_IO_READ, 77 FTL_IO_WRITE, 78 FTL_IO_ERASE, 79 }; 80 81 struct ftl_io_init_opts { 82 struct spdk_ftl_dev *dev; 83 84 /* IO descriptor */ 85 struct ftl_io *io; 86 87 /* Size of IO descriptor */ 88 size_t size; 89 90 /* IO flags */ 91 int flags; 92 93 /* IO type */ 94 enum ftl_io_type type; 95 96 /* Number of split requests */ 97 size_t iov_cnt; 98 99 /* RWB entry */ 100 struct ftl_rwb_batch *rwb_batch; 101 102 /* Band to which the IO is directed */ 103 struct ftl_band *band; 104 105 /* Request size */ 106 size_t req_size; 107 108 /* Data */ 109 void *data; 110 111 /* Metadata */ 112 void *md; 113 114 /* Callback */ 115 spdk_ftl_fn fn; 116 }; 117 118 struct ftl_cb { 119 /* Callback function */ 120 spdk_ftl_fn fn; 121 122 /* Callback's context */ 123 void *ctx; 124 }; 125 126 struct ftl_io_channel { 127 /* IO pool element size */ 128 size_t elem_size; 129 130 /* IO pool */ 131 struct spdk_mempool *io_pool; 132 }; 133 134 /* General IO descriptor */ 135 struct ftl_io { 136 /* Device */ 137 struct spdk_ftl_dev *dev; 138 139 /* IO channel */ 140 struct spdk_io_channel *ch; 141 142 union { 143 /* LBA table */ 144 uint64_t *lbas; 145 146 /* First LBA */ 147 uint64_t lba; 148 }; 149 150 /* First PPA */ 151 struct ftl_ppa ppa; 152 153 /* Number of processed lbks */ 154 size_t pos; 155 156 /* Number of lbks */ 157 size_t lbk_cnt; 158 159 union { 160 /* IO vector table */ 161 struct iovec *iovs; 162 163 /* Single iovec */ 164 struct iovec iov; 165 }; 166 167 /* Metadata */ 168 void *md; 169 170 /* Number of IO vectors */ 171 size_t iov_cnt; 172 173 /* Position within the iovec */ 174 size_t iov_pos; 175 176 /* Offset within the iovec (in lbks) */ 177 size_t iov_off; 178 179 /* RWB entry (valid only for RWB-based IO) */ 180 struct ftl_rwb_batch *rwb_batch; 181 182 /* Band this IO is being written to */ 183 struct ftl_band *band; 184 185 /* Request status */ 186 int status; 187 188 /* Number of split requests */ 189 size_t req_cnt; 190 191 /* Completion callback */ 192 struct ftl_cb cb; 193 194 /* Flags */ 195 int flags; 196 197 /* IO type */ 198 enum ftl_io_type type; 199 200 /* Trace group id */ 201 uint64_t trace; 202 203 TAILQ_ENTRY(ftl_io) retry_entry; 204 }; 205 206 /* Metadata IO */ 207 struct ftl_md_io { 208 /* Parent IO structure */ 209 struct ftl_io io; 210 211 /* Destination metadata pointer */ 212 struct ftl_md *md; 213 214 /* Metadata's buffer */ 215 void *buf; 216 217 /* Serialization/deserialization callback */ 218 ftl_md_pack_fn pack_fn; 219 220 /* User's callback */ 221 struct ftl_cb cb; 222 }; 223 224 static inline bool 225 ftl_io_mode_ppa(const struct ftl_io *io) 226 { 227 return io->flags & FTL_IO_PPA_MODE; 228 } 229 230 static inline bool 231 ftl_io_mode_lba(const struct ftl_io *io) 232 { 233 return !ftl_io_mode_ppa(io); 234 } 235 236 static inline bool 237 ftl_io_done(const struct ftl_io *io) 238 { 239 return io->req_cnt == 0 && !(io->flags & FTL_IO_RETRY); 240 } 241 242 struct ftl_io *ftl_io_alloc(struct spdk_io_channel *ch); 243 void ftl_io_free(struct ftl_io *io); 244 struct ftl_io *ftl_io_init_internal(const struct ftl_io_init_opts *opts); 245 void ftl_io_reinit(struct ftl_io *io, spdk_ftl_fn cb, 246 void *ctx, int flags, int type); 247 void ftl_io_clear(struct ftl_io *io); 248 void ftl_io_inc_req(struct ftl_io *io); 249 void ftl_io_dec_req(struct ftl_io *io); 250 struct iovec *ftl_io_iovec(struct ftl_io *io); 251 uint64_t ftl_io_current_lba(struct ftl_io *io); 252 void ftl_io_update_iovec(struct ftl_io *io, size_t lbk_cnt); 253 size_t ftl_iovec_num_lbks(struct iovec *iov, size_t iov_cnt); 254 void *ftl_io_iovec_addr(struct ftl_io *io); 255 size_t ftl_io_iovec_len_left(struct ftl_io *io); 256 int ftl_io_init_iovec(struct ftl_io *io, void *buf, 257 size_t iov_cnt, size_t req_size); 258 struct ftl_io *ftl_io_init_internal(const struct ftl_io_init_opts *opts); 259 struct ftl_io *ftl_io_rwb_init(struct spdk_ftl_dev *dev, struct ftl_band *band, 260 struct ftl_rwb_batch *entry, spdk_ftl_fn cb); 261 struct ftl_io *ftl_io_erase_init(struct ftl_band *band, size_t lbk_cnt, spdk_ftl_fn cb); 262 void ftl_io_user_init(struct spdk_ftl_dev *dev, struct ftl_io *io, uint64_t lba, size_t lbk_cnt, 263 struct iovec *iov, size_t iov_cnt, 264 spdk_ftl_fn fn, void *cb_arg, int type); 265 void *ftl_io_get_md(const struct ftl_io *io); 266 void ftl_io_complete(struct ftl_io *io); 267 void ftl_io_process_error(struct ftl_io *io, const struct spdk_nvme_cpl *status); 268 269 #endif /* FTL_IO_H */ 270