2 * Copyright (c) 2003 Silicon Graphics International Corp.
3 * Copyright (c) 2009-2011 Spectra Logic Corporation
4 * Copyright (c) 2012 The FreeBSD Foundation
7 * Portions of this software were developed by Edward Tomasz Napierala
8 * under sponsorship from the FreeBSD Foundation.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions, and the following disclaimer,
15 * without modification.
16 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
17 * substantially similar to the "NO WARRANTY" disclaimer below
18 * ("Disclaimer") and any redistribution must be conditioned upon
19 * including a substantially similar Disclaimer requirement for further
20 * binary redistribution.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
32 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGES.
35 * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_backend_block.c#5 $
38 * CAM Target Layer driver backend for block devices.
40 * Author: Ken Merry <ken@FreeBSD.org>
42 #include <sys/cdefs.h>
43 __FBSDID("$FreeBSD$");
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/types.h>
49 #include <sys/kthread.h>
51 #include <sys/fcntl.h>
52 #include <sys/limits.h>
54 #include <sys/mutex.h>
55 #include <sys/condvar.h>
56 #include <sys/malloc.h>
58 #include <sys/ioccom.h>
59 #include <sys/queue.h>
61 #include <sys/endian.h>
64 #include <sys/taskqueue.h>
65 #include <sys/vnode.h>
66 #include <sys/namei.h>
67 #include <sys/mount.h>
69 #include <sys/fcntl.h>
70 #include <sys/filedesc.h>
71 #include <sys/filio.h>
74 #include <sys/module.h>
76 #include <sys/devicestat.h>
77 #include <sys/sysctl.h>
79 #include <geom/geom.h>
82 #include <cam/scsi/scsi_all.h>
83 #include <cam/scsi/scsi_da.h>
84 #include <cam/ctl/ctl_io.h>
85 #include <cam/ctl/ctl.h>
86 #include <cam/ctl/ctl_backend.h>
87 #include <cam/ctl/ctl_ioctl.h>
88 #include <cam/ctl/ctl_ha.h>
89 #include <cam/ctl/ctl_scsi_all.h>
90 #include <cam/ctl/ctl_private.h>
91 #include <cam/ctl/ctl_error.h>
94 * The idea here is that we'll allocate enough S/G space to hold a 1MB
95 * I/O. If we get an I/O larger than that, we'll split it.
97 #define CTLBLK_HALF_IO_SIZE (512 * 1024)
98 #define CTLBLK_MAX_IO_SIZE (CTLBLK_HALF_IO_SIZE * 2)
99 #define CTLBLK_MAX_SEG MAXPHYS
100 #define CTLBLK_HALF_SEGS MAX(CTLBLK_HALF_IO_SIZE / CTLBLK_MAX_SEG, 1)
101 #define CTLBLK_MAX_SEGS (CTLBLK_HALF_SEGS * 2)
104 #define DPRINTF(fmt, args...) \
105 printf("cbb(%s:%d): " fmt, __FUNCTION__, __LINE__, ##args)
107 #define DPRINTF(fmt, args...) do {} while(0)
111 ((struct ctl_ptr_len_flags *)&(io)->io_hdr.ctl_private[CTL_PRIV_BACKEND])
113 ((struct ctl_lba_len_flags *)&(io)->io_hdr.ctl_private[CTL_PRIV_LBA_LEN])
115 SDT_PROVIDER_DEFINE(cbb);
118 CTL_BE_BLOCK_LUN_UNCONFIGURED = 0x01,
119 CTL_BE_BLOCK_LUN_CONFIG_ERR = 0x02,
120 CTL_BE_BLOCK_LUN_WAITING = 0x04,
121 } ctl_be_block_lun_flags;
129 struct ctl_be_block_filedata {
133 union ctl_be_block_bedata {
134 struct ctl_be_block_filedata file;
137 struct ctl_be_block_io;
138 struct ctl_be_block_lun;
140 typedef void (*cbb_dispatch_t)(struct ctl_be_block_lun *be_lun,
141 struct ctl_be_block_io *beio);
142 typedef uint64_t (*cbb_getattr_t)(struct ctl_be_block_lun *be_lun,
143 const char *attrname);
146 * Backend LUN structure. There is a 1:1 mapping between a block device
147 * and a backend block LUN, and between a backend block LUN and a CTL LUN.
149 struct ctl_be_block_lun {
150 struct ctl_lun_create_params params;
153 ctl_be_block_type dev_type;
155 union ctl_be_block_bedata backend;
156 cbb_dispatch_t dispatch;
157 cbb_dispatch_t lun_flush;
158 cbb_dispatch_t unmap;
159 cbb_dispatch_t get_lba_status;
160 cbb_getattr_t getattr;
162 uint64_t size_blocks;
164 struct ctl_be_block_softc *softc;
165 struct devstat *disk_stats;
166 ctl_be_block_lun_flags flags;
167 STAILQ_ENTRY(ctl_be_block_lun) links;
168 struct ctl_be_lun cbe_lun;
169 struct taskqueue *io_taskqueue;
172 STAILQ_HEAD(, ctl_io_hdr) input_queue;
173 STAILQ_HEAD(, ctl_io_hdr) config_read_queue;
174 STAILQ_HEAD(, ctl_io_hdr) config_write_queue;
175 STAILQ_HEAD(, ctl_io_hdr) datamove_queue;
176 struct mtx_padalign io_lock;
177 struct mtx_padalign queue_lock;
181 * Overall softc structure for the block backend module.
183 struct ctl_be_block_softc {
186 STAILQ_HEAD(, ctl_be_block_lun) lun_list;
189 static struct ctl_be_block_softc backend_block_softc;
192 * Per-I/O information.
194 struct ctl_be_block_io {
196 struct ctl_sg_entry sg_segs[CTLBLK_MAX_SEGS];
197 struct iovec xiovecs[CTLBLK_MAX_SEGS];
204 struct bintime ds_t0;
205 devstat_tag_type ds_tag_type;
206 devstat_trans_flags ds_trans_type;
210 struct ctl_be_block_softc *softc;
211 struct ctl_be_block_lun *lun;
212 void (*beio_cont)(struct ctl_be_block_io *beio); /* to continue processing */
215 extern struct ctl_softc *control_softc;
217 static int cbb_num_threads = 14;
218 SYSCTL_NODE(_kern_cam_ctl, OID_AUTO, block, CTLFLAG_RD, 0,
219 "CAM Target Layer Block Backend");
220 SYSCTL_INT(_kern_cam_ctl_block, OID_AUTO, num_threads, CTLFLAG_RWTUN,
221 &cbb_num_threads, 0, "Number of threads per backing file");
223 static struct ctl_be_block_io *ctl_alloc_beio(struct ctl_be_block_softc *softc);
224 static void ctl_free_beio(struct ctl_be_block_io *beio);
225 static void ctl_complete_beio(struct ctl_be_block_io *beio);
226 static int ctl_be_block_move_done(union ctl_io *io);
227 static void ctl_be_block_biodone(struct bio *bio);
228 static void ctl_be_block_flush_file(struct ctl_be_block_lun *be_lun,
229 struct ctl_be_block_io *beio);
230 static void ctl_be_block_dispatch_file(struct ctl_be_block_lun *be_lun,
231 struct ctl_be_block_io *beio);
232 static void ctl_be_block_gls_file(struct ctl_be_block_lun *be_lun,
233 struct ctl_be_block_io *beio);
234 static uint64_t ctl_be_block_getattr_file(struct ctl_be_block_lun *be_lun,
235 const char *attrname);
236 static void ctl_be_block_flush_dev(struct ctl_be_block_lun *be_lun,
237 struct ctl_be_block_io *beio);
238 static void ctl_be_block_unmap_dev(struct ctl_be_block_lun *be_lun,
239 struct ctl_be_block_io *beio);
240 static void ctl_be_block_dispatch_dev(struct ctl_be_block_lun *be_lun,
241 struct ctl_be_block_io *beio);
242 static uint64_t ctl_be_block_getattr_dev(struct ctl_be_block_lun *be_lun,
243 const char *attrname);
244 static void ctl_be_block_cr_dispatch(struct ctl_be_block_lun *be_lun,
246 static void ctl_be_block_cw_dispatch(struct ctl_be_block_lun *be_lun,
248 static void ctl_be_block_dispatch(struct ctl_be_block_lun *be_lun,
250 static void ctl_be_block_worker(void *context, int pending);
251 static int ctl_be_block_submit(union ctl_io *io);
252 static int ctl_be_block_ioctl(struct cdev *dev, u_long cmd, caddr_t addr,
253 int flag, struct thread *td);
254 static int ctl_be_block_open_file(struct ctl_be_block_lun *be_lun,
255 struct ctl_lun_req *req);
256 static int ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun,
257 struct ctl_lun_req *req);
258 static int ctl_be_block_close(struct ctl_be_block_lun *be_lun);
259 static int ctl_be_block_open(struct ctl_be_block_softc *softc,
260 struct ctl_be_block_lun *be_lun,
261 struct ctl_lun_req *req);
262 static int ctl_be_block_create(struct ctl_be_block_softc *softc,
263 struct ctl_lun_req *req);
264 static int ctl_be_block_rm(struct ctl_be_block_softc *softc,
265 struct ctl_lun_req *req);
266 static int ctl_be_block_modify_file(struct ctl_be_block_lun *be_lun,
267 struct ctl_lun_req *req);
268 static int ctl_be_block_modify_dev(struct ctl_be_block_lun *be_lun,
269 struct ctl_lun_req *req);
270 static int ctl_be_block_modify(struct ctl_be_block_softc *softc,
271 struct ctl_lun_req *req);
272 static void ctl_be_block_lun_shutdown(void *be_lun);
273 static void ctl_be_block_lun_config_status(void *be_lun,
274 ctl_lun_config_status status);
275 static int ctl_be_block_config_write(union ctl_io *io);
276 static int ctl_be_block_config_read(union ctl_io *io);
277 static int ctl_be_block_lun_info(void *be_lun, struct sbuf *sb);
278 static uint64_t ctl_be_block_lun_attr(void *be_lun, const char *attrname);
279 int ctl_be_block_init(void);
281 static struct ctl_backend_driver ctl_be_block_driver =
284 .flags = CTL_BE_FLAG_HAS_CONFIG,
285 .init = ctl_be_block_init,
286 .data_submit = ctl_be_block_submit,
287 .data_move_done = ctl_be_block_move_done,
288 .config_read = ctl_be_block_config_read,
289 .config_write = ctl_be_block_config_write,
290 .ioctl = ctl_be_block_ioctl,
291 .lun_info = ctl_be_block_lun_info,
292 .lun_attr = ctl_be_block_lun_attr
295 MALLOC_DEFINE(M_CTLBLK, "ctlblk", "Memory used for CTL block backend");
296 CTL_BACKEND_DECLARE(cbb, ctl_be_block_driver);
298 static uma_zone_t beio_zone;
300 static struct ctl_be_block_io *
301 ctl_alloc_beio(struct ctl_be_block_softc *softc)
303 struct ctl_be_block_io *beio;
305 beio = uma_zalloc(beio_zone, M_WAITOK | M_ZERO);
311 ctl_free_beio(struct ctl_be_block_io *beio)
318 for (i = 0; i < beio->num_segs; i++) {
319 if (beio->sg_segs[i].addr == NULL)
322 uma_zfree(beio->lun->lun_zone, beio->sg_segs[i].addr);
323 beio->sg_segs[i].addr = NULL;
325 /* For compare we had two equal S/G lists. */
326 if (ARGS(beio->io)->flags & CTL_LLF_COMPARE) {
327 uma_zfree(beio->lun->lun_zone,
328 beio->sg_segs[i + CTLBLK_HALF_SEGS].addr);
329 beio->sg_segs[i + CTLBLK_HALF_SEGS].addr = NULL;
333 if (duplicate_free > 0) {
334 printf("%s: %d duplicate frees out of %d segments\n", __func__,
335 duplicate_free, beio->num_segs);
338 uma_zfree(beio_zone, beio);
342 ctl_complete_beio(struct ctl_be_block_io *beio)
344 union ctl_io *io = beio->io;
346 if (beio->beio_cont != NULL) {
347 beio->beio_cont(beio);
350 ctl_data_submit_done(io);
355 ctl_be_block_move_done(union ctl_io *io)
357 struct ctl_be_block_io *beio;
358 struct ctl_be_block_lun *be_lun;
359 struct ctl_lba_len_flags *lbalen;
361 struct bintime cur_bt;
365 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
368 DPRINTF("entered\n");
372 bintime_sub(&cur_bt, &io->io_hdr.dma_start_bt);
373 bintime_add(&io->io_hdr.dma_bt, &cur_bt);
374 io->io_hdr.num_dmas++;
376 io->scsiio.kern_rel_offset += io->scsiio.kern_data_len;
379 * We set status at this point for read commands, and write
380 * commands with errors.
382 if (io->io_hdr.flags & CTL_FLAG_ABORT) {
384 } else if ((io->io_hdr.port_status == 0) &&
385 ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE)) {
386 lbalen = ARGS(beio->io);
387 if (lbalen->flags & CTL_LLF_READ) {
388 ctl_set_success(&io->scsiio);
389 } else if (lbalen->flags & CTL_LLF_COMPARE) {
390 /* We have two data blocks ready for comparison. */
391 for (i = 0; i < beio->num_segs; i++) {
392 if (memcmp(beio->sg_segs[i].addr,
393 beio->sg_segs[i + CTLBLK_HALF_SEGS].addr,
394 beio->sg_segs[i].len) != 0)
397 if (i < beio->num_segs)
398 ctl_set_sense(&io->scsiio,
400 /*sense_key*/ SSD_KEY_MISCOMPARE,
405 ctl_set_success(&io->scsiio);
407 } else if ((io->io_hdr.port_status != 0) &&
408 ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE ||
409 (io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS)) {
411 * For hardware error sense keys, the sense key
412 * specific value is defined to be a retry count,
413 * but we use it to pass back an internal FETD
414 * error code. XXX KDM Hopefully the FETD is only
415 * using 16 bits for an error code, since that's
416 * all the space we have in the sks field.
418 ctl_set_internal_failure(&io->scsiio,
421 io->io_hdr.port_status);
425 * If this is a read, or a write with errors, it is done.
427 if ((beio->bio_cmd == BIO_READ)
428 || ((io->io_hdr.flags & CTL_FLAG_ABORT) != 0)
429 || ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE)) {
430 ctl_complete_beio(beio);
435 * At this point, we have a write and the DMA completed
436 * successfully. We now have to queue it to the task queue to
437 * execute the backend I/O. That is because we do blocking
438 * memory allocations, and in the file backing case, blocking I/O.
439 * This move done routine is generally called in the SIM's
440 * interrupt context, and therefore we cannot block.
442 mtx_lock(&be_lun->queue_lock);
444 * XXX KDM make sure that links is okay to use at this point.
445 * Otherwise, we either need to add another field to ctl_io_hdr,
446 * or deal with resource allocation here.
448 STAILQ_INSERT_TAIL(&be_lun->datamove_queue, &io->io_hdr, links);
449 mtx_unlock(&be_lun->queue_lock);
451 taskqueue_enqueue(be_lun->io_taskqueue, &be_lun->io_task);
457 ctl_be_block_biodone(struct bio *bio)
459 struct ctl_be_block_io *beio;
460 struct ctl_be_block_lun *be_lun;
464 beio = bio->bio_caller1;
468 DPRINTF("entered\n");
470 error = bio->bio_error;
471 mtx_lock(&be_lun->io_lock);
475 beio->num_bios_done++;
478 * XXX KDM will this cause WITNESS to complain? Holding a lock
479 * during the free might cause it to complain.
484 * If the send complete bit isn't set, or we aren't the last I/O to
485 * complete, then we're done.
487 if ((beio->send_complete == 0)
488 || (beio->num_bios_done < beio->num_bios_sent)) {
489 mtx_unlock(&be_lun->io_lock);
494 * At this point, we've verified that we are the last I/O to
495 * complete, so it's safe to drop the lock.
497 devstat_end_transaction(beio->lun->disk_stats, beio->io_len,
498 beio->ds_tag_type, beio->ds_trans_type,
499 /*now*/ NULL, /*then*/&beio->ds_t0);
500 mtx_unlock(&be_lun->io_lock);
503 * If there are any errors from the backing device, we fail the
504 * entire I/O with a medium error.
506 if (beio->num_errors > 0) {
507 if (error == EOPNOTSUPP) {
508 ctl_set_invalid_opcode(&io->scsiio);
509 } else if (error == ENOSPC || error == EDQUOT) {
510 ctl_set_space_alloc_fail(&io->scsiio);
511 } else if (beio->bio_cmd == BIO_FLUSH) {
512 /* XXX KDM is there is a better error here? */
513 ctl_set_internal_failure(&io->scsiio,
515 /*retry_count*/ 0xbad2);
517 ctl_set_medium_error(&io->scsiio);
518 ctl_complete_beio(beio);
523 * If this is a write, a flush, a delete or verify, we're all done.
524 * If this is a read, we can now send the data to the user.
526 if ((beio->bio_cmd == BIO_WRITE)
527 || (beio->bio_cmd == BIO_FLUSH)
528 || (beio->bio_cmd == BIO_DELETE)
529 || (ARGS(io)->flags & CTL_LLF_VERIFY)) {
530 ctl_set_success(&io->scsiio);
531 ctl_complete_beio(beio);
533 if ((ARGS(io)->flags & CTL_LLF_READ) &&
534 beio->beio_cont == NULL)
535 ctl_set_success(&io->scsiio);
537 getbintime(&io->io_hdr.dma_start_bt);
544 ctl_be_block_flush_file(struct ctl_be_block_lun *be_lun,
545 struct ctl_be_block_io *beio)
547 union ctl_io *io = beio->io;
548 struct mount *mountpoint;
549 int error, lock_flags;
551 DPRINTF("entered\n");
553 binuptime(&beio->ds_t0);
554 mtx_lock(&be_lun->io_lock);
555 devstat_start_transaction(beio->lun->disk_stats, &beio->ds_t0);
556 mtx_unlock(&be_lun->io_lock);
558 (void) vn_start_write(be_lun->vn, &mountpoint, V_WAIT);
560 if (MNT_SHARED_WRITES(mountpoint)
561 || ((mountpoint == NULL)
562 && MNT_SHARED_WRITES(be_lun->vn->v_mount)))
563 lock_flags = LK_SHARED;
565 lock_flags = LK_EXCLUSIVE;
567 vn_lock(be_lun->vn, lock_flags | LK_RETRY);
569 error = VOP_FSYNC(be_lun->vn, beio->io_arg ? MNT_NOWAIT : MNT_WAIT,
571 VOP_UNLOCK(be_lun->vn, 0);
573 vn_finished_write(mountpoint);
575 mtx_lock(&be_lun->io_lock);
576 devstat_end_transaction(beio->lun->disk_stats, beio->io_len,
577 beio->ds_tag_type, beio->ds_trans_type,
578 /*now*/ NULL, /*then*/&beio->ds_t0);
579 mtx_unlock(&be_lun->io_lock);
582 ctl_set_success(&io->scsiio);
584 /* XXX KDM is there is a better error here? */
585 ctl_set_internal_failure(&io->scsiio,
587 /*retry_count*/ 0xbad1);
590 ctl_complete_beio(beio);
593 SDT_PROBE_DEFINE1(cbb, kernel, read, file_start, "uint64_t");
594 SDT_PROBE_DEFINE1(cbb, kernel, write, file_start, "uint64_t");
595 SDT_PROBE_DEFINE1(cbb, kernel, read, file_done,"uint64_t");
596 SDT_PROBE_DEFINE1(cbb, kernel, write, file_done, "uint64_t");
599 ctl_be_block_dispatch_file(struct ctl_be_block_lun *be_lun,
600 struct ctl_be_block_io *beio)
602 struct ctl_be_block_filedata *file_data;
605 struct iovec *xiovec;
609 DPRINTF("entered\n");
611 file_data = &be_lun->backend.file;
614 if (ARGS(io)->flags & CTL_LLF_DPO)
616 if (beio->bio_cmd == BIO_WRITE && ARGS(io)->flags & CTL_LLF_FUA)
619 bzero(&xuio, sizeof(xuio));
620 if (beio->bio_cmd == BIO_READ) {
621 SDT_PROBE(cbb, kernel, read, file_start, 0, 0, 0, 0, 0);
622 xuio.uio_rw = UIO_READ;
624 SDT_PROBE(cbb, kernel, write, file_start, 0, 0, 0, 0, 0);
625 xuio.uio_rw = UIO_WRITE;
627 xuio.uio_offset = beio->io_offset;
628 xuio.uio_resid = beio->io_len;
629 xuio.uio_segflg = UIO_SYSSPACE;
630 xuio.uio_iov = beio->xiovecs;
631 xuio.uio_iovcnt = beio->num_segs;
632 xuio.uio_td = curthread;
634 for (i = 0, xiovec = xuio.uio_iov; i < xuio.uio_iovcnt; i++, xiovec++) {
635 xiovec->iov_base = beio->sg_segs[i].addr;
636 xiovec->iov_len = beio->sg_segs[i].len;
639 binuptime(&beio->ds_t0);
640 mtx_lock(&be_lun->io_lock);
641 devstat_start_transaction(beio->lun->disk_stats, &beio->ds_t0);
642 mtx_unlock(&be_lun->io_lock);
644 if (beio->bio_cmd == BIO_READ) {
645 vn_lock(be_lun->vn, LK_SHARED | LK_RETRY);
648 * UFS pays attention to IO_DIRECT for reads. If the
649 * DIRECTIO option is configured into the kernel, it calls
650 * ffs_rawread(). But that only works for single-segment
651 * uios with user space addresses. In our case, with a
652 * kernel uio, it still reads into the buffer cache, but it
653 * will just try to release the buffer from the cache later
656 * ZFS does not pay attention to IO_DIRECT for reads.
658 * UFS does not pay attention to IO_SYNC for reads.
660 * ZFS pays attention to IO_SYNC (which translates into the
661 * Solaris define FRSYNC for zfs_read()) for reads. It
662 * attempts to sync the file before reading.
664 error = VOP_READ(be_lun->vn, &xuio, flags, file_data->cred);
666 VOP_UNLOCK(be_lun->vn, 0);
667 SDT_PROBE(cbb, kernel, read, file_done, 0, 0, 0, 0, 0);
669 struct mount *mountpoint;
672 (void)vn_start_write(be_lun->vn, &mountpoint, V_WAIT);
674 if (MNT_SHARED_WRITES(mountpoint)
675 || ((mountpoint == NULL)
676 && MNT_SHARED_WRITES(be_lun->vn->v_mount)))
677 lock_flags = LK_SHARED;
679 lock_flags = LK_EXCLUSIVE;
681 vn_lock(be_lun->vn, lock_flags | LK_RETRY);
684 * UFS pays attention to IO_DIRECT for writes. The write
685 * is done asynchronously. (Normally the write would just
686 * get put into cache.
688 * UFS pays attention to IO_SYNC for writes. It will
689 * attempt to write the buffer out synchronously if that
692 * ZFS does not pay attention to IO_DIRECT for writes.
694 * ZFS pays attention to IO_SYNC (a.k.a. FSYNC or FRSYNC)
695 * for writes. It will flush the transaction from the
696 * cache before returning.
698 error = VOP_WRITE(be_lun->vn, &xuio, flags, file_data->cred);
699 VOP_UNLOCK(be_lun->vn, 0);
701 vn_finished_write(mountpoint);
702 SDT_PROBE(cbb, kernel, write, file_done, 0, 0, 0, 0, 0);
705 mtx_lock(&be_lun->io_lock);
706 devstat_end_transaction(beio->lun->disk_stats, beio->io_len,
707 beio->ds_tag_type, beio->ds_trans_type,
708 /*now*/ NULL, /*then*/&beio->ds_t0);
709 mtx_unlock(&be_lun->io_lock);
712 * If we got an error, set the sense data to "MEDIUM ERROR" and
713 * return the I/O to the user.
718 ctl_scsi_path_string(io, path_str, sizeof(path_str));
719 printf("%s%s command returned errno %d\n", path_str,
720 (beio->bio_cmd == BIO_READ) ? "READ" : "WRITE", error);
721 if (error == ENOSPC || error == EDQUOT) {
722 ctl_set_space_alloc_fail(&io->scsiio);
724 ctl_set_medium_error(&io->scsiio);
725 ctl_complete_beio(beio);
730 * If this is a write or a verify, we're all done.
731 * If this is a read, we can now send the data to the user.
733 if ((beio->bio_cmd == BIO_WRITE) ||
734 (ARGS(io)->flags & CTL_LLF_VERIFY)) {
735 ctl_set_success(&io->scsiio);
736 ctl_complete_beio(beio);
738 if ((ARGS(io)->flags & CTL_LLF_READ) &&
739 beio->beio_cont == NULL)
740 ctl_set_success(&io->scsiio);
742 getbintime(&io->io_hdr.dma_start_bt);
749 ctl_be_block_gls_file(struct ctl_be_block_lun *be_lun,
750 struct ctl_be_block_io *beio)
752 union ctl_io *io = beio->io;
753 struct ctl_lba_len_flags *lbalen = ARGS(io);
754 struct scsi_get_lba_status_data *data;
758 DPRINTF("entered\n");
760 off = roff = ((off_t)lbalen->lba) * be_lun->cbe_lun.blocksize;
761 vn_lock(be_lun->vn, LK_SHARED | LK_RETRY);
762 error = VOP_IOCTL(be_lun->vn, FIOSEEKHOLE, &off,
763 0, curthread->td_ucred, curthread);
764 if (error == 0 && off > roff)
765 status = 0; /* mapped up to off */
767 error = VOP_IOCTL(be_lun->vn, FIOSEEKDATA, &off,
768 0, curthread->td_ucred, curthread);
769 if (error == 0 && off > roff)
770 status = 1; /* deallocated up to off */
772 status = 0; /* unknown up to the end */
773 off = be_lun->size_bytes;
776 VOP_UNLOCK(be_lun->vn, 0);
778 data = (struct scsi_get_lba_status_data *)io->scsiio.kern_data_ptr;
779 scsi_u64to8b(lbalen->lba, data->descr[0].addr);
780 scsi_ulto4b(MIN(UINT32_MAX, off / be_lun->cbe_lun.blocksize -
781 lbalen->lba), data->descr[0].length);
782 data->descr[0].status = status;
784 ctl_complete_beio(beio);
788 ctl_be_block_getattr_file(struct ctl_be_block_lun *be_lun, const char *attrname)
791 struct statfs statfs;
796 if (be_lun->vn == NULL)
798 vn_lock(be_lun->vn, LK_SHARED | LK_RETRY);
799 if (strcmp(attrname, "blocksused") == 0) {
800 error = VOP_GETATTR(be_lun->vn, &vattr, curthread->td_ucred);
802 val = vattr.va_bytes / be_lun->cbe_lun.blocksize;
804 if (strcmp(attrname, "blocksavail") == 0 &&
805 (be_lun->vn->v_iflag & VI_DOOMED) == 0) {
806 error = VFS_STATFS(be_lun->vn->v_mount, &statfs);
808 val = statfs.f_bavail * statfs.f_bsize /
809 be_lun->cbe_lun.blocksize;
811 VOP_UNLOCK(be_lun->vn, 0);
816 ctl_be_block_dispatch_zvol(struct ctl_be_block_lun *be_lun,
817 struct ctl_be_block_io *beio)
823 struct iovec *xiovec;
824 int error, flags, i, ref;
826 DPRINTF("entered\n");
830 if (ARGS(io)->flags & CTL_LLF_DPO)
832 if (beio->bio_cmd == BIO_WRITE && ARGS(io)->flags & CTL_LLF_FUA)
835 bzero(&xuio, sizeof(xuio));
836 if (beio->bio_cmd == BIO_READ) {
837 SDT_PROBE(cbb, kernel, read, file_start, 0, 0, 0, 0, 0);
838 xuio.uio_rw = UIO_READ;
840 SDT_PROBE(cbb, kernel, write, file_start, 0, 0, 0, 0, 0);
841 xuio.uio_rw = UIO_WRITE;
843 xuio.uio_offset = beio->io_offset;
844 xuio.uio_resid = beio->io_len;
845 xuio.uio_segflg = UIO_SYSSPACE;
846 xuio.uio_iov = beio->xiovecs;
847 xuio.uio_iovcnt = beio->num_segs;
848 xuio.uio_td = curthread;
850 for (i = 0, xiovec = xuio.uio_iov; i < xuio.uio_iovcnt; i++, xiovec++) {
851 xiovec->iov_base = beio->sg_segs[i].addr;
852 xiovec->iov_len = beio->sg_segs[i].len;
855 binuptime(&beio->ds_t0);
856 mtx_lock(&be_lun->io_lock);
857 devstat_start_transaction(beio->lun->disk_stats, &beio->ds_t0);
858 mtx_unlock(&be_lun->io_lock);
860 csw = devvn_refthread(be_lun->vn, &dev, &ref);
862 if (beio->bio_cmd == BIO_READ)
863 error = csw->d_read(dev, &xuio, flags);
865 error = csw->d_write(dev, &xuio, flags);
866 dev_relthread(dev, ref);
870 if (beio->bio_cmd == BIO_READ)
871 SDT_PROBE(cbb, kernel, read, file_done, 0, 0, 0, 0, 0);
873 SDT_PROBE(cbb, kernel, write, file_done, 0, 0, 0, 0, 0);
875 mtx_lock(&be_lun->io_lock);
876 devstat_end_transaction(beio->lun->disk_stats, beio->io_len,
877 beio->ds_tag_type, beio->ds_trans_type,
878 /*now*/ NULL, /*then*/&beio->ds_t0);
879 mtx_unlock(&be_lun->io_lock);
882 * If we got an error, set the sense data to "MEDIUM ERROR" and
883 * return the I/O to the user.
886 if (error == ENOSPC || error == EDQUOT) {
887 ctl_set_space_alloc_fail(&io->scsiio);
889 ctl_set_medium_error(&io->scsiio);
890 ctl_complete_beio(beio);
895 * If this is a write or a verify, we're all done.
896 * If this is a read, we can now send the data to the user.
898 if ((beio->bio_cmd == BIO_WRITE) ||
899 (ARGS(io)->flags & CTL_LLF_VERIFY)) {
900 ctl_set_success(&io->scsiio);
901 ctl_complete_beio(beio);
903 if ((ARGS(io)->flags & CTL_LLF_READ) &&
904 beio->beio_cont == NULL)
905 ctl_set_success(&io->scsiio);
907 getbintime(&io->io_hdr.dma_start_bt);
914 ctl_be_block_gls_zvol(struct ctl_be_block_lun *be_lun,
915 struct ctl_be_block_io *beio)
917 union ctl_io *io = beio->io;
920 struct ctl_lba_len_flags *lbalen = ARGS(io);
921 struct scsi_get_lba_status_data *data;
923 int error, ref, status;
925 DPRINTF("entered\n");
927 csw = devvn_refthread(be_lun->vn, &dev, &ref);
929 status = 0; /* unknown up to the end */
930 off = be_lun->size_bytes;
933 off = roff = ((off_t)lbalen->lba) * be_lun->cbe_lun.blocksize;
934 error = csw->d_ioctl(dev, FIOSEEKHOLE, (caddr_t)&off, FREAD,
936 if (error == 0 && off > roff)
937 status = 0; /* mapped up to off */
939 error = csw->d_ioctl(dev, FIOSEEKDATA, (caddr_t)&off, FREAD,
941 if (error == 0 && off > roff)
942 status = 1; /* deallocated up to off */
944 status = 0; /* unknown up to the end */
945 off = be_lun->size_bytes;
948 dev_relthread(dev, ref);
951 data = (struct scsi_get_lba_status_data *)io->scsiio.kern_data_ptr;
952 scsi_u64to8b(lbalen->lba, data->descr[0].addr);
953 scsi_ulto4b(MIN(UINT32_MAX, off / be_lun->cbe_lun.blocksize -
954 lbalen->lba), data->descr[0].length);
955 data->descr[0].status = status;
957 ctl_complete_beio(beio);
961 ctl_be_block_flush_dev(struct ctl_be_block_lun *be_lun,
962 struct ctl_be_block_io *beio)
972 DPRINTF("entered\n");
974 /* This can't fail, it's a blocking allocation. */
977 bio->bio_cmd = BIO_FLUSH;
980 bio->bio_done = ctl_be_block_biodone;
981 bio->bio_caller1 = beio;
985 * We don't need to acquire the LUN lock here, because we are only
986 * sending one bio, and so there is no other context to synchronize
989 beio->num_bios_sent = 1;
990 beio->send_complete = 1;
992 binuptime(&beio->ds_t0);
993 mtx_lock(&be_lun->io_lock);
994 devstat_start_transaction(be_lun->disk_stats, &beio->ds_t0);
995 mtx_unlock(&be_lun->io_lock);
997 csw = devvn_refthread(be_lun->vn, &dev, &ref);
1000 csw->d_strategy(bio);
1001 dev_relthread(dev, ref);
1003 bio->bio_error = ENXIO;
1004 ctl_be_block_biodone(bio);
1009 ctl_be_block_unmap_dev_range(struct ctl_be_block_lun *be_lun,
1010 struct ctl_be_block_io *beio,
1011 uint64_t off, uint64_t len, int last)
1019 csw = devvn_refthread(be_lun->vn, &dev, &ref);
1020 maxlen = LONG_MAX - (LONG_MAX % be_lun->cbe_lun.blocksize);
1022 bio = g_alloc_bio();
1023 bio->bio_cmd = BIO_DELETE;
1025 bio->bio_offset = off;
1026 bio->bio_length = MIN(len, maxlen);
1028 bio->bio_done = ctl_be_block_biodone;
1029 bio->bio_caller1 = beio;
1030 bio->bio_pblkno = off / be_lun->cbe_lun.blocksize;
1032 off += bio->bio_length;
1033 len -= bio->bio_length;
1035 mtx_lock(&be_lun->io_lock);
1036 beio->num_bios_sent++;
1037 if (last && len == 0)
1038 beio->send_complete = 1;
1039 mtx_unlock(&be_lun->io_lock);
1042 csw->d_strategy(bio);
1044 bio->bio_error = ENXIO;
1045 ctl_be_block_biodone(bio);
1049 dev_relthread(dev, ref);
1053 ctl_be_block_unmap_dev(struct ctl_be_block_lun *be_lun,
1054 struct ctl_be_block_io *beio)
1057 struct ctl_ptr_len_flags *ptrlen;
1058 struct scsi_unmap_desc *buf, *end;
1063 DPRINTF("entered\n");
1065 binuptime(&beio->ds_t0);
1066 mtx_lock(&be_lun->io_lock);
1067 devstat_start_transaction(be_lun->disk_stats, &beio->ds_t0);
1068 mtx_unlock(&be_lun->io_lock);
1070 if (beio->io_offset == -1) {
1072 ptrlen = (struct ctl_ptr_len_flags *)&io->io_hdr.ctl_private[CTL_PRIV_LBA_LEN];
1073 buf = (struct scsi_unmap_desc *)ptrlen->ptr;
1074 end = buf + ptrlen->len / sizeof(*buf);
1075 for (; buf < end; buf++) {
1076 len = (uint64_t)scsi_4btoul(buf->length) *
1077 be_lun->cbe_lun.blocksize;
1078 beio->io_len += len;
1079 ctl_be_block_unmap_dev_range(be_lun, beio,
1080 scsi_8btou64(buf->lba) * be_lun->cbe_lun.blocksize,
1081 len, (end - buf < 2) ? TRUE : FALSE);
1084 ctl_be_block_unmap_dev_range(be_lun, beio,
1085 beio->io_offset, beio->io_len, TRUE);
1089 ctl_be_block_dispatch_dev(struct ctl_be_block_lun *be_lun,
1090 struct ctl_be_block_io *beio)
1092 TAILQ_HEAD(, bio) queue = TAILQ_HEAD_INITIALIZER(queue);
1097 int i, max_iosize, ref;
1099 DPRINTF("entered\n");
1100 csw = devvn_refthread(be_lun->vn, &dev, &ref);
1103 * We have to limit our I/O size to the maximum supported by the
1104 * backend device. Hopefully it is MAXPHYS. If the driver doesn't
1105 * set it properly, use DFLTPHYS.
1108 max_iosize = dev->si_iosize_max;
1109 if (max_iosize < PAGE_SIZE)
1110 max_iosize = DFLTPHYS;
1112 max_iosize = DFLTPHYS;
1114 cur_offset = beio->io_offset;
1115 for (i = 0; i < beio->num_segs; i++) {
1119 cur_size = beio->sg_segs[i].len;
1120 cur_ptr = beio->sg_segs[i].addr;
1122 while (cur_size > 0) {
1123 /* This can't fail, it's a blocking allocation. */
1124 bio = g_alloc_bio();
1126 KASSERT(bio != NULL, ("g_alloc_bio() failed!\n"));
1128 bio->bio_cmd = beio->bio_cmd;
1130 bio->bio_caller1 = beio;
1131 bio->bio_length = min(cur_size, max_iosize);
1132 bio->bio_offset = cur_offset;
1133 bio->bio_data = cur_ptr;
1134 bio->bio_done = ctl_be_block_biodone;
1135 bio->bio_pblkno = cur_offset / be_lun->cbe_lun.blocksize;
1137 cur_offset += bio->bio_length;
1138 cur_ptr += bio->bio_length;
1139 cur_size -= bio->bio_length;
1141 TAILQ_INSERT_TAIL(&queue, bio, bio_queue);
1142 beio->num_bios_sent++;
1145 binuptime(&beio->ds_t0);
1146 mtx_lock(&be_lun->io_lock);
1147 devstat_start_transaction(be_lun->disk_stats, &beio->ds_t0);
1148 beio->send_complete = 1;
1149 mtx_unlock(&be_lun->io_lock);
1152 * Fire off all allocated requests!
1154 while ((bio = TAILQ_FIRST(&queue)) != NULL) {
1155 TAILQ_REMOVE(&queue, bio, bio_queue);
1157 csw->d_strategy(bio);
1159 bio->bio_error = ENXIO;
1160 ctl_be_block_biodone(bio);
1164 dev_relthread(dev, ref);
1168 ctl_be_block_getattr_dev(struct ctl_be_block_lun *be_lun, const char *attrname)
1170 struct diocgattr_arg arg;
1175 csw = devvn_refthread(be_lun->vn, &dev, &ref);
1177 return (UINT64_MAX);
1178 strlcpy(arg.name, attrname, sizeof(arg.name));
1179 arg.len = sizeof(arg.value.off);
1181 error = csw->d_ioctl(dev, DIOCGATTR, (caddr_t)&arg, FREAD,
1185 dev_relthread(dev, ref);
1187 return (UINT64_MAX);
1188 return (arg.value.off);
1192 ctl_be_block_cw_dispatch_sync(struct ctl_be_block_lun *be_lun,
1195 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
1196 struct ctl_be_block_io *beio;
1197 struct ctl_lba_len_flags *lbalen;
1199 DPRINTF("entered\n");
1200 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
1201 lbalen = (struct ctl_lba_len_flags *)&io->io_hdr.ctl_private[CTL_PRIV_LBA_LEN];
1203 beio->io_len = lbalen->len * cbe_lun->blocksize;
1204 beio->io_offset = lbalen->lba * cbe_lun->blocksize;
1205 beio->io_arg = (lbalen->flags & SSC_IMMED) != 0;
1206 beio->bio_cmd = BIO_FLUSH;
1207 beio->ds_trans_type = DEVSTAT_NO_DATA;
1209 be_lun->lun_flush(be_lun, beio);
1213 ctl_be_block_cw_done_ws(struct ctl_be_block_io *beio)
1218 ctl_free_beio(beio);
1219 if ((io->io_hdr.flags & CTL_FLAG_ABORT) ||
1220 ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE &&
1221 (io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS)) {
1222 ctl_config_write_done(io);
1226 ctl_be_block_config_write(io);
1230 ctl_be_block_cw_dispatch_ws(struct ctl_be_block_lun *be_lun,
1233 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
1234 struct ctl_be_block_io *beio;
1235 struct ctl_lba_len_flags *lbalen;
1236 uint64_t len_left, lba;
1237 uint32_t pb, pbo, adj;
1241 DPRINTF("entered\n");
1243 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
1244 lbalen = ARGS(beio->io);
1246 if (lbalen->flags & ~(SWS_LBDATA | SWS_UNMAP | SWS_ANCHOR | SWS_NDOB) ||
1247 (lbalen->flags & (SWS_UNMAP | SWS_ANCHOR) && be_lun->unmap == NULL)) {
1248 ctl_free_beio(beio);
1249 ctl_set_invalid_field(&io->scsiio,
1255 ctl_config_write_done(io);
1259 if (lbalen->flags & (SWS_UNMAP | SWS_ANCHOR)) {
1260 beio->io_offset = lbalen->lba * cbe_lun->blocksize;
1261 beio->io_len = (uint64_t)lbalen->len * cbe_lun->blocksize;
1262 beio->bio_cmd = BIO_DELETE;
1263 beio->ds_trans_type = DEVSTAT_FREE;
1265 be_lun->unmap(be_lun, beio);
1269 beio->bio_cmd = BIO_WRITE;
1270 beio->ds_trans_type = DEVSTAT_WRITE;
1272 DPRINTF("WRITE SAME at LBA %jx len %u\n",
1273 (uintmax_t)lbalen->lba, lbalen->len);
1275 pb = cbe_lun->blocksize << be_lun->cbe_lun.pblockexp;
1276 if (be_lun->cbe_lun.pblockoff > 0)
1277 pbo = pb - cbe_lun->blocksize * be_lun->cbe_lun.pblockoff;
1280 len_left = (uint64_t)lbalen->len * cbe_lun->blocksize;
1281 for (i = 0, lba = 0; i < CTLBLK_MAX_SEGS && len_left > 0; i++) {
1284 * Setup the S/G entry for this chunk.
1286 seglen = MIN(CTLBLK_MAX_SEG, len_left);
1287 if (pb > cbe_lun->blocksize) {
1288 adj = ((lbalen->lba + lba) * cbe_lun->blocksize +
1293 seglen -= seglen % cbe_lun->blocksize;
1295 seglen -= seglen % cbe_lun->blocksize;
1296 beio->sg_segs[i].len = seglen;
1297 beio->sg_segs[i].addr = uma_zalloc(be_lun->lun_zone, M_WAITOK);
1299 DPRINTF("segment %d addr %p len %zd\n", i,
1300 beio->sg_segs[i].addr, beio->sg_segs[i].len);
1305 buf = beio->sg_segs[i].addr;
1307 for (; buf < end; buf += cbe_lun->blocksize) {
1308 memcpy(buf, io->scsiio.kern_data_ptr, cbe_lun->blocksize);
1309 if (lbalen->flags & SWS_LBDATA)
1310 scsi_ulto4b(lbalen->lba + lba, buf);
1315 beio->io_offset = lbalen->lba * cbe_lun->blocksize;
1316 beio->io_len = lba * cbe_lun->blocksize;
1318 /* We can not do all in one run. Correct and schedule rerun. */
1322 beio->beio_cont = ctl_be_block_cw_done_ws;
1325 be_lun->dispatch(be_lun, beio);
1329 ctl_be_block_cw_dispatch_unmap(struct ctl_be_block_lun *be_lun,
1332 struct ctl_be_block_io *beio;
1333 struct ctl_ptr_len_flags *ptrlen;
1335 DPRINTF("entered\n");
1337 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
1338 ptrlen = (struct ctl_ptr_len_flags *)&io->io_hdr.ctl_private[CTL_PRIV_LBA_LEN];
1340 if ((ptrlen->flags & ~SU_ANCHOR) != 0 || be_lun->unmap == NULL) {
1341 ctl_free_beio(beio);
1342 ctl_set_invalid_field(&io->scsiio,
1348 ctl_config_write_done(io);
1353 beio->io_offset = -1;
1354 beio->bio_cmd = BIO_DELETE;
1355 beio->ds_trans_type = DEVSTAT_FREE;
1357 be_lun->unmap(be_lun, beio);
1361 ctl_be_block_cr_done(struct ctl_be_block_io *beio)
1366 ctl_free_beio(beio);
1367 ctl_config_read_done(io);
1371 ctl_be_block_cr_dispatch(struct ctl_be_block_lun *be_lun,
1374 struct ctl_be_block_io *beio;
1375 struct ctl_be_block_softc *softc;
1377 DPRINTF("entered\n");
1379 softc = be_lun->softc;
1380 beio = ctl_alloc_beio(softc);
1383 beio->beio_cont = ctl_be_block_cr_done;
1384 PRIV(io)->ptr = (void *)beio;
1386 switch (io->scsiio.cdb[0]) {
1387 case SERVICE_ACTION_IN: /* GET LBA STATUS */
1389 beio->ds_trans_type = DEVSTAT_NO_DATA;
1390 beio->ds_tag_type = DEVSTAT_TAG_ORDERED;
1392 if (be_lun->get_lba_status)
1393 be_lun->get_lba_status(be_lun, beio);
1395 ctl_be_block_cr_done(beio);
1398 panic("Unhandled CDB type %#x", io->scsiio.cdb[0]);
1404 ctl_be_block_cw_done(struct ctl_be_block_io *beio)
1409 ctl_free_beio(beio);
1410 ctl_config_write_done(io);
1414 ctl_be_block_cw_dispatch(struct ctl_be_block_lun *be_lun,
1417 struct ctl_be_block_io *beio;
1418 struct ctl_be_block_softc *softc;
1420 DPRINTF("entered\n");
1422 softc = be_lun->softc;
1423 beio = ctl_alloc_beio(softc);
1426 beio->beio_cont = ctl_be_block_cw_done;
1427 switch (io->scsiio.tag_type) {
1428 case CTL_TAG_ORDERED:
1429 beio->ds_tag_type = DEVSTAT_TAG_ORDERED;
1431 case CTL_TAG_HEAD_OF_QUEUE:
1432 beio->ds_tag_type = DEVSTAT_TAG_HEAD;
1434 case CTL_TAG_UNTAGGED:
1435 case CTL_TAG_SIMPLE:
1438 beio->ds_tag_type = DEVSTAT_TAG_SIMPLE;
1441 PRIV(io)->ptr = (void *)beio;
1443 switch (io->scsiio.cdb[0]) {
1444 case SYNCHRONIZE_CACHE:
1445 case SYNCHRONIZE_CACHE_16:
1446 ctl_be_block_cw_dispatch_sync(be_lun, io);
1450 ctl_be_block_cw_dispatch_ws(be_lun, io);
1453 ctl_be_block_cw_dispatch_unmap(be_lun, io);
1456 panic("Unhandled CDB type %#x", io->scsiio.cdb[0]);
1461 SDT_PROBE_DEFINE1(cbb, kernel, read, start, "uint64_t");
1462 SDT_PROBE_DEFINE1(cbb, kernel, write, start, "uint64_t");
1463 SDT_PROBE_DEFINE1(cbb, kernel, read, alloc_done, "uint64_t");
1464 SDT_PROBE_DEFINE1(cbb, kernel, write, alloc_done, "uint64_t");
1467 ctl_be_block_next(struct ctl_be_block_io *beio)
1469 struct ctl_be_block_lun *be_lun;
1474 ctl_free_beio(beio);
1475 if ((io->io_hdr.flags & CTL_FLAG_ABORT) ||
1476 ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE &&
1477 (io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS)) {
1478 ctl_data_submit_done(io);
1482 io->io_hdr.status &= ~CTL_STATUS_MASK;
1483 io->io_hdr.status |= CTL_STATUS_NONE;
1485 mtx_lock(&be_lun->queue_lock);
1487 * XXX KDM make sure that links is okay to use at this point.
1488 * Otherwise, we either need to add another field to ctl_io_hdr,
1489 * or deal with resource allocation here.
1491 STAILQ_INSERT_TAIL(&be_lun->input_queue, &io->io_hdr, links);
1492 mtx_unlock(&be_lun->queue_lock);
1494 taskqueue_enqueue(be_lun->io_taskqueue, &be_lun->io_task);
1498 ctl_be_block_dispatch(struct ctl_be_block_lun *be_lun,
1501 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
1502 struct ctl_be_block_io *beio;
1503 struct ctl_be_block_softc *softc;
1504 struct ctl_lba_len_flags *lbalen;
1505 struct ctl_ptr_len_flags *bptrlen;
1506 uint64_t len_left, lbas;
1509 softc = be_lun->softc;
1511 DPRINTF("entered\n");
1514 if (lbalen->flags & CTL_LLF_WRITE) {
1515 SDT_PROBE(cbb, kernel, write, start, 0, 0, 0, 0, 0);
1517 SDT_PROBE(cbb, kernel, read, start, 0, 0, 0, 0, 0);
1520 beio = ctl_alloc_beio(softc);
1524 bptrlen->ptr = (void *)beio;
1526 switch (io->scsiio.tag_type) {
1527 case CTL_TAG_ORDERED:
1528 beio->ds_tag_type = DEVSTAT_TAG_ORDERED;
1530 case CTL_TAG_HEAD_OF_QUEUE:
1531 beio->ds_tag_type = DEVSTAT_TAG_HEAD;
1533 case CTL_TAG_UNTAGGED:
1534 case CTL_TAG_SIMPLE:
1537 beio->ds_tag_type = DEVSTAT_TAG_SIMPLE;
1541 if (lbalen->flags & CTL_LLF_WRITE) {
1542 beio->bio_cmd = BIO_WRITE;
1543 beio->ds_trans_type = DEVSTAT_WRITE;
1545 beio->bio_cmd = BIO_READ;
1546 beio->ds_trans_type = DEVSTAT_READ;
1549 DPRINTF("%s at LBA %jx len %u @%ju\n",
1550 (beio->bio_cmd == BIO_READ) ? "READ" : "WRITE",
1551 (uintmax_t)lbalen->lba, lbalen->len, bptrlen->len);
1552 if (lbalen->flags & CTL_LLF_COMPARE)
1553 lbas = CTLBLK_HALF_IO_SIZE;
1555 lbas = CTLBLK_MAX_IO_SIZE;
1556 lbas = MIN(lbalen->len - bptrlen->len, lbas / cbe_lun->blocksize);
1557 beio->io_offset = (lbalen->lba + bptrlen->len) * cbe_lun->blocksize;
1558 beio->io_len = lbas * cbe_lun->blocksize;
1559 bptrlen->len += lbas;
1561 for (i = 0, len_left = beio->io_len; len_left > 0; i++) {
1562 KASSERT(i < CTLBLK_MAX_SEGS, ("Too many segs (%d >= %d)",
1563 i, CTLBLK_MAX_SEGS));
1566 * Setup the S/G entry for this chunk.
1568 beio->sg_segs[i].len = min(CTLBLK_MAX_SEG, len_left);
1569 beio->sg_segs[i].addr = uma_zalloc(be_lun->lun_zone, M_WAITOK);
1571 DPRINTF("segment %d addr %p len %zd\n", i,
1572 beio->sg_segs[i].addr, beio->sg_segs[i].len);
1574 /* Set up second segment for compare operation. */
1575 if (lbalen->flags & CTL_LLF_COMPARE) {
1576 beio->sg_segs[i + CTLBLK_HALF_SEGS].len =
1577 beio->sg_segs[i].len;
1578 beio->sg_segs[i + CTLBLK_HALF_SEGS].addr =
1579 uma_zalloc(be_lun->lun_zone, M_WAITOK);
1583 len_left -= beio->sg_segs[i].len;
1585 if (bptrlen->len < lbalen->len)
1586 beio->beio_cont = ctl_be_block_next;
1587 io->scsiio.be_move_done = ctl_be_block_move_done;
1588 /* For compare we have separate S/G lists for read and datamove. */
1589 if (lbalen->flags & CTL_LLF_COMPARE)
1590 io->scsiio.kern_data_ptr = (uint8_t *)&beio->sg_segs[CTLBLK_HALF_SEGS];
1592 io->scsiio.kern_data_ptr = (uint8_t *)beio->sg_segs;
1593 io->scsiio.kern_data_len = beio->io_len;
1594 io->scsiio.kern_data_resid = 0;
1595 io->scsiio.kern_sg_entries = beio->num_segs;
1596 io->io_hdr.flags |= CTL_FLAG_ALLOCATED | CTL_FLAG_KDPTR_SGLIST;
1599 * For the read case, we need to read the data into our buffers and
1600 * then we can send it back to the user. For the write case, we
1601 * need to get the data from the user first.
1603 if (beio->bio_cmd == BIO_READ) {
1604 SDT_PROBE(cbb, kernel, read, alloc_done, 0, 0, 0, 0, 0);
1605 be_lun->dispatch(be_lun, beio);
1607 SDT_PROBE(cbb, kernel, write, alloc_done, 0, 0, 0, 0, 0);
1609 getbintime(&io->io_hdr.dma_start_bt);
1616 ctl_be_block_worker(void *context, int pending)
1618 struct ctl_be_block_lun *be_lun = (struct ctl_be_block_lun *)context;
1619 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
1621 struct ctl_be_block_io *beio;
1623 DPRINTF("entered\n");
1625 * Fetch and process I/Os from all queues. If we detect LUN
1626 * CTL_LUN_FLAG_OFFLINE status here -- it is result of a race,
1627 * so make response maximally opaque to not confuse initiator.
1630 mtx_lock(&be_lun->queue_lock);
1631 io = (union ctl_io *)STAILQ_FIRST(&be_lun->datamove_queue);
1633 DPRINTF("datamove queue\n");
1634 STAILQ_REMOVE(&be_lun->datamove_queue, &io->io_hdr,
1636 mtx_unlock(&be_lun->queue_lock);
1637 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
1638 if (cbe_lun->flags & CTL_LUN_FLAG_OFFLINE) {
1639 ctl_set_busy(&io->scsiio);
1640 ctl_complete_beio(beio);
1643 be_lun->dispatch(be_lun, beio);
1646 io = (union ctl_io *)STAILQ_FIRST(&be_lun->config_write_queue);
1648 DPRINTF("config write queue\n");
1649 STAILQ_REMOVE(&be_lun->config_write_queue, &io->io_hdr,
1651 mtx_unlock(&be_lun->queue_lock);
1652 if (cbe_lun->flags & CTL_LUN_FLAG_OFFLINE) {
1653 ctl_set_busy(&io->scsiio);
1654 ctl_config_write_done(io);
1657 ctl_be_block_cw_dispatch(be_lun, io);
1660 io = (union ctl_io *)STAILQ_FIRST(&be_lun->config_read_queue);
1662 DPRINTF("config read queue\n");
1663 STAILQ_REMOVE(&be_lun->config_read_queue, &io->io_hdr,
1665 mtx_unlock(&be_lun->queue_lock);
1666 if (cbe_lun->flags & CTL_LUN_FLAG_OFFLINE) {
1667 ctl_set_busy(&io->scsiio);
1668 ctl_config_read_done(io);
1671 ctl_be_block_cr_dispatch(be_lun, io);
1674 io = (union ctl_io *)STAILQ_FIRST(&be_lun->input_queue);
1676 DPRINTF("input queue\n");
1677 STAILQ_REMOVE(&be_lun->input_queue, &io->io_hdr,
1679 mtx_unlock(&be_lun->queue_lock);
1680 if (cbe_lun->flags & CTL_LUN_FLAG_OFFLINE) {
1681 ctl_set_busy(&io->scsiio);
1682 ctl_data_submit_done(io);
1685 ctl_be_block_dispatch(be_lun, io);
1690 * If we get here, there is no work left in the queues, so
1691 * just break out and let the task queue go to sleep.
1693 mtx_unlock(&be_lun->queue_lock);
1699 * Entry point from CTL to the backend for I/O. We queue everything to a
1700 * work thread, so this just puts the I/O on a queue and wakes up the
1704 ctl_be_block_submit(union ctl_io *io)
1706 struct ctl_be_block_lun *be_lun;
1707 struct ctl_be_lun *cbe_lun;
1709 DPRINTF("entered\n");
1711 cbe_lun = (struct ctl_be_lun *)io->io_hdr.ctl_private[
1712 CTL_PRIV_BACKEND_LUN].ptr;
1713 be_lun = (struct ctl_be_block_lun *)cbe_lun->be_lun;
1716 * Make sure we only get SCSI I/O.
1718 KASSERT(io->io_hdr.io_type == CTL_IO_SCSI, ("Non-SCSI I/O (type "
1719 "%#x) encountered", io->io_hdr.io_type));
1723 mtx_lock(&be_lun->queue_lock);
1725 * XXX KDM make sure that links is okay to use at this point.
1726 * Otherwise, we either need to add another field to ctl_io_hdr,
1727 * or deal with resource allocation here.
1729 STAILQ_INSERT_TAIL(&be_lun->input_queue, &io->io_hdr, links);
1730 mtx_unlock(&be_lun->queue_lock);
1731 taskqueue_enqueue(be_lun->io_taskqueue, &be_lun->io_task);
1733 return (CTL_RETVAL_COMPLETE);
1737 ctl_be_block_ioctl(struct cdev *dev, u_long cmd, caddr_t addr,
1738 int flag, struct thread *td)
1740 struct ctl_be_block_softc *softc;
1743 softc = &backend_block_softc;
1749 struct ctl_lun_req *lun_req;
1751 lun_req = (struct ctl_lun_req *)addr;
1753 switch (lun_req->reqtype) {
1754 case CTL_LUNREQ_CREATE:
1755 error = ctl_be_block_create(softc, lun_req);
1758 error = ctl_be_block_rm(softc, lun_req);
1760 case CTL_LUNREQ_MODIFY:
1761 error = ctl_be_block_modify(softc, lun_req);
1764 lun_req->status = CTL_LUN_ERROR;
1765 snprintf(lun_req->error_str, sizeof(lun_req->error_str),
1766 "invalid LUN request type %d",
1781 ctl_be_block_open_file(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
1783 struct ctl_be_lun *cbe_lun;
1784 struct ctl_be_block_filedata *file_data;
1785 struct ctl_lun_create_params *params;
1788 off_t ps, pss, po, pos, us, uss, uo, uos;
1792 cbe_lun = &be_lun->cbe_lun;
1793 file_data = &be_lun->backend.file;
1794 params = &be_lun->params;
1796 be_lun->dev_type = CTL_BE_BLOCK_FILE;
1797 be_lun->dispatch = ctl_be_block_dispatch_file;
1798 be_lun->lun_flush = ctl_be_block_flush_file;
1799 be_lun->get_lba_status = ctl_be_block_gls_file;
1800 be_lun->getattr = ctl_be_block_getattr_file;
1801 be_lun->unmap = NULL;
1802 cbe_lun->flags &= ~CTL_LUN_FLAG_UNMAP;
1804 error = VOP_GETATTR(be_lun->vn, &vattr, curthread->td_ucred);
1806 snprintf(req->error_str, sizeof(req->error_str),
1807 "error calling VOP_GETATTR() for file %s",
1813 * Verify that we have the ability to upgrade to exclusive
1814 * access on this file so we can trap errors at open instead
1815 * of reporting them during first access.
1817 if (VOP_ISLOCKED(be_lun->vn) != LK_EXCLUSIVE) {
1818 vn_lock(be_lun->vn, LK_UPGRADE | LK_RETRY);
1819 if (be_lun->vn->v_iflag & VI_DOOMED) {
1821 snprintf(req->error_str, sizeof(req->error_str),
1822 "error locking file %s", be_lun->dev_path);
1827 file_data->cred = crhold(curthread->td_ucred);
1828 if (params->lun_size_bytes != 0)
1829 be_lun->size_bytes = params->lun_size_bytes;
1831 be_lun->size_bytes = vattr.va_size;
1834 * For files we can use any logical block size. Prefer 512 bytes
1835 * for compatibility reasons. If file's vattr.va_blocksize
1836 * (preferred I/O block size) is bigger and multiple to chosen
1837 * logical block size -- report it as physical block size.
1839 if (params->blocksize_bytes != 0)
1840 cbe_lun->blocksize = params->blocksize_bytes;
1842 cbe_lun->blocksize = 512;
1843 be_lun->size_blocks = be_lun->size_bytes / cbe_lun->blocksize;
1844 cbe_lun->maxlba = (be_lun->size_blocks == 0) ?
1845 0 : (be_lun->size_blocks - 1);
1847 us = ps = vattr.va_blocksize;
1850 value = ctl_get_opt(&cbe_lun->options, "pblocksize");
1852 ctl_expand_number(value, &ps);
1853 value = ctl_get_opt(&cbe_lun->options, "pblockoffset");
1855 ctl_expand_number(value, &po);
1856 pss = ps / cbe_lun->blocksize;
1857 pos = po / cbe_lun->blocksize;
1858 if ((pss > 0) && (pss * cbe_lun->blocksize == ps) && (pss >= pos) &&
1859 ((pss & (pss - 1)) == 0) && (pos * cbe_lun->blocksize == po)) {
1860 cbe_lun->pblockexp = fls(pss) - 1;
1861 cbe_lun->pblockoff = (pss - pos) % pss;
1864 value = ctl_get_opt(&cbe_lun->options, "ublocksize");
1866 ctl_expand_number(value, &us);
1867 value = ctl_get_opt(&cbe_lun->options, "ublockoffset");
1869 ctl_expand_number(value, &uo);
1870 uss = us / cbe_lun->blocksize;
1871 uos = uo / cbe_lun->blocksize;
1872 if ((uss > 0) && (uss * cbe_lun->blocksize == us) && (uss >= uos) &&
1873 ((uss & (uss - 1)) == 0) && (uos * cbe_lun->blocksize == uo)) {
1874 cbe_lun->ublockexp = fls(uss) - 1;
1875 cbe_lun->ublockoff = (uss - uos) % uss;
1879 * Sanity check. The media size has to be at least one
1882 if (be_lun->size_bytes < cbe_lun->blocksize) {
1884 snprintf(req->error_str, sizeof(req->error_str),
1885 "file %s size %ju < block size %u", be_lun->dev_path,
1886 (uintmax_t)be_lun->size_bytes, cbe_lun->blocksize);
1889 cbe_lun->opttxferlen = CTLBLK_MAX_IO_SIZE / cbe_lun->blocksize;
1894 ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
1896 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
1897 struct ctl_lun_create_params *params;
1901 int error, atomic, maxio, ref, unmap, tmp;
1902 off_t ps, pss, po, pos, us, uss, uo, uos, otmp;
1904 params = &be_lun->params;
1906 be_lun->dev_type = CTL_BE_BLOCK_DEV;
1907 csw = devvn_refthread(be_lun->vn, &dev, &ref);
1910 if (strcmp(csw->d_name, "zvol") == 0) {
1911 be_lun->dispatch = ctl_be_block_dispatch_zvol;
1912 be_lun->get_lba_status = ctl_be_block_gls_zvol;
1913 atomic = maxio = CTLBLK_MAX_IO_SIZE;
1915 be_lun->dispatch = ctl_be_block_dispatch_dev;
1916 be_lun->get_lba_status = NULL;
1918 maxio = dev->si_iosize_max;
1921 if (maxio > CTLBLK_MAX_IO_SIZE)
1922 maxio = CTLBLK_MAX_IO_SIZE;
1924 be_lun->lun_flush = ctl_be_block_flush_dev;
1925 be_lun->getattr = ctl_be_block_getattr_dev;
1926 be_lun->unmap = ctl_be_block_unmap_dev;
1928 if (!csw->d_ioctl) {
1929 dev_relthread(dev, ref);
1930 snprintf(req->error_str, sizeof(req->error_str),
1931 "no d_ioctl for device %s!", be_lun->dev_path);
1935 error = csw->d_ioctl(dev, DIOCGSECTORSIZE, (caddr_t)&tmp, FREAD,
1938 dev_relthread(dev, ref);
1939 snprintf(req->error_str, sizeof(req->error_str),
1940 "error %d returned for DIOCGSECTORSIZE ioctl "
1941 "on %s!", error, be_lun->dev_path);
1946 * If the user has asked for a blocksize that is greater than the
1947 * backing device's blocksize, we can do it only if the blocksize
1948 * the user is asking for is an even multiple of the underlying
1949 * device's blocksize.
1951 if ((params->blocksize_bytes != 0) &&
1952 (params->blocksize_bytes >= tmp)) {
1953 if (params->blocksize_bytes % tmp == 0) {
1954 cbe_lun->blocksize = params->blocksize_bytes;
1956 dev_relthread(dev, ref);
1957 snprintf(req->error_str, sizeof(req->error_str),
1958 "requested blocksize %u is not an even "
1959 "multiple of backing device blocksize %u",
1960 params->blocksize_bytes, tmp);
1963 } else if (params->blocksize_bytes != 0) {
1964 dev_relthread(dev, ref);
1965 snprintf(req->error_str, sizeof(req->error_str),
1966 "requested blocksize %u < backing device "
1967 "blocksize %u", params->blocksize_bytes, tmp);
1970 cbe_lun->blocksize = tmp;
1972 error = csw->d_ioctl(dev, DIOCGMEDIASIZE, (caddr_t)&otmp, FREAD,
1975 dev_relthread(dev, ref);
1976 snprintf(req->error_str, sizeof(req->error_str),
1977 "error %d returned for DIOCGMEDIASIZE "
1978 " ioctl on %s!", error,
1983 if (params->lun_size_bytes != 0) {
1984 if (params->lun_size_bytes > otmp) {
1985 dev_relthread(dev, ref);
1986 snprintf(req->error_str, sizeof(req->error_str),
1987 "requested LUN size %ju > backing device "
1989 (uintmax_t)params->lun_size_bytes,
1994 be_lun->size_bytes = params->lun_size_bytes;
1996 be_lun->size_bytes = otmp;
1997 be_lun->size_blocks = be_lun->size_bytes / cbe_lun->blocksize;
1998 cbe_lun->maxlba = (be_lun->size_blocks == 0) ?
1999 0 : (be_lun->size_blocks - 1);
2001 error = csw->d_ioctl(dev, DIOCGSTRIPESIZE, (caddr_t)&ps, FREAD,
2006 error = csw->d_ioctl(dev, DIOCGSTRIPEOFFSET, (caddr_t)&po,
2014 value = ctl_get_opt(&cbe_lun->options, "pblocksize");
2016 ctl_expand_number(value, &ps);
2017 value = ctl_get_opt(&cbe_lun->options, "pblockoffset");
2019 ctl_expand_number(value, &po);
2020 pss = ps / cbe_lun->blocksize;
2021 pos = po / cbe_lun->blocksize;
2022 if ((pss > 0) && (pss * cbe_lun->blocksize == ps) && (pss >= pos) &&
2023 ((pss & (pss - 1)) == 0) && (pos * cbe_lun->blocksize == po)) {
2024 cbe_lun->pblockexp = fls(pss) - 1;
2025 cbe_lun->pblockoff = (pss - pos) % pss;
2028 value = ctl_get_opt(&cbe_lun->options, "ublocksize");
2030 ctl_expand_number(value, &us);
2031 value = ctl_get_opt(&cbe_lun->options, "ublockoffset");
2033 ctl_expand_number(value, &uo);
2034 uss = us / cbe_lun->blocksize;
2035 uos = uo / cbe_lun->blocksize;
2036 if ((uss > 0) && (uss * cbe_lun->blocksize == us) && (uss >= uos) &&
2037 ((uss & (uss - 1)) == 0) && (uos * cbe_lun->blocksize == uo)) {
2038 cbe_lun->ublockexp = fls(uss) - 1;
2039 cbe_lun->ublockoff = (uss - uos) % uss;
2042 cbe_lun->atomicblock = atomic / cbe_lun->blocksize;
2043 cbe_lun->opttxferlen = maxio / cbe_lun->blocksize;
2045 if (be_lun->dispatch == ctl_be_block_dispatch_zvol) {
2048 struct diocgattr_arg arg;
2050 strlcpy(arg.name, "GEOM::candelete", sizeof(arg.name));
2051 arg.len = sizeof(arg.value.i);
2052 error = csw->d_ioctl(dev, DIOCGATTR, (caddr_t)&arg, FREAD,
2054 unmap = (error == 0) ? arg.value.i : 0;
2056 value = ctl_get_opt(&cbe_lun->options, "unmap");
2058 unmap = (strcmp(value, "on") == 0);
2060 cbe_lun->flags |= CTL_LUN_FLAG_UNMAP;
2062 cbe_lun->flags &= ~CTL_LUN_FLAG_UNMAP;
2064 dev_relthread(dev, ref);
2069 ctl_be_block_close(struct ctl_be_block_lun *be_lun)
2071 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
2076 if ((cbe_lun->flags & CTL_LUN_FLAG_READONLY) == 0)
2078 (void)vn_close(be_lun->vn, flags, NOCRED, curthread);
2081 switch (be_lun->dev_type) {
2082 case CTL_BE_BLOCK_DEV:
2084 case CTL_BE_BLOCK_FILE:
2085 if (be_lun->backend.file.cred != NULL) {
2086 crfree(be_lun->backend.file.cred);
2087 be_lun->backend.file.cred = NULL;
2090 case CTL_BE_BLOCK_NONE:
2093 panic("Unexpected backend type.");
2096 be_lun->dev_type = CTL_BE_BLOCK_NONE;
2102 ctl_be_block_open(struct ctl_be_block_softc *softc,
2103 struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
2105 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
2106 struct nameidata nd;
2111 if (rootvnode == NULL) {
2112 snprintf(req->error_str, sizeof(req->error_str),
2113 "Root filesystem is not mounted");
2118 value = ctl_get_opt(&cbe_lun->options, "file");
2119 if (value == NULL) {
2120 snprintf(req->error_str, sizeof(req->error_str),
2121 "no file argument specified");
2124 free(be_lun->dev_path, M_CTLBLK);
2125 be_lun->dev_path = strdup(value, M_CTLBLK);
2128 value = ctl_get_opt(&cbe_lun->options, "readonly");
2129 if (value == NULL || strcmp(value, "on") != 0)
2133 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, be_lun->dev_path, curthread);
2134 error = vn_open(&nd, &flags, 0, NULL);
2135 if ((error == EROFS || error == EACCES) && (flags & FWRITE)) {
2141 * This is the only reasonable guess we can make as far as
2142 * path if the user doesn't give us a fully qualified path.
2143 * If they want to specify a file, they need to specify the
2146 if (be_lun->dev_path[0] != '/') {
2149 asprintf(&dev_name, M_CTLBLK, "/dev/%s",
2151 free(be_lun->dev_path, M_CTLBLK);
2152 be_lun->dev_path = dev_name;
2155 snprintf(req->error_str, sizeof(req->error_str),
2156 "error opening %s: %d", be_lun->dev_path, error);
2160 cbe_lun->flags &= ~CTL_LUN_FLAG_READONLY;
2162 cbe_lun->flags |= CTL_LUN_FLAG_READONLY;
2164 NDFREE(&nd, NDF_ONLY_PNBUF);
2165 be_lun->vn = nd.ni_vp;
2167 /* We only support disks and files. */
2168 if (vn_isdisk(be_lun->vn, &error)) {
2169 error = ctl_be_block_open_dev(be_lun, req);
2170 } else if (be_lun->vn->v_type == VREG) {
2171 error = ctl_be_block_open_file(be_lun, req);
2174 snprintf(req->error_str, sizeof(req->error_str),
2175 "%s is not a disk or plain file", be_lun->dev_path);
2177 VOP_UNLOCK(be_lun->vn, 0);
2180 ctl_be_block_close(be_lun);
2181 cbe_lun->serseq = CTL_LUN_SERSEQ_OFF;
2182 if (be_lun->dispatch != ctl_be_block_dispatch_dev)
2183 cbe_lun->serseq = CTL_LUN_SERSEQ_READ;
2184 value = ctl_get_opt(&cbe_lun->options, "serseq");
2185 if (value != NULL && strcmp(value, "on") == 0)
2186 cbe_lun->serseq = CTL_LUN_SERSEQ_ON;
2187 else if (value != NULL && strcmp(value, "read") == 0)
2188 cbe_lun->serseq = CTL_LUN_SERSEQ_READ;
2189 else if (value != NULL && strcmp(value, "off") == 0)
2190 cbe_lun->serseq = CTL_LUN_SERSEQ_OFF;
2195 ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
2197 struct ctl_be_lun *cbe_lun;
2198 struct ctl_be_block_lun *be_lun;
2199 struct ctl_lun_create_params *params;
2200 char num_thread_str[16];
2203 int retval, num_threads;
2204 int tmp_num_threads;
2206 params = &req->reqdata.create;
2208 req->status = CTL_LUN_OK;
2210 be_lun = malloc(sizeof(*be_lun), M_CTLBLK, M_ZERO | M_WAITOK);
2211 cbe_lun = &be_lun->cbe_lun;
2212 cbe_lun->be_lun = be_lun;
2213 be_lun->params = req->reqdata.create;
2214 be_lun->softc = softc;
2215 STAILQ_INIT(&be_lun->input_queue);
2216 STAILQ_INIT(&be_lun->config_read_queue);
2217 STAILQ_INIT(&be_lun->config_write_queue);
2218 STAILQ_INIT(&be_lun->datamove_queue);
2219 sprintf(be_lun->lunname, "cblk%d", softc->num_luns);
2220 mtx_init(&be_lun->io_lock, "cblk io lock", NULL, MTX_DEF);
2221 mtx_init(&be_lun->queue_lock, "cblk queue lock", NULL, MTX_DEF);
2222 ctl_init_opts(&cbe_lun->options,
2223 req->num_be_args, req->kern_be_args);
2224 be_lun->lun_zone = uma_zcreate(be_lun->lunname, CTLBLK_MAX_SEG,
2225 NULL, NULL, NULL, NULL, /*align*/ 0, /*flags*/0);
2226 if (be_lun->lun_zone == NULL) {
2227 snprintf(req->error_str, sizeof(req->error_str),
2228 "error allocating UMA zone");
2232 if (params->flags & CTL_LUN_FLAG_DEV_TYPE)
2233 cbe_lun->lun_type = params->device_type;
2235 cbe_lun->lun_type = T_DIRECT;
2236 be_lun->flags = CTL_BE_BLOCK_LUN_UNCONFIGURED;
2238 value = ctl_get_opt(&cbe_lun->options, "ha_role");
2239 if (value != NULL) {
2240 if (strcmp(value, "primary") == 0)
2241 cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY;
2242 } else if (control_softc->flags & CTL_FLAG_ACTIVE_SHELF)
2243 cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY;
2245 if (cbe_lun->lun_type == T_DIRECT) {
2246 be_lun->size_bytes = params->lun_size_bytes;
2247 if (params->blocksize_bytes != 0)
2248 cbe_lun->blocksize = params->blocksize_bytes;
2250 cbe_lun->blocksize = 512;
2251 be_lun->size_blocks = be_lun->size_bytes / cbe_lun->blocksize;
2252 cbe_lun->maxlba = (be_lun->size_blocks == 0) ?
2253 0 : (be_lun->size_blocks - 1);
2255 if ((cbe_lun->flags & CTL_LUN_FLAG_PRIMARY) ||
2256 control_softc->ha_mode == CTL_HA_MODE_SER_ONLY) {
2257 retval = ctl_be_block_open(softc, be_lun, req);
2260 req->status = CTL_LUN_WARNING;
2263 num_threads = cbb_num_threads;
2269 * XXX This searching loop might be refactored to be combined with
2272 value = ctl_get_opt(&cbe_lun->options, "num_threads");
2273 if (value != NULL) {
2274 tmp_num_threads = strtol(value, NULL, 0);
2277 * We don't let the user specify less than one
2278 * thread, but hope he's clueful enough not to
2279 * specify 1000 threads.
2281 if (tmp_num_threads < 1) {
2282 snprintf(req->error_str, sizeof(req->error_str),
2283 "invalid number of threads %s",
2287 num_threads = tmp_num_threads;
2290 if (be_lun->vn == NULL)
2291 cbe_lun->flags |= CTL_LUN_FLAG_OFFLINE;
2292 /* Tell the user the blocksize we ended up using */
2293 params->lun_size_bytes = be_lun->size_bytes;
2294 params->blocksize_bytes = cbe_lun->blocksize;
2295 if (params->flags & CTL_LUN_FLAG_ID_REQ) {
2296 cbe_lun->req_lun_id = params->req_lun_id;
2297 cbe_lun->flags |= CTL_LUN_FLAG_ID_REQ;
2299 cbe_lun->req_lun_id = 0;
2301 cbe_lun->lun_shutdown = ctl_be_block_lun_shutdown;
2302 cbe_lun->lun_config_status = ctl_be_block_lun_config_status;
2303 cbe_lun->be = &ctl_be_block_driver;
2305 if ((params->flags & CTL_LUN_FLAG_SERIAL_NUM) == 0) {
2306 snprintf(tmpstr, sizeof(tmpstr), "MYSERIAL%4d",
2308 strncpy((char *)cbe_lun->serial_num, tmpstr,
2309 MIN(sizeof(cbe_lun->serial_num), sizeof(tmpstr)));
2311 /* Tell the user what we used for a serial number */
2312 strncpy((char *)params->serial_num, tmpstr,
2313 MIN(sizeof(params->serial_num), sizeof(tmpstr)));
2315 strncpy((char *)cbe_lun->serial_num, params->serial_num,
2316 MIN(sizeof(cbe_lun->serial_num),
2317 sizeof(params->serial_num)));
2319 if ((params->flags & CTL_LUN_FLAG_DEVID) == 0) {
2320 snprintf(tmpstr, sizeof(tmpstr), "MYDEVID%4d", softc->num_luns);
2321 strncpy((char *)cbe_lun->device_id, tmpstr,
2322 MIN(sizeof(cbe_lun->device_id), sizeof(tmpstr)));
2324 /* Tell the user what we used for a device ID */
2325 strncpy((char *)params->device_id, tmpstr,
2326 MIN(sizeof(params->device_id), sizeof(tmpstr)));
2328 strncpy((char *)cbe_lun->device_id, params->device_id,
2329 MIN(sizeof(cbe_lun->device_id),
2330 sizeof(params->device_id)));
2333 TASK_INIT(&be_lun->io_task, /*priority*/0, ctl_be_block_worker, be_lun);
2335 be_lun->io_taskqueue = taskqueue_create(be_lun->lunname, M_WAITOK,
2336 taskqueue_thread_enqueue, /*context*/&be_lun->io_taskqueue);
2338 if (be_lun->io_taskqueue == NULL) {
2339 snprintf(req->error_str, sizeof(req->error_str),
2340 "unable to create taskqueue");
2345 * Note that we start the same number of threads by default for
2346 * both the file case and the block device case. For the file
2347 * case, we need multiple threads to allow concurrency, because the
2348 * vnode interface is designed to be a blocking interface. For the
2349 * block device case, ZFS zvols at least will block the caller's
2350 * context in many instances, and so we need multiple threads to
2351 * overcome that problem. Other block devices don't need as many
2352 * threads, but they shouldn't cause too many problems.
2354 * If the user wants to just have a single thread for a block
2355 * device, he can specify that when the LUN is created, or change
2356 * the tunable/sysctl to alter the default number of threads.
2358 retval = taskqueue_start_threads(&be_lun->io_taskqueue,
2359 /*num threads*/num_threads,
2362 "%s taskq", be_lun->lunname);
2367 be_lun->num_threads = num_threads;
2369 mtx_lock(&softc->lock);
2371 STAILQ_INSERT_TAIL(&softc->lun_list, be_lun, links);
2373 mtx_unlock(&softc->lock);
2375 retval = ctl_add_lun(&be_lun->cbe_lun);
2377 mtx_lock(&softc->lock);
2378 STAILQ_REMOVE(&softc->lun_list, be_lun, ctl_be_block_lun,
2381 mtx_unlock(&softc->lock);
2382 snprintf(req->error_str, sizeof(req->error_str),
2383 "ctl_add_lun() returned error %d, see dmesg for "
2389 mtx_lock(&softc->lock);
2392 * Tell the config_status routine that we're waiting so it won't
2393 * clean up the LUN in the event of an error.
2395 be_lun->flags |= CTL_BE_BLOCK_LUN_WAITING;
2397 while (be_lun->flags & CTL_BE_BLOCK_LUN_UNCONFIGURED) {
2398 retval = msleep(be_lun, &softc->lock, PCATCH, "ctlblk", 0);
2399 if (retval == EINTR)
2402 be_lun->flags &= ~CTL_BE_BLOCK_LUN_WAITING;
2404 if (be_lun->flags & CTL_BE_BLOCK_LUN_CONFIG_ERR) {
2405 snprintf(req->error_str, sizeof(req->error_str),
2406 "LUN configuration error, see dmesg for details");
2407 STAILQ_REMOVE(&softc->lun_list, be_lun, ctl_be_block_lun,
2410 mtx_unlock(&softc->lock);
2413 params->req_lun_id = cbe_lun->lun_id;
2416 mtx_unlock(&softc->lock);
2418 be_lun->disk_stats = devstat_new_entry("cbb", params->req_lun_id,
2420 DEVSTAT_ALL_SUPPORTED,
2422 | DEVSTAT_TYPE_IF_OTHER,
2423 DEVSTAT_PRIORITY_OTHER);
2428 req->status = CTL_LUN_ERROR;
2430 if (be_lun->io_taskqueue != NULL)
2431 taskqueue_free(be_lun->io_taskqueue);
2432 ctl_be_block_close(be_lun);
2433 if (be_lun->dev_path != NULL)
2434 free(be_lun->dev_path, M_CTLBLK);
2435 if (be_lun->lun_zone != NULL)
2436 uma_zdestroy(be_lun->lun_zone);
2437 ctl_free_opts(&cbe_lun->options);
2438 mtx_destroy(&be_lun->queue_lock);
2439 mtx_destroy(&be_lun->io_lock);
2440 free(be_lun, M_CTLBLK);
2446 ctl_be_block_rm(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
2448 struct ctl_lun_rm_params *params;
2449 struct ctl_be_block_lun *be_lun;
2450 struct ctl_be_lun *cbe_lun;
2453 params = &req->reqdata.rm;
2455 mtx_lock(&softc->lock);
2456 STAILQ_FOREACH(be_lun, &softc->lun_list, links) {
2457 if (be_lun->cbe_lun.lun_id == params->lun_id)
2460 mtx_unlock(&softc->lock);
2462 if (be_lun == NULL) {
2463 snprintf(req->error_str, sizeof(req->error_str),
2464 "LUN %u is not managed by the block backend",
2468 cbe_lun = &be_lun->cbe_lun;
2470 retval = ctl_disable_lun(cbe_lun);
2472 snprintf(req->error_str, sizeof(req->error_str),
2473 "error %d returned from ctl_disable_lun() for "
2474 "LUN %d", retval, params->lun_id);
2478 if (be_lun->vn != NULL) {
2479 cbe_lun->flags |= CTL_LUN_FLAG_OFFLINE;
2480 ctl_lun_offline(cbe_lun);
2481 taskqueue_drain_all(be_lun->io_taskqueue);
2482 ctl_be_block_close(be_lun);
2485 retval = ctl_invalidate_lun(cbe_lun);
2487 snprintf(req->error_str, sizeof(req->error_str),
2488 "error %d returned from ctl_invalidate_lun() for "
2489 "LUN %d", retval, params->lun_id);
2493 mtx_lock(&softc->lock);
2494 be_lun->flags |= CTL_BE_BLOCK_LUN_WAITING;
2495 while ((be_lun->flags & CTL_BE_BLOCK_LUN_UNCONFIGURED) == 0) {
2496 retval = msleep(be_lun, &softc->lock, PCATCH, "ctlblk", 0);
2497 if (retval == EINTR)
2500 be_lun->flags &= ~CTL_BE_BLOCK_LUN_WAITING;
2502 if ((be_lun->flags & CTL_BE_BLOCK_LUN_UNCONFIGURED) == 0) {
2503 snprintf(req->error_str, sizeof(req->error_str),
2504 "interrupted waiting for LUN to be freed");
2505 mtx_unlock(&softc->lock);
2509 STAILQ_REMOVE(&softc->lun_list, be_lun, ctl_be_block_lun, links);
2512 mtx_unlock(&softc->lock);
2514 taskqueue_drain_all(be_lun->io_taskqueue);
2515 taskqueue_free(be_lun->io_taskqueue);
2517 if (be_lun->disk_stats != NULL)
2518 devstat_remove_entry(be_lun->disk_stats);
2520 uma_zdestroy(be_lun->lun_zone);
2522 ctl_free_opts(&cbe_lun->options);
2523 free(be_lun->dev_path, M_CTLBLK);
2524 mtx_destroy(&be_lun->queue_lock);
2525 mtx_destroy(&be_lun->io_lock);
2526 free(be_lun, M_CTLBLK);
2528 req->status = CTL_LUN_OK;
2534 req->status = CTL_LUN_ERROR;
2540 ctl_be_block_modify_file(struct ctl_be_block_lun *be_lun,
2541 struct ctl_lun_req *req)
2543 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
2546 struct ctl_lun_create_params *params = &be_lun->params;
2548 if (params->lun_size_bytes != 0) {
2549 be_lun->size_bytes = params->lun_size_bytes;
2551 vn_lock(be_lun->vn, LK_SHARED | LK_RETRY);
2552 error = VOP_GETATTR(be_lun->vn, &vattr, curthread->td_ucred);
2553 VOP_UNLOCK(be_lun->vn, 0);
2555 snprintf(req->error_str, sizeof(req->error_str),
2556 "error calling VOP_GETATTR() for file %s",
2560 be_lun->size_bytes = vattr.va_size;
2562 be_lun->size_blocks = be_lun->size_bytes / cbe_lun->blocksize;
2563 cbe_lun->maxlba = (be_lun->size_blocks == 0) ?
2564 0 : (be_lun->size_blocks - 1);
2569 ctl_be_block_modify_dev(struct ctl_be_block_lun *be_lun,
2570 struct ctl_lun_req *req)
2572 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
2573 struct ctl_lun_create_params *params = &be_lun->params;
2576 uint64_t size_bytes;
2579 csw = devvn_refthread(be_lun->vn, &dev, &ref);
2582 if (csw->d_ioctl == NULL) {
2583 dev_relthread(dev, ref);
2584 snprintf(req->error_str, sizeof(req->error_str),
2585 "no d_ioctl for device %s!", be_lun->dev_path);
2589 error = csw->d_ioctl(dev, DIOCGMEDIASIZE, (caddr_t)&size_bytes, FREAD,
2591 dev_relthread(dev, ref);
2593 snprintf(req->error_str, sizeof(req->error_str),
2594 "error %d returned for DIOCGMEDIASIZE ioctl "
2595 "on %s!", error, be_lun->dev_path);
2599 if (params->lun_size_bytes != 0) {
2600 if (params->lun_size_bytes > size_bytes) {
2601 snprintf(req->error_str, sizeof(req->error_str),
2602 "requested LUN size %ju > backing device "
2604 (uintmax_t)params->lun_size_bytes,
2605 (uintmax_t)size_bytes);
2608 be_lun->size_bytes = params->lun_size_bytes;
2610 be_lun->size_bytes = size_bytes;
2612 be_lun->size_blocks = be_lun->size_bytes / cbe_lun->blocksize;
2613 cbe_lun->maxlba = (be_lun->size_blocks == 0) ?
2614 0 : (be_lun->size_blocks - 1);
2619 ctl_be_block_modify(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
2621 struct ctl_lun_modify_params *params;
2622 struct ctl_be_block_lun *be_lun;
2623 struct ctl_be_lun *cbe_lun;
2628 params = &req->reqdata.modify;
2630 mtx_lock(&softc->lock);
2631 STAILQ_FOREACH(be_lun, &softc->lun_list, links) {
2632 if (be_lun->cbe_lun.lun_id == params->lun_id)
2635 mtx_unlock(&softc->lock);
2637 if (be_lun == NULL) {
2638 snprintf(req->error_str, sizeof(req->error_str),
2639 "LUN %u is not managed by the block backend",
2643 cbe_lun = &be_lun->cbe_lun;
2645 if (params->lun_size_bytes != 0)
2646 be_lun->params.lun_size_bytes = params->lun_size_bytes;
2647 ctl_update_opts(&cbe_lun->options, req->num_be_args, req->kern_be_args);
2649 wasprim = (cbe_lun->flags & CTL_LUN_FLAG_PRIMARY);
2650 value = ctl_get_opt(&cbe_lun->options, "ha_role");
2651 if (value != NULL) {
2652 if (strcmp(value, "primary") == 0)
2653 cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY;
2655 cbe_lun->flags &= ~CTL_LUN_FLAG_PRIMARY;
2656 } else if (control_softc->flags & CTL_FLAG_ACTIVE_SHELF)
2657 cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY;
2659 cbe_lun->flags &= ~CTL_LUN_FLAG_PRIMARY;
2660 if (wasprim != (cbe_lun->flags & CTL_LUN_FLAG_PRIMARY)) {
2661 if (cbe_lun->flags & CTL_LUN_FLAG_PRIMARY)
2662 ctl_lun_primary(cbe_lun);
2664 ctl_lun_secondary(cbe_lun);
2667 oldsize = be_lun->size_blocks;
2668 if ((cbe_lun->flags & CTL_LUN_FLAG_PRIMARY) ||
2669 control_softc->ha_mode == CTL_HA_MODE_SER_ONLY) {
2670 if (be_lun->vn == NULL)
2671 error = ctl_be_block_open(softc, be_lun, req);
2672 else if (vn_isdisk(be_lun->vn, &error))
2673 error = ctl_be_block_modify_dev(be_lun, req);
2674 else if (be_lun->vn->v_type == VREG)
2675 error = ctl_be_block_modify_file(be_lun, req);
2678 if ((cbe_lun->flags & CTL_LUN_FLAG_OFFLINE) &&
2679 be_lun->vn != NULL) {
2680 cbe_lun->flags &= ~CTL_LUN_FLAG_OFFLINE;
2681 ctl_lun_online(cbe_lun);
2684 if (be_lun->vn != NULL) {
2685 cbe_lun->flags |= CTL_LUN_FLAG_OFFLINE;
2686 ctl_lun_offline(cbe_lun);
2687 taskqueue_drain_all(be_lun->io_taskqueue);
2688 error = ctl_be_block_close(be_lun);
2692 if (be_lun->size_blocks != oldsize)
2693 ctl_lun_capacity_changed(cbe_lun);
2695 /* Tell the user the exact size we ended up using */
2696 params->lun_size_bytes = be_lun->size_bytes;
2698 req->status = error ? CTL_LUN_WARNING : CTL_LUN_OK;
2702 req->status = CTL_LUN_ERROR;
2707 ctl_be_block_lun_shutdown(void *be_lun)
2709 struct ctl_be_block_lun *lun;
2710 struct ctl_be_block_softc *softc;
2712 lun = (struct ctl_be_block_lun *)be_lun;
2716 mtx_lock(&softc->lock);
2717 lun->flags |= CTL_BE_BLOCK_LUN_UNCONFIGURED;
2718 if (lun->flags & CTL_BE_BLOCK_LUN_WAITING)
2720 mtx_unlock(&softc->lock);
2725 ctl_be_block_lun_config_status(void *be_lun, ctl_lun_config_status status)
2727 struct ctl_be_block_lun *lun;
2728 struct ctl_be_block_softc *softc;
2730 lun = (struct ctl_be_block_lun *)be_lun;
2733 if (status == CTL_LUN_CONFIG_OK) {
2734 mtx_lock(&softc->lock);
2735 lun->flags &= ~CTL_BE_BLOCK_LUN_UNCONFIGURED;
2736 if (lun->flags & CTL_BE_BLOCK_LUN_WAITING)
2738 mtx_unlock(&softc->lock);
2741 * We successfully added the LUN, attempt to enable it.
2743 if (ctl_enable_lun(&lun->cbe_lun) != 0) {
2744 printf("%s: ctl_enable_lun() failed!\n", __func__);
2745 if (ctl_invalidate_lun(&lun->cbe_lun) != 0) {
2746 printf("%s: ctl_invalidate_lun() failed!\n",
2755 mtx_lock(&softc->lock);
2756 lun->flags &= ~CTL_BE_BLOCK_LUN_UNCONFIGURED;
2757 lun->flags |= CTL_BE_BLOCK_LUN_CONFIG_ERR;
2759 mtx_unlock(&softc->lock);
2764 ctl_be_block_config_write(union ctl_io *io)
2766 struct ctl_be_block_lun *be_lun;
2767 struct ctl_be_lun *cbe_lun;
2772 DPRINTF("entered\n");
2774 cbe_lun = (struct ctl_be_lun *)io->io_hdr.ctl_private[
2775 CTL_PRIV_BACKEND_LUN].ptr;
2776 be_lun = (struct ctl_be_block_lun *)cbe_lun->be_lun;
2778 switch (io->scsiio.cdb[0]) {
2779 case SYNCHRONIZE_CACHE:
2780 case SYNCHRONIZE_CACHE_16:
2785 * The upper level CTL code will filter out any CDBs with
2786 * the immediate bit set and return the proper error.
2788 * We don't really need to worry about what LBA range the
2789 * user asked to be synced out. When they issue a sync
2790 * cache command, we'll sync out the whole thing.
2792 mtx_lock(&be_lun->queue_lock);
2793 STAILQ_INSERT_TAIL(&be_lun->config_write_queue, &io->io_hdr,
2795 mtx_unlock(&be_lun->queue_lock);
2796 taskqueue_enqueue(be_lun->io_taskqueue, &be_lun->io_task);
2798 case START_STOP_UNIT: {
2799 struct scsi_start_stop_unit *cdb;
2801 cdb = (struct scsi_start_stop_unit *)io->scsiio.cdb;
2803 if (cdb->how & SSS_START)
2804 retval = ctl_start_lun(cbe_lun);
2806 retval = ctl_stop_lun(cbe_lun);
2808 * XXX KDM Copan-specific offline behavior.
2809 * Figure out a reasonable way to port this?
2813 && (cdb->byte2 & SSS_ONOFFLINE))
2814 retval = ctl_lun_offline(cbe_lun);
2819 * In general, the above routines should not fail. They
2820 * just set state for the LUN. So we've got something
2821 * pretty wrong here if we can't start or stop the LUN.
2824 ctl_set_internal_failure(&io->scsiio,
2826 /*retry_count*/ 0xf051);
2827 retval = CTL_RETVAL_COMPLETE;
2829 ctl_set_success(&io->scsiio);
2831 ctl_config_write_done(io);
2835 ctl_set_invalid_opcode(&io->scsiio);
2836 ctl_config_write_done(io);
2837 retval = CTL_RETVAL_COMPLETE;
2845 ctl_be_block_config_read(union ctl_io *io)
2847 struct ctl_be_block_lun *be_lun;
2848 struct ctl_be_lun *cbe_lun;
2851 DPRINTF("entered\n");
2853 cbe_lun = (struct ctl_be_lun *)io->io_hdr.ctl_private[
2854 CTL_PRIV_BACKEND_LUN].ptr;
2855 be_lun = (struct ctl_be_block_lun *)cbe_lun->be_lun;
2857 switch (io->scsiio.cdb[0]) {
2858 case SERVICE_ACTION_IN:
2859 if (io->scsiio.cdb[1] == SGLS_SERVICE_ACTION) {
2860 mtx_lock(&be_lun->queue_lock);
2861 STAILQ_INSERT_TAIL(&be_lun->config_read_queue,
2862 &io->io_hdr, links);
2863 mtx_unlock(&be_lun->queue_lock);
2864 taskqueue_enqueue(be_lun->io_taskqueue,
2866 retval = CTL_RETVAL_QUEUED;
2869 ctl_set_invalid_field(&io->scsiio,
2875 ctl_config_read_done(io);
2876 retval = CTL_RETVAL_COMPLETE;
2879 ctl_set_invalid_opcode(&io->scsiio);
2880 ctl_config_read_done(io);
2881 retval = CTL_RETVAL_COMPLETE;
2889 ctl_be_block_lun_info(void *be_lun, struct sbuf *sb)
2891 struct ctl_be_block_lun *lun;
2894 lun = (struct ctl_be_block_lun *)be_lun;
2897 retval = sbuf_printf(sb, "\t<num_threads>");
2902 retval = sbuf_printf(sb, "%d", lun->num_threads);
2907 retval = sbuf_printf(sb, "</num_threads>\n");
2915 ctl_be_block_lun_attr(void *be_lun, const char *attrname)
2917 struct ctl_be_block_lun *lun = (struct ctl_be_block_lun *)be_lun;
2919 if (lun->getattr == NULL)
2920 return (UINT64_MAX);
2921 return (lun->getattr(lun, attrname));
2925 ctl_be_block_init(void)
2927 struct ctl_be_block_softc *softc;
2930 softc = &backend_block_softc;
2933 mtx_init(&softc->lock, "ctlblock", NULL, MTX_DEF);
2934 beio_zone = uma_zcreate("beio", sizeof(struct ctl_be_block_io),
2935 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
2936 STAILQ_INIT(&softc->lun_list);