Lines Matching +full:max +full:- +full:adj
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
5 * Copyright (c) 2009-2011 Spectra Logic Corporation
7 * Copyright (c) 2014-2021 Alexander Motin <mav@FreeBSD.org>
41 * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_backend_block.c#5 $
108 #define CTLBLK_MAX_SEG MIN(1024 * 1024, MAX(CTLBLK_MIN_SEG, maxphys))
119 ((struct ctl_ptr_len_flags *)&(io)->io_hdr.ctl_private[CTL_PRIV_BACKEND])
121 ((struct ctl_lba_len_flags *)&(io)->io_hdr.ctl_private[CTL_PRIV_LBA_LEN])
122 #define DSM_RANGE(io) ((io)->io_hdr.ctl_private[CTL_PRIV_LBA_LEN].integer)
202 * Per-I/O information.
311 sg->addr = uma_zalloc(softc->bufmin_zone, M_WAITOK);
315 sg->addr = uma_zalloc(softc->bufmax_zone, M_WAITOK);
317 sg->len = len;
324 if (sg->len <= CTLBLK_MIN_SEG) {
325 uma_zfree(softc->bufmin_zone, sg->addr);
327 KASSERT(sg->len <= CTLBLK_MAX_SEG,
328 ("Too large free %zu > %lu", sg->len, CTLBLK_MAX_SEG));
329 uma_zfree(softc->bufmax_zone, sg->addr);
338 beio = uma_zalloc(softc->beio_zone, M_WAITOK | M_ZERO);
339 beio->softc = softc;
340 beio->refcnt = 1;
347 struct ctl_be_block_softc *softc = beio->softc;
350 for (i = 0; i < beio->num_segs; i++) {
351 ctl_free_seg(softc, &beio->sg_segs[i]);
354 if (beio->two_sglists) {
356 &beio->sg_segs[i + CTLBLK_HALF_SEGS]);
360 uma_zfree(softc->beio_zone, beio);
368 if (atomic_fetchadd_int(&beio->refcnt, diff) + diff == 0)
376 ctl_refcnt_beio(beio, -1);
382 union ctl_io *io = beio->io;
384 if (beio->beio_cont != NULL) {
385 beio->beio_cont(beio);
395 switch (io->io_hdr.io_type) {
399 ctl_set_internal_failure(&io->scsiio,
403 ctl_set_medium_error(&io->scsiio, bio_cmd == BIO_READ);
410 ctl_nvme_set_write_fault(&io->nvmeio);
413 ctl_nvme_set_unrecoverable_read_error(&io->nvmeio);
416 ctl_nvme_set_internal_error(&io->nvmeio);
444 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
446 for (i = 0; i < beio->num_segs; i++) {
447 res = cmp(beio->sg_segs[i].addr,
448 beio->sg_segs[i + CTLBLK_HALF_SEGS].addr,
449 beio->sg_segs[i].len);
451 if (res < beio->sg_segs[i].len)
454 if (i < beio->num_segs) {
467 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
475 if ((io->io_hdr.flags & CTL_FLAG_ABORT) == 0 &&
476 (io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE) {
478 if (lbalen->flags & CTL_LLF_READ) {
480 } else if (lbalen->flags & CTL_LLF_COMPARE) {
489 if ((beio->bio_cmd == BIO_READ)
490 || ((io->io_hdr.flags & CTL_FLAG_ABORT) != 0)
491 || ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE)) {
507 be_lun->dispatch(be_lun, beio);
509 mtx_lock(&be_lun->queue_lock);
510 STAILQ_INSERT_TAIL(&be_lun->datamove_queue, &io->io_hdr, links);
511 mtx_unlock(&be_lun->queue_lock);
512 taskqueue_enqueue(be_lun->io_taskqueue, &be_lun->io_task);
520 struct ctl_be_block_io *beio = bio->bio_caller1;
521 struct ctl_be_block_lun *be_lun = beio->lun;
522 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
526 io = beio->io;
530 error = bio->bio_error;
531 mtx_lock(&be_lun->io_lock);
533 (beio->first_error == 0 ||
534 bio->bio_offset < beio->first_error_offset)) {
535 beio->first_error = error;
536 beio->first_error_offset = bio->bio_offset;
539 beio->num_bios_done++;
551 if ((beio->send_complete == 0)
552 || (beio->num_bios_done < beio->num_bios_sent)) {
553 mtx_unlock(&be_lun->io_lock);
561 devstat_end_transaction(beio->lun->disk_stats, beio->io_len,
562 beio->ds_tag_type, beio->ds_trans_type,
563 /*now*/ NULL, /*then*/&beio->ds_t0);
564 mtx_unlock(&be_lun->io_lock);
570 error = beio->first_error;
579 ctl_be_block_io_error(io, beio->bio_cmd,
590 if ((beio->bio_cmd == BIO_WRITE)
591 || (beio->bio_cmd == BIO_FLUSH)
592 || (beio->bio_cmd == BIO_DELETE)
593 || (ARGS(io)->flags & CTL_LLF_VERIFY)) {
597 if ((ARGS(io)->flags & CTL_LLF_READ) &&
598 beio->beio_cont == NULL) {
600 if (cbe_lun->serseq >= CTL_LUN_SERSEQ_SOFT)
611 union ctl_io *io = beio->io;
617 binuptime(&beio->ds_t0);
618 devstat_start_transaction(beio->lun->disk_stats, &beio->ds_t0);
620 (void) vn_start_write(be_lun->vn, &mountpoint, V_WAIT);
622 vn_lock(be_lun->vn, vn_lktype_write(mountpoint, be_lun->vn) |
624 error = VOP_FSYNC(be_lun->vn, beio->io_arg ? MNT_NOWAIT : MNT_WAIT,
626 VOP_UNLOCK(be_lun->vn);
630 mtx_lock(&be_lun->io_lock);
631 devstat_end_transaction(beio->lun->disk_stats, beio->io_len,
632 beio->ds_tag_type, beio->ds_trans_type,
633 /*now*/ NULL, /*then*/&beio->ds_t0);
634 mtx_unlock(&be_lun->io_lock);
655 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
665 file_data = &be_lun->backend.file;
666 io = beio->io;
668 if (ARGS(io)->flags & CTL_LLF_DPO)
670 if (beio->bio_cmd == BIO_WRITE && ARGS(io)->flags & CTL_LLF_FUA)
674 if (beio->bio_cmd == BIO_READ) {
681 xuio.uio_offset = beio->io_offset;
682 xuio.uio_resid = beio->io_len;
684 xuio.uio_iov = beio->xiovecs;
685 xuio.uio_iovcnt = beio->num_segs;
689 xiovec->iov_base = beio->sg_segs[i].addr;
690 xiovec->iov_len = beio->sg_segs[i].len;
693 binuptime(&beio->ds_t0);
694 devstat_start_transaction(beio->lun->disk_stats, &beio->ds_t0);
696 if (beio->bio_cmd == BIO_READ) {
697 vn_lock(be_lun->vn, LK_SHARED | LK_RETRY);
699 if (beio->beio_cont == NULL &&
700 cbe_lun->serseq == CTL_LUN_SERSEQ_SOFT)
705 * ffs_rawread(). But that only works for single-segment
719 error = VOP_READ(be_lun->vn, &xuio, flags, file_data->cred);
721 VOP_UNLOCK(be_lun->vn);
728 s = beio->io_len - xuio.uio_resid;
729 for (i = 0; i < beio->num_segs; i++) {
730 if (s >= beio->sg_segs[i].len) {
731 s -= beio->sg_segs[i].len;
734 bzero((uint8_t *)beio->sg_segs[i].addr + s,
735 beio->sg_segs[i].len - s);
742 (void)vn_start_write(be_lun->vn, &mountpoint, V_WAIT);
743 vn_lock(be_lun->vn, vn_lktype_write(mountpoint,
744 be_lun->vn) | LK_RETRY);
761 error = VOP_WRITE(be_lun->vn, &xuio, flags, file_data->cred);
762 VOP_UNLOCK(be_lun->vn);
768 mtx_lock(&be_lun->io_lock);
769 devstat_end_transaction(beio->lun->disk_stats, beio->io_len,
770 beio->ds_tag_type, beio->ds_trans_type,
771 /*now*/ NULL, /*then*/&beio->ds_t0);
772 mtx_unlock(&be_lun->io_lock);
784 ctl_be_block_io_error(io, beio->bio_cmd, 0);
794 if ((beio->bio_cmd == BIO_WRITE) ||
795 (ARGS(io)->flags & CTL_LLF_VERIFY)) {
799 if ((ARGS(io)->flags & CTL_LLF_READ) &&
800 beio->beio_cont == NULL) {
802 if (cbe_lun->serseq > CTL_LUN_SERSEQ_SOFT)
813 union ctl_io *io = beio->io;
823 off = roff = ((off_t)lbalen->lba) * be_lun->cbe_lun.blocksize;
824 vn_lock(be_lun->vn, LK_SHARED | LK_RETRY);
825 error = VOP_IOCTL(be_lun->vn, FIOSEEKHOLE, &off,
826 0, curthread->td_ucred, curthread);
830 error = VOP_IOCTL(be_lun->vn, FIOSEEKDATA, &off,
831 0, curthread->td_ucred, curthread);
836 off = be_lun->size_bytes;
839 VOP_UNLOCK(be_lun->vn);
841 data = (struct scsi_get_lba_status_data *)io->scsiio.kern_data_ptr;
842 scsi_u64to8b(lbalen->lba, data->descr[0].addr);
843 scsi_ulto4b(MIN(UINT32_MAX, off / be_lun->cbe_lun.blocksize -
844 lbalen->lba), data->descr[0].length);
845 data->descr[0].status = status;
859 if (be_lun->vn == NULL)
861 vn_lock(be_lun->vn, LK_SHARED | LK_RETRY);
863 error = VOP_GETATTR(be_lun->vn, &vattr, curthread->td_ucred);
865 val = vattr.va_bytes / be_lun->cbe_lun.blocksize;
868 !VN_IS_DOOMED(be_lun->vn)) {
869 error = VFS_STATFS(be_lun->vn->v_mount, &statfs);
872 be_lun->cbe_lun.blocksize;
874 VOP_UNLOCK(be_lun->vn);
890 io = beio->io;
891 file_data = &be_lun->backend.file;
895 binuptime(&beio->ds_t0);
896 devstat_start_transaction(be_lun->disk_stats, &beio->ds_t0);
898 (void)vn_start_write(be_lun->vn, &mp, V_WAIT);
899 vn_lock(be_lun->vn, vn_lktype_write(mp, be_lun->vn) | LK_RETRY);
900 if (beio->io_offset == -1) {
901 beio->io_len = 0;
903 &io->io_hdr.ctl_private[CTL_PRIV_LBA_LEN];
904 buf = (struct scsi_unmap_desc *)ptrlen->ptr;
905 end = buf + ptrlen->len / sizeof(*buf);
907 off = (off_t)scsi_8btou64(buf->lba) *
908 be_lun->cbe_lun.blocksize;
909 len = (off_t)scsi_4btoul(buf->length) *
910 be_lun->cbe_lun.blocksize;
911 beio->io_len += len;
912 error = vn_deallocate(be_lun->vn, &off, &len,
913 0, IO_NOMACCHECK | IO_NODELOCKED, file_data->cred,
920 off = beio->io_offset;
921 len = beio->io_len;
922 error = vn_deallocate(be_lun->vn, &off, &len, 0,
923 IO_NOMACCHECK | IO_NODELOCKED, file_data->cred, NOCRED);
925 VOP_UNLOCK(be_lun->vn);
928 mtx_lock(&be_lun->io_lock);
929 devstat_end_transaction(beio->lun->disk_stats, beio->io_len,
930 beio->ds_tag_type, beio->ds_trans_type,
931 /*now*/ NULL, /*then*/&beio->ds_t0);
932 mtx_unlock(&be_lun->io_lock);
960 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
970 io = beio->io;
972 if (ARGS(io)->flags & CTL_LLF_DPO)
974 if (beio->bio_cmd == BIO_WRITE && ARGS(io)->flags & CTL_LLF_FUA)
978 if (beio->bio_cmd == BIO_READ) {
985 xuio.uio_offset = beio->io_offset;
986 xuio.uio_resid = beio->io_len;
988 xuio.uio_iov = beio->xiovecs;
989 xuio.uio_iovcnt = beio->num_segs;
993 xiovec->iov_base = beio->sg_segs[i].addr;
994 xiovec->iov_len = beio->sg_segs[i].len;
997 binuptime(&beio->ds_t0);
998 devstat_start_transaction(beio->lun->disk_stats, &beio->ds_t0);
1000 csw = devvn_refthread(be_lun->vn, &dev, &ref);
1002 if (beio->bio_cmd == BIO_READ) {
1003 if (beio->beio_cont == NULL &&
1004 cbe_lun->serseq == CTL_LUN_SERSEQ_SOFT)
1006 error = csw->d_read(dev, &xuio, flags);
1008 error = csw->d_write(dev, &xuio, flags);
1013 if (beio->bio_cmd == BIO_READ)
1018 mtx_lock(&be_lun->io_lock);
1019 devstat_end_transaction(beio->lun->disk_stats, beio->io_len,
1020 beio->ds_tag_type, beio->ds_trans_type,
1021 /*now*/ NULL, /*then*/&beio->ds_t0);
1022 mtx_unlock(&be_lun->io_lock);
1034 ctl_be_block_io_error(io, beio->bio_cmd, 0);
1044 if ((beio->bio_cmd == BIO_WRITE) ||
1045 (ARGS(io)->flags & CTL_LLF_VERIFY)) {
1049 if ((ARGS(io)->flags & CTL_LLF_READ) &&
1050 beio->beio_cont == NULL) {
1052 if (cbe_lun->serseq > CTL_LUN_SERSEQ_SOFT)
1063 union ctl_io *io = beio->io;
1075 csw = devvn_refthread(be_lun->vn, &dev, &ref);
1078 off = be_lun->size_bytes;
1081 off = roff = ((off_t)lbalen->lba) * be_lun->cbe_lun.blocksize;
1082 error = csw->d_ioctl(dev, FIOSEEKHOLE, (caddr_t)&off, FREAD,
1087 error = csw->d_ioctl(dev, FIOSEEKDATA, (caddr_t)&off, FREAD,
1093 off = be_lun->size_bytes;
1099 data = (struct scsi_get_lba_status_data *)io->scsiio.kern_data_ptr;
1100 scsi_u64to8b(lbalen->lba, data->descr[0].addr);
1101 scsi_ulto4b(MIN(UINT32_MAX, off / be_lun->cbe_lun.blocksize -
1102 lbalen->lba), data->descr[0].length);
1103 data->descr[0].status = status;
1122 bio->bio_cmd = BIO_FLUSH;
1123 bio->bio_offset = 0;
1124 bio->bio_data = 0;
1125 bio->bio_done = ctl_be_block_biodone;
1126 bio->bio_caller1 = beio;
1127 bio->bio_pblkno = 0;
1134 beio->num_bios_sent = 1;
1135 beio->send_complete = 1;
1137 binuptime(&beio->ds_t0);
1138 devstat_start_transaction(be_lun->disk_stats, &beio->ds_t0);
1140 csw = devvn_refthread(be_lun->vn, &dev, &ref);
1142 bio->bio_dev = dev;
1143 csw->d_strategy(bio);
1146 bio->bio_error = ENXIO;
1162 csw = devvn_refthread(be_lun->vn, &dev, &ref);
1163 maxlen = LONG_MAX - (LONG_MAX % be_lun->cbe_lun.blocksize);
1166 bio->bio_cmd = BIO_DELETE;
1167 bio->bio_dev = dev;
1168 bio->bio_offset = off;
1169 bio->bio_length = MIN(len, maxlen);
1170 bio->bio_data = 0;
1171 bio->bio_done = ctl_be_block_biodone;
1172 bio->bio_caller1 = beio;
1173 bio->bio_pblkno = off / be_lun->cbe_lun.blocksize;
1175 off += bio->bio_length;
1176 len -= bio->bio_length;
1178 mtx_lock(&be_lun->io_lock);
1179 beio->num_bios_sent++;
1181 beio->send_complete = 1;
1182 mtx_unlock(&be_lun->io_lock);
1185 csw->d_strategy(bio);
1187 bio->bio_error = ENXIO;
1204 io = beio->io;
1208 binuptime(&beio->ds_t0);
1209 devstat_start_transaction(be_lun->disk_stats, &beio->ds_t0);
1211 if (beio->io_offset == -1) {
1212 beio->io_len = 0;
1213 ptrlen = (struct ctl_ptr_len_flags *)&io->io_hdr.ctl_private[CTL_PRIV_LBA_LEN];
1214 buf = (struct scsi_unmap_desc *)ptrlen->ptr;
1215 end = buf + ptrlen->len / sizeof(*buf);
1217 len = (uint64_t)scsi_4btoul(buf->length) *
1218 be_lun->cbe_lun.blocksize;
1219 beio->io_len += len;
1221 scsi_8btou64(buf->lba) * be_lun->cbe_lun.blocksize,
1222 len, (end - buf < 2) ? TRUE : FALSE);
1226 beio->io_offset, beio->io_len, TRUE);
1241 csw = devvn_refthread(be_lun->vn, &dev, &ref);
1248 max_iosize = dev->si_iosize_max;
1254 cur_offset = beio->io_offset;
1255 for (i = 0; i < beio->num_segs; i++) {
1259 cur_size = beio->sg_segs[i].len;
1260 cur_ptr = beio->sg_segs[i].addr;
1268 bio->bio_cmd = beio->bio_cmd;
1269 bio->bio_dev = dev;
1270 bio->bio_caller1 = beio;
1271 bio->bio_length = min(cur_size, max_iosize);
1272 bio->bio_offset = cur_offset;
1273 bio->bio_data = cur_ptr;
1274 bio->bio_done = ctl_be_block_biodone;
1275 bio->bio_pblkno = cur_offset / be_lun->cbe_lun.blocksize;
1277 cur_offset += bio->bio_length;
1278 cur_ptr += bio->bio_length;
1279 cur_size -= bio->bio_length;
1282 beio->num_bios_sent++;
1285 beio->send_complete = 1;
1286 binuptime(&beio->ds_t0);
1287 devstat_start_transaction(be_lun->disk_stats, &beio->ds_t0);
1295 csw->d_strategy(bio);
1297 bio->bio_error = ENXIO;
1313 csw = devvn_refthread(be_lun->vn, &dev, &ref);
1318 if (csw->d_ioctl) {
1319 error = csw->d_ioctl(dev, DIOCGATTR, (caddr_t)&arg, FREAD,
1333 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
1336 nsdata = (struct nvme_namespace_data *)io->nvmeio.kern_data_ptr;
1338 nsdata->nsze = htole64(be_lun->size_blocks);
1339 nsdata->ncap = nsdata->nsze;
1340 nsdata->nuse = nsdata->nsze;
1341 nsdata->nlbaf = 1 - 1;
1342 nsdata->dlfeat = NVMEM(NVME_NS_DATA_DLFEAT_DWZ) |
1344 nsdata->flbas = NVMEF(NVME_NS_DATA_FLBAS_FORMAT, 0);
1345 nsdata->lbaf[0] = NVMEF(NVME_NS_DATA_LBAF_LBADS,
1346 ffs(cbe_lun->blocksize) - 1);
1356 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
1358 ctl_lun_nvme_ids(cbe_lun, io->nvmeio.kern_data_ptr);
1366 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
1371 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
1372 lbalen = (struct ctl_lba_len_flags *)&io->io_hdr.ctl_private[CTL_PRIV_LBA_LEN];
1374 beio->io_len = lbalen->len * cbe_lun->blocksize;
1375 beio->io_offset = lbalen->lba * cbe_lun->blocksize;
1376 beio->io_arg = (lbalen->flags & SSC_IMMED) != 0;
1377 beio->bio_cmd = BIO_FLUSH;
1378 beio->ds_trans_type = DEVSTAT_NO_DATA;
1380 be_lun->lun_flush(be_lun, beio);
1388 io = beio->io;
1390 if ((io->io_hdr.flags & CTL_FLAG_ABORT) ||
1391 ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE &&
1392 (io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS)) {
1404 struct ctl_be_block_softc *softc = be_lun->softc;
1405 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
1409 uint32_t pb, pbo, adj;
1417 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
1420 if (lbalen->flags & ~(SWS_LBDATA | SWS_UNMAP | SWS_ANCHOR | SWS_NDOB) ||
1421 (lbalen->flags & (SWS_UNMAP | SWS_ANCHOR) && be_lun->unmap == NULL)) {
1423 ctl_set_invalid_field(&io->scsiio,
1433 if (lbalen->flags & (SWS_UNMAP | SWS_ANCHOR)) {
1434 beio->io_offset = lbalen->lba * cbe_lun->blocksize;
1435 beio->io_len = (uint64_t)lbalen->len * cbe_lun->blocksize;
1436 beio->bio_cmd = BIO_DELETE;
1437 beio->ds_trans_type = DEVSTAT_FREE;
1439 be_lun->unmap(be_lun, beio);
1443 beio->bio_cmd = BIO_WRITE;
1444 beio->ds_trans_type = DEVSTAT_WRITE;
1447 (uintmax_t)lbalen->lba, lbalen->len);
1449 pb = cbe_lun->blocksize << be_lun->cbe_lun.pblockexp;
1450 if (be_lun->cbe_lun.pblockoff > 0)
1451 pbo = pb - cbe_lun->blocksize * be_lun->cbe_lun.pblockoff;
1454 len_left = (uint64_t)lbalen->len * cbe_lun->blocksize;
1460 if (pb > cbe_lun->blocksize) {
1461 adj = ((lbalen->lba + lba) * cbe_lun->blocksize +
1462 seglen - pbo) % pb;
1463 if (seglen > adj)
1464 seglen -= adj;
1466 seglen -= seglen % cbe_lun->blocksize;
1468 seglen -= seglen % cbe_lun->blocksize;
1469 ctl_alloc_seg(softc, &beio->sg_segs[i], seglen);
1472 beio->sg_segs[i].addr, beio->sg_segs[i].len);
1474 beio->num_segs++;
1475 len_left -= seglen;
1477 buf = beio->sg_segs[i].addr;
1479 for (; buf < end; buf += cbe_lun->blocksize) {
1480 if (lbalen->flags & SWS_NDOB) {
1481 memset(buf, 0, cbe_lun->blocksize);
1483 memcpy(buf, io->scsiio.kern_data_ptr,
1484 cbe_lun->blocksize);
1486 if (lbalen->flags & SWS_LBDATA)
1487 scsi_ulto4b(lbalen->lba + lba, buf);
1492 beio->io_offset = lbalen->lba * cbe_lun->blocksize;
1493 beio->io_len = lba * cbe_lun->blocksize;
1497 lbalen->lba += lba;
1498 lbalen->len -= lba;
1499 beio->beio_cont = ctl_be_block_cw_done_ws;
1502 be_lun->dispatch(be_lun, beio);
1516 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
1517 ptrlen = (struct ctl_ptr_len_flags *)&io->io_hdr.ctl_private[CTL_PRIV_LBA_LEN];
1519 if ((ptrlen->flags & ~SU_ANCHOR) != 0 || be_lun->unmap == NULL) {
1521 ctl_set_invalid_field(&io->scsiio,
1531 beio->io_len = 0;
1532 beio->io_offset = -1;
1533 beio->bio_cmd = BIO_DELETE;
1534 beio->ds_trans_type = DEVSTAT_FREE;
1536 be_lun->unmap(be_lun, beio);
1546 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
1548 beio->io_len = be_lun->size_bytes;
1549 beio->io_offset = 0;
1550 beio->io_arg = 1;
1551 beio->bio_cmd = BIO_FLUSH;
1552 beio->ds_trans_type = DEVSTAT_NO_DATA;
1554 be_lun->lun_flush(be_lun, beio);
1561 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
1567 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
1574 beio->io_offset = lbalen->lba * cbe_lun->blocksize;
1575 beio->io_len = (uint64_t)lbalen->len * cbe_lun->blocksize;
1576 beio->bio_cmd = BIO_DELETE;
1577 beio->ds_trans_type = DEVSTAT_FREE;
1579 be_lun->unmap(be_lun, beio);
1586 struct ctl_be_block_softc *softc = be_lun->softc;
1587 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
1591 uint32_t pb, pbo, adj;
1598 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
1601 if ((le32toh(io->nvmeio.cmd.cdw12) & (1U << 25)) != 0 &&
1602 be_lun->unmap != NULL) {
1603 beio->io_offset = lbalen->lba * cbe_lun->blocksize;
1604 beio->io_len = (uint64_t)lbalen->len * cbe_lun->blocksize;
1605 beio->bio_cmd = BIO_DELETE;
1606 beio->ds_trans_type = DEVSTAT_FREE;
1608 be_lun->unmap(be_lun, beio);
1612 beio->bio_cmd = BIO_WRITE;
1613 beio->ds_trans_type = DEVSTAT_WRITE;
1616 (uintmax_t)lbalen->lba, lbalen->len);
1618 pb = cbe_lun->blocksize << be_lun->cbe_lun.pblockexp;
1619 if (be_lun->cbe_lun.pblockoff > 0)
1620 pbo = pb - cbe_lun->blocksize * be_lun->cbe_lun.pblockoff;
1623 len_left = (uint64_t)lbalen->len * cbe_lun->blocksize;
1629 if (pb > cbe_lun->blocksize) {
1630 adj = ((lbalen->lba + lba) * cbe_lun->blocksize +
1631 seglen - pbo) % pb;
1632 if (seglen > adj)
1633 seglen -= adj;
1635 seglen -= seglen % cbe_lun->blocksize;
1637 seglen -= seglen % cbe_lun->blocksize;
1638 ctl_alloc_seg(softc, &beio->sg_segs[i], seglen);
1641 beio->sg_segs[i].addr, beio->sg_segs[i].len);
1643 beio->num_segs++;
1644 len_left -= seglen;
1646 memset(beio->sg_segs[i].addr, 0, seglen);
1647 lba += seglen / cbe_lun->blocksize;
1650 beio->io_offset = lbalen->lba * cbe_lun->blocksize;
1651 beio->io_len = lba * cbe_lun->blocksize;
1655 lbalen->lba += lba;
1656 lbalen->len -= lba;
1657 beio->beio_cont = ctl_be_block_cw_done_ws;
1660 be_lun->dispatch(be_lun, beio);
1667 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
1676 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
1678 if (be_lun->unmap == NULL) {
1680 ctl_nvme_set_success(&io->nvmeio);
1685 ranges = le32toh(io->nvmeio.cmd.cdw10) & 0xff;
1686 r = (struct nvme_dsm_range *)io->nvmeio.kern_data_ptr;
1697 ctl_nvme_set_success(&io->nvmeio);
1705 beio->beio_cont = ctl_be_block_cw_done_ws;
1711 beio->io_offset = lba * cbe_lun->blocksize;
1712 beio->io_len = (uint64_t)num_blocks * cbe_lun->blocksize;
1713 beio->bio_cmd = BIO_DELETE;
1714 beio->ds_trans_type = DEVSTAT_FREE;
1716 be_lun->unmap(be_lun, beio);
1724 io = beio->io;
1738 softc = be_lun->softc;
1740 beio->io = io;
1741 beio->lun = be_lun;
1742 beio->beio_cont = ctl_be_block_scsi_cr_done;
1743 PRIV(io)->ptr = (void *)beio;
1745 switch (io->scsiio.cdb[0]) {
1747 beio->bio_cmd = -1;
1748 beio->ds_trans_type = DEVSTAT_NO_DATA;
1749 beio->ds_tag_type = DEVSTAT_TAG_ORDERED;
1750 beio->io_len = 0;
1751 if (be_lun->get_lba_status)
1752 be_lun->get_lba_status(be_lun, beio);
1757 panic("Unhandled CDB type %#x", io->scsiio.cdb[0]);
1770 MPASS(io->nvmeio.cmd.opc == NVME_OPC_IDENTIFY);
1772 cns = le32toh(io->nvmeio.cmd.cdw10) & 0xff;
1789 switch (io->io_hdr.io_type) {
1806 io = beio->io;
1819 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
1821 switch (io->scsiio.tag_type) {
1823 beio->ds_tag_type = DEVSTAT_TAG_ORDERED;
1826 beio->ds_tag_type = DEVSTAT_TAG_HEAD;
1832 beio->ds_tag_type = DEVSTAT_TAG_SIMPLE;
1836 switch (io->scsiio.cdb[0]) {
1849 panic("Unhandled CDB type %#x", io->scsiio.cdb[0]);
1862 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
1863 beio->ds_tag_type = DEVSTAT_TAG_SIMPLE;
1865 switch (io->nvmeio.cmd.opc) {
1890 softc = be_lun->softc;
1892 beio->io = io;
1893 beio->lun = be_lun;
1894 beio->beio_cont = ctl_be_block_cw_done;
1895 PRIV(io)->ptr = (void *)beio;
1897 switch (io->io_hdr.io_type) {
1920 io = beio->io;
1921 be_lun = beio->lun;
1923 if ((io->io_hdr.flags & CTL_FLAG_ABORT) ||
1924 ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE &&
1925 (io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS)) {
1930 io->io_hdr.status &= ~CTL_STATUS_MASK;
1931 io->io_hdr.status |= CTL_STATUS_NONE;
1933 mtx_lock(&be_lun->queue_lock);
1934 STAILQ_INSERT_TAIL(&be_lun->input_queue, &io->io_hdr, links);
1935 mtx_unlock(&be_lun->queue_lock);
1936 taskqueue_enqueue(be_lun->io_taskqueue, &be_lun->io_task);
1943 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
1951 softc = be_lun->softc;
1956 if (lbalen->flags & CTL_LLF_WRITE) {
1963 beio->io = io;
1964 beio->lun = be_lun;
1966 bptrlen->ptr = (void *)beio;
1968 switch (io->io_hdr.io_type) {
1970 switch (io->scsiio.tag_type) {
1972 beio->ds_tag_type = DEVSTAT_TAG_ORDERED;
1975 beio->ds_tag_type = DEVSTAT_TAG_HEAD;
1981 beio->ds_tag_type = DEVSTAT_TAG_SIMPLE;
1986 beio->ds_tag_type = DEVSTAT_TAG_SIMPLE;
1992 if (lbalen->flags & CTL_LLF_WRITE) {
1993 beio->bio_cmd = BIO_WRITE;
1994 beio->ds_trans_type = DEVSTAT_WRITE;
1996 beio->bio_cmd = BIO_READ;
1997 beio->ds_trans_type = DEVSTAT_READ;
2001 (beio->bio_cmd == BIO_READ) ? "READ" : "WRITE",
2002 (uintmax_t)lbalen->lba, lbalen->len, bptrlen->len);
2004 if (lbalen->flags & CTL_LLF_COMPARE) {
2005 beio->two_sglists = 1;
2008 lbas = MIN(lbalen->len - bptrlen->len, lbas / cbe_lun->blocksize);
2009 beio->io_offset = (lbalen->lba + bptrlen->len) * cbe_lun->blocksize;
2010 beio->io_len = lbas * cbe_lun->blocksize;
2011 bptrlen->len += lbas;
2013 for (i = 0, len_left = beio->io_len; len_left > 0; i++) {
2020 ctl_alloc_seg(softc, &beio->sg_segs[i],
2024 beio->sg_segs[i].addr, beio->sg_segs[i].len);
2027 if (beio->two_sglists) {
2029 &beio->sg_segs[i + CTLBLK_HALF_SEGS],
2030 beio->sg_segs[i].len);
2033 beio->num_segs++;
2034 len_left -= beio->sg_segs[i].len;
2036 if (bptrlen->len < lbalen->len)
2037 beio->beio_cont = ctl_be_block_next;
2040 if (beio->two_sglists)
2041 ctl_set_kern_data_ptr(io, &beio->sg_segs[CTLBLK_HALF_SEGS]);
2043 ctl_set_kern_data_ptr(io, beio->sg_segs);
2044 ctl_set_kern_data_len(io, beio->io_len);
2045 ctl_set_kern_sg_entries(io, beio->num_segs);
2048 io->io_hdr.flags |= CTL_FLAG_ALLOCATED;
2055 if (beio->bio_cmd == BIO_READ) {
2057 be_lun->dispatch(be_lun, beio);
2068 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
2075 * CTL_LUN_FLAG_NO_MEDIA status here -- it is result of a race,
2079 mtx_lock(&be_lun->queue_lock);
2080 io = (union ctl_io *)STAILQ_FIRST(&be_lun->datamove_queue);
2083 STAILQ_REMOVE_HEAD(&be_lun->datamove_queue, links);
2084 mtx_unlock(&be_lun->queue_lock);
2085 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
2086 if (cbe_lun->flags & CTL_LUN_FLAG_NO_MEDIA) {
2091 be_lun->dispatch(be_lun, beio);
2094 io = (union ctl_io *)STAILQ_FIRST(&be_lun->config_write_queue);
2097 STAILQ_REMOVE_HEAD(&be_lun->config_write_queue, links);
2098 mtx_unlock(&be_lun->queue_lock);
2099 if (cbe_lun->flags & CTL_LUN_FLAG_NO_MEDIA) {
2107 io = (union ctl_io *)STAILQ_FIRST(&be_lun->config_read_queue);
2110 STAILQ_REMOVE_HEAD(&be_lun->config_read_queue, links);
2111 mtx_unlock(&be_lun->queue_lock);
2112 if (cbe_lun->flags & CTL_LUN_FLAG_NO_MEDIA) {
2120 io = (union ctl_io *)STAILQ_FIRST(&be_lun->input_queue);
2123 STAILQ_REMOVE_HEAD(&be_lun->input_queue, links);
2124 mtx_unlock(&be_lun->queue_lock);
2125 if (cbe_lun->flags & CTL_LUN_FLAG_NO_MEDIA) {
2138 mtx_unlock(&be_lun->queue_lock);
2159 PRIV(io)->len = 0;
2161 mtx_lock(&be_lun->queue_lock);
2162 STAILQ_INSERT_TAIL(&be_lun->input_queue, &io->io_hdr, links);
2163 mtx_unlock(&be_lun->queue_lock);
2164 taskqueue_enqueue(be_lun->io_taskqueue, &be_lun->io_task);
2183 switch (lun_req->reqtype) {
2194 lun_req->status = CTL_LUN_ERROR;
2195 snprintf(lun_req->error_str, sizeof(lun_req->error_str),
2197 lun_req->reqtype);
2222 cbe_lun = &be_lun->cbe_lun;
2223 file_data = &be_lun->backend.file;
2224 params = &be_lun->params;
2226 be_lun->dev_type = CTL_BE_BLOCK_FILE;
2227 be_lun->dispatch = ctl_be_block_dispatch_file;
2228 be_lun->lun_flush = ctl_be_block_flush_file;
2229 be_lun->get_lba_status = ctl_be_block_gls_file;
2230 be_lun->getattr = ctl_be_block_getattr_file;
2231 be_lun->unmap = ctl_be_block_unmap_file;
2232 cbe_lun->flags &= ~CTL_LUN_FLAG_UNMAP;
2234 error = VOP_GETATTR(be_lun->vn, &vattr, curthread->td_ucred);
2236 snprintf(req->error_str, sizeof(req->error_str),
2238 be_lun->dev_path);
2242 error = VOP_PATHCONF(be_lun->vn, _PC_DEALLOC_PRESENT, &pconf);
2244 snprintf(req->error_str, sizeof(req->error_str),
2246 be_lun->dev_path);
2250 cbe_lun->flags |= CTL_LUN_FLAG_UNMAP;
2252 file_data->cred = crhold(curthread->td_ucred);
2253 if (params->lun_size_bytes != 0)
2254 be_lun->size_bytes = params->lun_size_bytes;
2256 be_lun->size_bytes = vattr.va_size;
2262 * logical block size -- report it as physical block size.
2264 if (params->blocksize_bytes != 0)
2265 cbe_lun->blocksize = params->blocksize_bytes;
2266 else if (cbe_lun->lun_type == T_CDROM)
2267 cbe_lun->blocksize = 2048;
2269 cbe_lun->blocksize = 512;
2270 be_lun->size_blocks = be_lun->size_bytes / cbe_lun->blocksize;
2271 cbe_lun->maxlba = (be_lun->size_blocks == 0) ?
2272 0 : (be_lun->size_blocks - 1);
2277 value = dnvlist_get_string(cbe_lun->options, "pblocksize", NULL);
2280 value = dnvlist_get_string(cbe_lun->options, "pblockoffset", NULL);
2283 pss = ps / cbe_lun->blocksize;
2284 pos = po / cbe_lun->blocksize;
2285 if ((pss > 0) && (pss * cbe_lun->blocksize == ps) && (pss >= pos) &&
2286 ((pss & (pss - 1)) == 0) && (pos * cbe_lun->blocksize == po)) {
2287 cbe_lun->pblockexp = fls(pss) - 1;
2288 cbe_lun->pblockoff = (pss - pos) % pss;
2291 value = dnvlist_get_string(cbe_lun->options, "ublocksize", NULL);
2294 value = dnvlist_get_string(cbe_lun->options, "ublockoffset", NULL);
2297 uss = us / cbe_lun->blocksize;
2298 uos = uo / cbe_lun->blocksize;
2299 if ((uss > 0) && (uss * cbe_lun->blocksize == us) && (uss >= uos) &&
2300 ((uss & (uss - 1)) == 0) && (uos * cbe_lun->blocksize == uo)) {
2301 cbe_lun->ublockexp = fls(uss) - 1;
2302 cbe_lun->ublockoff = (uss - uos) % uss;
2309 if (be_lun->size_bytes < cbe_lun->blocksize) {
2311 snprintf(req->error_str, sizeof(req->error_str),
2312 "file %s size %ju < block size %u", be_lun->dev_path,
2313 (uintmax_t)be_lun->size_bytes, cbe_lun->blocksize);
2316 cbe_lun->opttxferlen = CTLBLK_MAX_IO_SIZE / cbe_lun->blocksize;
2323 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
2331 params = &be_lun->params;
2333 be_lun->dev_type = CTL_BE_BLOCK_DEV;
2334 csw = devvn_refthread(be_lun->vn, &dev, &ref);
2337 if (strcmp(csw->d_name, "zvol") == 0) {
2338 be_lun->dispatch = ctl_be_block_dispatch_zvol;
2339 be_lun->get_lba_status = ctl_be_block_gls_zvol;
2342 be_lun->dispatch = ctl_be_block_dispatch_dev;
2343 be_lun->get_lba_status = NULL;
2345 maxio = dev->si_iosize_max;
2351 be_lun->lun_flush = ctl_be_block_flush_dev;
2352 be_lun->getattr = ctl_be_block_getattr_dev;
2353 be_lun->unmap = ctl_be_block_unmap_dev;
2355 if (!csw->d_ioctl) {
2357 snprintf(req->error_str, sizeof(req->error_str),
2358 "no d_ioctl for device %s!", be_lun->dev_path);
2362 error = csw->d_ioctl(dev, DIOCGSECTORSIZE, (caddr_t)&tmp, FREAD,
2366 snprintf(req->error_str, sizeof(req->error_str),
2368 "on %s!", error, be_lun->dev_path);
2378 if ((params->blocksize_bytes != 0) &&
2379 (params->blocksize_bytes >= tmp)) {
2380 if (params->blocksize_bytes % tmp == 0) {
2381 cbe_lun->blocksize = params->blocksize_bytes;
2384 snprintf(req->error_str, sizeof(req->error_str),
2387 params->blocksize_bytes, tmp);
2390 } else if (params->blocksize_bytes != 0) {
2392 snprintf(req->error_str, sizeof(req->error_str),
2394 "blocksize %u", params->blocksize_bytes, tmp);
2396 } else if (cbe_lun->lun_type == T_CDROM)
2397 cbe_lun->blocksize = MAX(tmp, 2048);
2399 cbe_lun->blocksize = tmp;
2401 error = csw->d_ioctl(dev, DIOCGMEDIASIZE, (caddr_t)&otmp, FREAD,
2405 snprintf(req->error_str, sizeof(req->error_str),
2408 be_lun->dev_path);
2412 if (params->lun_size_bytes != 0) {
2413 if (params->lun_size_bytes > otmp) {
2415 snprintf(req->error_str, sizeof(req->error_str),
2418 (uintmax_t)params->lun_size_bytes,
2423 be_lun->size_bytes = params->lun_size_bytes;
2425 be_lun->size_bytes = otmp;
2426 be_lun->size_blocks = be_lun->size_bytes / cbe_lun->blocksize;
2427 cbe_lun->maxlba = (be_lun->size_blocks == 0) ?
2428 0 : (be_lun->size_blocks - 1);
2430 error = csw->d_ioctl(dev, DIOCGSTRIPESIZE, (caddr_t)&ps, FREAD,
2435 error = csw->d_ioctl(dev, DIOCGSTRIPEOFFSET, (caddr_t)&po,
2443 value = dnvlist_get_string(cbe_lun->options, "pblocksize", NULL);
2446 value = dnvlist_get_string(cbe_lun->options, "pblockoffset", NULL);
2449 pss = ps / cbe_lun->blocksize;
2450 pos = po / cbe_lun->blocksize;
2451 if ((pss > 0) && (pss * cbe_lun->blocksize == ps) && (pss >= pos) &&
2452 ((pss & (pss - 1)) == 0) && (pos * cbe_lun->blocksize == po)) {
2453 cbe_lun->pblockexp = fls(pss) - 1;
2454 cbe_lun->pblockoff = (pss - pos) % pss;
2457 value = dnvlist_get_string(cbe_lun->options, "ublocksize", NULL);
2460 value = dnvlist_get_string(cbe_lun->options, "ublockoffset", NULL);
2463 uss = us / cbe_lun->blocksize;
2464 uos = uo / cbe_lun->blocksize;
2465 if ((uss > 0) && (uss * cbe_lun->blocksize == us) && (uss >= uos) &&
2466 ((uss & (uss - 1)) == 0) && (uos * cbe_lun->blocksize == uo)) {
2467 cbe_lun->ublockexp = fls(uss) - 1;
2468 cbe_lun->ublockoff = (uss - uos) % uss;
2471 cbe_lun->atomicblock = atomic / cbe_lun->blocksize;
2472 cbe_lun->opttxferlen = maxio / cbe_lun->blocksize;
2474 if (be_lun->dispatch == ctl_be_block_dispatch_zvol) {
2481 error = csw->d_ioctl(dev, DIOCGATTR, (caddr_t)&arg, FREAD,
2485 value = dnvlist_get_string(cbe_lun->options, "unmap", NULL);
2489 cbe_lun->flags |= CTL_LUN_FLAG_UNMAP;
2491 cbe_lun->flags &= ~CTL_LUN_FLAG_UNMAP;
2500 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
2503 if (be_lun->vn) {
2505 if ((cbe_lun->flags & CTL_LUN_FLAG_READONLY) == 0)
2507 (void)vn_close(be_lun->vn, flags, NOCRED, curthread);
2508 be_lun->vn = NULL;
2510 switch (be_lun->dev_type) {
2514 if (be_lun->backend.file.cred != NULL) {
2515 crfree(be_lun->backend.file.cred);
2516 be_lun->backend.file.cred = NULL;
2522 panic("Unexpected backend type %d", be_lun->dev_type);
2525 be_lun->dev_type = CTL_BE_BLOCK_NONE;
2533 struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun;
2540 snprintf(req->error_str, sizeof(req->error_str),
2546 value = dnvlist_get_string(cbe_lun->options, "file", NULL);
2548 snprintf(req->error_str, sizeof(req->error_str),
2552 free(be_lun->dev_path, M_CTLBLK);
2553 be_lun->dev_path = strdup(value, M_CTLBLK);
2556 value = dnvlist_get_string(cbe_lun->options, "readonly", NULL);
2560 } else if (cbe_lun->lun_type == T_DIRECT)
2564 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, be_lun->dev_path);
2577 if (be_lun->dev_path[0] != '/') {
2581 be_lun->dev_path);
2582 free(be_lun->dev_path, M_CTLBLK);
2583 be_lun->dev_path = dev_name;
2586 snprintf(req->error_str, sizeof(req->error_str),
2587 "error opening %s: %d", be_lun->dev_path, error);
2591 cbe_lun->flags &= ~CTL_LUN_FLAG_READONLY;
2593 cbe_lun->flags |= CTL_LUN_FLAG_READONLY;
2596 be_lun->vn = nd.ni_vp;
2599 if (vn_isdisk_error(be_lun->vn, &error)) {
2601 } else if (be_lun->vn->v_type == VREG) {
2605 snprintf(req->error_str, sizeof(req->error_str),
2606 "%s is not a disk or plain file", be_lun->dev_path);
2608 VOP_UNLOCK(be_lun->vn);
2612 cbe_lun->serseq = CTL_LUN_SERSEQ_OFF;
2613 if (be_lun->dispatch != ctl_be_block_dispatch_dev)
2614 cbe_lun->serseq = CTL_LUN_SERSEQ_SOFT;
2615 value = dnvlist_get_string(cbe_lun->options, "serseq", NULL);
2617 cbe_lun->serseq = CTL_LUN_SERSEQ_ON;
2619 cbe_lun->serseq = CTL_LUN_SERSEQ_READ;
2621 cbe_lun->serseq = CTL_LUN_SERSEQ_SOFT;
2623 cbe_lun->serseq = CTL_LUN_SERSEQ_OFF;
2639 params = &req->reqdata.create;
2641 req->status = CTL_LUN_OK;
2644 cbe_lun = &be_lun->cbe_lun;
2645 be_lun->params = req->reqdata.create;
2646 be_lun->softc = softc;
2647 STAILQ_INIT(&be_lun->input_queue);
2648 STAILQ_INIT(&be_lun->config_read_queue);
2649 STAILQ_INIT(&be_lun->config_write_queue);
2650 STAILQ_INIT(&be_lun->datamove_queue);
2651 mtx_init(&be_lun->io_lock, "ctlblock io", NULL, MTX_DEF);
2652 mtx_init(&be_lun->queue_lock, "ctlblock queue", NULL, MTX_DEF);
2653 cbe_lun->options = nvlist_clone(req->args_nvl);
2655 if (params->flags & CTL_LUN_FLAG_DEV_TYPE)
2656 cbe_lun->lun_type = params->device_type;
2658 cbe_lun->lun_type = T_DIRECT;
2659 be_lun->flags = 0;
2660 cbe_lun->flags = 0;
2661 value = dnvlist_get_string(cbe_lun->options, "ha_role", NULL);
2664 cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY;
2665 } else if (control_softc->flags & CTL_FLAG_ACTIVE_SHELF)
2666 cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY;
2668 if (cbe_lun->lun_type == T_DIRECT ||
2669 cbe_lun->lun_type == T_CDROM) {
2670 be_lun->size_bytes = params->lun_size_bytes;
2671 if (params->blocksize_bytes != 0)
2672 cbe_lun->blocksize = params->blocksize_bytes;
2673 else if (cbe_lun->lun_type == T_CDROM)
2674 cbe_lun->blocksize = 2048;
2676 cbe_lun->blocksize = 512;
2677 be_lun->size_blocks = be_lun->size_bytes / cbe_lun->blocksize;
2678 cbe_lun->maxlba = (be_lun->size_blocks == 0) ?
2679 0 : (be_lun->size_blocks - 1);
2681 if ((cbe_lun->flags & CTL_LUN_FLAG_PRIMARY) ||
2682 control_softc->ha_mode == CTL_HA_MODE_SER_ONLY) {
2686 req->status = CTL_LUN_WARNING;
2694 value = dnvlist_get_string(cbe_lun->options, "num_threads", NULL);
2704 snprintf(req->error_str, sizeof(req->error_str),
2712 if (be_lun->vn == NULL)
2713 cbe_lun->flags |= CTL_LUN_FLAG_NO_MEDIA;
2715 params->lun_size_bytes = be_lun->size_bytes;
2716 params->blocksize_bytes = cbe_lun->blocksize;
2717 if (params->flags & CTL_LUN_FLAG_ID_REQ) {
2718 cbe_lun->req_lun_id = params->req_lun_id;
2719 cbe_lun->flags |= CTL_LUN_FLAG_ID_REQ;
2721 cbe_lun->req_lun_id = 0;
2723 cbe_lun->lun_shutdown = ctl_be_block_lun_shutdown;
2724 cbe_lun->be = &ctl_be_block_driver;
2726 if ((params->flags & CTL_LUN_FLAG_SERIAL_NUM) == 0) {
2728 softc->num_luns);
2729 strncpy((char *)cbe_lun->serial_num, tmpstr,
2730 MIN(sizeof(cbe_lun->serial_num), sizeof(tmpstr)));
2733 strncpy((char *)params->serial_num, tmpstr,
2734 MIN(sizeof(params->serial_num), sizeof(tmpstr)));
2736 strncpy((char *)cbe_lun->serial_num, params->serial_num,
2737 MIN(sizeof(cbe_lun->serial_num),
2738 sizeof(params->serial_num)));
2740 if ((params->flags & CTL_LUN_FLAG_DEVID) == 0) {
2741 snprintf(tmpstr, sizeof(tmpstr), "MYDEVID%04d", softc->num_luns);
2742 strncpy((char *)cbe_lun->device_id, tmpstr,
2743 MIN(sizeof(cbe_lun->device_id), sizeof(tmpstr)));
2746 strncpy((char *)params->device_id, tmpstr,
2747 MIN(sizeof(params->device_id), sizeof(tmpstr)));
2749 strncpy((char *)cbe_lun->device_id, params->device_id,
2750 MIN(sizeof(cbe_lun->device_id),
2751 sizeof(params->device_id)));
2754 TASK_INIT(&be_lun->io_task, /*priority*/0, ctl_be_block_worker, be_lun);
2756 be_lun->io_taskqueue = taskqueue_create("ctlblocktq", M_WAITOK,
2757 taskqueue_thread_enqueue, /*context*/&be_lun->io_taskqueue);
2759 if (be_lun->io_taskqueue == NULL) {
2760 snprintf(req->error_str, sizeof(req->error_str),
2779 retval = taskqueue_start_threads_in_proc(&be_lun->io_taskqueue,
2782 /*proc*/control_softc->ctl_proc,
2788 be_lun->num_threads = num_threads;
2790 retval = ctl_add_lun(&be_lun->cbe_lun);
2792 snprintf(req->error_str, sizeof(req->error_str),
2799 be_lun->disk_stats = devstat_new_entry("cbb", cbe_lun->lun_id,
2800 cbe_lun->blocksize,
2802 cbe_lun->lun_type
2806 mtx_lock(&softc->lock);
2807 softc->num_luns++;
2808 SLIST_INSERT_HEAD(&softc->lun_list, be_lun, links);
2809 mtx_unlock(&softc->lock);
2811 params->req_lun_id = cbe_lun->lun_id;
2816 req->status = CTL_LUN_ERROR;
2818 if (be_lun->io_taskqueue != NULL)
2819 taskqueue_free(be_lun->io_taskqueue);
2821 if (be_lun->dev_path != NULL)
2822 free(be_lun->dev_path, M_CTLBLK);
2823 nvlist_destroy(cbe_lun->options);
2824 mtx_destroy(&be_lun->queue_lock);
2825 mtx_destroy(&be_lun->io_lock);
2839 params = &req->reqdata.rm;
2841 sx_xlock(&softc->modify_lock);
2842 mtx_lock(&softc->lock);
2843 SLIST_FOREACH(be_lun, &softc->lun_list, links) {
2844 if (be_lun->cbe_lun.lun_id == params->lun_id) {
2845 SLIST_REMOVE(&softc->lun_list, be_lun,
2847 softc->num_luns--;
2851 mtx_unlock(&softc->lock);
2852 sx_xunlock(&softc->modify_lock);
2854 snprintf(req->error_str, sizeof(req->error_str),
2856 params->lun_id);
2859 cbe_lun = &be_lun->cbe_lun;
2861 if (be_lun->vn != NULL) {
2862 cbe_lun->flags |= CTL_LUN_FLAG_NO_MEDIA;
2864 taskqueue_drain_all(be_lun->io_taskqueue);
2868 mtx_lock(&softc->lock);
2869 be_lun->flags |= CTL_BE_BLOCK_LUN_WAITING;
2870 mtx_unlock(&softc->lock);
2874 snprintf(req->error_str, sizeof(req->error_str),
2876 "LUN %d", retval, params->lun_id);
2877 mtx_lock(&softc->lock);
2878 be_lun->flags &= ~CTL_BE_BLOCK_LUN_WAITING;
2879 mtx_unlock(&softc->lock);
2883 mtx_lock(&softc->lock);
2884 while ((be_lun->flags & CTL_BE_BLOCK_LUN_UNCONFIGURED) == 0) {
2885 retval = msleep(be_lun, &softc->lock, PCATCH, "ctlblockrm", 0);
2889 be_lun->flags &= ~CTL_BE_BLOCK_LUN_WAITING;
2890 if (be_lun->flags & CTL_BE_BLOCK_LUN_UNCONFIGURED) {
2891 mtx_unlock(&softc->lock);
2894 mtx_unlock(&softc->lock);
2898 req->status = CTL_LUN_OK;
2902 req->status = CTL_LUN_ERROR;
2916 params = &req->reqdata.modify;
2918 sx_xlock(&softc->modify_lock);
2919 mtx_lock(&softc->lock);
2920 SLIST_FOREACH(be_lun, &softc->lun_list, links) {
2921 if (be_lun->cbe_lun.lun_id == params->lun_id)
2924 mtx_unlock(&softc->lock);
2926 snprintf(req->error_str, sizeof(req->error_str),
2928 params->lun_id);
2931 cbe_lun = &be_lun->cbe_lun;
2933 if (params->lun_size_bytes != 0)
2934 be_lun->params.lun_size_bytes = params->lun_size_bytes;
2936 if (req->args_nvl != NULL) {
2937 nvlist_destroy(cbe_lun->options);
2938 cbe_lun->options = nvlist_clone(req->args_nvl);
2941 wasprim = (cbe_lun->flags & CTL_LUN_FLAG_PRIMARY);
2942 value = dnvlist_get_string(cbe_lun->options, "ha_role", NULL);
2945 cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY;
2947 cbe_lun->flags &= ~CTL_LUN_FLAG_PRIMARY;
2948 } else if (control_softc->flags & CTL_FLAG_ACTIVE_SHELF)
2949 cbe_lun->flags |= CTL_LUN_FLAG_PRIMARY;
2951 cbe_lun->flags &= ~CTL_LUN_FLAG_PRIMARY;
2952 if (wasprim != (cbe_lun->flags & CTL_LUN_FLAG_PRIMARY)) {
2953 if (cbe_lun->flags & CTL_LUN_FLAG_PRIMARY)
2959 oldsize = be_lun->size_blocks;
2960 if ((cbe_lun->flags & CTL_LUN_FLAG_PRIMARY) ||
2961 control_softc->ha_mode == CTL_HA_MODE_SER_ONLY) {
2962 if (be_lun->vn == NULL)
2964 else if (vn_isdisk_error(be_lun->vn, &error))
2966 else if (be_lun->vn->v_type == VREG) {
2967 vn_lock(be_lun->vn, LK_SHARED | LK_RETRY);
2969 VOP_UNLOCK(be_lun->vn);
2972 if ((cbe_lun->flags & CTL_LUN_FLAG_NO_MEDIA) &&
2973 be_lun->vn != NULL) {
2974 cbe_lun->flags &= ~CTL_LUN_FLAG_NO_MEDIA;
2976 } else if ((cbe_lun->flags & CTL_LUN_FLAG_NO_MEDIA) == 0 &&
2977 be_lun->vn == NULL) {
2978 cbe_lun->flags |= CTL_LUN_FLAG_NO_MEDIA;
2981 cbe_lun->flags &= ~CTL_LUN_FLAG_EJECTED;
2983 if (be_lun->vn != NULL) {
2984 cbe_lun->flags |= CTL_LUN_FLAG_NO_MEDIA;
2986 taskqueue_drain_all(be_lun->io_taskqueue);
2991 if (be_lun->size_blocks != oldsize)
2995 params->lun_size_bytes = be_lun->size_bytes;
2997 sx_xunlock(&softc->modify_lock);
2998 req->status = error ? CTL_LUN_WARNING : CTL_LUN_OK;
3002 sx_xunlock(&softc->modify_lock);
3003 req->status = CTL_LUN_ERROR;
3011 struct ctl_be_block_softc *softc = be_lun->softc;
3013 taskqueue_drain_all(be_lun->io_taskqueue);
3014 taskqueue_free(be_lun->io_taskqueue);
3015 if (be_lun->disk_stats != NULL)
3016 devstat_remove_entry(be_lun->disk_stats);
3017 nvlist_destroy(be_lun->cbe_lun.options);
3018 free(be_lun->dev_path, M_CTLBLK);
3019 mtx_destroy(&be_lun->queue_lock);
3020 mtx_destroy(&be_lun->io_lock);
3022 mtx_lock(&softc->lock);
3023 be_lun->flags |= CTL_BE_BLOCK_LUN_UNCONFIGURED;
3024 if (be_lun->flags & CTL_BE_BLOCK_LUN_WAITING)
3028 mtx_unlock(&softc->lock);
3044 switch (io->scsiio.cdb[0]) {
3058 mtx_lock(&be_lun->queue_lock);
3059 STAILQ_INSERT_TAIL(&be_lun->config_write_queue, &io->io_hdr,
3061 mtx_unlock(&be_lun->queue_lock);
3062 taskqueue_enqueue(be_lun->io_taskqueue, &be_lun->io_task);
3068 cdb = (struct scsi_start_stop_unit *)io->scsiio.cdb;
3069 if ((cdb->how & SSS_PC_MASK) != 0) {
3070 ctl_set_success(&io->scsiio);
3074 if (cdb->how & SSS_START) {
3075 if ((cdb->how & SSS_LOEJ) && be_lun->vn == NULL) {
3077 cbe_lun->flags &= ~CTL_LUN_FLAG_EJECTED;
3079 cbe_lun->flags &= ~CTL_LUN_FLAG_NO_MEDIA;
3082 cbe_lun->flags |= CTL_LUN_FLAG_NO_MEDIA;
3089 if (cdb->how & SSS_LOEJ) {
3090 cbe_lun->flags |= CTL_LUN_FLAG_NO_MEDIA;
3091 cbe_lun->flags |= CTL_LUN_FLAG_EJECTED;
3093 if (be_lun->vn != NULL)
3098 ctl_set_success(&io->scsiio);
3103 ctl_set_success(&io->scsiio);
3107 ctl_set_invalid_opcode(&io->scsiio);
3125 switch (io->nvmeio.cmd.opc) {
3132 mtx_lock(&be_lun->queue_lock);
3133 STAILQ_INSERT_TAIL(&be_lun->config_write_queue, &io->io_hdr,
3135 mtx_unlock(&be_lun->queue_lock);
3136 taskqueue_enqueue(be_lun->io_taskqueue, &be_lun->io_task);
3139 ctl_nvme_set_invalid_opcode(&io->nvmeio);
3149 switch (io->io_hdr.io_type) {
3169 switch (io->scsiio.cdb[0]) {
3171 if (io->scsiio.cdb[1] == SGLS_SERVICE_ACTION) {
3172 mtx_lock(&be_lun->queue_lock);
3173 STAILQ_INSERT_TAIL(&be_lun->config_read_queue,
3174 &io->io_hdr, links);
3175 mtx_unlock(&be_lun->queue_lock);
3176 taskqueue_enqueue(be_lun->io_taskqueue,
3177 &be_lun->io_task);
3181 ctl_set_invalid_field(&io->scsiio,
3191 ctl_set_invalid_opcode(&io->scsiio);
3209 switch (io->nvmeio.cmd.opc) {
3214 cns = le32toh(io->nvmeio.cmd.cdw10) & 0xff;
3218 mtx_lock(&be_lun->queue_lock);
3219 STAILQ_INSERT_TAIL(&be_lun->config_read_queue,
3220 &io->io_hdr, links);
3221 mtx_unlock(&be_lun->queue_lock);
3222 taskqueue_enqueue(be_lun->io_taskqueue,
3223 &be_lun->io_task);
3226 ctl_nvme_set_invalid_field(&io->nvmeio);
3233 ctl_nvme_set_invalid_opcode(&io->nvmeio);
3243 switch (io->io_hdr.io_type) {
3262 retval = sbuf_printf(sb, "%d", lun->num_threads);
3276 if (lun->getattr == NULL)
3278 return (lun->getattr(lun, attrname));
3286 sx_init(&softc->modify_lock, "ctlblock modify");
3287 mtx_init(&softc->lock, "ctlblock", NULL, MTX_DEF);
3288 softc->beio_zone = uma_zcreate("beio", sizeof(struct ctl_be_block_io),
3290 softc->bufmin_zone = uma_zcreate("ctlblockmin", CTLBLK_MIN_SEG,
3293 softc->bufmax_zone = uma_zcreate("ctlblockmax", CTLBLK_MAX_SEG,
3295 SLIST_INIT(&softc->lun_list);
3305 mtx_lock(&softc->lock);
3306 while ((lun = SLIST_FIRST(&softc->lun_list)) != NULL) {
3307 SLIST_REMOVE_HEAD(&softc->lun_list, links);
3308 softc->num_luns--;
3314 mtx_unlock(&softc->lock);
3315 ctl_remove_lun(&lun->cbe_lun);
3316 mtx_lock(&softc->lock);
3318 mtx_unlock(&softc->lock);
3319 uma_zdestroy(softc->bufmin_zone);
3321 uma_zdestroy(softc->bufmax_zone);
3322 uma_zdestroy(softc->beio_zone);
3323 mtx_destroy(&softc->lock);
3324 sx_destroy(&softc->modify_lock);