io-cmd-file.c (9678B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * NVMe Over Fabrics Target File I/O commands implementation. 4 * Copyright (c) 2017-2018 Western Digital Corporation or its 5 * affiliates. 6 */ 7#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 8#include <linux/uio.h> 9#include <linux/falloc.h> 10#include <linux/file.h> 11#include <linux/fs.h> 12#include "nvmet.h" 13 14#define NVMET_MAX_MPOOL_BVEC 16 15#define NVMET_MIN_MPOOL_OBJ 16 16 17void nvmet_file_ns_revalidate(struct nvmet_ns *ns) 18{ 19 ns->size = i_size_read(ns->file->f_mapping->host); 20} 21 22void nvmet_file_ns_disable(struct nvmet_ns *ns) 23{ 24 if (ns->file) { 25 if (ns->buffered_io) 26 flush_workqueue(buffered_io_wq); 27 mempool_destroy(ns->bvec_pool); 28 ns->bvec_pool = NULL; 29 kmem_cache_destroy(ns->bvec_cache); 30 ns->bvec_cache = NULL; 31 fput(ns->file); 32 ns->file = NULL; 33 } 34} 35 36int nvmet_file_ns_enable(struct nvmet_ns *ns) 37{ 38 int flags = O_RDWR | O_LARGEFILE; 39 int ret = 0; 40 41 if (!ns->buffered_io) 42 flags |= O_DIRECT; 43 44 ns->file = filp_open(ns->device_path, flags, 0); 45 if (IS_ERR(ns->file)) { 46 ret = PTR_ERR(ns->file); 47 pr_err("failed to open file %s: (%d)\n", 48 ns->device_path, ret); 49 ns->file = NULL; 50 return ret; 51 } 52 53 nvmet_file_ns_revalidate(ns); 54 55 /* 56 * i_blkbits can be greater than the universally accepted upper bound, 57 * so make sure we export a sane namespace lba_shift. 58 */ 59 ns->blksize_shift = min_t(u8, 60 file_inode(ns->file)->i_blkbits, 12); 61 62 ns->bvec_cache = kmem_cache_create("nvmet-bvec", 63 NVMET_MAX_MPOOL_BVEC * sizeof(struct bio_vec), 64 0, SLAB_HWCACHE_ALIGN, NULL); 65 if (!ns->bvec_cache) { 66 ret = -ENOMEM; 67 goto err; 68 } 69 70 ns->bvec_pool = mempool_create(NVMET_MIN_MPOOL_OBJ, mempool_alloc_slab, 71 mempool_free_slab, ns->bvec_cache); 72 73 if (!ns->bvec_pool) { 74 ret = -ENOMEM; 75 goto err; 76 } 77 78 return ret; 79err: 80 ns->size = 0; 81 ns->blksize_shift = 0; 82 nvmet_file_ns_disable(ns); 83 return ret; 84} 85 86static void nvmet_file_init_bvec(struct bio_vec *bv, struct scatterlist *sg) 87{ 88 bv->bv_page = sg_page(sg); 89 bv->bv_offset = sg->offset; 90 bv->bv_len = sg->length; 91} 92 93static ssize_t nvmet_file_submit_bvec(struct nvmet_req *req, loff_t pos, 94 unsigned long nr_segs, size_t count, int ki_flags) 95{ 96 struct kiocb *iocb = &req->f.iocb; 97 ssize_t (*call_iter)(struct kiocb *iocb, struct iov_iter *iter); 98 struct iov_iter iter; 99 int rw; 100 101 if (req->cmd->rw.opcode == nvme_cmd_write) { 102 if (req->cmd->rw.control & cpu_to_le16(NVME_RW_FUA)) 103 ki_flags |= IOCB_DSYNC; 104 call_iter = req->ns->file->f_op->write_iter; 105 rw = WRITE; 106 } else { 107 call_iter = req->ns->file->f_op->read_iter; 108 rw = READ; 109 } 110 111 iov_iter_bvec(&iter, rw, req->f.bvec, nr_segs, count); 112 113 iocb->ki_pos = pos; 114 iocb->ki_filp = req->ns->file; 115 iocb->ki_flags = ki_flags | iocb_flags(req->ns->file); 116 117 return call_iter(iocb, &iter); 118} 119 120static void nvmet_file_io_done(struct kiocb *iocb, long ret) 121{ 122 struct nvmet_req *req = container_of(iocb, struct nvmet_req, f.iocb); 123 u16 status = NVME_SC_SUCCESS; 124 125 if (req->f.bvec != req->inline_bvec) { 126 if (likely(req->f.mpool_alloc == false)) 127 kfree(req->f.bvec); 128 else 129 mempool_free(req->f.bvec, req->ns->bvec_pool); 130 } 131 132 if (unlikely(ret != req->transfer_len)) 133 status = errno_to_nvme_status(req, ret); 134 nvmet_req_complete(req, status); 135} 136 137static bool nvmet_file_execute_io(struct nvmet_req *req, int ki_flags) 138{ 139 ssize_t nr_bvec = req->sg_cnt; 140 unsigned long bv_cnt = 0; 141 bool is_sync = false; 142 size_t len = 0, total_len = 0; 143 ssize_t ret = 0; 144 loff_t pos; 145 int i; 146 struct scatterlist *sg; 147 148 if (req->f.mpool_alloc && nr_bvec > NVMET_MAX_MPOOL_BVEC) 149 is_sync = true; 150 151 pos = le64_to_cpu(req->cmd->rw.slba) << req->ns->blksize_shift; 152 if (unlikely(pos + req->transfer_len > req->ns->size)) { 153 nvmet_req_complete(req, errno_to_nvme_status(req, -ENOSPC)); 154 return true; 155 } 156 157 memset(&req->f.iocb, 0, sizeof(struct kiocb)); 158 for_each_sg(req->sg, sg, req->sg_cnt, i) { 159 nvmet_file_init_bvec(&req->f.bvec[bv_cnt], sg); 160 len += req->f.bvec[bv_cnt].bv_len; 161 total_len += req->f.bvec[bv_cnt].bv_len; 162 bv_cnt++; 163 164 WARN_ON_ONCE((nr_bvec - 1) < 0); 165 166 if (unlikely(is_sync) && 167 (nr_bvec - 1 == 0 || bv_cnt == NVMET_MAX_MPOOL_BVEC)) { 168 ret = nvmet_file_submit_bvec(req, pos, bv_cnt, len, 0); 169 if (ret < 0) 170 goto complete; 171 172 pos += len; 173 bv_cnt = 0; 174 len = 0; 175 } 176 nr_bvec--; 177 } 178 179 if (WARN_ON_ONCE(total_len != req->transfer_len)) { 180 ret = -EIO; 181 goto complete; 182 } 183 184 if (unlikely(is_sync)) { 185 ret = total_len; 186 goto complete; 187 } 188 189 /* 190 * A NULL ki_complete ask for synchronous execution, which we want 191 * for the IOCB_NOWAIT case. 192 */ 193 if (!(ki_flags & IOCB_NOWAIT)) 194 req->f.iocb.ki_complete = nvmet_file_io_done; 195 196 ret = nvmet_file_submit_bvec(req, pos, bv_cnt, total_len, ki_flags); 197 198 switch (ret) { 199 case -EIOCBQUEUED: 200 return true; 201 case -EAGAIN: 202 if (WARN_ON_ONCE(!(ki_flags & IOCB_NOWAIT))) 203 goto complete; 204 return false; 205 case -EOPNOTSUPP: 206 /* 207 * For file systems returning error -EOPNOTSUPP, handle 208 * IOCB_NOWAIT error case separately and retry without 209 * IOCB_NOWAIT. 210 */ 211 if ((ki_flags & IOCB_NOWAIT)) 212 return false; 213 break; 214 } 215 216complete: 217 nvmet_file_io_done(&req->f.iocb, ret); 218 return true; 219} 220 221static void nvmet_file_buffered_io_work(struct work_struct *w) 222{ 223 struct nvmet_req *req = container_of(w, struct nvmet_req, f.work); 224 225 nvmet_file_execute_io(req, 0); 226} 227 228static void nvmet_file_submit_buffered_io(struct nvmet_req *req) 229{ 230 INIT_WORK(&req->f.work, nvmet_file_buffered_io_work); 231 queue_work(buffered_io_wq, &req->f.work); 232} 233 234static void nvmet_file_execute_rw(struct nvmet_req *req) 235{ 236 ssize_t nr_bvec = req->sg_cnt; 237 238 if (!nvmet_check_transfer_len(req, nvmet_rw_data_len(req))) 239 return; 240 241 if (!req->sg_cnt || !nr_bvec) { 242 nvmet_req_complete(req, 0); 243 return; 244 } 245 246 if (nr_bvec > NVMET_MAX_INLINE_BIOVEC) 247 req->f.bvec = kmalloc_array(nr_bvec, sizeof(struct bio_vec), 248 GFP_KERNEL); 249 else 250 req->f.bvec = req->inline_bvec; 251 252 if (unlikely(!req->f.bvec)) { 253 /* fallback under memory pressure */ 254 req->f.bvec = mempool_alloc(req->ns->bvec_pool, GFP_KERNEL); 255 req->f.mpool_alloc = true; 256 } else 257 req->f.mpool_alloc = false; 258 259 if (req->ns->buffered_io) { 260 if (likely(!req->f.mpool_alloc) && 261 (req->ns->file->f_mode & FMODE_NOWAIT) && 262 nvmet_file_execute_io(req, IOCB_NOWAIT)) 263 return; 264 nvmet_file_submit_buffered_io(req); 265 } else 266 nvmet_file_execute_io(req, 0); 267} 268 269u16 nvmet_file_flush(struct nvmet_req *req) 270{ 271 return errno_to_nvme_status(req, vfs_fsync(req->ns->file, 1)); 272} 273 274static void nvmet_file_flush_work(struct work_struct *w) 275{ 276 struct nvmet_req *req = container_of(w, struct nvmet_req, f.work); 277 278 nvmet_req_complete(req, nvmet_file_flush(req)); 279} 280 281static void nvmet_file_execute_flush(struct nvmet_req *req) 282{ 283 if (!nvmet_check_transfer_len(req, 0)) 284 return; 285 INIT_WORK(&req->f.work, nvmet_file_flush_work); 286 queue_work(nvmet_wq, &req->f.work); 287} 288 289static void nvmet_file_execute_discard(struct nvmet_req *req) 290{ 291 int mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE; 292 struct nvme_dsm_range range; 293 loff_t offset, len; 294 u16 status = 0; 295 int ret; 296 int i; 297 298 for (i = 0; i <= le32_to_cpu(req->cmd->dsm.nr); i++) { 299 status = nvmet_copy_from_sgl(req, i * sizeof(range), &range, 300 sizeof(range)); 301 if (status) 302 break; 303 304 offset = le64_to_cpu(range.slba) << req->ns->blksize_shift; 305 len = le32_to_cpu(range.nlb); 306 len <<= req->ns->blksize_shift; 307 if (offset + len > req->ns->size) { 308 req->error_slba = le64_to_cpu(range.slba); 309 status = errno_to_nvme_status(req, -ENOSPC); 310 break; 311 } 312 313 ret = vfs_fallocate(req->ns->file, mode, offset, len); 314 if (ret && ret != -EOPNOTSUPP) { 315 req->error_slba = le64_to_cpu(range.slba); 316 status = errno_to_nvme_status(req, ret); 317 break; 318 } 319 } 320 321 nvmet_req_complete(req, status); 322} 323 324static void nvmet_file_dsm_work(struct work_struct *w) 325{ 326 struct nvmet_req *req = container_of(w, struct nvmet_req, f.work); 327 328 switch (le32_to_cpu(req->cmd->dsm.attributes)) { 329 case NVME_DSMGMT_AD: 330 nvmet_file_execute_discard(req); 331 return; 332 case NVME_DSMGMT_IDR: 333 case NVME_DSMGMT_IDW: 334 default: 335 /* Not supported yet */ 336 nvmet_req_complete(req, 0); 337 return; 338 } 339} 340 341static void nvmet_file_execute_dsm(struct nvmet_req *req) 342{ 343 if (!nvmet_check_data_len_lte(req, nvmet_dsm_len(req))) 344 return; 345 INIT_WORK(&req->f.work, nvmet_file_dsm_work); 346 queue_work(nvmet_wq, &req->f.work); 347} 348 349static void nvmet_file_write_zeroes_work(struct work_struct *w) 350{ 351 struct nvmet_req *req = container_of(w, struct nvmet_req, f.work); 352 struct nvme_write_zeroes_cmd *write_zeroes = &req->cmd->write_zeroes; 353 int mode = FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE; 354 loff_t offset; 355 loff_t len; 356 int ret; 357 358 offset = le64_to_cpu(write_zeroes->slba) << req->ns->blksize_shift; 359 len = (((sector_t)le16_to_cpu(write_zeroes->length) + 1) << 360 req->ns->blksize_shift); 361 362 if (unlikely(offset + len > req->ns->size)) { 363 nvmet_req_complete(req, errno_to_nvme_status(req, -ENOSPC)); 364 return; 365 } 366 367 ret = vfs_fallocate(req->ns->file, mode, offset, len); 368 nvmet_req_complete(req, ret < 0 ? errno_to_nvme_status(req, ret) : 0); 369} 370 371static void nvmet_file_execute_write_zeroes(struct nvmet_req *req) 372{ 373 if (!nvmet_check_transfer_len(req, 0)) 374 return; 375 INIT_WORK(&req->f.work, nvmet_file_write_zeroes_work); 376 queue_work(nvmet_wq, &req->f.work); 377} 378 379u16 nvmet_file_parse_io_cmd(struct nvmet_req *req) 380{ 381 switch (req->cmd->common.opcode) { 382 case nvme_cmd_read: 383 case nvme_cmd_write: 384 req->execute = nvmet_file_execute_rw; 385 return 0; 386 case nvme_cmd_flush: 387 req->execute = nvmet_file_execute_flush; 388 return 0; 389 case nvme_cmd_dsm: 390 req->execute = nvmet_file_execute_dsm; 391 return 0; 392 case nvme_cmd_write_zeroes: 393 req->execute = nvmet_file_execute_write_zeroes; 394 return 0; 395 default: 396 return nvmet_report_invalid_opcode(req); 397 } 398}