]> Git Repo - linux.git/blob - drivers/nvme/target/io-cmd-file.c
Merge tag 'cxl-for-6.0' of git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl
[linux.git] / drivers / nvme / target / io-cmd-file.c
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
17 void nvmet_file_ns_revalidate(struct nvmet_ns *ns)
18 {
19         ns->size = i_size_read(ns->file->f_mapping->host);
20 }
21
22 void 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
36 int 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;
79 err:
80         ns->size = 0;
81         ns->blksize_shift = 0;
82         nvmet_file_ns_disable(ns);
83         return ret;
84 }
85
86 static 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
93 static 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->ki_filp->f_iocb_flags;
116
117         return call_iter(iocb, &iter);
118 }
119
120 static 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
137 static 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
216 complete:
217         nvmet_file_io_done(&req->f.iocb, ret);
218         return true;
219 }
220
221 static 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
228 static 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
234 static 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
269 u16 nvmet_file_flush(struct nvmet_req *req)
270 {
271         return errno_to_nvme_status(req, vfs_fsync(req->ns->file, 1));
272 }
273
274 static 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
281 static 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
289 static 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
324 static 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
341 static 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
349 static 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
371 static 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
379 u16 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 }
This page took 0.056923 seconds and 4 git commands to generate.