Deleted Added
full compact
ctl_backend_block.c (267641) ctl_backend_block.c (267877)
1/*-
2 * Copyright (c) 2003 Silicon Graphics International Corp.
3 * Copyright (c) 2009-2011 Spectra Logic Corporation
4 * Copyright (c) 2012 The FreeBSD Foundation
5 * All rights reserved.
6 *
7 * Portions of this software were developed by Edward Tomasz Napierala
8 * under sponsorship from the FreeBSD Foundation.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
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.
21 *
22 * NO WARRANTY
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.
34 *
35 * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_backend_block.c#5 $
36 */
37/*
38 * CAM Target Layer driver backend for block devices.
39 *
40 * Author: Ken Merry <ken@FreeBSD.org>
41 */
42#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2003 Silicon Graphics International Corp.
3 * Copyright (c) 2009-2011 Spectra Logic Corporation
4 * Copyright (c) 2012 The FreeBSD Foundation
5 * All rights reserved.
6 *
7 * Portions of this software were developed by Edward Tomasz Napierala
8 * under sponsorship from the FreeBSD Foundation.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
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.
21 *
22 * NO WARRANTY
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.
34 *
35 * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_backend_block.c#5 $
36 */
37/*
38 * CAM Target Layer driver backend for block devices.
39 *
40 * Author: Ken Merry <ken@FreeBSD.org>
41 */
42#include <sys/cdefs.h>
43__FBSDID("$FreeBSD: head/sys/cam/ctl/ctl_backend_block.c 267641 2014-06-19 12:43:41Z mav $");
43__FBSDID("$FreeBSD: head/sys/cam/ctl/ctl_backend_block.c 267877 2014-06-25 17:54:36Z mav $");
44
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>
50#include <sys/bio.h>
51#include <sys/fcntl.h>
52#include <sys/limits.h>
53#include <sys/lock.h>
54#include <sys/mutex.h>
55#include <sys/condvar.h>
56#include <sys/malloc.h>
57#include <sys/conf.h>
58#include <sys/ioccom.h>
59#include <sys/queue.h>
60#include <sys/sbuf.h>
61#include <sys/endian.h>
62#include <sys/uio.h>
63#include <sys/buf.h>
64#include <sys/taskqueue.h>
65#include <sys/vnode.h>
66#include <sys/namei.h>
67#include <sys/mount.h>
68#include <sys/disk.h>
69#include <sys/fcntl.h>
70#include <sys/filedesc.h>
71#include <sys/proc.h>
72#include <sys/pcpu.h>
73#include <sys/module.h>
74#include <sys/sdt.h>
75#include <sys/devicestat.h>
76#include <sys/sysctl.h>
77
78#include <geom/geom.h>
79
80#include <cam/cam.h>
81#include <cam/scsi/scsi_all.h>
82#include <cam/scsi/scsi_da.h>
83#include <cam/ctl/ctl_io.h>
84#include <cam/ctl/ctl.h>
85#include <cam/ctl/ctl_backend.h>
86#include <cam/ctl/ctl_frontend_internal.h>
87#include <cam/ctl/ctl_ioctl.h>
88#include <cam/ctl/ctl_scsi_all.h>
89#include <cam/ctl/ctl_error.h>
90
91/*
92 * The idea here is that we'll allocate enough S/G space to hold a 1MB
93 * I/O. If we get an I/O larger than that, we'll split it.
94 */
95#define CTLBLK_HALF_IO_SIZE (512 * 1024)
96#define CTLBLK_MAX_IO_SIZE (CTLBLK_HALF_IO_SIZE * 2)
97#define CTLBLK_MAX_SEG MAXPHYS
98#define CTLBLK_HALF_SEGS MAX(CTLBLK_HALF_IO_SIZE / CTLBLK_MAX_SEG, 1)
99#define CTLBLK_MAX_SEGS (CTLBLK_HALF_SEGS * 2)
100
101#ifdef CTLBLK_DEBUG
102#define DPRINTF(fmt, args...) \
103 printf("cbb(%s:%d): " fmt, __FUNCTION__, __LINE__, ##args)
104#else
105#define DPRINTF(fmt, args...) do {} while(0)
106#endif
107
108#define PRIV(io) \
109 ((struct ctl_ptr_len_flags *)&(io)->io_hdr.ctl_private[CTL_PRIV_BACKEND])
110#define ARGS(io) \
111 ((struct ctl_lba_len_flags *)&(io)->io_hdr.ctl_private[CTL_PRIV_LBA_LEN])
112
113SDT_PROVIDER_DEFINE(cbb);
114
115typedef enum {
116 CTL_BE_BLOCK_LUN_UNCONFIGURED = 0x01,
117 CTL_BE_BLOCK_LUN_CONFIG_ERR = 0x02,
118 CTL_BE_BLOCK_LUN_WAITING = 0x04,
119 CTL_BE_BLOCK_LUN_MULTI_THREAD = 0x08
120} ctl_be_block_lun_flags;
121
122typedef enum {
123 CTL_BE_BLOCK_NONE,
124 CTL_BE_BLOCK_DEV,
125 CTL_BE_BLOCK_FILE
126} ctl_be_block_type;
127
128struct ctl_be_block_devdata {
129 struct cdev *cdev;
130 struct cdevsw *csw;
131 int dev_ref;
132};
133
134struct ctl_be_block_filedata {
135 struct ucred *cred;
136};
137
138union ctl_be_block_bedata {
139 struct ctl_be_block_devdata dev;
140 struct ctl_be_block_filedata file;
141};
142
143struct ctl_be_block_io;
144struct ctl_be_block_lun;
145
146typedef void (*cbb_dispatch_t)(struct ctl_be_block_lun *be_lun,
147 struct ctl_be_block_io *beio);
148
149/*
150 * Backend LUN structure. There is a 1:1 mapping between a block device
151 * and a backend block LUN, and between a backend block LUN and a CTL LUN.
152 */
153struct ctl_be_block_lun {
154 struct ctl_block_disk *disk;
155 char lunname[32];
156 char *dev_path;
157 ctl_be_block_type dev_type;
158 struct vnode *vn;
159 union ctl_be_block_bedata backend;
160 cbb_dispatch_t dispatch;
161 cbb_dispatch_t lun_flush;
162 cbb_dispatch_t unmap;
44
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>
50#include <sys/bio.h>
51#include <sys/fcntl.h>
52#include <sys/limits.h>
53#include <sys/lock.h>
54#include <sys/mutex.h>
55#include <sys/condvar.h>
56#include <sys/malloc.h>
57#include <sys/conf.h>
58#include <sys/ioccom.h>
59#include <sys/queue.h>
60#include <sys/sbuf.h>
61#include <sys/endian.h>
62#include <sys/uio.h>
63#include <sys/buf.h>
64#include <sys/taskqueue.h>
65#include <sys/vnode.h>
66#include <sys/namei.h>
67#include <sys/mount.h>
68#include <sys/disk.h>
69#include <sys/fcntl.h>
70#include <sys/filedesc.h>
71#include <sys/proc.h>
72#include <sys/pcpu.h>
73#include <sys/module.h>
74#include <sys/sdt.h>
75#include <sys/devicestat.h>
76#include <sys/sysctl.h>
77
78#include <geom/geom.h>
79
80#include <cam/cam.h>
81#include <cam/scsi/scsi_all.h>
82#include <cam/scsi/scsi_da.h>
83#include <cam/ctl/ctl_io.h>
84#include <cam/ctl/ctl.h>
85#include <cam/ctl/ctl_backend.h>
86#include <cam/ctl/ctl_frontend_internal.h>
87#include <cam/ctl/ctl_ioctl.h>
88#include <cam/ctl/ctl_scsi_all.h>
89#include <cam/ctl/ctl_error.h>
90
91/*
92 * The idea here is that we'll allocate enough S/G space to hold a 1MB
93 * I/O. If we get an I/O larger than that, we'll split it.
94 */
95#define CTLBLK_HALF_IO_SIZE (512 * 1024)
96#define CTLBLK_MAX_IO_SIZE (CTLBLK_HALF_IO_SIZE * 2)
97#define CTLBLK_MAX_SEG MAXPHYS
98#define CTLBLK_HALF_SEGS MAX(CTLBLK_HALF_IO_SIZE / CTLBLK_MAX_SEG, 1)
99#define CTLBLK_MAX_SEGS (CTLBLK_HALF_SEGS * 2)
100
101#ifdef CTLBLK_DEBUG
102#define DPRINTF(fmt, args...) \
103 printf("cbb(%s:%d): " fmt, __FUNCTION__, __LINE__, ##args)
104#else
105#define DPRINTF(fmt, args...) do {} while(0)
106#endif
107
108#define PRIV(io) \
109 ((struct ctl_ptr_len_flags *)&(io)->io_hdr.ctl_private[CTL_PRIV_BACKEND])
110#define ARGS(io) \
111 ((struct ctl_lba_len_flags *)&(io)->io_hdr.ctl_private[CTL_PRIV_LBA_LEN])
112
113SDT_PROVIDER_DEFINE(cbb);
114
115typedef enum {
116 CTL_BE_BLOCK_LUN_UNCONFIGURED = 0x01,
117 CTL_BE_BLOCK_LUN_CONFIG_ERR = 0x02,
118 CTL_BE_BLOCK_LUN_WAITING = 0x04,
119 CTL_BE_BLOCK_LUN_MULTI_THREAD = 0x08
120} ctl_be_block_lun_flags;
121
122typedef enum {
123 CTL_BE_BLOCK_NONE,
124 CTL_BE_BLOCK_DEV,
125 CTL_BE_BLOCK_FILE
126} ctl_be_block_type;
127
128struct ctl_be_block_devdata {
129 struct cdev *cdev;
130 struct cdevsw *csw;
131 int dev_ref;
132};
133
134struct ctl_be_block_filedata {
135 struct ucred *cred;
136};
137
138union ctl_be_block_bedata {
139 struct ctl_be_block_devdata dev;
140 struct ctl_be_block_filedata file;
141};
142
143struct ctl_be_block_io;
144struct ctl_be_block_lun;
145
146typedef void (*cbb_dispatch_t)(struct ctl_be_block_lun *be_lun,
147 struct ctl_be_block_io *beio);
148
149/*
150 * Backend LUN structure. There is a 1:1 mapping between a block device
151 * and a backend block LUN, and between a backend block LUN and a CTL LUN.
152 */
153struct ctl_be_block_lun {
154 struct ctl_block_disk *disk;
155 char lunname[32];
156 char *dev_path;
157 ctl_be_block_type dev_type;
158 struct vnode *vn;
159 union ctl_be_block_bedata backend;
160 cbb_dispatch_t dispatch;
161 cbb_dispatch_t lun_flush;
162 cbb_dispatch_t unmap;
163 struct mtx lock;
164 uma_zone_t lun_zone;
165 uint64_t size_blocks;
166 uint64_t size_bytes;
167 uint32_t blocksize;
168 int blocksize_shift;
169 uint16_t pblockexp;
170 uint16_t pblockoff;
171 struct ctl_be_block_softc *softc;
172 struct devstat *disk_stats;
173 ctl_be_block_lun_flags flags;
174 STAILQ_ENTRY(ctl_be_block_lun) links;
175 struct ctl_be_lun ctl_be_lun;
176 struct taskqueue *io_taskqueue;
177 struct task io_task;
178 int num_threads;
179 STAILQ_HEAD(, ctl_io_hdr) input_queue;
180 STAILQ_HEAD(, ctl_io_hdr) config_write_queue;
181 STAILQ_HEAD(, ctl_io_hdr) datamove_queue;
163 uma_zone_t lun_zone;
164 uint64_t size_blocks;
165 uint64_t size_bytes;
166 uint32_t blocksize;
167 int blocksize_shift;
168 uint16_t pblockexp;
169 uint16_t pblockoff;
170 struct ctl_be_block_softc *softc;
171 struct devstat *disk_stats;
172 ctl_be_block_lun_flags flags;
173 STAILQ_ENTRY(ctl_be_block_lun) links;
174 struct ctl_be_lun ctl_be_lun;
175 struct taskqueue *io_taskqueue;
176 struct task io_task;
177 int num_threads;
178 STAILQ_HEAD(, ctl_io_hdr) input_queue;
179 STAILQ_HEAD(, ctl_io_hdr) config_write_queue;
180 STAILQ_HEAD(, ctl_io_hdr) datamove_queue;
181 struct mtx_padalign io_lock;
182 struct mtx_padalign queue_lock;
182};
183
184/*
185 * Overall softc structure for the block backend module.
186 */
187struct ctl_be_block_softc {
188 struct mtx lock;
189 int num_disks;
190 STAILQ_HEAD(, ctl_block_disk) disk_list;
191 int num_luns;
192 STAILQ_HEAD(, ctl_be_block_lun) lun_list;
193};
194
195static struct ctl_be_block_softc backend_block_softc;
196
197/*
198 * Per-I/O information.
199 */
200struct ctl_be_block_io {
201 union ctl_io *io;
202 struct ctl_sg_entry sg_segs[CTLBLK_MAX_SEGS];
203 struct iovec xiovecs[CTLBLK_MAX_SEGS];
204 int bio_cmd;
205 int bio_flags;
206 int num_segs;
207 int num_bios_sent;
208 int num_bios_done;
209 int send_complete;
210 int num_errors;
211 struct bintime ds_t0;
212 devstat_tag_type ds_tag_type;
213 devstat_trans_flags ds_trans_type;
214 uint64_t io_len;
215 uint64_t io_offset;
216 struct ctl_be_block_softc *softc;
217 struct ctl_be_block_lun *lun;
218 void (*beio_cont)(struct ctl_be_block_io *beio); /* to continue processing */
219};
220
221static int cbb_num_threads = 14;
222TUNABLE_INT("kern.cam.ctl.block.num_threads", &cbb_num_threads);
223SYSCTL_NODE(_kern_cam_ctl, OID_AUTO, block, CTLFLAG_RD, 0,
224 "CAM Target Layer Block Backend");
225SYSCTL_INT(_kern_cam_ctl_block, OID_AUTO, num_threads, CTLFLAG_RW,
226 &cbb_num_threads, 0, "Number of threads per backing file");
227
228static struct ctl_be_block_io *ctl_alloc_beio(struct ctl_be_block_softc *softc);
229static void ctl_free_beio(struct ctl_be_block_io *beio);
230static void ctl_complete_beio(struct ctl_be_block_io *beio);
231static int ctl_be_block_move_done(union ctl_io *io);
232static void ctl_be_block_biodone(struct bio *bio);
233static void ctl_be_block_flush_file(struct ctl_be_block_lun *be_lun,
234 struct ctl_be_block_io *beio);
235static void ctl_be_block_dispatch_file(struct ctl_be_block_lun *be_lun,
236 struct ctl_be_block_io *beio);
237static void ctl_be_block_flush_dev(struct ctl_be_block_lun *be_lun,
238 struct ctl_be_block_io *beio);
239static void ctl_be_block_unmap_dev(struct ctl_be_block_lun *be_lun,
240 struct ctl_be_block_io *beio);
241static void ctl_be_block_dispatch_dev(struct ctl_be_block_lun *be_lun,
242 struct ctl_be_block_io *beio);
243static void ctl_be_block_cw_dispatch(struct ctl_be_block_lun *be_lun,
244 union ctl_io *io);
245static void ctl_be_block_dispatch(struct ctl_be_block_lun *be_lun,
246 union ctl_io *io);
247static void ctl_be_block_worker(void *context, int pending);
248static int ctl_be_block_submit(union ctl_io *io);
249static int ctl_be_block_ioctl(struct cdev *dev, u_long cmd, caddr_t addr,
250 int flag, struct thread *td);
251static int ctl_be_block_open_file(struct ctl_be_block_lun *be_lun,
252 struct ctl_lun_req *req);
253static int ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun,
254 struct ctl_lun_req *req);
255static int ctl_be_block_close(struct ctl_be_block_lun *be_lun);
256static int ctl_be_block_open(struct ctl_be_block_softc *softc,
257 struct ctl_be_block_lun *be_lun,
258 struct ctl_lun_req *req);
259static int ctl_be_block_create(struct ctl_be_block_softc *softc,
260 struct ctl_lun_req *req);
261static int ctl_be_block_rm(struct ctl_be_block_softc *softc,
262 struct ctl_lun_req *req);
263static int ctl_be_block_modify_file(struct ctl_be_block_lun *be_lun,
264 struct ctl_lun_req *req);
265static int ctl_be_block_modify_dev(struct ctl_be_block_lun *be_lun,
266 struct ctl_lun_req *req);
267static int ctl_be_block_modify(struct ctl_be_block_softc *softc,
268 struct ctl_lun_req *req);
269static void ctl_be_block_lun_shutdown(void *be_lun);
270static void ctl_be_block_lun_config_status(void *be_lun,
271 ctl_lun_config_status status);
272static int ctl_be_block_config_write(union ctl_io *io);
273static int ctl_be_block_config_read(union ctl_io *io);
274static int ctl_be_block_lun_info(void *be_lun, struct sbuf *sb);
275int ctl_be_block_init(void);
276
277static struct ctl_backend_driver ctl_be_block_driver =
278{
279 .name = "block",
280 .flags = CTL_BE_FLAG_HAS_CONFIG,
281 .init = ctl_be_block_init,
282 .data_submit = ctl_be_block_submit,
283 .data_move_done = ctl_be_block_move_done,
284 .config_read = ctl_be_block_config_read,
285 .config_write = ctl_be_block_config_write,
286 .ioctl = ctl_be_block_ioctl,
287 .lun_info = ctl_be_block_lun_info
288};
289
290MALLOC_DEFINE(M_CTLBLK, "ctlblk", "Memory used for CTL block backend");
291CTL_BACKEND_DECLARE(cbb, ctl_be_block_driver);
292
293static uma_zone_t beio_zone;
294
295static struct ctl_be_block_io *
296ctl_alloc_beio(struct ctl_be_block_softc *softc)
297{
298 struct ctl_be_block_io *beio;
299
300 beio = uma_zalloc(beio_zone, M_WAITOK | M_ZERO);
301 beio->softc = softc;
302 return (beio);
303}
304
305static void
306ctl_free_beio(struct ctl_be_block_io *beio)
307{
308 int duplicate_free;
309 int i;
310
311 duplicate_free = 0;
312
313 for (i = 0; i < beio->num_segs; i++) {
314 if (beio->sg_segs[i].addr == NULL)
315 duplicate_free++;
316
317 uma_zfree(beio->lun->lun_zone, beio->sg_segs[i].addr);
318 beio->sg_segs[i].addr = NULL;
319
320 /* For compare we had two equal S/G lists. */
321 if (ARGS(beio->io)->flags & CTL_LLF_COMPARE) {
322 uma_zfree(beio->lun->lun_zone,
323 beio->sg_segs[i + CTLBLK_HALF_SEGS].addr);
324 beio->sg_segs[i + CTLBLK_HALF_SEGS].addr = NULL;
325 }
326 }
327
328 if (duplicate_free > 0) {
329 printf("%s: %d duplicate frees out of %d segments\n", __func__,
330 duplicate_free, beio->num_segs);
331 }
332
333 uma_zfree(beio_zone, beio);
334}
335
336static void
337ctl_complete_beio(struct ctl_be_block_io *beio)
338{
183};
184
185/*
186 * Overall softc structure for the block backend module.
187 */
188struct ctl_be_block_softc {
189 struct mtx lock;
190 int num_disks;
191 STAILQ_HEAD(, ctl_block_disk) disk_list;
192 int num_luns;
193 STAILQ_HEAD(, ctl_be_block_lun) lun_list;
194};
195
196static struct ctl_be_block_softc backend_block_softc;
197
198/*
199 * Per-I/O information.
200 */
201struct ctl_be_block_io {
202 union ctl_io *io;
203 struct ctl_sg_entry sg_segs[CTLBLK_MAX_SEGS];
204 struct iovec xiovecs[CTLBLK_MAX_SEGS];
205 int bio_cmd;
206 int bio_flags;
207 int num_segs;
208 int num_bios_sent;
209 int num_bios_done;
210 int send_complete;
211 int num_errors;
212 struct bintime ds_t0;
213 devstat_tag_type ds_tag_type;
214 devstat_trans_flags ds_trans_type;
215 uint64_t io_len;
216 uint64_t io_offset;
217 struct ctl_be_block_softc *softc;
218 struct ctl_be_block_lun *lun;
219 void (*beio_cont)(struct ctl_be_block_io *beio); /* to continue processing */
220};
221
222static int cbb_num_threads = 14;
223TUNABLE_INT("kern.cam.ctl.block.num_threads", &cbb_num_threads);
224SYSCTL_NODE(_kern_cam_ctl, OID_AUTO, block, CTLFLAG_RD, 0,
225 "CAM Target Layer Block Backend");
226SYSCTL_INT(_kern_cam_ctl_block, OID_AUTO, num_threads, CTLFLAG_RW,
227 &cbb_num_threads, 0, "Number of threads per backing file");
228
229static struct ctl_be_block_io *ctl_alloc_beio(struct ctl_be_block_softc *softc);
230static void ctl_free_beio(struct ctl_be_block_io *beio);
231static void ctl_complete_beio(struct ctl_be_block_io *beio);
232static int ctl_be_block_move_done(union ctl_io *io);
233static void ctl_be_block_biodone(struct bio *bio);
234static void ctl_be_block_flush_file(struct ctl_be_block_lun *be_lun,
235 struct ctl_be_block_io *beio);
236static void ctl_be_block_dispatch_file(struct ctl_be_block_lun *be_lun,
237 struct ctl_be_block_io *beio);
238static void ctl_be_block_flush_dev(struct ctl_be_block_lun *be_lun,
239 struct ctl_be_block_io *beio);
240static void ctl_be_block_unmap_dev(struct ctl_be_block_lun *be_lun,
241 struct ctl_be_block_io *beio);
242static void ctl_be_block_dispatch_dev(struct ctl_be_block_lun *be_lun,
243 struct ctl_be_block_io *beio);
244static void ctl_be_block_cw_dispatch(struct ctl_be_block_lun *be_lun,
245 union ctl_io *io);
246static void ctl_be_block_dispatch(struct ctl_be_block_lun *be_lun,
247 union ctl_io *io);
248static void ctl_be_block_worker(void *context, int pending);
249static int ctl_be_block_submit(union ctl_io *io);
250static int ctl_be_block_ioctl(struct cdev *dev, u_long cmd, caddr_t addr,
251 int flag, struct thread *td);
252static int ctl_be_block_open_file(struct ctl_be_block_lun *be_lun,
253 struct ctl_lun_req *req);
254static int ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun,
255 struct ctl_lun_req *req);
256static int ctl_be_block_close(struct ctl_be_block_lun *be_lun);
257static int ctl_be_block_open(struct ctl_be_block_softc *softc,
258 struct ctl_be_block_lun *be_lun,
259 struct ctl_lun_req *req);
260static int ctl_be_block_create(struct ctl_be_block_softc *softc,
261 struct ctl_lun_req *req);
262static int ctl_be_block_rm(struct ctl_be_block_softc *softc,
263 struct ctl_lun_req *req);
264static int ctl_be_block_modify_file(struct ctl_be_block_lun *be_lun,
265 struct ctl_lun_req *req);
266static int ctl_be_block_modify_dev(struct ctl_be_block_lun *be_lun,
267 struct ctl_lun_req *req);
268static int ctl_be_block_modify(struct ctl_be_block_softc *softc,
269 struct ctl_lun_req *req);
270static void ctl_be_block_lun_shutdown(void *be_lun);
271static void ctl_be_block_lun_config_status(void *be_lun,
272 ctl_lun_config_status status);
273static int ctl_be_block_config_write(union ctl_io *io);
274static int ctl_be_block_config_read(union ctl_io *io);
275static int ctl_be_block_lun_info(void *be_lun, struct sbuf *sb);
276int ctl_be_block_init(void);
277
278static struct ctl_backend_driver ctl_be_block_driver =
279{
280 .name = "block",
281 .flags = CTL_BE_FLAG_HAS_CONFIG,
282 .init = ctl_be_block_init,
283 .data_submit = ctl_be_block_submit,
284 .data_move_done = ctl_be_block_move_done,
285 .config_read = ctl_be_block_config_read,
286 .config_write = ctl_be_block_config_write,
287 .ioctl = ctl_be_block_ioctl,
288 .lun_info = ctl_be_block_lun_info
289};
290
291MALLOC_DEFINE(M_CTLBLK, "ctlblk", "Memory used for CTL block backend");
292CTL_BACKEND_DECLARE(cbb, ctl_be_block_driver);
293
294static uma_zone_t beio_zone;
295
296static struct ctl_be_block_io *
297ctl_alloc_beio(struct ctl_be_block_softc *softc)
298{
299 struct ctl_be_block_io *beio;
300
301 beio = uma_zalloc(beio_zone, M_WAITOK | M_ZERO);
302 beio->softc = softc;
303 return (beio);
304}
305
306static void
307ctl_free_beio(struct ctl_be_block_io *beio)
308{
309 int duplicate_free;
310 int i;
311
312 duplicate_free = 0;
313
314 for (i = 0; i < beio->num_segs; i++) {
315 if (beio->sg_segs[i].addr == NULL)
316 duplicate_free++;
317
318 uma_zfree(beio->lun->lun_zone, beio->sg_segs[i].addr);
319 beio->sg_segs[i].addr = NULL;
320
321 /* For compare we had two equal S/G lists. */
322 if (ARGS(beio->io)->flags & CTL_LLF_COMPARE) {
323 uma_zfree(beio->lun->lun_zone,
324 beio->sg_segs[i + CTLBLK_HALF_SEGS].addr);
325 beio->sg_segs[i + CTLBLK_HALF_SEGS].addr = NULL;
326 }
327 }
328
329 if (duplicate_free > 0) {
330 printf("%s: %d duplicate frees out of %d segments\n", __func__,
331 duplicate_free, beio->num_segs);
332 }
333
334 uma_zfree(beio_zone, beio);
335}
336
337static void
338ctl_complete_beio(struct ctl_be_block_io *beio)
339{
339 union ctl_io *io;
340 int io_len;
340 union ctl_io *io = beio->io;
341
341
342 io = beio->io;
343
344 if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS)
345 io_len = beio->io_len;
346 else
347 io_len = 0;
348
349 devstat_end_transaction(beio->lun->disk_stats,
350 /*bytes*/ io_len,
351 beio->ds_tag_type,
352 beio->ds_trans_type,
353 /*now*/ NULL,
354 /*then*/&beio->ds_t0);
355
356 if (beio->beio_cont != NULL) {
357 beio->beio_cont(beio);
358 } else {
359 ctl_free_beio(beio);
360 ctl_data_submit_done(io);
361 }
362}
363
364static int
365ctl_be_block_move_done(union ctl_io *io)
366{
367 struct ctl_be_block_io *beio;
368 struct ctl_be_block_lun *be_lun;
369 struct ctl_lba_len_flags *lbalen;
370#ifdef CTL_TIME_IO
371 struct bintime cur_bt;
372#endif
373 int i;
374
375 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
376 be_lun = beio->lun;
377
378 DPRINTF("entered\n");
379
380#ifdef CTL_TIME_IO
381 getbintime(&cur_bt);
382 bintime_sub(&cur_bt, &io->io_hdr.dma_start_bt);
383 bintime_add(&io->io_hdr.dma_bt, &cur_bt);
384 io->io_hdr.num_dmas++;
385#endif
386 io->scsiio.kern_rel_offset += io->scsiio.kern_data_len;
387
388 /*
389 * We set status at this point for read commands, and write
390 * commands with errors.
391 */
392 if ((io->io_hdr.port_status == 0) &&
393 ((io->io_hdr.flags & CTL_FLAG_ABORT) == 0) &&
394 ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE)) {
395 lbalen = ARGS(beio->io);
396 if (lbalen->flags & CTL_LLF_READ) {
397 ctl_set_success(&io->scsiio);
398 } else if (lbalen->flags & CTL_LLF_COMPARE) {
399 /* We have two data blocks ready for comparison. */
400 for (i = 0; i < beio->num_segs; i++) {
401 if (memcmp(beio->sg_segs[i].addr,
402 beio->sg_segs[i + CTLBLK_HALF_SEGS].addr,
403 beio->sg_segs[i].len) != 0)
404 break;
405 }
406 if (i < beio->num_segs)
407 ctl_set_sense(&io->scsiio,
408 /*current_error*/ 1,
409 /*sense_key*/ SSD_KEY_MISCOMPARE,
410 /*asc*/ 0x1D,
411 /*ascq*/ 0x00,
412 SSD_ELEM_NONE);
413 else
414 ctl_set_success(&io->scsiio);
415 }
416 }
417 else if ((io->io_hdr.port_status != 0)
418 && ((io->io_hdr.flags & CTL_FLAG_ABORT) == 0)
419 && ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE)) {
420 /*
421 * For hardware error sense keys, the sense key
422 * specific value is defined to be a retry count,
423 * but we use it to pass back an internal FETD
424 * error code. XXX KDM Hopefully the FETD is only
425 * using 16 bits for an error code, since that's
426 * all the space we have in the sks field.
427 */
428 ctl_set_internal_failure(&io->scsiio,
429 /*sks_valid*/ 1,
430 /*retry_count*/
431 io->io_hdr.port_status);
432 }
433
434 /*
435 * If this is a read, or a write with errors, it is done.
436 */
437 if ((beio->bio_cmd == BIO_READ)
438 || ((io->io_hdr.flags & CTL_FLAG_ABORT) != 0)
439 || ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE)) {
440 ctl_complete_beio(beio);
441 return (0);
442 }
443
444 /*
445 * At this point, we have a write and the DMA completed
446 * successfully. We now have to queue it to the task queue to
447 * execute the backend I/O. That is because we do blocking
448 * memory allocations, and in the file backing case, blocking I/O.
449 * This move done routine is generally called in the SIM's
450 * interrupt context, and therefore we cannot block.
451 */
342 if (beio->beio_cont != NULL) {
343 beio->beio_cont(beio);
344 } else {
345 ctl_free_beio(beio);
346 ctl_data_submit_done(io);
347 }
348}
349
350static int
351ctl_be_block_move_done(union ctl_io *io)
352{
353 struct ctl_be_block_io *beio;
354 struct ctl_be_block_lun *be_lun;
355 struct ctl_lba_len_flags *lbalen;
356#ifdef CTL_TIME_IO
357 struct bintime cur_bt;
358#endif
359 int i;
360
361 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
362 be_lun = beio->lun;
363
364 DPRINTF("entered\n");
365
366#ifdef CTL_TIME_IO
367 getbintime(&cur_bt);
368 bintime_sub(&cur_bt, &io->io_hdr.dma_start_bt);
369 bintime_add(&io->io_hdr.dma_bt, &cur_bt);
370 io->io_hdr.num_dmas++;
371#endif
372 io->scsiio.kern_rel_offset += io->scsiio.kern_data_len;
373
374 /*
375 * We set status at this point for read commands, and write
376 * commands with errors.
377 */
378 if ((io->io_hdr.port_status == 0) &&
379 ((io->io_hdr.flags & CTL_FLAG_ABORT) == 0) &&
380 ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE)) {
381 lbalen = ARGS(beio->io);
382 if (lbalen->flags & CTL_LLF_READ) {
383 ctl_set_success(&io->scsiio);
384 } else if (lbalen->flags & CTL_LLF_COMPARE) {
385 /* We have two data blocks ready for comparison. */
386 for (i = 0; i < beio->num_segs; i++) {
387 if (memcmp(beio->sg_segs[i].addr,
388 beio->sg_segs[i + CTLBLK_HALF_SEGS].addr,
389 beio->sg_segs[i].len) != 0)
390 break;
391 }
392 if (i < beio->num_segs)
393 ctl_set_sense(&io->scsiio,
394 /*current_error*/ 1,
395 /*sense_key*/ SSD_KEY_MISCOMPARE,
396 /*asc*/ 0x1D,
397 /*ascq*/ 0x00,
398 SSD_ELEM_NONE);
399 else
400 ctl_set_success(&io->scsiio);
401 }
402 }
403 else if ((io->io_hdr.port_status != 0)
404 && ((io->io_hdr.flags & CTL_FLAG_ABORT) == 0)
405 && ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE)) {
406 /*
407 * For hardware error sense keys, the sense key
408 * specific value is defined to be a retry count,
409 * but we use it to pass back an internal FETD
410 * error code. XXX KDM Hopefully the FETD is only
411 * using 16 bits for an error code, since that's
412 * all the space we have in the sks field.
413 */
414 ctl_set_internal_failure(&io->scsiio,
415 /*sks_valid*/ 1,
416 /*retry_count*/
417 io->io_hdr.port_status);
418 }
419
420 /*
421 * If this is a read, or a write with errors, it is done.
422 */
423 if ((beio->bio_cmd == BIO_READ)
424 || ((io->io_hdr.flags & CTL_FLAG_ABORT) != 0)
425 || ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE)) {
426 ctl_complete_beio(beio);
427 return (0);
428 }
429
430 /*
431 * At this point, we have a write and the DMA completed
432 * successfully. We now have to queue it to the task queue to
433 * execute the backend I/O. That is because we do blocking
434 * memory allocations, and in the file backing case, blocking I/O.
435 * This move done routine is generally called in the SIM's
436 * interrupt context, and therefore we cannot block.
437 */
452 mtx_lock(&be_lun->lock);
438 mtx_lock(&be_lun->queue_lock);
453 /*
454 * XXX KDM make sure that links is okay to use at this point.
455 * Otherwise, we either need to add another field to ctl_io_hdr,
456 * or deal with resource allocation here.
457 */
458 STAILQ_INSERT_TAIL(&be_lun->datamove_queue, &io->io_hdr, links);
439 /*
440 * XXX KDM make sure that links is okay to use at this point.
441 * Otherwise, we either need to add another field to ctl_io_hdr,
442 * or deal with resource allocation here.
443 */
444 STAILQ_INSERT_TAIL(&be_lun->datamove_queue, &io->io_hdr, links);
459 mtx_unlock(&be_lun->lock);
445 mtx_unlock(&be_lun->queue_lock);
460
461 taskqueue_enqueue(be_lun->io_taskqueue, &be_lun->io_task);
462
463 return (0);
464}
465
466static void
467ctl_be_block_biodone(struct bio *bio)
468{
469 struct ctl_be_block_io *beio;
470 struct ctl_be_block_lun *be_lun;
471 union ctl_io *io;
472 int error;
473
474 beio = bio->bio_caller1;
475 be_lun = beio->lun;
476 io = beio->io;
477
478 DPRINTF("entered\n");
479
480 error = bio->bio_error;
446
447 taskqueue_enqueue(be_lun->io_taskqueue, &be_lun->io_task);
448
449 return (0);
450}
451
452static void
453ctl_be_block_biodone(struct bio *bio)
454{
455 struct ctl_be_block_io *beio;
456 struct ctl_be_block_lun *be_lun;
457 union ctl_io *io;
458 int error;
459
460 beio = bio->bio_caller1;
461 be_lun = beio->lun;
462 io = beio->io;
463
464 DPRINTF("entered\n");
465
466 error = bio->bio_error;
481 mtx_lock(&be_lun->lock);
467 mtx_lock(&be_lun->io_lock);
482 if (error != 0)
483 beio->num_errors++;
484
485 beio->num_bios_done++;
486
487 /*
488 * XXX KDM will this cause WITNESS to complain? Holding a lock
489 * during the free might cause it to complain.
490 */
491 g_destroy_bio(bio);
492
493 /*
494 * If the send complete bit isn't set, or we aren't the last I/O to
495 * complete, then we're done.
496 */
497 if ((beio->send_complete == 0)
498 || (beio->num_bios_done < beio->num_bios_sent)) {
468 if (error != 0)
469 beio->num_errors++;
470
471 beio->num_bios_done++;
472
473 /*
474 * XXX KDM will this cause WITNESS to complain? Holding a lock
475 * during the free might cause it to complain.
476 */
477 g_destroy_bio(bio);
478
479 /*
480 * If the send complete bit isn't set, or we aren't the last I/O to
481 * complete, then we're done.
482 */
483 if ((beio->send_complete == 0)
484 || (beio->num_bios_done < beio->num_bios_sent)) {
499 mtx_unlock(&be_lun->lock);
485 mtx_unlock(&be_lun->io_lock);
500 return;
501 }
502
503 /*
504 * At this point, we've verified that we are the last I/O to
505 * complete, so it's safe to drop the lock.
506 */
486 return;
487 }
488
489 /*
490 * At this point, we've verified that we are the last I/O to
491 * complete, so it's safe to drop the lock.
492 */
507 mtx_unlock(&be_lun->lock);
493 devstat_end_transaction(beio->lun->disk_stats, beio->io_len,
494 beio->ds_tag_type, beio->ds_trans_type,
495 /*now*/ NULL, /*then*/&beio->ds_t0);
496 mtx_unlock(&be_lun->io_lock);
508
509 /*
510 * If there are any errors from the backing device, we fail the
511 * entire I/O with a medium error.
512 */
513 if (beio->num_errors > 0) {
514 if (error == EOPNOTSUPP) {
515 ctl_set_invalid_opcode(&io->scsiio);
516 } else if (beio->bio_cmd == BIO_FLUSH) {
517 /* XXX KDM is there is a better error here? */
518 ctl_set_internal_failure(&io->scsiio,
519 /*sks_valid*/ 1,
520 /*retry_count*/ 0xbad2);
521 } else
522 ctl_set_medium_error(&io->scsiio);
523 ctl_complete_beio(beio);
524 return;
525 }
526
527 /*
528 * If this is a write, a flush, a delete or verify, we're all done.
529 * If this is a read, we can now send the data to the user.
530 */
531 if ((beio->bio_cmd == BIO_WRITE)
532 || (beio->bio_cmd == BIO_FLUSH)
533 || (beio->bio_cmd == BIO_DELETE)
534 || (ARGS(io)->flags & CTL_LLF_VERIFY)) {
535 ctl_set_success(&io->scsiio);
536 ctl_complete_beio(beio);
537 } else {
538#ifdef CTL_TIME_IO
539 getbintime(&io->io_hdr.dma_start_bt);
540#endif
541 ctl_datamove(io);
542 }
543}
544
545static void
546ctl_be_block_flush_file(struct ctl_be_block_lun *be_lun,
547 struct ctl_be_block_io *beio)
548{
497
498 /*
499 * If there are any errors from the backing device, we fail the
500 * entire I/O with a medium error.
501 */
502 if (beio->num_errors > 0) {
503 if (error == EOPNOTSUPP) {
504 ctl_set_invalid_opcode(&io->scsiio);
505 } else if (beio->bio_cmd == BIO_FLUSH) {
506 /* XXX KDM is there is a better error here? */
507 ctl_set_internal_failure(&io->scsiio,
508 /*sks_valid*/ 1,
509 /*retry_count*/ 0xbad2);
510 } else
511 ctl_set_medium_error(&io->scsiio);
512 ctl_complete_beio(beio);
513 return;
514 }
515
516 /*
517 * If this is a write, a flush, a delete or verify, we're all done.
518 * If this is a read, we can now send the data to the user.
519 */
520 if ((beio->bio_cmd == BIO_WRITE)
521 || (beio->bio_cmd == BIO_FLUSH)
522 || (beio->bio_cmd == BIO_DELETE)
523 || (ARGS(io)->flags & CTL_LLF_VERIFY)) {
524 ctl_set_success(&io->scsiio);
525 ctl_complete_beio(beio);
526 } else {
527#ifdef CTL_TIME_IO
528 getbintime(&io->io_hdr.dma_start_bt);
529#endif
530 ctl_datamove(io);
531 }
532}
533
534static void
535ctl_be_block_flush_file(struct ctl_be_block_lun *be_lun,
536 struct ctl_be_block_io *beio)
537{
549 union ctl_io *io;
538 union ctl_io *io = beio->io;
550 struct mount *mountpoint;
551 int error, lock_flags;
552
553 DPRINTF("entered\n");
554
539 struct mount *mountpoint;
540 int error, lock_flags;
541
542 DPRINTF("entered\n");
543
555 io = beio->io;
544 binuptime(&beio->ds_t0);
545 mtx_lock(&be_lun->io_lock);
546 devstat_start_transaction(beio->lun->disk_stats, &beio->ds_t0);
547 mtx_unlock(&be_lun->io_lock);
556
548
557 (void) vn_start_write(be_lun->vn, &mountpoint, V_WAIT);
549 (void) vn_start_write(be_lun->vn, &mountpoint, V_WAIT);
558
559 if (MNT_SHARED_WRITES(mountpoint)
560 || ((mountpoint == NULL)
561 && MNT_SHARED_WRITES(be_lun->vn->v_mount)))
562 lock_flags = LK_SHARED;
563 else
564 lock_flags = LK_EXCLUSIVE;
565
566 vn_lock(be_lun->vn, lock_flags | LK_RETRY);
567
550
551 if (MNT_SHARED_WRITES(mountpoint)
552 || ((mountpoint == NULL)
553 && MNT_SHARED_WRITES(be_lun->vn->v_mount)))
554 lock_flags = LK_SHARED;
555 else
556 lock_flags = LK_EXCLUSIVE;
557
558 vn_lock(be_lun->vn, lock_flags | LK_RETRY);
559
568 binuptime(&beio->ds_t0);
569 devstat_start_transaction(beio->lun->disk_stats, &beio->ds_t0);
570
571 error = VOP_FSYNC(be_lun->vn, MNT_WAIT, curthread);
572 VOP_UNLOCK(be_lun->vn, 0);
573
574 vn_finished_write(mountpoint);
575
560 error = VOP_FSYNC(be_lun->vn, MNT_WAIT, curthread);
561 VOP_UNLOCK(be_lun->vn, 0);
562
563 vn_finished_write(mountpoint);
564
565 mtx_lock(&be_lun->io_lock);
566 devstat_end_transaction(beio->lun->disk_stats, beio->io_len,
567 beio->ds_tag_type, beio->ds_trans_type,
568 /*now*/ NULL, /*then*/&beio->ds_t0);
569 mtx_unlock(&be_lun->io_lock);
570
576 if (error == 0)
577 ctl_set_success(&io->scsiio);
578 else {
579 /* XXX KDM is there is a better error here? */
580 ctl_set_internal_failure(&io->scsiio,
581 /*sks_valid*/ 1,
582 /*retry_count*/ 0xbad1);
583 }
584
585 ctl_complete_beio(beio);
586}
587
588SDT_PROBE_DEFINE1(cbb, kernel, read, file_start, "uint64_t");
589SDT_PROBE_DEFINE1(cbb, kernel, write, file_start, "uint64_t");
590SDT_PROBE_DEFINE1(cbb, kernel, read, file_done,"uint64_t");
591SDT_PROBE_DEFINE1(cbb, kernel, write, file_done, "uint64_t");
592
593static void
594ctl_be_block_dispatch_file(struct ctl_be_block_lun *be_lun,
595 struct ctl_be_block_io *beio)
596{
597 struct ctl_be_block_filedata *file_data;
598 union ctl_io *io;
599 struct uio xuio;
600 struct iovec *xiovec;
601 int flags;
602 int error, i;
603
604 DPRINTF("entered\n");
605
606 file_data = &be_lun->backend.file;
607 io = beio->io;
608 flags = beio->bio_flags;
609
610 bzero(&xuio, sizeof(xuio));
611 if (beio->bio_cmd == BIO_READ) {
612 SDT_PROBE(cbb, kernel, read, file_start, 0, 0, 0, 0, 0);
613 xuio.uio_rw = UIO_READ;
614 } else {
615 SDT_PROBE(cbb, kernel, write, file_start, 0, 0, 0, 0, 0);
616 xuio.uio_rw = UIO_WRITE;
617 }
618 xuio.uio_offset = beio->io_offset;
619 xuio.uio_resid = beio->io_len;
620 xuio.uio_segflg = UIO_SYSSPACE;
621 xuio.uio_iov = beio->xiovecs;
622 xuio.uio_iovcnt = beio->num_segs;
623 xuio.uio_td = curthread;
624
625 for (i = 0, xiovec = xuio.uio_iov; i < xuio.uio_iovcnt; i++, xiovec++) {
626 xiovec->iov_base = beio->sg_segs[i].addr;
627 xiovec->iov_len = beio->sg_segs[i].len;
628 }
629
571 if (error == 0)
572 ctl_set_success(&io->scsiio);
573 else {
574 /* XXX KDM is there is a better error here? */
575 ctl_set_internal_failure(&io->scsiio,
576 /*sks_valid*/ 1,
577 /*retry_count*/ 0xbad1);
578 }
579
580 ctl_complete_beio(beio);
581}
582
583SDT_PROBE_DEFINE1(cbb, kernel, read, file_start, "uint64_t");
584SDT_PROBE_DEFINE1(cbb, kernel, write, file_start, "uint64_t");
585SDT_PROBE_DEFINE1(cbb, kernel, read, file_done,"uint64_t");
586SDT_PROBE_DEFINE1(cbb, kernel, write, file_done, "uint64_t");
587
588static void
589ctl_be_block_dispatch_file(struct ctl_be_block_lun *be_lun,
590 struct ctl_be_block_io *beio)
591{
592 struct ctl_be_block_filedata *file_data;
593 union ctl_io *io;
594 struct uio xuio;
595 struct iovec *xiovec;
596 int flags;
597 int error, i;
598
599 DPRINTF("entered\n");
600
601 file_data = &be_lun->backend.file;
602 io = beio->io;
603 flags = beio->bio_flags;
604
605 bzero(&xuio, sizeof(xuio));
606 if (beio->bio_cmd == BIO_READ) {
607 SDT_PROBE(cbb, kernel, read, file_start, 0, 0, 0, 0, 0);
608 xuio.uio_rw = UIO_READ;
609 } else {
610 SDT_PROBE(cbb, kernel, write, file_start, 0, 0, 0, 0, 0);
611 xuio.uio_rw = UIO_WRITE;
612 }
613 xuio.uio_offset = beio->io_offset;
614 xuio.uio_resid = beio->io_len;
615 xuio.uio_segflg = UIO_SYSSPACE;
616 xuio.uio_iov = beio->xiovecs;
617 xuio.uio_iovcnt = beio->num_segs;
618 xuio.uio_td = curthread;
619
620 for (i = 0, xiovec = xuio.uio_iov; i < xuio.uio_iovcnt; i++, xiovec++) {
621 xiovec->iov_base = beio->sg_segs[i].addr;
622 xiovec->iov_len = beio->sg_segs[i].len;
623 }
624
625 binuptime(&beio->ds_t0);
626 mtx_lock(&be_lun->io_lock);
627 devstat_start_transaction(beio->lun->disk_stats, &beio->ds_t0);
628 mtx_unlock(&be_lun->io_lock);
629
630 if (beio->bio_cmd == BIO_READ) {
631 vn_lock(be_lun->vn, LK_SHARED | LK_RETRY);
632
630 if (beio->bio_cmd == BIO_READ) {
631 vn_lock(be_lun->vn, LK_SHARED | LK_RETRY);
632
633 binuptime(&beio->ds_t0);
634 devstat_start_transaction(beio->lun->disk_stats, &beio->ds_t0);
635
636 /*
637 * UFS pays attention to IO_DIRECT for reads. If the
638 * DIRECTIO option is configured into the kernel, it calls
639 * ffs_rawread(). But that only works for single-segment
640 * uios with user space addresses. In our case, with a
641 * kernel uio, it still reads into the buffer cache, but it
642 * will just try to release the buffer from the cache later
643 * on in ffs_read().
644 *
645 * ZFS does not pay attention to IO_DIRECT for reads.
646 *
647 * UFS does not pay attention to IO_SYNC for reads.
648 *
649 * ZFS pays attention to IO_SYNC (which translates into the
650 * Solaris define FRSYNC for zfs_read()) for reads. It
651 * attempts to sync the file before reading.
652 *
653 * So, to attempt to provide some barrier semantics in the
654 * BIO_ORDERED case, set both IO_DIRECT and IO_SYNC.
655 */
656 error = VOP_READ(be_lun->vn, &xuio, (flags & BIO_ORDERED) ?
657 (IO_DIRECT|IO_SYNC) : 0, file_data->cred);
658
659 VOP_UNLOCK(be_lun->vn, 0);
660 SDT_PROBE(cbb, kernel, read, file_done, 0, 0, 0, 0, 0);
661 } else {
662 struct mount *mountpoint;
663 int lock_flags;
664
665 (void)vn_start_write(be_lun->vn, &mountpoint, V_WAIT);
666
667 if (MNT_SHARED_WRITES(mountpoint)
668 || ((mountpoint == NULL)
669 && MNT_SHARED_WRITES(be_lun->vn->v_mount)))
670 lock_flags = LK_SHARED;
671 else
672 lock_flags = LK_EXCLUSIVE;
673
674 vn_lock(be_lun->vn, lock_flags | LK_RETRY);
675
633 /*
634 * UFS pays attention to IO_DIRECT for reads. If the
635 * DIRECTIO option is configured into the kernel, it calls
636 * ffs_rawread(). But that only works for single-segment
637 * uios with user space addresses. In our case, with a
638 * kernel uio, it still reads into the buffer cache, but it
639 * will just try to release the buffer from the cache later
640 * on in ffs_read().
641 *
642 * ZFS does not pay attention to IO_DIRECT for reads.
643 *
644 * UFS does not pay attention to IO_SYNC for reads.
645 *
646 * ZFS pays attention to IO_SYNC (which translates into the
647 * Solaris define FRSYNC for zfs_read()) for reads. It
648 * attempts to sync the file before reading.
649 *
650 * So, to attempt to provide some barrier semantics in the
651 * BIO_ORDERED case, set both IO_DIRECT and IO_SYNC.
652 */
653 error = VOP_READ(be_lun->vn, &xuio, (flags & BIO_ORDERED) ?
654 (IO_DIRECT|IO_SYNC) : 0, file_data->cred);
655
656 VOP_UNLOCK(be_lun->vn, 0);
657 SDT_PROBE(cbb, kernel, read, file_done, 0, 0, 0, 0, 0);
658 } else {
659 struct mount *mountpoint;
660 int lock_flags;
661
662 (void)vn_start_write(be_lun->vn, &mountpoint, V_WAIT);
663
664 if (MNT_SHARED_WRITES(mountpoint)
665 || ((mountpoint == NULL)
666 && MNT_SHARED_WRITES(be_lun->vn->v_mount)))
667 lock_flags = LK_SHARED;
668 else
669 lock_flags = LK_EXCLUSIVE;
670
671 vn_lock(be_lun->vn, lock_flags | LK_RETRY);
672
676 binuptime(&beio->ds_t0);
677 devstat_start_transaction(beio->lun->disk_stats, &beio->ds_t0);
678
679 /*
680 * UFS pays attention to IO_DIRECT for writes. The write
681 * is done asynchronously. (Normally the write would just
682 * get put into cache.
683 *
684 * UFS pays attention to IO_SYNC for writes. It will
685 * attempt to write the buffer out synchronously if that
686 * flag is set.
687 *
688 * ZFS does not pay attention to IO_DIRECT for writes.
689 *
690 * ZFS pays attention to IO_SYNC (a.k.a. FSYNC or FRSYNC)
691 * for writes. It will flush the transaction from the
692 * cache before returning.
693 *
694 * So if we've got the BIO_ORDERED flag set, we want
695 * IO_SYNC in either the UFS or ZFS case.
696 */
697 error = VOP_WRITE(be_lun->vn, &xuio, (flags & BIO_ORDERED) ?
698 IO_SYNC : 0, file_data->cred);
699 VOP_UNLOCK(be_lun->vn, 0);
700
701 vn_finished_write(mountpoint);
702 SDT_PROBE(cbb, kernel, write, file_done, 0, 0, 0, 0, 0);
703 }
704
673 /*
674 * UFS pays attention to IO_DIRECT for writes. The write
675 * is done asynchronously. (Normally the write would just
676 * get put into cache.
677 *
678 * UFS pays attention to IO_SYNC for writes. It will
679 * attempt to write the buffer out synchronously if that
680 * flag is set.
681 *
682 * ZFS does not pay attention to IO_DIRECT for writes.
683 *
684 * ZFS pays attention to IO_SYNC (a.k.a. FSYNC or FRSYNC)
685 * for writes. It will flush the transaction from the
686 * cache before returning.
687 *
688 * So if we've got the BIO_ORDERED flag set, we want
689 * IO_SYNC in either the UFS or ZFS case.
690 */
691 error = VOP_WRITE(be_lun->vn, &xuio, (flags & BIO_ORDERED) ?
692 IO_SYNC : 0, file_data->cred);
693 VOP_UNLOCK(be_lun->vn, 0);
694
695 vn_finished_write(mountpoint);
696 SDT_PROBE(cbb, kernel, write, file_done, 0, 0, 0, 0, 0);
697 }
698
699 mtx_lock(&be_lun->io_lock);
700 devstat_end_transaction(beio->lun->disk_stats, beio->io_len,
701 beio->ds_tag_type, beio->ds_trans_type,
702 /*now*/ NULL, /*then*/&beio->ds_t0);
703 mtx_unlock(&be_lun->io_lock);
704
705 /*
706 * If we got an error, set the sense data to "MEDIUM ERROR" and
707 * return the I/O to the user.
708 */
709 if (error != 0) {
710 char path_str[32];
711
712 ctl_scsi_path_string(io, path_str, sizeof(path_str));
713 /*
714 * XXX KDM ZFS returns ENOSPC when the underlying
715 * filesystem fills up. What kind of SCSI error should we
716 * return for that?
717 */
718 printf("%s%s command returned errno %d\n", path_str,
719 (beio->bio_cmd == BIO_READ) ? "READ" : "WRITE", error);
720 ctl_set_medium_error(&io->scsiio);
721 ctl_complete_beio(beio);
722 return;
723 }
724
725 /*
726 * If this is a write, we're all done.
727 * If this is a read, we can now send the data to the user.
728 */
729 if (ARGS(io)->flags & (CTL_LLF_WRITE | CTL_LLF_VERIFY)) {
730 ctl_set_success(&io->scsiio);
731 ctl_complete_beio(beio);
732 } else {
733#ifdef CTL_TIME_IO
734 getbintime(&io->io_hdr.dma_start_bt);
735#endif
736 ctl_datamove(io);
737 }
738}
739
740static void
741ctl_be_block_flush_dev(struct ctl_be_block_lun *be_lun,
742 struct ctl_be_block_io *beio)
743{
744 struct bio *bio;
745 union ctl_io *io;
746 struct ctl_be_block_devdata *dev_data;
747
748 dev_data = &be_lun->backend.dev;
749 io = beio->io;
750
751 DPRINTF("entered\n");
752
753 /* This can't fail, it's a blocking allocation. */
754 bio = g_alloc_bio();
755
756 bio->bio_cmd = BIO_FLUSH;
757 bio->bio_flags |= BIO_ORDERED;
758 bio->bio_dev = dev_data->cdev;
759 bio->bio_offset = 0;
760 bio->bio_data = 0;
761 bio->bio_done = ctl_be_block_biodone;
762 bio->bio_caller1 = beio;
763 bio->bio_pblkno = 0;
764
765 /*
766 * We don't need to acquire the LUN lock here, because we are only
767 * sending one bio, and so there is no other context to synchronize
768 * with.
769 */
770 beio->num_bios_sent = 1;
771 beio->send_complete = 1;
772
773 binuptime(&beio->ds_t0);
705 /*
706 * If we got an error, set the sense data to "MEDIUM ERROR" and
707 * return the I/O to the user.
708 */
709 if (error != 0) {
710 char path_str[32];
711
712 ctl_scsi_path_string(io, path_str, sizeof(path_str));
713 /*
714 * XXX KDM ZFS returns ENOSPC when the underlying
715 * filesystem fills up. What kind of SCSI error should we
716 * return for that?
717 */
718 printf("%s%s command returned errno %d\n", path_str,
719 (beio->bio_cmd == BIO_READ) ? "READ" : "WRITE", error);
720 ctl_set_medium_error(&io->scsiio);
721 ctl_complete_beio(beio);
722 return;
723 }
724
725 /*
726 * If this is a write, we're all done.
727 * If this is a read, we can now send the data to the user.
728 */
729 if (ARGS(io)->flags & (CTL_LLF_WRITE | CTL_LLF_VERIFY)) {
730 ctl_set_success(&io->scsiio);
731 ctl_complete_beio(beio);
732 } else {
733#ifdef CTL_TIME_IO
734 getbintime(&io->io_hdr.dma_start_bt);
735#endif
736 ctl_datamove(io);
737 }
738}
739
740static void
741ctl_be_block_flush_dev(struct ctl_be_block_lun *be_lun,
742 struct ctl_be_block_io *beio)
743{
744 struct bio *bio;
745 union ctl_io *io;
746 struct ctl_be_block_devdata *dev_data;
747
748 dev_data = &be_lun->backend.dev;
749 io = beio->io;
750
751 DPRINTF("entered\n");
752
753 /* This can't fail, it's a blocking allocation. */
754 bio = g_alloc_bio();
755
756 bio->bio_cmd = BIO_FLUSH;
757 bio->bio_flags |= BIO_ORDERED;
758 bio->bio_dev = dev_data->cdev;
759 bio->bio_offset = 0;
760 bio->bio_data = 0;
761 bio->bio_done = ctl_be_block_biodone;
762 bio->bio_caller1 = beio;
763 bio->bio_pblkno = 0;
764
765 /*
766 * We don't need to acquire the LUN lock here, because we are only
767 * sending one bio, and so there is no other context to synchronize
768 * with.
769 */
770 beio->num_bios_sent = 1;
771 beio->send_complete = 1;
772
773 binuptime(&beio->ds_t0);
774 mtx_lock(&be_lun->io_lock);
774 devstat_start_transaction(be_lun->disk_stats, &beio->ds_t0);
775 devstat_start_transaction(be_lun->disk_stats, &beio->ds_t0);
776 mtx_unlock(&be_lun->io_lock);
775
776 (*dev_data->csw->d_strategy)(bio);
777}
778
779static void
780ctl_be_block_unmap_dev_range(struct ctl_be_block_lun *be_lun,
781 struct ctl_be_block_io *beio,
782 uint64_t off, uint64_t len, int last)
783{
784 struct bio *bio;
785 struct ctl_be_block_devdata *dev_data;
786 uint64_t maxlen;
787
788 dev_data = &be_lun->backend.dev;
789 maxlen = LONG_MAX - (LONG_MAX % be_lun->blocksize);
790 while (len > 0) {
791 bio = g_alloc_bio();
792 bio->bio_cmd = BIO_DELETE;
793 bio->bio_flags |= beio->bio_flags;
794 bio->bio_dev = dev_data->cdev;
795 bio->bio_offset = off;
796 bio->bio_length = MIN(len, maxlen);
797 bio->bio_data = 0;
798 bio->bio_done = ctl_be_block_biodone;
799 bio->bio_caller1 = beio;
800 bio->bio_pblkno = off / be_lun->blocksize;
801
802 off += bio->bio_length;
803 len -= bio->bio_length;
804
777
778 (*dev_data->csw->d_strategy)(bio);
779}
780
781static void
782ctl_be_block_unmap_dev_range(struct ctl_be_block_lun *be_lun,
783 struct ctl_be_block_io *beio,
784 uint64_t off, uint64_t len, int last)
785{
786 struct bio *bio;
787 struct ctl_be_block_devdata *dev_data;
788 uint64_t maxlen;
789
790 dev_data = &be_lun->backend.dev;
791 maxlen = LONG_MAX - (LONG_MAX % be_lun->blocksize);
792 while (len > 0) {
793 bio = g_alloc_bio();
794 bio->bio_cmd = BIO_DELETE;
795 bio->bio_flags |= beio->bio_flags;
796 bio->bio_dev = dev_data->cdev;
797 bio->bio_offset = off;
798 bio->bio_length = MIN(len, maxlen);
799 bio->bio_data = 0;
800 bio->bio_done = ctl_be_block_biodone;
801 bio->bio_caller1 = beio;
802 bio->bio_pblkno = off / be_lun->blocksize;
803
804 off += bio->bio_length;
805 len -= bio->bio_length;
806
805 mtx_lock(&be_lun->lock);
807 mtx_lock(&be_lun->io_lock);
806 beio->num_bios_sent++;
807 if (last && len == 0)
808 beio->send_complete = 1;
808 beio->num_bios_sent++;
809 if (last && len == 0)
810 beio->send_complete = 1;
809 mtx_unlock(&be_lun->lock);
811 mtx_unlock(&be_lun->io_lock);
810
811 (*dev_data->csw->d_strategy)(bio);
812 }
813}
814
815static void
816ctl_be_block_unmap_dev(struct ctl_be_block_lun *be_lun,
817 struct ctl_be_block_io *beio)
818{
819 union ctl_io *io;
820 struct ctl_be_block_devdata *dev_data;
821 struct ctl_ptr_len_flags *ptrlen;
822 struct scsi_unmap_desc *buf, *end;
823 uint64_t len;
824
825 dev_data = &be_lun->backend.dev;
826 io = beio->io;
827
828 DPRINTF("entered\n");
829
830 binuptime(&beio->ds_t0);
812
813 (*dev_data->csw->d_strategy)(bio);
814 }
815}
816
817static void
818ctl_be_block_unmap_dev(struct ctl_be_block_lun *be_lun,
819 struct ctl_be_block_io *beio)
820{
821 union ctl_io *io;
822 struct ctl_be_block_devdata *dev_data;
823 struct ctl_ptr_len_flags *ptrlen;
824 struct scsi_unmap_desc *buf, *end;
825 uint64_t len;
826
827 dev_data = &be_lun->backend.dev;
828 io = beio->io;
829
830 DPRINTF("entered\n");
831
832 binuptime(&beio->ds_t0);
833 mtx_lock(&be_lun->io_lock);
831 devstat_start_transaction(be_lun->disk_stats, &beio->ds_t0);
834 devstat_start_transaction(be_lun->disk_stats, &beio->ds_t0);
835 mtx_unlock(&be_lun->io_lock);
832
833 if (beio->io_offset == -1) {
834 beio->io_len = 0;
835 ptrlen = (struct ctl_ptr_len_flags *)&io->io_hdr.ctl_private[CTL_PRIV_LBA_LEN];
836 buf = (struct scsi_unmap_desc *)ptrlen->ptr;
837 end = buf + ptrlen->len / sizeof(*buf);
838 for (; buf < end; buf++) {
839 len = (uint64_t)scsi_4btoul(buf->length) *
840 be_lun->blocksize;
841 beio->io_len += len;
842 ctl_be_block_unmap_dev_range(be_lun, beio,
843 scsi_8btou64(buf->lba) * be_lun->blocksize, len,
844 (end - buf < 2) ? TRUE : FALSE);
845 }
846 } else
847 ctl_be_block_unmap_dev_range(be_lun, beio,
848 beio->io_offset, beio->io_len, TRUE);
849}
850
851static void
852ctl_be_block_dispatch_dev(struct ctl_be_block_lun *be_lun,
853 struct ctl_be_block_io *beio)
854{
836
837 if (beio->io_offset == -1) {
838 beio->io_len = 0;
839 ptrlen = (struct ctl_ptr_len_flags *)&io->io_hdr.ctl_private[CTL_PRIV_LBA_LEN];
840 buf = (struct scsi_unmap_desc *)ptrlen->ptr;
841 end = buf + ptrlen->len / sizeof(*buf);
842 for (; buf < end; buf++) {
843 len = (uint64_t)scsi_4btoul(buf->length) *
844 be_lun->blocksize;
845 beio->io_len += len;
846 ctl_be_block_unmap_dev_range(be_lun, beio,
847 scsi_8btou64(buf->lba) * be_lun->blocksize, len,
848 (end - buf < 2) ? TRUE : FALSE);
849 }
850 } else
851 ctl_be_block_unmap_dev_range(be_lun, beio,
852 beio->io_offset, beio->io_len, TRUE);
853}
854
855static void
856ctl_be_block_dispatch_dev(struct ctl_be_block_lun *be_lun,
857 struct ctl_be_block_io *beio)
858{
859 TAILQ_HEAD(, bio) queue = TAILQ_HEAD_INITIALIZER(queue);
855 int i;
856 struct bio *bio;
857 struct ctl_be_block_devdata *dev_data;
858 off_t cur_offset;
859 int max_iosize;
860
861 DPRINTF("entered\n");
862
863 dev_data = &be_lun->backend.dev;
864
865 /*
866 * We have to limit our I/O size to the maximum supported by the
867 * backend device. Hopefully it is MAXPHYS. If the driver doesn't
868 * set it properly, use DFLTPHYS.
869 */
870 max_iosize = dev_data->cdev->si_iosize_max;
871 if (max_iosize < PAGE_SIZE)
872 max_iosize = DFLTPHYS;
873
874 cur_offset = beio->io_offset;
860 int i;
861 struct bio *bio;
862 struct ctl_be_block_devdata *dev_data;
863 off_t cur_offset;
864 int max_iosize;
865
866 DPRINTF("entered\n");
867
868 dev_data = &be_lun->backend.dev;
869
870 /*
871 * We have to limit our I/O size to the maximum supported by the
872 * backend device. Hopefully it is MAXPHYS. If the driver doesn't
873 * set it properly, use DFLTPHYS.
874 */
875 max_iosize = dev_data->cdev->si_iosize_max;
876 if (max_iosize < PAGE_SIZE)
877 max_iosize = DFLTPHYS;
878
879 cur_offset = beio->io_offset;
875
876 /*
877 * XXX KDM need to accurately reflect the number of I/Os outstanding
878 * to a device.
879 */
880 binuptime(&beio->ds_t0);
881 devstat_start_transaction(be_lun->disk_stats, &beio->ds_t0);
882
883 for (i = 0; i < beio->num_segs; i++) {
884 size_t cur_size;
885 uint8_t *cur_ptr;
886
887 cur_size = beio->sg_segs[i].len;
888 cur_ptr = beio->sg_segs[i].addr;
889
890 while (cur_size > 0) {
891 /* This can't fail, it's a blocking allocation. */
892 bio = g_alloc_bio();
893
894 KASSERT(bio != NULL, ("g_alloc_bio() failed!\n"));
895
896 bio->bio_cmd = beio->bio_cmd;
897 bio->bio_flags |= beio->bio_flags;
898 bio->bio_dev = dev_data->cdev;
899 bio->bio_caller1 = beio;
900 bio->bio_length = min(cur_size, max_iosize);
901 bio->bio_offset = cur_offset;
902 bio->bio_data = cur_ptr;
903 bio->bio_done = ctl_be_block_biodone;
904 bio->bio_pblkno = cur_offset / be_lun->blocksize;
905
906 cur_offset += bio->bio_length;
907 cur_ptr += bio->bio_length;
908 cur_size -= bio->bio_length;
909
880 for (i = 0; i < beio->num_segs; i++) {
881 size_t cur_size;
882 uint8_t *cur_ptr;
883
884 cur_size = beio->sg_segs[i].len;
885 cur_ptr = beio->sg_segs[i].addr;
886
887 while (cur_size > 0) {
888 /* This can't fail, it's a blocking allocation. */
889 bio = g_alloc_bio();
890
891 KASSERT(bio != NULL, ("g_alloc_bio() failed!\n"));
892
893 bio->bio_cmd = beio->bio_cmd;
894 bio->bio_flags |= beio->bio_flags;
895 bio->bio_dev = dev_data->cdev;
896 bio->bio_caller1 = beio;
897 bio->bio_length = min(cur_size, max_iosize);
898 bio->bio_offset = cur_offset;
899 bio->bio_data = cur_ptr;
900 bio->bio_done = ctl_be_block_biodone;
901 bio->bio_pblkno = cur_offset / be_lun->blocksize;
902
903 cur_offset += bio->bio_length;
904 cur_ptr += bio->bio_length;
905 cur_size -= bio->bio_length;
906
910 /*
911 * Make sure we set the complete bit just before we
912 * issue the last bio so we don't wind up with a
913 * race.
914 *
915 * Use the LUN mutex here instead of a combination
916 * of atomic variables for simplicity.
917 *
918 * XXX KDM we could have a per-IO lock, but that
919 * would cause additional per-IO setup and teardown
920 * overhead. Hopefully there won't be too much
921 * contention on the LUN lock.
922 */
923 mtx_lock(&be_lun->lock);
924
907 TAILQ_INSERT_TAIL(&queue, bio, bio_queue);
925 beio->num_bios_sent++;
908 beio->num_bios_sent++;
926
927 if ((i == beio->num_segs - 1)
928 && (cur_size == 0))
929 beio->send_complete = 1;
930
931 mtx_unlock(&be_lun->lock);
932
933 (*dev_data->csw->d_strategy)(bio);
934 }
935 }
909 }
910 }
911 binuptime(&beio->ds_t0);
912 mtx_lock(&be_lun->io_lock);
913 devstat_start_transaction(be_lun->disk_stats, &beio->ds_t0);
914 beio->send_complete = 1;
915 mtx_unlock(&be_lun->io_lock);
916
917 /*
918 * Fire off all allocated requests!
919 */
920 while ((bio = TAILQ_FIRST(&queue)) != NULL) {
921 TAILQ_REMOVE(&queue, bio, bio_queue);
922 (*dev_data->csw->d_strategy)(bio);
923 }
936}
937
938static void
939ctl_be_block_cw_done_ws(struct ctl_be_block_io *beio)
940{
941 union ctl_io *io;
942
943 io = beio->io;
944 ctl_free_beio(beio);
945 if ((io->io_hdr.flags & CTL_FLAG_ABORT) ||
946 ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE &&
947 (io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS)) {
948 ctl_config_write_done(io);
949 return;
950 }
951
952 ctl_be_block_config_write(io);
953}
954
955static void
956ctl_be_block_cw_dispatch_ws(struct ctl_be_block_lun *be_lun,
957 union ctl_io *io)
958{
959 struct ctl_be_block_io *beio;
960 struct ctl_be_block_softc *softc;
961 struct ctl_lba_len_flags *lbalen;
962 uint64_t len_left, lba;
963 int i, seglen;
964 uint8_t *buf, *end;
965
966 DPRINTF("entered\n");
967
968 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
969 softc = be_lun->softc;
970 lbalen = ARGS(beio->io);
971
972 if (lbalen->flags & ~(SWS_LBDATA | SWS_UNMAP) ||
973 (lbalen->flags & SWS_UNMAP && be_lun->unmap == NULL)) {
974 ctl_free_beio(beio);
975 ctl_set_invalid_field(&io->scsiio,
976 /*sks_valid*/ 1,
977 /*command*/ 1,
978 /*field*/ 1,
979 /*bit_valid*/ 0,
980 /*bit*/ 0);
981 ctl_config_write_done(io);
982 return;
983 }
984
985 /*
986 * If the I/O came down with an ordered or head of queue tag, set
987 * the BIO_ORDERED attribute. For head of queue tags, that's
988 * pretty much the best we can do.
989 */
990 if ((io->scsiio.tag_type == CTL_TAG_ORDERED)
991 || (io->scsiio.tag_type == CTL_TAG_HEAD_OF_QUEUE))
992 beio->bio_flags = BIO_ORDERED;
993
994 switch (io->scsiio.tag_type) {
995 case CTL_TAG_ORDERED:
996 beio->ds_tag_type = DEVSTAT_TAG_ORDERED;
997 break;
998 case CTL_TAG_HEAD_OF_QUEUE:
999 beio->ds_tag_type = DEVSTAT_TAG_HEAD;
1000 break;
1001 case CTL_TAG_UNTAGGED:
1002 case CTL_TAG_SIMPLE:
1003 case CTL_TAG_ACA:
1004 default:
1005 beio->ds_tag_type = DEVSTAT_TAG_SIMPLE;
1006 break;
1007 }
1008
1009 if (lbalen->flags & SWS_UNMAP) {
1010 beio->io_offset = lbalen->lba * be_lun->blocksize;
1011 beio->io_len = (uint64_t)lbalen->len * be_lun->blocksize;
1012 beio->bio_cmd = BIO_DELETE;
1013 beio->ds_trans_type = DEVSTAT_FREE;
1014
1015 be_lun->unmap(be_lun, beio);
1016 return;
1017 }
1018
1019 beio->bio_cmd = BIO_WRITE;
1020 beio->ds_trans_type = DEVSTAT_WRITE;
1021
1022 DPRINTF("WRITE SAME at LBA %jx len %u\n",
1023 (uintmax_t)lbalen->lba, lbalen->len);
1024
1025 len_left = (uint64_t)lbalen->len * be_lun->blocksize;
1026 for (i = 0, lba = 0; i < CTLBLK_MAX_SEGS && len_left > 0; i++) {
1027
1028 /*
1029 * Setup the S/G entry for this chunk.
1030 */
1031 seglen = MIN(CTLBLK_MAX_SEG, len_left);
1032 seglen -= seglen % be_lun->blocksize;
1033 beio->sg_segs[i].len = seglen;
1034 beio->sg_segs[i].addr = uma_zalloc(be_lun->lun_zone, M_WAITOK);
1035
1036 DPRINTF("segment %d addr %p len %zd\n", i,
1037 beio->sg_segs[i].addr, beio->sg_segs[i].len);
1038
1039 beio->num_segs++;
1040 len_left -= seglen;
1041
1042 buf = beio->sg_segs[i].addr;
1043 end = buf + seglen;
1044 for (; buf < end; buf += be_lun->blocksize) {
1045 memcpy(buf, io->scsiio.kern_data_ptr, be_lun->blocksize);
1046 if (lbalen->flags & SWS_LBDATA)
1047 scsi_ulto4b(lbalen->lba + lba, buf);
1048 lba++;
1049 }
1050 }
1051
1052 beio->io_offset = lbalen->lba * be_lun->blocksize;
1053 beio->io_len = lba * be_lun->blocksize;
1054
1055 /* We can not do all in one run. Correct and schedule rerun. */
1056 if (len_left > 0) {
1057 lbalen->lba += lba;
1058 lbalen->len -= lba;
1059 beio->beio_cont = ctl_be_block_cw_done_ws;
1060 }
1061
1062 be_lun->dispatch(be_lun, beio);
1063}
1064
1065static void
1066ctl_be_block_cw_dispatch_unmap(struct ctl_be_block_lun *be_lun,
1067 union ctl_io *io)
1068{
1069 struct ctl_be_block_io *beio;
1070 struct ctl_be_block_softc *softc;
1071 struct ctl_ptr_len_flags *ptrlen;
1072
1073 DPRINTF("entered\n");
1074
1075 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
1076 softc = be_lun->softc;
1077 ptrlen = (struct ctl_ptr_len_flags *)&io->io_hdr.ctl_private[CTL_PRIV_LBA_LEN];
1078
1079 if (ptrlen->flags != 0 || be_lun->unmap == NULL) {
1080 ctl_free_beio(beio);
1081 ctl_set_invalid_field(&io->scsiio,
1082 /*sks_valid*/ 0,
1083 /*command*/ 1,
1084 /*field*/ 0,
1085 /*bit_valid*/ 0,
1086 /*bit*/ 0);
1087 ctl_config_write_done(io);
1088 return;
1089 }
1090
1091 /*
1092 * If the I/O came down with an ordered or head of queue tag, set
1093 * the BIO_ORDERED attribute. For head of queue tags, that's
1094 * pretty much the best we can do.
1095 */
1096 if ((io->scsiio.tag_type == CTL_TAG_ORDERED)
1097 || (io->scsiio.tag_type == CTL_TAG_HEAD_OF_QUEUE))
1098 beio->bio_flags = BIO_ORDERED;
1099
1100 switch (io->scsiio.tag_type) {
1101 case CTL_TAG_ORDERED:
1102 beio->ds_tag_type = DEVSTAT_TAG_ORDERED;
1103 break;
1104 case CTL_TAG_HEAD_OF_QUEUE:
1105 beio->ds_tag_type = DEVSTAT_TAG_HEAD;
1106 break;
1107 case CTL_TAG_UNTAGGED:
1108 case CTL_TAG_SIMPLE:
1109 case CTL_TAG_ACA:
1110 default:
1111 beio->ds_tag_type = DEVSTAT_TAG_SIMPLE;
1112 break;
1113 }
1114
1115 beio->io_len = 0;
1116 beio->io_offset = -1;
1117
1118 beio->bio_cmd = BIO_DELETE;
1119 beio->ds_trans_type = DEVSTAT_FREE;
1120
1121 DPRINTF("UNMAP\n");
1122
1123 be_lun->unmap(be_lun, beio);
1124}
1125
1126static void
1127ctl_be_block_cw_done(struct ctl_be_block_io *beio)
1128{
1129 union ctl_io *io;
1130
1131 io = beio->io;
1132 ctl_free_beio(beio);
1133 ctl_config_write_done(io);
1134}
1135
1136static void
1137ctl_be_block_cw_dispatch(struct ctl_be_block_lun *be_lun,
1138 union ctl_io *io)
1139{
1140 struct ctl_be_block_io *beio;
1141 struct ctl_be_block_softc *softc;
1142
1143 DPRINTF("entered\n");
1144
1145 softc = be_lun->softc;
1146 beio = ctl_alloc_beio(softc);
1147 beio->io = io;
1148 beio->lun = be_lun;
1149 beio->beio_cont = ctl_be_block_cw_done;
1150 PRIV(io)->ptr = (void *)beio;
1151
1152 switch (io->scsiio.cdb[0]) {
1153 case SYNCHRONIZE_CACHE:
1154 case SYNCHRONIZE_CACHE_16:
1155 beio->bio_cmd = BIO_FLUSH;
1156 beio->ds_trans_type = DEVSTAT_NO_DATA;
1157 beio->ds_tag_type = DEVSTAT_TAG_ORDERED;
1158 beio->io_len = 0;
1159 be_lun->lun_flush(be_lun, beio);
1160 break;
1161 case WRITE_SAME_10:
1162 case WRITE_SAME_16:
1163 ctl_be_block_cw_dispatch_ws(be_lun, io);
1164 break;
1165 case UNMAP:
1166 ctl_be_block_cw_dispatch_unmap(be_lun, io);
1167 break;
1168 default:
1169 panic("Unhandled CDB type %#x", io->scsiio.cdb[0]);
1170 break;
1171 }
1172}
1173
1174SDT_PROBE_DEFINE1(cbb, kernel, read, start, "uint64_t");
1175SDT_PROBE_DEFINE1(cbb, kernel, write, start, "uint64_t");
1176SDT_PROBE_DEFINE1(cbb, kernel, read, alloc_done, "uint64_t");
1177SDT_PROBE_DEFINE1(cbb, kernel, write, alloc_done, "uint64_t");
1178
1179static void
1180ctl_be_block_next(struct ctl_be_block_io *beio)
1181{
1182 struct ctl_be_block_lun *be_lun;
1183 union ctl_io *io;
1184
1185 io = beio->io;
1186 be_lun = beio->lun;
1187 ctl_free_beio(beio);
1188 if ((io->io_hdr.flags & CTL_FLAG_ABORT) ||
1189 ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE &&
1190 (io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS)) {
1191 ctl_data_submit_done(io);
1192 return;
1193 }
1194
1195 io->io_hdr.status &= ~CTL_STATUS_MASK;
1196 io->io_hdr.status |= CTL_STATUS_NONE;
1197
924}
925
926static void
927ctl_be_block_cw_done_ws(struct ctl_be_block_io *beio)
928{
929 union ctl_io *io;
930
931 io = beio->io;
932 ctl_free_beio(beio);
933 if ((io->io_hdr.flags & CTL_FLAG_ABORT) ||
934 ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE &&
935 (io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS)) {
936 ctl_config_write_done(io);
937 return;
938 }
939
940 ctl_be_block_config_write(io);
941}
942
943static void
944ctl_be_block_cw_dispatch_ws(struct ctl_be_block_lun *be_lun,
945 union ctl_io *io)
946{
947 struct ctl_be_block_io *beio;
948 struct ctl_be_block_softc *softc;
949 struct ctl_lba_len_flags *lbalen;
950 uint64_t len_left, lba;
951 int i, seglen;
952 uint8_t *buf, *end;
953
954 DPRINTF("entered\n");
955
956 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
957 softc = be_lun->softc;
958 lbalen = ARGS(beio->io);
959
960 if (lbalen->flags & ~(SWS_LBDATA | SWS_UNMAP) ||
961 (lbalen->flags & SWS_UNMAP && be_lun->unmap == NULL)) {
962 ctl_free_beio(beio);
963 ctl_set_invalid_field(&io->scsiio,
964 /*sks_valid*/ 1,
965 /*command*/ 1,
966 /*field*/ 1,
967 /*bit_valid*/ 0,
968 /*bit*/ 0);
969 ctl_config_write_done(io);
970 return;
971 }
972
973 /*
974 * If the I/O came down with an ordered or head of queue tag, set
975 * the BIO_ORDERED attribute. For head of queue tags, that's
976 * pretty much the best we can do.
977 */
978 if ((io->scsiio.tag_type == CTL_TAG_ORDERED)
979 || (io->scsiio.tag_type == CTL_TAG_HEAD_OF_QUEUE))
980 beio->bio_flags = BIO_ORDERED;
981
982 switch (io->scsiio.tag_type) {
983 case CTL_TAG_ORDERED:
984 beio->ds_tag_type = DEVSTAT_TAG_ORDERED;
985 break;
986 case CTL_TAG_HEAD_OF_QUEUE:
987 beio->ds_tag_type = DEVSTAT_TAG_HEAD;
988 break;
989 case CTL_TAG_UNTAGGED:
990 case CTL_TAG_SIMPLE:
991 case CTL_TAG_ACA:
992 default:
993 beio->ds_tag_type = DEVSTAT_TAG_SIMPLE;
994 break;
995 }
996
997 if (lbalen->flags & SWS_UNMAP) {
998 beio->io_offset = lbalen->lba * be_lun->blocksize;
999 beio->io_len = (uint64_t)lbalen->len * be_lun->blocksize;
1000 beio->bio_cmd = BIO_DELETE;
1001 beio->ds_trans_type = DEVSTAT_FREE;
1002
1003 be_lun->unmap(be_lun, beio);
1004 return;
1005 }
1006
1007 beio->bio_cmd = BIO_WRITE;
1008 beio->ds_trans_type = DEVSTAT_WRITE;
1009
1010 DPRINTF("WRITE SAME at LBA %jx len %u\n",
1011 (uintmax_t)lbalen->lba, lbalen->len);
1012
1013 len_left = (uint64_t)lbalen->len * be_lun->blocksize;
1014 for (i = 0, lba = 0; i < CTLBLK_MAX_SEGS && len_left > 0; i++) {
1015
1016 /*
1017 * Setup the S/G entry for this chunk.
1018 */
1019 seglen = MIN(CTLBLK_MAX_SEG, len_left);
1020 seglen -= seglen % be_lun->blocksize;
1021 beio->sg_segs[i].len = seglen;
1022 beio->sg_segs[i].addr = uma_zalloc(be_lun->lun_zone, M_WAITOK);
1023
1024 DPRINTF("segment %d addr %p len %zd\n", i,
1025 beio->sg_segs[i].addr, beio->sg_segs[i].len);
1026
1027 beio->num_segs++;
1028 len_left -= seglen;
1029
1030 buf = beio->sg_segs[i].addr;
1031 end = buf + seglen;
1032 for (; buf < end; buf += be_lun->blocksize) {
1033 memcpy(buf, io->scsiio.kern_data_ptr, be_lun->blocksize);
1034 if (lbalen->flags & SWS_LBDATA)
1035 scsi_ulto4b(lbalen->lba + lba, buf);
1036 lba++;
1037 }
1038 }
1039
1040 beio->io_offset = lbalen->lba * be_lun->blocksize;
1041 beio->io_len = lba * be_lun->blocksize;
1042
1043 /* We can not do all in one run. Correct and schedule rerun. */
1044 if (len_left > 0) {
1045 lbalen->lba += lba;
1046 lbalen->len -= lba;
1047 beio->beio_cont = ctl_be_block_cw_done_ws;
1048 }
1049
1050 be_lun->dispatch(be_lun, beio);
1051}
1052
1053static void
1054ctl_be_block_cw_dispatch_unmap(struct ctl_be_block_lun *be_lun,
1055 union ctl_io *io)
1056{
1057 struct ctl_be_block_io *beio;
1058 struct ctl_be_block_softc *softc;
1059 struct ctl_ptr_len_flags *ptrlen;
1060
1061 DPRINTF("entered\n");
1062
1063 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
1064 softc = be_lun->softc;
1065 ptrlen = (struct ctl_ptr_len_flags *)&io->io_hdr.ctl_private[CTL_PRIV_LBA_LEN];
1066
1067 if (ptrlen->flags != 0 || be_lun->unmap == NULL) {
1068 ctl_free_beio(beio);
1069 ctl_set_invalid_field(&io->scsiio,
1070 /*sks_valid*/ 0,
1071 /*command*/ 1,
1072 /*field*/ 0,
1073 /*bit_valid*/ 0,
1074 /*bit*/ 0);
1075 ctl_config_write_done(io);
1076 return;
1077 }
1078
1079 /*
1080 * If the I/O came down with an ordered or head of queue tag, set
1081 * the BIO_ORDERED attribute. For head of queue tags, that's
1082 * pretty much the best we can do.
1083 */
1084 if ((io->scsiio.tag_type == CTL_TAG_ORDERED)
1085 || (io->scsiio.tag_type == CTL_TAG_HEAD_OF_QUEUE))
1086 beio->bio_flags = BIO_ORDERED;
1087
1088 switch (io->scsiio.tag_type) {
1089 case CTL_TAG_ORDERED:
1090 beio->ds_tag_type = DEVSTAT_TAG_ORDERED;
1091 break;
1092 case CTL_TAG_HEAD_OF_QUEUE:
1093 beio->ds_tag_type = DEVSTAT_TAG_HEAD;
1094 break;
1095 case CTL_TAG_UNTAGGED:
1096 case CTL_TAG_SIMPLE:
1097 case CTL_TAG_ACA:
1098 default:
1099 beio->ds_tag_type = DEVSTAT_TAG_SIMPLE;
1100 break;
1101 }
1102
1103 beio->io_len = 0;
1104 beio->io_offset = -1;
1105
1106 beio->bio_cmd = BIO_DELETE;
1107 beio->ds_trans_type = DEVSTAT_FREE;
1108
1109 DPRINTF("UNMAP\n");
1110
1111 be_lun->unmap(be_lun, beio);
1112}
1113
1114static void
1115ctl_be_block_cw_done(struct ctl_be_block_io *beio)
1116{
1117 union ctl_io *io;
1118
1119 io = beio->io;
1120 ctl_free_beio(beio);
1121 ctl_config_write_done(io);
1122}
1123
1124static void
1125ctl_be_block_cw_dispatch(struct ctl_be_block_lun *be_lun,
1126 union ctl_io *io)
1127{
1128 struct ctl_be_block_io *beio;
1129 struct ctl_be_block_softc *softc;
1130
1131 DPRINTF("entered\n");
1132
1133 softc = be_lun->softc;
1134 beio = ctl_alloc_beio(softc);
1135 beio->io = io;
1136 beio->lun = be_lun;
1137 beio->beio_cont = ctl_be_block_cw_done;
1138 PRIV(io)->ptr = (void *)beio;
1139
1140 switch (io->scsiio.cdb[0]) {
1141 case SYNCHRONIZE_CACHE:
1142 case SYNCHRONIZE_CACHE_16:
1143 beio->bio_cmd = BIO_FLUSH;
1144 beio->ds_trans_type = DEVSTAT_NO_DATA;
1145 beio->ds_tag_type = DEVSTAT_TAG_ORDERED;
1146 beio->io_len = 0;
1147 be_lun->lun_flush(be_lun, beio);
1148 break;
1149 case WRITE_SAME_10:
1150 case WRITE_SAME_16:
1151 ctl_be_block_cw_dispatch_ws(be_lun, io);
1152 break;
1153 case UNMAP:
1154 ctl_be_block_cw_dispatch_unmap(be_lun, io);
1155 break;
1156 default:
1157 panic("Unhandled CDB type %#x", io->scsiio.cdb[0]);
1158 break;
1159 }
1160}
1161
1162SDT_PROBE_DEFINE1(cbb, kernel, read, start, "uint64_t");
1163SDT_PROBE_DEFINE1(cbb, kernel, write, start, "uint64_t");
1164SDT_PROBE_DEFINE1(cbb, kernel, read, alloc_done, "uint64_t");
1165SDT_PROBE_DEFINE1(cbb, kernel, write, alloc_done, "uint64_t");
1166
1167static void
1168ctl_be_block_next(struct ctl_be_block_io *beio)
1169{
1170 struct ctl_be_block_lun *be_lun;
1171 union ctl_io *io;
1172
1173 io = beio->io;
1174 be_lun = beio->lun;
1175 ctl_free_beio(beio);
1176 if ((io->io_hdr.flags & CTL_FLAG_ABORT) ||
1177 ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE &&
1178 (io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS)) {
1179 ctl_data_submit_done(io);
1180 return;
1181 }
1182
1183 io->io_hdr.status &= ~CTL_STATUS_MASK;
1184 io->io_hdr.status |= CTL_STATUS_NONE;
1185
1198 mtx_lock(&be_lun->lock);
1186 mtx_lock(&be_lun->queue_lock);
1199 /*
1200 * XXX KDM make sure that links is okay to use at this point.
1201 * Otherwise, we either need to add another field to ctl_io_hdr,
1202 * or deal with resource allocation here.
1203 */
1204 STAILQ_INSERT_TAIL(&be_lun->input_queue, &io->io_hdr, links);
1187 /*
1188 * XXX KDM make sure that links is okay to use at this point.
1189 * Otherwise, we either need to add another field to ctl_io_hdr,
1190 * or deal with resource allocation here.
1191 */
1192 STAILQ_INSERT_TAIL(&be_lun->input_queue, &io->io_hdr, links);
1205 mtx_unlock(&be_lun->lock);
1193 mtx_unlock(&be_lun->queue_lock);
1206
1207 taskqueue_enqueue(be_lun->io_taskqueue, &be_lun->io_task);
1208}
1209
1210static void
1211ctl_be_block_dispatch(struct ctl_be_block_lun *be_lun,
1212 union ctl_io *io)
1213{
1214 struct ctl_be_block_io *beio;
1215 struct ctl_be_block_softc *softc;
1216 struct ctl_lba_len_flags *lbalen;
1217 struct ctl_ptr_len_flags *bptrlen;
1218 uint64_t len_left, lbas;
1219 int i;
1220
1221 softc = be_lun->softc;
1222
1223 DPRINTF("entered\n");
1224
1225 lbalen = ARGS(io);
1226 if (lbalen->flags & CTL_LLF_WRITE) {
1227 SDT_PROBE(cbb, kernel, write, start, 0, 0, 0, 0, 0);
1228 } else {
1229 SDT_PROBE(cbb, kernel, read, start, 0, 0, 0, 0, 0);
1230 }
1231
1232 beio = ctl_alloc_beio(softc);
1233 beio->io = io;
1234 beio->lun = be_lun;
1235 bptrlen = PRIV(io);
1236 bptrlen->ptr = (void *)beio;
1237
1238 /*
1239 * If the I/O came down with an ordered or head of queue tag, set
1240 * the BIO_ORDERED attribute. For head of queue tags, that's
1241 * pretty much the best we can do.
1242 *
1243 * XXX KDM we don't have a great way to easily know about the FUA
1244 * bit right now (it is decoded in ctl_read_write(), but we don't
1245 * pass that knowledge to the backend), and in any case we would
1246 * need to determine how to handle it.
1247 */
1248 if ((io->scsiio.tag_type == CTL_TAG_ORDERED)
1249 || (io->scsiio.tag_type == CTL_TAG_HEAD_OF_QUEUE))
1250 beio->bio_flags = BIO_ORDERED;
1251
1252 switch (io->scsiio.tag_type) {
1253 case CTL_TAG_ORDERED:
1254 beio->ds_tag_type = DEVSTAT_TAG_ORDERED;
1255 break;
1256 case CTL_TAG_HEAD_OF_QUEUE:
1257 beio->ds_tag_type = DEVSTAT_TAG_HEAD;
1258 break;
1259 case CTL_TAG_UNTAGGED:
1260 case CTL_TAG_SIMPLE:
1261 case CTL_TAG_ACA:
1262 default:
1263 beio->ds_tag_type = DEVSTAT_TAG_SIMPLE;
1264 break;
1265 }
1266
1267 if (lbalen->flags & CTL_LLF_WRITE) {
1268 beio->bio_cmd = BIO_WRITE;
1269 beio->ds_trans_type = DEVSTAT_WRITE;
1270 } else {
1271 beio->bio_cmd = BIO_READ;
1272 beio->ds_trans_type = DEVSTAT_READ;
1273 }
1274
1275 DPRINTF("%s at LBA %jx len %u @%ju\n",
1276 (beio->bio_cmd == BIO_READ) ? "READ" : "WRITE",
1277 (uintmax_t)lbalen->lba, lbalen->len, bptrlen->len);
1278 if (lbalen->flags & CTL_LLF_COMPARE)
1279 lbas = CTLBLK_HALF_IO_SIZE;
1280 else
1281 lbas = CTLBLK_MAX_IO_SIZE;
1282 lbas = MIN(lbalen->len - bptrlen->len, lbas / be_lun->blocksize);
1283 beio->io_offset = (lbalen->lba + bptrlen->len) * be_lun->blocksize;
1284 beio->io_len = lbas * be_lun->blocksize;
1285 bptrlen->len += lbas;
1286
1287 for (i = 0, len_left = beio->io_len; len_left > 0; i++) {
1288 KASSERT(i < CTLBLK_MAX_SEGS, ("Too many segs (%d >= %d)",
1289 i, CTLBLK_MAX_SEGS));
1290
1291 /*
1292 * Setup the S/G entry for this chunk.
1293 */
1294 beio->sg_segs[i].len = min(CTLBLK_MAX_SEG, len_left);
1295 beio->sg_segs[i].addr = uma_zalloc(be_lun->lun_zone, M_WAITOK);
1296
1297 DPRINTF("segment %d addr %p len %zd\n", i,
1298 beio->sg_segs[i].addr, beio->sg_segs[i].len);
1299
1300 /* Set up second segment for compare operation. */
1301 if (lbalen->flags & CTL_LLF_COMPARE) {
1302 beio->sg_segs[i + CTLBLK_HALF_SEGS].len =
1303 beio->sg_segs[i].len;
1304 beio->sg_segs[i + CTLBLK_HALF_SEGS].addr =
1305 uma_zalloc(be_lun->lun_zone, M_WAITOK);
1306 }
1307
1308 beio->num_segs++;
1309 len_left -= beio->sg_segs[i].len;
1310 }
1311 if (bptrlen->len < lbalen->len)
1312 beio->beio_cont = ctl_be_block_next;
1313 io->scsiio.be_move_done = ctl_be_block_move_done;
1314 /* For compare we have separate S/G lists for read and datamove. */
1315 if (lbalen->flags & CTL_LLF_COMPARE)
1316 io->scsiio.kern_data_ptr = (uint8_t *)&beio->sg_segs[CTLBLK_HALF_SEGS];
1317 else
1318 io->scsiio.kern_data_ptr = (uint8_t *)beio->sg_segs;
1319 io->scsiio.kern_data_len = beio->io_len;
1320 io->scsiio.kern_data_resid = 0;
1321 io->scsiio.kern_sg_entries = beio->num_segs;
1322 io->io_hdr.flags |= CTL_FLAG_ALLOCATED | CTL_FLAG_KDPTR_SGLIST;
1323
1324 /*
1325 * For the read case, we need to read the data into our buffers and
1326 * then we can send it back to the user. For the write case, we
1327 * need to get the data from the user first.
1328 */
1329 if (beio->bio_cmd == BIO_READ) {
1330 SDT_PROBE(cbb, kernel, read, alloc_done, 0, 0, 0, 0, 0);
1331 be_lun->dispatch(be_lun, beio);
1332 } else {
1333 SDT_PROBE(cbb, kernel, write, alloc_done, 0, 0, 0, 0, 0);
1334#ifdef CTL_TIME_IO
1335 getbintime(&io->io_hdr.dma_start_bt);
1336#endif
1337 ctl_datamove(io);
1338 }
1339}
1340
1341static void
1342ctl_be_block_worker(void *context, int pending)
1343{
1344 struct ctl_be_block_lun *be_lun;
1345 struct ctl_be_block_softc *softc;
1346 union ctl_io *io;
1347
1348 be_lun = (struct ctl_be_block_lun *)context;
1349 softc = be_lun->softc;
1350
1351 DPRINTF("entered\n");
1352
1194
1195 taskqueue_enqueue(be_lun->io_taskqueue, &be_lun->io_task);
1196}
1197
1198static void
1199ctl_be_block_dispatch(struct ctl_be_block_lun *be_lun,
1200 union ctl_io *io)
1201{
1202 struct ctl_be_block_io *beio;
1203 struct ctl_be_block_softc *softc;
1204 struct ctl_lba_len_flags *lbalen;
1205 struct ctl_ptr_len_flags *bptrlen;
1206 uint64_t len_left, lbas;
1207 int i;
1208
1209 softc = be_lun->softc;
1210
1211 DPRINTF("entered\n");
1212
1213 lbalen = ARGS(io);
1214 if (lbalen->flags & CTL_LLF_WRITE) {
1215 SDT_PROBE(cbb, kernel, write, start, 0, 0, 0, 0, 0);
1216 } else {
1217 SDT_PROBE(cbb, kernel, read, start, 0, 0, 0, 0, 0);
1218 }
1219
1220 beio = ctl_alloc_beio(softc);
1221 beio->io = io;
1222 beio->lun = be_lun;
1223 bptrlen = PRIV(io);
1224 bptrlen->ptr = (void *)beio;
1225
1226 /*
1227 * If the I/O came down with an ordered or head of queue tag, set
1228 * the BIO_ORDERED attribute. For head of queue tags, that's
1229 * pretty much the best we can do.
1230 *
1231 * XXX KDM we don't have a great way to easily know about the FUA
1232 * bit right now (it is decoded in ctl_read_write(), but we don't
1233 * pass that knowledge to the backend), and in any case we would
1234 * need to determine how to handle it.
1235 */
1236 if ((io->scsiio.tag_type == CTL_TAG_ORDERED)
1237 || (io->scsiio.tag_type == CTL_TAG_HEAD_OF_QUEUE))
1238 beio->bio_flags = BIO_ORDERED;
1239
1240 switch (io->scsiio.tag_type) {
1241 case CTL_TAG_ORDERED:
1242 beio->ds_tag_type = DEVSTAT_TAG_ORDERED;
1243 break;
1244 case CTL_TAG_HEAD_OF_QUEUE:
1245 beio->ds_tag_type = DEVSTAT_TAG_HEAD;
1246 break;
1247 case CTL_TAG_UNTAGGED:
1248 case CTL_TAG_SIMPLE:
1249 case CTL_TAG_ACA:
1250 default:
1251 beio->ds_tag_type = DEVSTAT_TAG_SIMPLE;
1252 break;
1253 }
1254
1255 if (lbalen->flags & CTL_LLF_WRITE) {
1256 beio->bio_cmd = BIO_WRITE;
1257 beio->ds_trans_type = DEVSTAT_WRITE;
1258 } else {
1259 beio->bio_cmd = BIO_READ;
1260 beio->ds_trans_type = DEVSTAT_READ;
1261 }
1262
1263 DPRINTF("%s at LBA %jx len %u @%ju\n",
1264 (beio->bio_cmd == BIO_READ) ? "READ" : "WRITE",
1265 (uintmax_t)lbalen->lba, lbalen->len, bptrlen->len);
1266 if (lbalen->flags & CTL_LLF_COMPARE)
1267 lbas = CTLBLK_HALF_IO_SIZE;
1268 else
1269 lbas = CTLBLK_MAX_IO_SIZE;
1270 lbas = MIN(lbalen->len - bptrlen->len, lbas / be_lun->blocksize);
1271 beio->io_offset = (lbalen->lba + bptrlen->len) * be_lun->blocksize;
1272 beio->io_len = lbas * be_lun->blocksize;
1273 bptrlen->len += lbas;
1274
1275 for (i = 0, len_left = beio->io_len; len_left > 0; i++) {
1276 KASSERT(i < CTLBLK_MAX_SEGS, ("Too many segs (%d >= %d)",
1277 i, CTLBLK_MAX_SEGS));
1278
1279 /*
1280 * Setup the S/G entry for this chunk.
1281 */
1282 beio->sg_segs[i].len = min(CTLBLK_MAX_SEG, len_left);
1283 beio->sg_segs[i].addr = uma_zalloc(be_lun->lun_zone, M_WAITOK);
1284
1285 DPRINTF("segment %d addr %p len %zd\n", i,
1286 beio->sg_segs[i].addr, beio->sg_segs[i].len);
1287
1288 /* Set up second segment for compare operation. */
1289 if (lbalen->flags & CTL_LLF_COMPARE) {
1290 beio->sg_segs[i + CTLBLK_HALF_SEGS].len =
1291 beio->sg_segs[i].len;
1292 beio->sg_segs[i + CTLBLK_HALF_SEGS].addr =
1293 uma_zalloc(be_lun->lun_zone, M_WAITOK);
1294 }
1295
1296 beio->num_segs++;
1297 len_left -= beio->sg_segs[i].len;
1298 }
1299 if (bptrlen->len < lbalen->len)
1300 beio->beio_cont = ctl_be_block_next;
1301 io->scsiio.be_move_done = ctl_be_block_move_done;
1302 /* For compare we have separate S/G lists for read and datamove. */
1303 if (lbalen->flags & CTL_LLF_COMPARE)
1304 io->scsiio.kern_data_ptr = (uint8_t *)&beio->sg_segs[CTLBLK_HALF_SEGS];
1305 else
1306 io->scsiio.kern_data_ptr = (uint8_t *)beio->sg_segs;
1307 io->scsiio.kern_data_len = beio->io_len;
1308 io->scsiio.kern_data_resid = 0;
1309 io->scsiio.kern_sg_entries = beio->num_segs;
1310 io->io_hdr.flags |= CTL_FLAG_ALLOCATED | CTL_FLAG_KDPTR_SGLIST;
1311
1312 /*
1313 * For the read case, we need to read the data into our buffers and
1314 * then we can send it back to the user. For the write case, we
1315 * need to get the data from the user first.
1316 */
1317 if (beio->bio_cmd == BIO_READ) {
1318 SDT_PROBE(cbb, kernel, read, alloc_done, 0, 0, 0, 0, 0);
1319 be_lun->dispatch(be_lun, beio);
1320 } else {
1321 SDT_PROBE(cbb, kernel, write, alloc_done, 0, 0, 0, 0, 0);
1322#ifdef CTL_TIME_IO
1323 getbintime(&io->io_hdr.dma_start_bt);
1324#endif
1325 ctl_datamove(io);
1326 }
1327}
1328
1329static void
1330ctl_be_block_worker(void *context, int pending)
1331{
1332 struct ctl_be_block_lun *be_lun;
1333 struct ctl_be_block_softc *softc;
1334 union ctl_io *io;
1335
1336 be_lun = (struct ctl_be_block_lun *)context;
1337 softc = be_lun->softc;
1338
1339 DPRINTF("entered\n");
1340
1353 mtx_lock(&be_lun->lock);
1341 mtx_lock(&be_lun->queue_lock);
1354 for (;;) {
1355 io = (union ctl_io *)STAILQ_FIRST(&be_lun->datamove_queue);
1356 if (io != NULL) {
1357 struct ctl_be_block_io *beio;
1358
1359 DPRINTF("datamove queue\n");
1360
1361 STAILQ_REMOVE(&be_lun->datamove_queue, &io->io_hdr,
1362 ctl_io_hdr, links);
1363
1342 for (;;) {
1343 io = (union ctl_io *)STAILQ_FIRST(&be_lun->datamove_queue);
1344 if (io != NULL) {
1345 struct ctl_be_block_io *beio;
1346
1347 DPRINTF("datamove queue\n");
1348
1349 STAILQ_REMOVE(&be_lun->datamove_queue, &io->io_hdr,
1350 ctl_io_hdr, links);
1351
1364 mtx_unlock(&be_lun->lock);
1352 mtx_unlock(&be_lun->queue_lock);
1365
1366 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
1367
1368 be_lun->dispatch(be_lun, beio);
1369
1353
1354 beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
1355
1356 be_lun->dispatch(be_lun, beio);
1357
1370 mtx_lock(&be_lun->lock);
1358 mtx_lock(&be_lun->queue_lock);
1371 continue;
1372 }
1373 io = (union ctl_io *)STAILQ_FIRST(&be_lun->config_write_queue);
1374 if (io != NULL) {
1375
1376 DPRINTF("config write queue\n");
1377
1378 STAILQ_REMOVE(&be_lun->config_write_queue, &io->io_hdr,
1379 ctl_io_hdr, links);
1380
1359 continue;
1360 }
1361 io = (union ctl_io *)STAILQ_FIRST(&be_lun->config_write_queue);
1362 if (io != NULL) {
1363
1364 DPRINTF("config write queue\n");
1365
1366 STAILQ_REMOVE(&be_lun->config_write_queue, &io->io_hdr,
1367 ctl_io_hdr, links);
1368
1381 mtx_unlock(&be_lun->lock);
1369 mtx_unlock(&be_lun->queue_lock);
1382
1383 ctl_be_block_cw_dispatch(be_lun, io);
1384
1370
1371 ctl_be_block_cw_dispatch(be_lun, io);
1372
1385 mtx_lock(&be_lun->lock);
1373 mtx_lock(&be_lun->queue_lock);
1386 continue;
1387 }
1388 io = (union ctl_io *)STAILQ_FIRST(&be_lun->input_queue);
1389 if (io != NULL) {
1390 DPRINTF("input queue\n");
1391
1392 STAILQ_REMOVE(&be_lun->input_queue, &io->io_hdr,
1393 ctl_io_hdr, links);
1374 continue;
1375 }
1376 io = (union ctl_io *)STAILQ_FIRST(&be_lun->input_queue);
1377 if (io != NULL) {
1378 DPRINTF("input queue\n");
1379
1380 STAILQ_REMOVE(&be_lun->input_queue, &io->io_hdr,
1381 ctl_io_hdr, links);
1394 mtx_unlock(&be_lun->lock);
1382 mtx_unlock(&be_lun->queue_lock);
1395
1396 /*
1397 * We must drop the lock, since this routine and
1398 * its children may sleep.
1399 */
1400 ctl_be_block_dispatch(be_lun, io);
1401
1383
1384 /*
1385 * We must drop the lock, since this routine and
1386 * its children may sleep.
1387 */
1388 ctl_be_block_dispatch(be_lun, io);
1389
1402 mtx_lock(&be_lun->lock);
1390 mtx_lock(&be_lun->queue_lock);
1403 continue;
1404 }
1405
1406 /*
1407 * If we get here, there is no work left in the queues, so
1408 * just break out and let the task queue go to sleep.
1409 */
1410 break;
1411 }
1391 continue;
1392 }
1393
1394 /*
1395 * If we get here, there is no work left in the queues, so
1396 * just break out and let the task queue go to sleep.
1397 */
1398 break;
1399 }
1412 mtx_unlock(&be_lun->lock);
1400 mtx_unlock(&be_lun->queue_lock);
1413}
1414
1415/*
1416 * Entry point from CTL to the backend for I/O. We queue everything to a
1417 * work thread, so this just puts the I/O on a queue and wakes up the
1418 * thread.
1419 */
1420static int
1421ctl_be_block_submit(union ctl_io *io)
1422{
1423 struct ctl_be_block_lun *be_lun;
1424 struct ctl_be_lun *ctl_be_lun;
1425
1426 DPRINTF("entered\n");
1427
1428 ctl_be_lun = (struct ctl_be_lun *)io->io_hdr.ctl_private[
1429 CTL_PRIV_BACKEND_LUN].ptr;
1430 be_lun = (struct ctl_be_block_lun *)ctl_be_lun->be_lun;
1431
1432 /*
1433 * Make sure we only get SCSI I/O.
1434 */
1435 KASSERT(io->io_hdr.io_type == CTL_IO_SCSI, ("Non-SCSI I/O (type "
1436 "%#x) encountered", io->io_hdr.io_type));
1437
1438 PRIV(io)->len = 0;
1439
1401}
1402
1403/*
1404 * Entry point from CTL to the backend for I/O. We queue everything to a
1405 * work thread, so this just puts the I/O on a queue and wakes up the
1406 * thread.
1407 */
1408static int
1409ctl_be_block_submit(union ctl_io *io)
1410{
1411 struct ctl_be_block_lun *be_lun;
1412 struct ctl_be_lun *ctl_be_lun;
1413
1414 DPRINTF("entered\n");
1415
1416 ctl_be_lun = (struct ctl_be_lun *)io->io_hdr.ctl_private[
1417 CTL_PRIV_BACKEND_LUN].ptr;
1418 be_lun = (struct ctl_be_block_lun *)ctl_be_lun->be_lun;
1419
1420 /*
1421 * Make sure we only get SCSI I/O.
1422 */
1423 KASSERT(io->io_hdr.io_type == CTL_IO_SCSI, ("Non-SCSI I/O (type "
1424 "%#x) encountered", io->io_hdr.io_type));
1425
1426 PRIV(io)->len = 0;
1427
1440 mtx_lock(&be_lun->lock);
1428 mtx_lock(&be_lun->queue_lock);
1441 /*
1442 * XXX KDM make sure that links is okay to use at this point.
1443 * Otherwise, we either need to add another field to ctl_io_hdr,
1444 * or deal with resource allocation here.
1445 */
1446 STAILQ_INSERT_TAIL(&be_lun->input_queue, &io->io_hdr, links);
1429 /*
1430 * XXX KDM make sure that links is okay to use at this point.
1431 * Otherwise, we either need to add another field to ctl_io_hdr,
1432 * or deal with resource allocation here.
1433 */
1434 STAILQ_INSERT_TAIL(&be_lun->input_queue, &io->io_hdr, links);
1447 mtx_unlock(&be_lun->lock);
1435 mtx_unlock(&be_lun->queue_lock);
1448 taskqueue_enqueue(be_lun->io_taskqueue, &be_lun->io_task);
1449
1450 return (CTL_RETVAL_COMPLETE);
1451}
1452
1453static int
1454ctl_be_block_ioctl(struct cdev *dev, u_long cmd, caddr_t addr,
1455 int flag, struct thread *td)
1456{
1457 struct ctl_be_block_softc *softc;
1458 int error;
1459
1460 softc = &backend_block_softc;
1461
1462 error = 0;
1463
1464 switch (cmd) {
1465 case CTL_LUN_REQ: {
1466 struct ctl_lun_req *lun_req;
1467
1468 lun_req = (struct ctl_lun_req *)addr;
1469
1470 switch (lun_req->reqtype) {
1471 case CTL_LUNREQ_CREATE:
1472 error = ctl_be_block_create(softc, lun_req);
1473 break;
1474 case CTL_LUNREQ_RM:
1475 error = ctl_be_block_rm(softc, lun_req);
1476 break;
1477 case CTL_LUNREQ_MODIFY:
1478 error = ctl_be_block_modify(softc, lun_req);
1479 break;
1480 default:
1481 lun_req->status = CTL_LUN_ERROR;
1482 snprintf(lun_req->error_str, sizeof(lun_req->error_str),
1483 "%s: invalid LUN request type %d", __func__,
1484 lun_req->reqtype);
1485 break;
1486 }
1487 break;
1488 }
1489 default:
1490 error = ENOTTY;
1491 break;
1492 }
1493
1494 return (error);
1495}
1496
1497static int
1498ctl_be_block_open_file(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
1499{
1500 struct ctl_be_block_filedata *file_data;
1501 struct ctl_lun_create_params *params;
1502 struct vattr vattr;
1503 int error;
1504
1505 error = 0;
1506 file_data = &be_lun->backend.file;
1507 params = &req->reqdata.create;
1508
1509 be_lun->dev_type = CTL_BE_BLOCK_FILE;
1510 be_lun->dispatch = ctl_be_block_dispatch_file;
1511 be_lun->lun_flush = ctl_be_block_flush_file;
1512
1513 error = VOP_GETATTR(be_lun->vn, &vattr, curthread->td_ucred);
1514 if (error != 0) {
1515 snprintf(req->error_str, sizeof(req->error_str),
1516 "error calling VOP_GETATTR() for file %s",
1517 be_lun->dev_path);
1518 return (error);
1519 }
1520
1521 /*
1522 * Verify that we have the ability to upgrade to exclusive
1523 * access on this file so we can trap errors at open instead
1524 * of reporting them during first access.
1525 */
1526 if (VOP_ISLOCKED(be_lun->vn) != LK_EXCLUSIVE) {
1527 vn_lock(be_lun->vn, LK_UPGRADE | LK_RETRY);
1528 if (be_lun->vn->v_iflag & VI_DOOMED) {
1529 error = EBADF;
1530 snprintf(req->error_str, sizeof(req->error_str),
1531 "error locking file %s", be_lun->dev_path);
1532 return (error);
1533 }
1534 }
1535
1536
1537 file_data->cred = crhold(curthread->td_ucred);
1538 if (params->lun_size_bytes != 0)
1539 be_lun->size_bytes = params->lun_size_bytes;
1540 else
1541 be_lun->size_bytes = vattr.va_size;
1542 /*
1543 * We set the multi thread flag for file operations because all
1544 * filesystems (in theory) are capable of allowing multiple readers
1545 * of a file at once. So we want to get the maximum possible
1546 * concurrency.
1547 */
1548 be_lun->flags |= CTL_BE_BLOCK_LUN_MULTI_THREAD;
1549
1550 /*
1551 * XXX KDM vattr.va_blocksize may be larger than 512 bytes here.
1552 * With ZFS, it is 131072 bytes. Block sizes that large don't work
1553 * with disklabel and UFS on FreeBSD at least. Large block sizes
1554 * may not work with other OSes as well. So just export a sector
1555 * size of 512 bytes, which should work with any OS or
1556 * application. Since our backing is a file, any block size will
1557 * work fine for the backing store.
1558 */
1559#if 0
1560 be_lun->blocksize= vattr.va_blocksize;
1561#endif
1562 if (params->blocksize_bytes != 0)
1563 be_lun->blocksize = params->blocksize_bytes;
1564 else
1565 be_lun->blocksize = 512;
1566
1567 /*
1568 * Sanity check. The media size has to be at least one
1569 * sector long.
1570 */
1571 if (be_lun->size_bytes < be_lun->blocksize) {
1572 error = EINVAL;
1573 snprintf(req->error_str, sizeof(req->error_str),
1574 "file %s size %ju < block size %u", be_lun->dev_path,
1575 (uintmax_t)be_lun->size_bytes, be_lun->blocksize);
1576 }
1577 return (error);
1578}
1579
1580static int
1581ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
1582{
1583 struct ctl_lun_create_params *params;
1584 struct vattr vattr;
1585 struct cdev *dev;
1586 struct cdevsw *devsw;
1587 int error;
1588 off_t ps, pss, po, pos;
1589
1590 params = &req->reqdata.create;
1591
1592 be_lun->dev_type = CTL_BE_BLOCK_DEV;
1593 be_lun->dispatch = ctl_be_block_dispatch_dev;
1594 be_lun->lun_flush = ctl_be_block_flush_dev;
1595 be_lun->unmap = ctl_be_block_unmap_dev;
1596 be_lun->backend.dev.cdev = be_lun->vn->v_rdev;
1597 be_lun->backend.dev.csw = dev_refthread(be_lun->backend.dev.cdev,
1598 &be_lun->backend.dev.dev_ref);
1599 if (be_lun->backend.dev.csw == NULL)
1600 panic("Unable to retrieve device switch");
1601
1602 error = VOP_GETATTR(be_lun->vn, &vattr, NOCRED);
1603 if (error) {
1604 snprintf(req->error_str, sizeof(req->error_str),
1605 "%s: error getting vnode attributes for device %s",
1606 __func__, be_lun->dev_path);
1607 return (error);
1608 }
1609
1610 dev = be_lun->vn->v_rdev;
1611 devsw = dev->si_devsw;
1612 if (!devsw->d_ioctl) {
1613 snprintf(req->error_str, sizeof(req->error_str),
1614 "%s: no d_ioctl for device %s!", __func__,
1615 be_lun->dev_path);
1616 return (ENODEV);
1617 }
1618
1619 error = devsw->d_ioctl(dev, DIOCGSECTORSIZE,
1620 (caddr_t)&be_lun->blocksize, FREAD,
1621 curthread);
1622 if (error) {
1623 snprintf(req->error_str, sizeof(req->error_str),
1624 "%s: error %d returned for DIOCGSECTORSIZE ioctl "
1625 "on %s!", __func__, error, be_lun->dev_path);
1626 return (error);
1627 }
1628
1629 /*
1630 * If the user has asked for a blocksize that is greater than the
1631 * backing device's blocksize, we can do it only if the blocksize
1632 * the user is asking for is an even multiple of the underlying
1633 * device's blocksize.
1634 */
1635 if ((params->blocksize_bytes != 0)
1636 && (params->blocksize_bytes > be_lun->blocksize)) {
1637 uint32_t bs_multiple, tmp_blocksize;
1638
1639 bs_multiple = params->blocksize_bytes / be_lun->blocksize;
1640
1641 tmp_blocksize = bs_multiple * be_lun->blocksize;
1642
1643 if (tmp_blocksize == params->blocksize_bytes) {
1644 be_lun->blocksize = params->blocksize_bytes;
1645 } else {
1646 snprintf(req->error_str, sizeof(req->error_str),
1647 "%s: requested blocksize %u is not an even "
1648 "multiple of backing device blocksize %u",
1649 __func__, params->blocksize_bytes,
1650 be_lun->blocksize);
1651 return (EINVAL);
1652
1653 }
1654 } else if ((params->blocksize_bytes != 0)
1655 && (params->blocksize_bytes != be_lun->blocksize)) {
1656 snprintf(req->error_str, sizeof(req->error_str),
1657 "%s: requested blocksize %u < backing device "
1658 "blocksize %u", __func__, params->blocksize_bytes,
1659 be_lun->blocksize);
1660 return (EINVAL);
1661 }
1662
1663 error = devsw->d_ioctl(dev, DIOCGMEDIASIZE,
1664 (caddr_t)&be_lun->size_bytes, FREAD,
1665 curthread);
1666 if (error) {
1667 snprintf(req->error_str, sizeof(req->error_str),
1668 "%s: error %d returned for DIOCGMEDIASIZE "
1669 " ioctl on %s!", __func__, error,
1670 be_lun->dev_path);
1671 return (error);
1672 }
1673
1674 if (params->lun_size_bytes != 0) {
1675 if (params->lun_size_bytes > be_lun->size_bytes) {
1676 snprintf(req->error_str, sizeof(req->error_str),
1677 "%s: requested LUN size %ju > backing device "
1678 "size %ju", __func__,
1679 (uintmax_t)params->lun_size_bytes,
1680 (uintmax_t)be_lun->size_bytes);
1681 return (EINVAL);
1682 }
1683
1684 be_lun->size_bytes = params->lun_size_bytes;
1685 }
1686
1687 error = devsw->d_ioctl(dev, DIOCGSTRIPESIZE,
1688 (caddr_t)&ps, FREAD, curthread);
1689 if (error)
1690 ps = po = 0;
1691 else {
1692 error = devsw->d_ioctl(dev, DIOCGSTRIPEOFFSET,
1693 (caddr_t)&po, FREAD, curthread);
1694 if (error)
1695 po = 0;
1696 }
1697 pss = ps / be_lun->blocksize;
1698 pos = po / be_lun->blocksize;
1699 if ((pss > 0) && (pss * be_lun->blocksize == ps) && (pss >= pos) &&
1700 ((pss & (pss - 1)) == 0) && (pos * be_lun->blocksize == po)) {
1701 be_lun->pblockexp = fls(pss) - 1;
1702 be_lun->pblockoff = (pss - pos) % pss;
1703 }
1704
1705 return (0);
1706}
1707
1708static int
1709ctl_be_block_close(struct ctl_be_block_lun *be_lun)
1710{
1711 DROP_GIANT();
1712 if (be_lun->vn) {
1713 int flags = FREAD | FWRITE;
1714
1715 switch (be_lun->dev_type) {
1716 case CTL_BE_BLOCK_DEV:
1717 if (be_lun->backend.dev.csw) {
1718 dev_relthread(be_lun->backend.dev.cdev,
1719 be_lun->backend.dev.dev_ref);
1720 be_lun->backend.dev.csw = NULL;
1721 be_lun->backend.dev.cdev = NULL;
1722 }
1723 break;
1724 case CTL_BE_BLOCK_FILE:
1725 break;
1726 case CTL_BE_BLOCK_NONE:
1727 break;
1728 default:
1729 panic("Unexpected backend type.");
1730 break;
1731 }
1732
1733 (void)vn_close(be_lun->vn, flags, NOCRED, curthread);
1734 be_lun->vn = NULL;
1735
1736 switch (be_lun->dev_type) {
1737 case CTL_BE_BLOCK_DEV:
1738 break;
1739 case CTL_BE_BLOCK_FILE:
1740 if (be_lun->backend.file.cred != NULL) {
1741 crfree(be_lun->backend.file.cred);
1742 be_lun->backend.file.cred = NULL;
1743 }
1744 break;
1745 case CTL_BE_BLOCK_NONE:
1746 break;
1747 default:
1748 panic("Unexpected backend type.");
1749 break;
1750 }
1751 }
1752 PICKUP_GIANT();
1753
1754 return (0);
1755}
1756
1757static int
1758ctl_be_block_open(struct ctl_be_block_softc *softc,
1759 struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
1760{
1761 struct nameidata nd;
1762 int flags;
1763 int error;
1764
1765 /*
1766 * XXX KDM allow a read-only option?
1767 */
1768 flags = FREAD | FWRITE;
1769 error = 0;
1770
1771 if (rootvnode == NULL) {
1772 snprintf(req->error_str, sizeof(req->error_str),
1773 "%s: Root filesystem is not mounted", __func__);
1774 return (1);
1775 }
1776
1777 if (!curthread->td_proc->p_fd->fd_cdir) {
1778 curthread->td_proc->p_fd->fd_cdir = rootvnode;
1779 VREF(rootvnode);
1780 }
1781 if (!curthread->td_proc->p_fd->fd_rdir) {
1782 curthread->td_proc->p_fd->fd_rdir = rootvnode;
1783 VREF(rootvnode);
1784 }
1785 if (!curthread->td_proc->p_fd->fd_jdir) {
1786 curthread->td_proc->p_fd->fd_jdir = rootvnode;
1787 VREF(rootvnode);
1788 }
1789
1790 again:
1791 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, be_lun->dev_path, curthread);
1792 error = vn_open(&nd, &flags, 0, NULL);
1793 if (error) {
1794 /*
1795 * This is the only reasonable guess we can make as far as
1796 * path if the user doesn't give us a fully qualified path.
1797 * If they want to specify a file, they need to specify the
1798 * full path.
1799 */
1800 if (be_lun->dev_path[0] != '/') {
1801 char *dev_path = "/dev/";
1802 char *dev_name;
1803
1804 /* Try adding device path at beginning of name */
1805 dev_name = malloc(strlen(be_lun->dev_path)
1806 + strlen(dev_path) + 1,
1807 M_CTLBLK, M_WAITOK);
1808 if (dev_name) {
1809 sprintf(dev_name, "%s%s", dev_path,
1810 be_lun->dev_path);
1811 free(be_lun->dev_path, M_CTLBLK);
1812 be_lun->dev_path = dev_name;
1813 goto again;
1814 }
1815 }
1816 snprintf(req->error_str, sizeof(req->error_str),
1817 "%s: error opening %s", __func__, be_lun->dev_path);
1818 return (error);
1819 }
1820
1821 NDFREE(&nd, NDF_ONLY_PNBUF);
1822
1823 be_lun->vn = nd.ni_vp;
1824
1825 /* We only support disks and files. */
1826 if (vn_isdisk(be_lun->vn, &error)) {
1827 error = ctl_be_block_open_dev(be_lun, req);
1828 } else if (be_lun->vn->v_type == VREG) {
1829 error = ctl_be_block_open_file(be_lun, req);
1830 } else {
1831 error = EINVAL;
1832 snprintf(req->error_str, sizeof(req->error_str),
1833 "%s is not a disk or plain file", be_lun->dev_path);
1834 }
1835 VOP_UNLOCK(be_lun->vn, 0);
1836
1837 if (error != 0) {
1838 ctl_be_block_close(be_lun);
1839 return (error);
1840 }
1841
1842 be_lun->blocksize_shift = fls(be_lun->blocksize) - 1;
1843 be_lun->size_blocks = be_lun->size_bytes >> be_lun->blocksize_shift;
1844
1845 return (0);
1846}
1847
1848static int
1849ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
1850{
1851 struct ctl_be_block_lun *be_lun;
1852 struct ctl_lun_create_params *params;
1853 char num_thread_str[16];
1854 char tmpstr[32];
1855 char *value;
1856 int retval, num_threads, unmap;
1857 int tmp_num_threads;
1858
1859 params = &req->reqdata.create;
1860 retval = 0;
1861
1862 num_threads = cbb_num_threads;
1863
1864 be_lun = malloc(sizeof(*be_lun), M_CTLBLK, M_ZERO | M_WAITOK);
1865
1866 be_lun->softc = softc;
1867 STAILQ_INIT(&be_lun->input_queue);
1868 STAILQ_INIT(&be_lun->config_write_queue);
1869 STAILQ_INIT(&be_lun->datamove_queue);
1870 sprintf(be_lun->lunname, "cblk%d", softc->num_luns);
1436 taskqueue_enqueue(be_lun->io_taskqueue, &be_lun->io_task);
1437
1438 return (CTL_RETVAL_COMPLETE);
1439}
1440
1441static int
1442ctl_be_block_ioctl(struct cdev *dev, u_long cmd, caddr_t addr,
1443 int flag, struct thread *td)
1444{
1445 struct ctl_be_block_softc *softc;
1446 int error;
1447
1448 softc = &backend_block_softc;
1449
1450 error = 0;
1451
1452 switch (cmd) {
1453 case CTL_LUN_REQ: {
1454 struct ctl_lun_req *lun_req;
1455
1456 lun_req = (struct ctl_lun_req *)addr;
1457
1458 switch (lun_req->reqtype) {
1459 case CTL_LUNREQ_CREATE:
1460 error = ctl_be_block_create(softc, lun_req);
1461 break;
1462 case CTL_LUNREQ_RM:
1463 error = ctl_be_block_rm(softc, lun_req);
1464 break;
1465 case CTL_LUNREQ_MODIFY:
1466 error = ctl_be_block_modify(softc, lun_req);
1467 break;
1468 default:
1469 lun_req->status = CTL_LUN_ERROR;
1470 snprintf(lun_req->error_str, sizeof(lun_req->error_str),
1471 "%s: invalid LUN request type %d", __func__,
1472 lun_req->reqtype);
1473 break;
1474 }
1475 break;
1476 }
1477 default:
1478 error = ENOTTY;
1479 break;
1480 }
1481
1482 return (error);
1483}
1484
1485static int
1486ctl_be_block_open_file(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
1487{
1488 struct ctl_be_block_filedata *file_data;
1489 struct ctl_lun_create_params *params;
1490 struct vattr vattr;
1491 int error;
1492
1493 error = 0;
1494 file_data = &be_lun->backend.file;
1495 params = &req->reqdata.create;
1496
1497 be_lun->dev_type = CTL_BE_BLOCK_FILE;
1498 be_lun->dispatch = ctl_be_block_dispatch_file;
1499 be_lun->lun_flush = ctl_be_block_flush_file;
1500
1501 error = VOP_GETATTR(be_lun->vn, &vattr, curthread->td_ucred);
1502 if (error != 0) {
1503 snprintf(req->error_str, sizeof(req->error_str),
1504 "error calling VOP_GETATTR() for file %s",
1505 be_lun->dev_path);
1506 return (error);
1507 }
1508
1509 /*
1510 * Verify that we have the ability to upgrade to exclusive
1511 * access on this file so we can trap errors at open instead
1512 * of reporting them during first access.
1513 */
1514 if (VOP_ISLOCKED(be_lun->vn) != LK_EXCLUSIVE) {
1515 vn_lock(be_lun->vn, LK_UPGRADE | LK_RETRY);
1516 if (be_lun->vn->v_iflag & VI_DOOMED) {
1517 error = EBADF;
1518 snprintf(req->error_str, sizeof(req->error_str),
1519 "error locking file %s", be_lun->dev_path);
1520 return (error);
1521 }
1522 }
1523
1524
1525 file_data->cred = crhold(curthread->td_ucred);
1526 if (params->lun_size_bytes != 0)
1527 be_lun->size_bytes = params->lun_size_bytes;
1528 else
1529 be_lun->size_bytes = vattr.va_size;
1530 /*
1531 * We set the multi thread flag for file operations because all
1532 * filesystems (in theory) are capable of allowing multiple readers
1533 * of a file at once. So we want to get the maximum possible
1534 * concurrency.
1535 */
1536 be_lun->flags |= CTL_BE_BLOCK_LUN_MULTI_THREAD;
1537
1538 /*
1539 * XXX KDM vattr.va_blocksize may be larger than 512 bytes here.
1540 * With ZFS, it is 131072 bytes. Block sizes that large don't work
1541 * with disklabel and UFS on FreeBSD at least. Large block sizes
1542 * may not work with other OSes as well. So just export a sector
1543 * size of 512 bytes, which should work with any OS or
1544 * application. Since our backing is a file, any block size will
1545 * work fine for the backing store.
1546 */
1547#if 0
1548 be_lun->blocksize= vattr.va_blocksize;
1549#endif
1550 if (params->blocksize_bytes != 0)
1551 be_lun->blocksize = params->blocksize_bytes;
1552 else
1553 be_lun->blocksize = 512;
1554
1555 /*
1556 * Sanity check. The media size has to be at least one
1557 * sector long.
1558 */
1559 if (be_lun->size_bytes < be_lun->blocksize) {
1560 error = EINVAL;
1561 snprintf(req->error_str, sizeof(req->error_str),
1562 "file %s size %ju < block size %u", be_lun->dev_path,
1563 (uintmax_t)be_lun->size_bytes, be_lun->blocksize);
1564 }
1565 return (error);
1566}
1567
1568static int
1569ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
1570{
1571 struct ctl_lun_create_params *params;
1572 struct vattr vattr;
1573 struct cdev *dev;
1574 struct cdevsw *devsw;
1575 int error;
1576 off_t ps, pss, po, pos;
1577
1578 params = &req->reqdata.create;
1579
1580 be_lun->dev_type = CTL_BE_BLOCK_DEV;
1581 be_lun->dispatch = ctl_be_block_dispatch_dev;
1582 be_lun->lun_flush = ctl_be_block_flush_dev;
1583 be_lun->unmap = ctl_be_block_unmap_dev;
1584 be_lun->backend.dev.cdev = be_lun->vn->v_rdev;
1585 be_lun->backend.dev.csw = dev_refthread(be_lun->backend.dev.cdev,
1586 &be_lun->backend.dev.dev_ref);
1587 if (be_lun->backend.dev.csw == NULL)
1588 panic("Unable to retrieve device switch");
1589
1590 error = VOP_GETATTR(be_lun->vn, &vattr, NOCRED);
1591 if (error) {
1592 snprintf(req->error_str, sizeof(req->error_str),
1593 "%s: error getting vnode attributes for device %s",
1594 __func__, be_lun->dev_path);
1595 return (error);
1596 }
1597
1598 dev = be_lun->vn->v_rdev;
1599 devsw = dev->si_devsw;
1600 if (!devsw->d_ioctl) {
1601 snprintf(req->error_str, sizeof(req->error_str),
1602 "%s: no d_ioctl for device %s!", __func__,
1603 be_lun->dev_path);
1604 return (ENODEV);
1605 }
1606
1607 error = devsw->d_ioctl(dev, DIOCGSECTORSIZE,
1608 (caddr_t)&be_lun->blocksize, FREAD,
1609 curthread);
1610 if (error) {
1611 snprintf(req->error_str, sizeof(req->error_str),
1612 "%s: error %d returned for DIOCGSECTORSIZE ioctl "
1613 "on %s!", __func__, error, be_lun->dev_path);
1614 return (error);
1615 }
1616
1617 /*
1618 * If the user has asked for a blocksize that is greater than the
1619 * backing device's blocksize, we can do it only if the blocksize
1620 * the user is asking for is an even multiple of the underlying
1621 * device's blocksize.
1622 */
1623 if ((params->blocksize_bytes != 0)
1624 && (params->blocksize_bytes > be_lun->blocksize)) {
1625 uint32_t bs_multiple, tmp_blocksize;
1626
1627 bs_multiple = params->blocksize_bytes / be_lun->blocksize;
1628
1629 tmp_blocksize = bs_multiple * be_lun->blocksize;
1630
1631 if (tmp_blocksize == params->blocksize_bytes) {
1632 be_lun->blocksize = params->blocksize_bytes;
1633 } else {
1634 snprintf(req->error_str, sizeof(req->error_str),
1635 "%s: requested blocksize %u is not an even "
1636 "multiple of backing device blocksize %u",
1637 __func__, params->blocksize_bytes,
1638 be_lun->blocksize);
1639 return (EINVAL);
1640
1641 }
1642 } else if ((params->blocksize_bytes != 0)
1643 && (params->blocksize_bytes != be_lun->blocksize)) {
1644 snprintf(req->error_str, sizeof(req->error_str),
1645 "%s: requested blocksize %u < backing device "
1646 "blocksize %u", __func__, params->blocksize_bytes,
1647 be_lun->blocksize);
1648 return (EINVAL);
1649 }
1650
1651 error = devsw->d_ioctl(dev, DIOCGMEDIASIZE,
1652 (caddr_t)&be_lun->size_bytes, FREAD,
1653 curthread);
1654 if (error) {
1655 snprintf(req->error_str, sizeof(req->error_str),
1656 "%s: error %d returned for DIOCGMEDIASIZE "
1657 " ioctl on %s!", __func__, error,
1658 be_lun->dev_path);
1659 return (error);
1660 }
1661
1662 if (params->lun_size_bytes != 0) {
1663 if (params->lun_size_bytes > be_lun->size_bytes) {
1664 snprintf(req->error_str, sizeof(req->error_str),
1665 "%s: requested LUN size %ju > backing device "
1666 "size %ju", __func__,
1667 (uintmax_t)params->lun_size_bytes,
1668 (uintmax_t)be_lun->size_bytes);
1669 return (EINVAL);
1670 }
1671
1672 be_lun->size_bytes = params->lun_size_bytes;
1673 }
1674
1675 error = devsw->d_ioctl(dev, DIOCGSTRIPESIZE,
1676 (caddr_t)&ps, FREAD, curthread);
1677 if (error)
1678 ps = po = 0;
1679 else {
1680 error = devsw->d_ioctl(dev, DIOCGSTRIPEOFFSET,
1681 (caddr_t)&po, FREAD, curthread);
1682 if (error)
1683 po = 0;
1684 }
1685 pss = ps / be_lun->blocksize;
1686 pos = po / be_lun->blocksize;
1687 if ((pss > 0) && (pss * be_lun->blocksize == ps) && (pss >= pos) &&
1688 ((pss & (pss - 1)) == 0) && (pos * be_lun->blocksize == po)) {
1689 be_lun->pblockexp = fls(pss) - 1;
1690 be_lun->pblockoff = (pss - pos) % pss;
1691 }
1692
1693 return (0);
1694}
1695
1696static int
1697ctl_be_block_close(struct ctl_be_block_lun *be_lun)
1698{
1699 DROP_GIANT();
1700 if (be_lun->vn) {
1701 int flags = FREAD | FWRITE;
1702
1703 switch (be_lun->dev_type) {
1704 case CTL_BE_BLOCK_DEV:
1705 if (be_lun->backend.dev.csw) {
1706 dev_relthread(be_lun->backend.dev.cdev,
1707 be_lun->backend.dev.dev_ref);
1708 be_lun->backend.dev.csw = NULL;
1709 be_lun->backend.dev.cdev = NULL;
1710 }
1711 break;
1712 case CTL_BE_BLOCK_FILE:
1713 break;
1714 case CTL_BE_BLOCK_NONE:
1715 break;
1716 default:
1717 panic("Unexpected backend type.");
1718 break;
1719 }
1720
1721 (void)vn_close(be_lun->vn, flags, NOCRED, curthread);
1722 be_lun->vn = NULL;
1723
1724 switch (be_lun->dev_type) {
1725 case CTL_BE_BLOCK_DEV:
1726 break;
1727 case CTL_BE_BLOCK_FILE:
1728 if (be_lun->backend.file.cred != NULL) {
1729 crfree(be_lun->backend.file.cred);
1730 be_lun->backend.file.cred = NULL;
1731 }
1732 break;
1733 case CTL_BE_BLOCK_NONE:
1734 break;
1735 default:
1736 panic("Unexpected backend type.");
1737 break;
1738 }
1739 }
1740 PICKUP_GIANT();
1741
1742 return (0);
1743}
1744
1745static int
1746ctl_be_block_open(struct ctl_be_block_softc *softc,
1747 struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
1748{
1749 struct nameidata nd;
1750 int flags;
1751 int error;
1752
1753 /*
1754 * XXX KDM allow a read-only option?
1755 */
1756 flags = FREAD | FWRITE;
1757 error = 0;
1758
1759 if (rootvnode == NULL) {
1760 snprintf(req->error_str, sizeof(req->error_str),
1761 "%s: Root filesystem is not mounted", __func__);
1762 return (1);
1763 }
1764
1765 if (!curthread->td_proc->p_fd->fd_cdir) {
1766 curthread->td_proc->p_fd->fd_cdir = rootvnode;
1767 VREF(rootvnode);
1768 }
1769 if (!curthread->td_proc->p_fd->fd_rdir) {
1770 curthread->td_proc->p_fd->fd_rdir = rootvnode;
1771 VREF(rootvnode);
1772 }
1773 if (!curthread->td_proc->p_fd->fd_jdir) {
1774 curthread->td_proc->p_fd->fd_jdir = rootvnode;
1775 VREF(rootvnode);
1776 }
1777
1778 again:
1779 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, be_lun->dev_path, curthread);
1780 error = vn_open(&nd, &flags, 0, NULL);
1781 if (error) {
1782 /*
1783 * This is the only reasonable guess we can make as far as
1784 * path if the user doesn't give us a fully qualified path.
1785 * If they want to specify a file, they need to specify the
1786 * full path.
1787 */
1788 if (be_lun->dev_path[0] != '/') {
1789 char *dev_path = "/dev/";
1790 char *dev_name;
1791
1792 /* Try adding device path at beginning of name */
1793 dev_name = malloc(strlen(be_lun->dev_path)
1794 + strlen(dev_path) + 1,
1795 M_CTLBLK, M_WAITOK);
1796 if (dev_name) {
1797 sprintf(dev_name, "%s%s", dev_path,
1798 be_lun->dev_path);
1799 free(be_lun->dev_path, M_CTLBLK);
1800 be_lun->dev_path = dev_name;
1801 goto again;
1802 }
1803 }
1804 snprintf(req->error_str, sizeof(req->error_str),
1805 "%s: error opening %s", __func__, be_lun->dev_path);
1806 return (error);
1807 }
1808
1809 NDFREE(&nd, NDF_ONLY_PNBUF);
1810
1811 be_lun->vn = nd.ni_vp;
1812
1813 /* We only support disks and files. */
1814 if (vn_isdisk(be_lun->vn, &error)) {
1815 error = ctl_be_block_open_dev(be_lun, req);
1816 } else if (be_lun->vn->v_type == VREG) {
1817 error = ctl_be_block_open_file(be_lun, req);
1818 } else {
1819 error = EINVAL;
1820 snprintf(req->error_str, sizeof(req->error_str),
1821 "%s is not a disk or plain file", be_lun->dev_path);
1822 }
1823 VOP_UNLOCK(be_lun->vn, 0);
1824
1825 if (error != 0) {
1826 ctl_be_block_close(be_lun);
1827 return (error);
1828 }
1829
1830 be_lun->blocksize_shift = fls(be_lun->blocksize) - 1;
1831 be_lun->size_blocks = be_lun->size_bytes >> be_lun->blocksize_shift;
1832
1833 return (0);
1834}
1835
1836static int
1837ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
1838{
1839 struct ctl_be_block_lun *be_lun;
1840 struct ctl_lun_create_params *params;
1841 char num_thread_str[16];
1842 char tmpstr[32];
1843 char *value;
1844 int retval, num_threads, unmap;
1845 int tmp_num_threads;
1846
1847 params = &req->reqdata.create;
1848 retval = 0;
1849
1850 num_threads = cbb_num_threads;
1851
1852 be_lun = malloc(sizeof(*be_lun), M_CTLBLK, M_ZERO | M_WAITOK);
1853
1854 be_lun->softc = softc;
1855 STAILQ_INIT(&be_lun->input_queue);
1856 STAILQ_INIT(&be_lun->config_write_queue);
1857 STAILQ_INIT(&be_lun->datamove_queue);
1858 sprintf(be_lun->lunname, "cblk%d", softc->num_luns);
1871 mtx_init(&be_lun->lock, be_lun->lunname, NULL, MTX_DEF);
1859 mtx_init(&be_lun->io_lock, "cblk io lock", NULL, MTX_DEF);
1860 mtx_init(&be_lun->queue_lock, "cblk queue lock", NULL, MTX_DEF);
1872 ctl_init_opts(&be_lun->ctl_be_lun, req);
1873
1874 be_lun->lun_zone = uma_zcreate(be_lun->lunname, CTLBLK_MAX_SEG,
1875 NULL, NULL, NULL, NULL, /*align*/ 0, /*flags*/0);
1876
1877 if (be_lun->lun_zone == NULL) {
1878 snprintf(req->error_str, sizeof(req->error_str),
1879 "%s: error allocating UMA zone", __func__);
1880 goto bailout_error;
1881 }
1882
1883 if (params->flags & CTL_LUN_FLAG_DEV_TYPE)
1884 be_lun->ctl_be_lun.lun_type = params->device_type;
1885 else
1886 be_lun->ctl_be_lun.lun_type = T_DIRECT;
1887
1888 if (be_lun->ctl_be_lun.lun_type == T_DIRECT) {
1889 value = ctl_get_opt(&be_lun->ctl_be_lun, "file");
1890 if (value == NULL) {
1891 snprintf(req->error_str, sizeof(req->error_str),
1892 "%s: no file argument specified", __func__);
1893 goto bailout_error;
1894 }
1895 be_lun->dev_path = strdup(value, M_CTLBLK);
1896
1897 retval = ctl_be_block_open(softc, be_lun, req);
1898 if (retval != 0) {
1899 retval = 0;
1900 goto bailout_error;
1901 }
1902
1903 /*
1904 * Tell the user the size of the file/device.
1905 */
1906 params->lun_size_bytes = be_lun->size_bytes;
1907
1908 /*
1909 * The maximum LBA is the size - 1.
1910 */
1911 be_lun->ctl_be_lun.maxlba = be_lun->size_blocks - 1;
1912 } else {
1913 /*
1914 * For processor devices, we don't have any size.
1915 */
1916 be_lun->blocksize = 0;
1917 be_lun->pblockexp = 0;
1918 be_lun->pblockoff = 0;
1919 be_lun->size_blocks = 0;
1920 be_lun->size_bytes = 0;
1921 be_lun->ctl_be_lun.maxlba = 0;
1922 params->lun_size_bytes = 0;
1923
1924 /*
1925 * Default to just 1 thread for processor devices.
1926 */
1927 num_threads = 1;
1928 }
1929
1930 /*
1931 * XXX This searching loop might be refactored to be combined with
1932 * the loop above,
1933 */
1934 value = ctl_get_opt(&be_lun->ctl_be_lun, "num_threads");
1935 if (value != NULL) {
1936 tmp_num_threads = strtol(value, NULL, 0);
1937
1938 /*
1939 * We don't let the user specify less than one
1940 * thread, but hope he's clueful enough not to
1941 * specify 1000 threads.
1942 */
1943 if (tmp_num_threads < 1) {
1944 snprintf(req->error_str, sizeof(req->error_str),
1945 "%s: invalid number of threads %s",
1946 __func__, num_thread_str);
1947 goto bailout_error;
1948 }
1949 num_threads = tmp_num_threads;
1950 }
1951 unmap = 0;
1952 value = ctl_get_opt(&be_lun->ctl_be_lun, "unmap");
1953 if (value != NULL && strcmp(value, "on") == 0)
1954 unmap = 1;
1955
1956 be_lun->flags = CTL_BE_BLOCK_LUN_UNCONFIGURED;
1957 be_lun->ctl_be_lun.flags = CTL_LUN_FLAG_PRIMARY;
1958 if (unmap)
1959 be_lun->ctl_be_lun.flags |= CTL_LUN_FLAG_UNMAP;
1960 be_lun->ctl_be_lun.be_lun = be_lun;
1961 be_lun->ctl_be_lun.blocksize = be_lun->blocksize;
1962 be_lun->ctl_be_lun.pblockexp = be_lun->pblockexp;
1963 be_lun->ctl_be_lun.pblockoff = be_lun->pblockoff;
1964 /* Tell the user the blocksize we ended up using */
1965 params->blocksize_bytes = be_lun->blocksize;
1966 if (params->flags & CTL_LUN_FLAG_ID_REQ) {
1967 be_lun->ctl_be_lun.req_lun_id = params->req_lun_id;
1968 be_lun->ctl_be_lun.flags |= CTL_LUN_FLAG_ID_REQ;
1969 } else
1970 be_lun->ctl_be_lun.req_lun_id = 0;
1971
1972 be_lun->ctl_be_lun.lun_shutdown = ctl_be_block_lun_shutdown;
1973 be_lun->ctl_be_lun.lun_config_status =
1974 ctl_be_block_lun_config_status;
1975 be_lun->ctl_be_lun.be = &ctl_be_block_driver;
1976
1977 if ((params->flags & CTL_LUN_FLAG_SERIAL_NUM) == 0) {
1978 snprintf(tmpstr, sizeof(tmpstr), "MYSERIAL%4d",
1979 softc->num_luns);
1980 strncpy((char *)be_lun->ctl_be_lun.serial_num, tmpstr,
1981 ctl_min(sizeof(be_lun->ctl_be_lun.serial_num),
1982 sizeof(tmpstr)));
1983
1984 /* Tell the user what we used for a serial number */
1985 strncpy((char *)params->serial_num, tmpstr,
1986 ctl_min(sizeof(params->serial_num), sizeof(tmpstr)));
1987 } else {
1988 strncpy((char *)be_lun->ctl_be_lun.serial_num,
1989 params->serial_num,
1990 ctl_min(sizeof(be_lun->ctl_be_lun.serial_num),
1991 sizeof(params->serial_num)));
1992 }
1993 if ((params->flags & CTL_LUN_FLAG_DEVID) == 0) {
1994 snprintf(tmpstr, sizeof(tmpstr), "MYDEVID%4d", softc->num_luns);
1995 strncpy((char *)be_lun->ctl_be_lun.device_id, tmpstr,
1996 ctl_min(sizeof(be_lun->ctl_be_lun.device_id),
1997 sizeof(tmpstr)));
1998
1999 /* Tell the user what we used for a device ID */
2000 strncpy((char *)params->device_id, tmpstr,
2001 ctl_min(sizeof(params->device_id), sizeof(tmpstr)));
2002 } else {
2003 strncpy((char *)be_lun->ctl_be_lun.device_id,
2004 params->device_id,
2005 ctl_min(sizeof(be_lun->ctl_be_lun.device_id),
2006 sizeof(params->device_id)));
2007 }
2008
2009 TASK_INIT(&be_lun->io_task, /*priority*/0, ctl_be_block_worker, be_lun);
2010
2011 be_lun->io_taskqueue = taskqueue_create(be_lun->lunname, M_WAITOK,
2012 taskqueue_thread_enqueue, /*context*/&be_lun->io_taskqueue);
2013
2014 if (be_lun->io_taskqueue == NULL) {
2015 snprintf(req->error_str, sizeof(req->error_str),
2016 "%s: Unable to create taskqueue", __func__);
2017 goto bailout_error;
2018 }
2019
2020 /*
2021 * Note that we start the same number of threads by default for
2022 * both the file case and the block device case. For the file
2023 * case, we need multiple threads to allow concurrency, because the
2024 * vnode interface is designed to be a blocking interface. For the
2025 * block device case, ZFS zvols at least will block the caller's
2026 * context in many instances, and so we need multiple threads to
2027 * overcome that problem. Other block devices don't need as many
2028 * threads, but they shouldn't cause too many problems.
2029 *
2030 * If the user wants to just have a single thread for a block
2031 * device, he can specify that when the LUN is created, or change
2032 * the tunable/sysctl to alter the default number of threads.
2033 */
2034 retval = taskqueue_start_threads(&be_lun->io_taskqueue,
2035 /*num threads*/num_threads,
2036 /*priority*/PWAIT,
2037 /*thread name*/
2038 "%s taskq", be_lun->lunname);
2039
2040 if (retval != 0)
2041 goto bailout_error;
2042
2043 be_lun->num_threads = num_threads;
2044
2045 mtx_lock(&softc->lock);
2046 softc->num_luns++;
2047 STAILQ_INSERT_TAIL(&softc->lun_list, be_lun, links);
2048
2049 mtx_unlock(&softc->lock);
2050
2051 retval = ctl_add_lun(&be_lun->ctl_be_lun);
2052 if (retval != 0) {
2053 mtx_lock(&softc->lock);
2054 STAILQ_REMOVE(&softc->lun_list, be_lun, ctl_be_block_lun,
2055 links);
2056 softc->num_luns--;
2057 mtx_unlock(&softc->lock);
2058 snprintf(req->error_str, sizeof(req->error_str),
2059 "%s: ctl_add_lun() returned error %d, see dmesg for "
2060 "details", __func__, retval);
2061 retval = 0;
2062 goto bailout_error;
2063 }
2064
2065 mtx_lock(&softc->lock);
2066
2067 /*
2068 * Tell the config_status routine that we're waiting so it won't
2069 * clean up the LUN in the event of an error.
2070 */
2071 be_lun->flags |= CTL_BE_BLOCK_LUN_WAITING;
2072
2073 while (be_lun->flags & CTL_BE_BLOCK_LUN_UNCONFIGURED) {
2074 retval = msleep(be_lun, &softc->lock, PCATCH, "ctlblk", 0);
2075 if (retval == EINTR)
2076 break;
2077 }
2078 be_lun->flags &= ~CTL_BE_BLOCK_LUN_WAITING;
2079
2080 if (be_lun->flags & CTL_BE_BLOCK_LUN_CONFIG_ERR) {
2081 snprintf(req->error_str, sizeof(req->error_str),
2082 "%s: LUN configuration error, see dmesg for details",
2083 __func__);
2084 STAILQ_REMOVE(&softc->lun_list, be_lun, ctl_be_block_lun,
2085 links);
2086 softc->num_luns--;
2087 mtx_unlock(&softc->lock);
2088 goto bailout_error;
2089 } else {
2090 params->req_lun_id = be_lun->ctl_be_lun.lun_id;
2091 }
2092
2093 mtx_unlock(&softc->lock);
2094
2095 be_lun->disk_stats = devstat_new_entry("cbb", params->req_lun_id,
2096 be_lun->blocksize,
2097 DEVSTAT_ALL_SUPPORTED,
2098 be_lun->ctl_be_lun.lun_type
2099 | DEVSTAT_TYPE_IF_OTHER,
2100 DEVSTAT_PRIORITY_OTHER);
2101
2102
2103 req->status = CTL_LUN_OK;
2104
2105 return (retval);
2106
2107bailout_error:
2108 req->status = CTL_LUN_ERROR;
2109
2110 if (be_lun->io_taskqueue != NULL)
2111 taskqueue_free(be_lun->io_taskqueue);
2112 ctl_be_block_close(be_lun);
2113 if (be_lun->dev_path != NULL)
2114 free(be_lun->dev_path, M_CTLBLK);
2115 if (be_lun->lun_zone != NULL)
2116 uma_zdestroy(be_lun->lun_zone);
2117 ctl_free_opts(&be_lun->ctl_be_lun);
1861 ctl_init_opts(&be_lun->ctl_be_lun, req);
1862
1863 be_lun->lun_zone = uma_zcreate(be_lun->lunname, CTLBLK_MAX_SEG,
1864 NULL, NULL, NULL, NULL, /*align*/ 0, /*flags*/0);
1865
1866 if (be_lun->lun_zone == NULL) {
1867 snprintf(req->error_str, sizeof(req->error_str),
1868 "%s: error allocating UMA zone", __func__);
1869 goto bailout_error;
1870 }
1871
1872 if (params->flags & CTL_LUN_FLAG_DEV_TYPE)
1873 be_lun->ctl_be_lun.lun_type = params->device_type;
1874 else
1875 be_lun->ctl_be_lun.lun_type = T_DIRECT;
1876
1877 if (be_lun->ctl_be_lun.lun_type == T_DIRECT) {
1878 value = ctl_get_opt(&be_lun->ctl_be_lun, "file");
1879 if (value == NULL) {
1880 snprintf(req->error_str, sizeof(req->error_str),
1881 "%s: no file argument specified", __func__);
1882 goto bailout_error;
1883 }
1884 be_lun->dev_path = strdup(value, M_CTLBLK);
1885
1886 retval = ctl_be_block_open(softc, be_lun, req);
1887 if (retval != 0) {
1888 retval = 0;
1889 goto bailout_error;
1890 }
1891
1892 /*
1893 * Tell the user the size of the file/device.
1894 */
1895 params->lun_size_bytes = be_lun->size_bytes;
1896
1897 /*
1898 * The maximum LBA is the size - 1.
1899 */
1900 be_lun->ctl_be_lun.maxlba = be_lun->size_blocks - 1;
1901 } else {
1902 /*
1903 * For processor devices, we don't have any size.
1904 */
1905 be_lun->blocksize = 0;
1906 be_lun->pblockexp = 0;
1907 be_lun->pblockoff = 0;
1908 be_lun->size_blocks = 0;
1909 be_lun->size_bytes = 0;
1910 be_lun->ctl_be_lun.maxlba = 0;
1911 params->lun_size_bytes = 0;
1912
1913 /*
1914 * Default to just 1 thread for processor devices.
1915 */
1916 num_threads = 1;
1917 }
1918
1919 /*
1920 * XXX This searching loop might be refactored to be combined with
1921 * the loop above,
1922 */
1923 value = ctl_get_opt(&be_lun->ctl_be_lun, "num_threads");
1924 if (value != NULL) {
1925 tmp_num_threads = strtol(value, NULL, 0);
1926
1927 /*
1928 * We don't let the user specify less than one
1929 * thread, but hope he's clueful enough not to
1930 * specify 1000 threads.
1931 */
1932 if (tmp_num_threads < 1) {
1933 snprintf(req->error_str, sizeof(req->error_str),
1934 "%s: invalid number of threads %s",
1935 __func__, num_thread_str);
1936 goto bailout_error;
1937 }
1938 num_threads = tmp_num_threads;
1939 }
1940 unmap = 0;
1941 value = ctl_get_opt(&be_lun->ctl_be_lun, "unmap");
1942 if (value != NULL && strcmp(value, "on") == 0)
1943 unmap = 1;
1944
1945 be_lun->flags = CTL_BE_BLOCK_LUN_UNCONFIGURED;
1946 be_lun->ctl_be_lun.flags = CTL_LUN_FLAG_PRIMARY;
1947 if (unmap)
1948 be_lun->ctl_be_lun.flags |= CTL_LUN_FLAG_UNMAP;
1949 be_lun->ctl_be_lun.be_lun = be_lun;
1950 be_lun->ctl_be_lun.blocksize = be_lun->blocksize;
1951 be_lun->ctl_be_lun.pblockexp = be_lun->pblockexp;
1952 be_lun->ctl_be_lun.pblockoff = be_lun->pblockoff;
1953 /* Tell the user the blocksize we ended up using */
1954 params->blocksize_bytes = be_lun->blocksize;
1955 if (params->flags & CTL_LUN_FLAG_ID_REQ) {
1956 be_lun->ctl_be_lun.req_lun_id = params->req_lun_id;
1957 be_lun->ctl_be_lun.flags |= CTL_LUN_FLAG_ID_REQ;
1958 } else
1959 be_lun->ctl_be_lun.req_lun_id = 0;
1960
1961 be_lun->ctl_be_lun.lun_shutdown = ctl_be_block_lun_shutdown;
1962 be_lun->ctl_be_lun.lun_config_status =
1963 ctl_be_block_lun_config_status;
1964 be_lun->ctl_be_lun.be = &ctl_be_block_driver;
1965
1966 if ((params->flags & CTL_LUN_FLAG_SERIAL_NUM) == 0) {
1967 snprintf(tmpstr, sizeof(tmpstr), "MYSERIAL%4d",
1968 softc->num_luns);
1969 strncpy((char *)be_lun->ctl_be_lun.serial_num, tmpstr,
1970 ctl_min(sizeof(be_lun->ctl_be_lun.serial_num),
1971 sizeof(tmpstr)));
1972
1973 /* Tell the user what we used for a serial number */
1974 strncpy((char *)params->serial_num, tmpstr,
1975 ctl_min(sizeof(params->serial_num), sizeof(tmpstr)));
1976 } else {
1977 strncpy((char *)be_lun->ctl_be_lun.serial_num,
1978 params->serial_num,
1979 ctl_min(sizeof(be_lun->ctl_be_lun.serial_num),
1980 sizeof(params->serial_num)));
1981 }
1982 if ((params->flags & CTL_LUN_FLAG_DEVID) == 0) {
1983 snprintf(tmpstr, sizeof(tmpstr), "MYDEVID%4d", softc->num_luns);
1984 strncpy((char *)be_lun->ctl_be_lun.device_id, tmpstr,
1985 ctl_min(sizeof(be_lun->ctl_be_lun.device_id),
1986 sizeof(tmpstr)));
1987
1988 /* Tell the user what we used for a device ID */
1989 strncpy((char *)params->device_id, tmpstr,
1990 ctl_min(sizeof(params->device_id), sizeof(tmpstr)));
1991 } else {
1992 strncpy((char *)be_lun->ctl_be_lun.device_id,
1993 params->device_id,
1994 ctl_min(sizeof(be_lun->ctl_be_lun.device_id),
1995 sizeof(params->device_id)));
1996 }
1997
1998 TASK_INIT(&be_lun->io_task, /*priority*/0, ctl_be_block_worker, be_lun);
1999
2000 be_lun->io_taskqueue = taskqueue_create(be_lun->lunname, M_WAITOK,
2001 taskqueue_thread_enqueue, /*context*/&be_lun->io_taskqueue);
2002
2003 if (be_lun->io_taskqueue == NULL) {
2004 snprintf(req->error_str, sizeof(req->error_str),
2005 "%s: Unable to create taskqueue", __func__);
2006 goto bailout_error;
2007 }
2008
2009 /*
2010 * Note that we start the same number of threads by default for
2011 * both the file case and the block device case. For the file
2012 * case, we need multiple threads to allow concurrency, because the
2013 * vnode interface is designed to be a blocking interface. For the
2014 * block device case, ZFS zvols at least will block the caller's
2015 * context in many instances, and so we need multiple threads to
2016 * overcome that problem. Other block devices don't need as many
2017 * threads, but they shouldn't cause too many problems.
2018 *
2019 * If the user wants to just have a single thread for a block
2020 * device, he can specify that when the LUN is created, or change
2021 * the tunable/sysctl to alter the default number of threads.
2022 */
2023 retval = taskqueue_start_threads(&be_lun->io_taskqueue,
2024 /*num threads*/num_threads,
2025 /*priority*/PWAIT,
2026 /*thread name*/
2027 "%s taskq", be_lun->lunname);
2028
2029 if (retval != 0)
2030 goto bailout_error;
2031
2032 be_lun->num_threads = num_threads;
2033
2034 mtx_lock(&softc->lock);
2035 softc->num_luns++;
2036 STAILQ_INSERT_TAIL(&softc->lun_list, be_lun, links);
2037
2038 mtx_unlock(&softc->lock);
2039
2040 retval = ctl_add_lun(&be_lun->ctl_be_lun);
2041 if (retval != 0) {
2042 mtx_lock(&softc->lock);
2043 STAILQ_REMOVE(&softc->lun_list, be_lun, ctl_be_block_lun,
2044 links);
2045 softc->num_luns--;
2046 mtx_unlock(&softc->lock);
2047 snprintf(req->error_str, sizeof(req->error_str),
2048 "%s: ctl_add_lun() returned error %d, see dmesg for "
2049 "details", __func__, retval);
2050 retval = 0;
2051 goto bailout_error;
2052 }
2053
2054 mtx_lock(&softc->lock);
2055
2056 /*
2057 * Tell the config_status routine that we're waiting so it won't
2058 * clean up the LUN in the event of an error.
2059 */
2060 be_lun->flags |= CTL_BE_BLOCK_LUN_WAITING;
2061
2062 while (be_lun->flags & CTL_BE_BLOCK_LUN_UNCONFIGURED) {
2063 retval = msleep(be_lun, &softc->lock, PCATCH, "ctlblk", 0);
2064 if (retval == EINTR)
2065 break;
2066 }
2067 be_lun->flags &= ~CTL_BE_BLOCK_LUN_WAITING;
2068
2069 if (be_lun->flags & CTL_BE_BLOCK_LUN_CONFIG_ERR) {
2070 snprintf(req->error_str, sizeof(req->error_str),
2071 "%s: LUN configuration error, see dmesg for details",
2072 __func__);
2073 STAILQ_REMOVE(&softc->lun_list, be_lun, ctl_be_block_lun,
2074 links);
2075 softc->num_luns--;
2076 mtx_unlock(&softc->lock);
2077 goto bailout_error;
2078 } else {
2079 params->req_lun_id = be_lun->ctl_be_lun.lun_id;
2080 }
2081
2082 mtx_unlock(&softc->lock);
2083
2084 be_lun->disk_stats = devstat_new_entry("cbb", params->req_lun_id,
2085 be_lun->blocksize,
2086 DEVSTAT_ALL_SUPPORTED,
2087 be_lun->ctl_be_lun.lun_type
2088 | DEVSTAT_TYPE_IF_OTHER,
2089 DEVSTAT_PRIORITY_OTHER);
2090
2091
2092 req->status = CTL_LUN_OK;
2093
2094 return (retval);
2095
2096bailout_error:
2097 req->status = CTL_LUN_ERROR;
2098
2099 if (be_lun->io_taskqueue != NULL)
2100 taskqueue_free(be_lun->io_taskqueue);
2101 ctl_be_block_close(be_lun);
2102 if (be_lun->dev_path != NULL)
2103 free(be_lun->dev_path, M_CTLBLK);
2104 if (be_lun->lun_zone != NULL)
2105 uma_zdestroy(be_lun->lun_zone);
2106 ctl_free_opts(&be_lun->ctl_be_lun);
2118 mtx_destroy(&be_lun->lock);
2107 mtx_destroy(&be_lun->queue_lock);
2108 mtx_destroy(&be_lun->io_lock);
2119 free(be_lun, M_CTLBLK);
2120
2121 return (retval);
2122}
2123
2124static int
2125ctl_be_block_rm(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
2126{
2127 struct ctl_lun_rm_params *params;
2128 struct ctl_be_block_lun *be_lun;
2129 int retval;
2130
2131 params = &req->reqdata.rm;
2132
2133 mtx_lock(&softc->lock);
2134
2135 be_lun = NULL;
2136
2137 STAILQ_FOREACH(be_lun, &softc->lun_list, links) {
2138 if (be_lun->ctl_be_lun.lun_id == params->lun_id)
2139 break;
2140 }
2141 mtx_unlock(&softc->lock);
2142
2143 if (be_lun == NULL) {
2144 snprintf(req->error_str, sizeof(req->error_str),
2145 "%s: LUN %u is not managed by the block backend",
2146 __func__, params->lun_id);
2147 goto bailout_error;
2148 }
2149
2150 retval = ctl_disable_lun(&be_lun->ctl_be_lun);
2151
2152 if (retval != 0) {
2153 snprintf(req->error_str, sizeof(req->error_str),
2154 "%s: error %d returned from ctl_disable_lun() for "
2155 "LUN %d", __func__, retval, params->lun_id);
2156 goto bailout_error;
2157
2158 }
2159
2160 retval = ctl_invalidate_lun(&be_lun->ctl_be_lun);
2161 if (retval != 0) {
2162 snprintf(req->error_str, sizeof(req->error_str),
2163 "%s: error %d returned from ctl_invalidate_lun() for "
2164 "LUN %d", __func__, retval, params->lun_id);
2165 goto bailout_error;
2166 }
2167
2168 mtx_lock(&softc->lock);
2169
2170 be_lun->flags |= CTL_BE_BLOCK_LUN_WAITING;
2171
2172 while ((be_lun->flags & CTL_BE_BLOCK_LUN_UNCONFIGURED) == 0) {
2173 retval = msleep(be_lun, &softc->lock, PCATCH, "ctlblk", 0);
2174 if (retval == EINTR)
2175 break;
2176 }
2177
2178 be_lun->flags &= ~CTL_BE_BLOCK_LUN_WAITING;
2179
2180 if ((be_lun->flags & CTL_BE_BLOCK_LUN_UNCONFIGURED) == 0) {
2181 snprintf(req->error_str, sizeof(req->error_str),
2182 "%s: interrupted waiting for LUN to be freed",
2183 __func__);
2184 mtx_unlock(&softc->lock);
2185 goto bailout_error;
2186 }
2187
2188 STAILQ_REMOVE(&softc->lun_list, be_lun, ctl_be_block_lun, links);
2189
2190 softc->num_luns--;
2191 mtx_unlock(&softc->lock);
2192
2193 taskqueue_drain(be_lun->io_taskqueue, &be_lun->io_task);
2194
2195 taskqueue_free(be_lun->io_taskqueue);
2196
2197 ctl_be_block_close(be_lun);
2198
2199 if (be_lun->disk_stats != NULL)
2200 devstat_remove_entry(be_lun->disk_stats);
2201
2202 uma_zdestroy(be_lun->lun_zone);
2203
2204 ctl_free_opts(&be_lun->ctl_be_lun);
2205 free(be_lun->dev_path, M_CTLBLK);
2109 free(be_lun, M_CTLBLK);
2110
2111 return (retval);
2112}
2113
2114static int
2115ctl_be_block_rm(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
2116{
2117 struct ctl_lun_rm_params *params;
2118 struct ctl_be_block_lun *be_lun;
2119 int retval;
2120
2121 params = &req->reqdata.rm;
2122
2123 mtx_lock(&softc->lock);
2124
2125 be_lun = NULL;
2126
2127 STAILQ_FOREACH(be_lun, &softc->lun_list, links) {
2128 if (be_lun->ctl_be_lun.lun_id == params->lun_id)
2129 break;
2130 }
2131 mtx_unlock(&softc->lock);
2132
2133 if (be_lun == NULL) {
2134 snprintf(req->error_str, sizeof(req->error_str),
2135 "%s: LUN %u is not managed by the block backend",
2136 __func__, params->lun_id);
2137 goto bailout_error;
2138 }
2139
2140 retval = ctl_disable_lun(&be_lun->ctl_be_lun);
2141
2142 if (retval != 0) {
2143 snprintf(req->error_str, sizeof(req->error_str),
2144 "%s: error %d returned from ctl_disable_lun() for "
2145 "LUN %d", __func__, retval, params->lun_id);
2146 goto bailout_error;
2147
2148 }
2149
2150 retval = ctl_invalidate_lun(&be_lun->ctl_be_lun);
2151 if (retval != 0) {
2152 snprintf(req->error_str, sizeof(req->error_str),
2153 "%s: error %d returned from ctl_invalidate_lun() for "
2154 "LUN %d", __func__, retval, params->lun_id);
2155 goto bailout_error;
2156 }
2157
2158 mtx_lock(&softc->lock);
2159
2160 be_lun->flags |= CTL_BE_BLOCK_LUN_WAITING;
2161
2162 while ((be_lun->flags & CTL_BE_BLOCK_LUN_UNCONFIGURED) == 0) {
2163 retval = msleep(be_lun, &softc->lock, PCATCH, "ctlblk", 0);
2164 if (retval == EINTR)
2165 break;
2166 }
2167
2168 be_lun->flags &= ~CTL_BE_BLOCK_LUN_WAITING;
2169
2170 if ((be_lun->flags & CTL_BE_BLOCK_LUN_UNCONFIGURED) == 0) {
2171 snprintf(req->error_str, sizeof(req->error_str),
2172 "%s: interrupted waiting for LUN to be freed",
2173 __func__);
2174 mtx_unlock(&softc->lock);
2175 goto bailout_error;
2176 }
2177
2178 STAILQ_REMOVE(&softc->lun_list, be_lun, ctl_be_block_lun, links);
2179
2180 softc->num_luns--;
2181 mtx_unlock(&softc->lock);
2182
2183 taskqueue_drain(be_lun->io_taskqueue, &be_lun->io_task);
2184
2185 taskqueue_free(be_lun->io_taskqueue);
2186
2187 ctl_be_block_close(be_lun);
2188
2189 if (be_lun->disk_stats != NULL)
2190 devstat_remove_entry(be_lun->disk_stats);
2191
2192 uma_zdestroy(be_lun->lun_zone);
2193
2194 ctl_free_opts(&be_lun->ctl_be_lun);
2195 free(be_lun->dev_path, M_CTLBLK);
2206
2196 mtx_destroy(&be_lun->queue_lock);
2197 mtx_destroy(&be_lun->io_lock);
2207 free(be_lun, M_CTLBLK);
2208
2209 req->status = CTL_LUN_OK;
2210
2211 return (0);
2212
2213bailout_error:
2214
2215 req->status = CTL_LUN_ERROR;
2216
2217 return (0);
2218}
2219
2220static int
2221ctl_be_block_modify_file(struct ctl_be_block_lun *be_lun,
2222 struct ctl_lun_req *req)
2223{
2224 struct vattr vattr;
2225 int error;
2226 struct ctl_lun_modify_params *params;
2227
2228 params = &req->reqdata.modify;
2229
2230 if (params->lun_size_bytes != 0) {
2231 be_lun->size_bytes = params->lun_size_bytes;
2232 } else {
2233 error = VOP_GETATTR(be_lun->vn, &vattr, curthread->td_ucred);
2234 if (error != 0) {
2235 snprintf(req->error_str, sizeof(req->error_str),
2236 "error calling VOP_GETATTR() for file %s",
2237 be_lun->dev_path);
2238 return (error);
2239 }
2240
2241 be_lun->size_bytes = vattr.va_size;
2242 }
2243
2244 return (0);
2245}
2246
2247static int
2248ctl_be_block_modify_dev(struct ctl_be_block_lun *be_lun,
2249 struct ctl_lun_req *req)
2250{
2251 struct cdev *dev;
2252 struct cdevsw *devsw;
2253 int error;
2254 struct ctl_lun_modify_params *params;
2255 uint64_t size_bytes;
2256
2257 params = &req->reqdata.modify;
2258
2259 dev = be_lun->vn->v_rdev;
2260 devsw = dev->si_devsw;
2261 if (!devsw->d_ioctl) {
2262 snprintf(req->error_str, sizeof(req->error_str),
2263 "%s: no d_ioctl for device %s!", __func__,
2264 be_lun->dev_path);
2265 return (ENODEV);
2266 }
2267
2268 error = devsw->d_ioctl(dev, DIOCGMEDIASIZE,
2269 (caddr_t)&size_bytes, FREAD,
2270 curthread);
2271 if (error) {
2272 snprintf(req->error_str, sizeof(req->error_str),
2273 "%s: error %d returned for DIOCGMEDIASIZE ioctl "
2274 "on %s!", __func__, error, be_lun->dev_path);
2275 return (error);
2276 }
2277
2278 if (params->lun_size_bytes != 0) {
2279 if (params->lun_size_bytes > size_bytes) {
2280 snprintf(req->error_str, sizeof(req->error_str),
2281 "%s: requested LUN size %ju > backing device "
2282 "size %ju", __func__,
2283 (uintmax_t)params->lun_size_bytes,
2284 (uintmax_t)size_bytes);
2285 return (EINVAL);
2286 }
2287
2288 be_lun->size_bytes = params->lun_size_bytes;
2289 } else {
2290 be_lun->size_bytes = size_bytes;
2291 }
2292
2293 return (0);
2294}
2295
2296static int
2297ctl_be_block_modify(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
2298{
2299 struct ctl_lun_modify_params *params;
2300 struct ctl_be_block_lun *be_lun;
2301 int error;
2302
2303 params = &req->reqdata.modify;
2304
2305 mtx_lock(&softc->lock);
2306
2307 be_lun = NULL;
2308
2309 STAILQ_FOREACH(be_lun, &softc->lun_list, links) {
2310 if (be_lun->ctl_be_lun.lun_id == params->lun_id)
2311 break;
2312 }
2313 mtx_unlock(&softc->lock);
2314
2315 if (be_lun == NULL) {
2316 snprintf(req->error_str, sizeof(req->error_str),
2317 "%s: LUN %u is not managed by the block backend",
2318 __func__, params->lun_id);
2319 goto bailout_error;
2320 }
2321
2322 if (params->lun_size_bytes != 0) {
2323 if (params->lun_size_bytes < be_lun->blocksize) {
2324 snprintf(req->error_str, sizeof(req->error_str),
2325 "%s: LUN size %ju < blocksize %u", __func__,
2326 params->lun_size_bytes, be_lun->blocksize);
2327 goto bailout_error;
2328 }
2329 }
2330
2331 vn_lock(be_lun->vn, LK_SHARED | LK_RETRY);
2332
2333 if (be_lun->vn->v_type == VREG)
2334 error = ctl_be_block_modify_file(be_lun, req);
2335 else
2336 error = ctl_be_block_modify_dev(be_lun, req);
2337
2338 VOP_UNLOCK(be_lun->vn, 0);
2339
2340 if (error != 0)
2341 goto bailout_error;
2342
2343 be_lun->size_blocks = be_lun->size_bytes >> be_lun->blocksize_shift;
2344
2345 /*
2346 * The maximum LBA is the size - 1.
2347 *
2348 * XXX: Note that this field is being updated without locking,
2349 * which might cause problems on 32-bit architectures.
2350 */
2351 be_lun->ctl_be_lun.maxlba = be_lun->size_blocks - 1;
2352 ctl_lun_capacity_changed(&be_lun->ctl_be_lun);
2353
2354 /* Tell the user the exact size we ended up using */
2355 params->lun_size_bytes = be_lun->size_bytes;
2356
2357 req->status = CTL_LUN_OK;
2358
2359 return (0);
2360
2361bailout_error:
2362 req->status = CTL_LUN_ERROR;
2363
2364 return (0);
2365}
2366
2367static void
2368ctl_be_block_lun_shutdown(void *be_lun)
2369{
2370 struct ctl_be_block_lun *lun;
2371 struct ctl_be_block_softc *softc;
2372
2373 lun = (struct ctl_be_block_lun *)be_lun;
2374
2375 softc = lun->softc;
2376
2377 mtx_lock(&softc->lock);
2378 lun->flags |= CTL_BE_BLOCK_LUN_UNCONFIGURED;
2379 if (lun->flags & CTL_BE_BLOCK_LUN_WAITING)
2380 wakeup(lun);
2381 mtx_unlock(&softc->lock);
2382
2383}
2384
2385static void
2386ctl_be_block_lun_config_status(void *be_lun, ctl_lun_config_status status)
2387{
2388 struct ctl_be_block_lun *lun;
2389 struct ctl_be_block_softc *softc;
2390
2391 lun = (struct ctl_be_block_lun *)be_lun;
2392 softc = lun->softc;
2393
2394 if (status == CTL_LUN_CONFIG_OK) {
2395 mtx_lock(&softc->lock);
2396 lun->flags &= ~CTL_BE_BLOCK_LUN_UNCONFIGURED;
2397 if (lun->flags & CTL_BE_BLOCK_LUN_WAITING)
2398 wakeup(lun);
2399 mtx_unlock(&softc->lock);
2400
2401 /*
2402 * We successfully added the LUN, attempt to enable it.
2403 */
2404 if (ctl_enable_lun(&lun->ctl_be_lun) != 0) {
2405 printf("%s: ctl_enable_lun() failed!\n", __func__);
2406 if (ctl_invalidate_lun(&lun->ctl_be_lun) != 0) {
2407 printf("%s: ctl_invalidate_lun() failed!\n",
2408 __func__);
2409 }
2410 }
2411
2412 return;
2413 }
2414
2415
2416 mtx_lock(&softc->lock);
2417 lun->flags &= ~CTL_BE_BLOCK_LUN_UNCONFIGURED;
2418 lun->flags |= CTL_BE_BLOCK_LUN_CONFIG_ERR;
2419 wakeup(lun);
2420 mtx_unlock(&softc->lock);
2421}
2422
2423
2424static int
2425ctl_be_block_config_write(union ctl_io *io)
2426{
2427 struct ctl_be_block_lun *be_lun;
2428 struct ctl_be_lun *ctl_be_lun;
2429 int retval;
2430
2431 retval = 0;
2432
2433 DPRINTF("entered\n");
2434
2435 ctl_be_lun = (struct ctl_be_lun *)io->io_hdr.ctl_private[
2436 CTL_PRIV_BACKEND_LUN].ptr;
2437 be_lun = (struct ctl_be_block_lun *)ctl_be_lun->be_lun;
2438
2439 switch (io->scsiio.cdb[0]) {
2440 case SYNCHRONIZE_CACHE:
2441 case SYNCHRONIZE_CACHE_16:
2442 case WRITE_SAME_10:
2443 case WRITE_SAME_16:
2444 case UNMAP:
2445 /*
2446 * The upper level CTL code will filter out any CDBs with
2447 * the immediate bit set and return the proper error.
2448 *
2449 * We don't really need to worry about what LBA range the
2450 * user asked to be synced out. When they issue a sync
2451 * cache command, we'll sync out the whole thing.
2452 */
2198 free(be_lun, M_CTLBLK);
2199
2200 req->status = CTL_LUN_OK;
2201
2202 return (0);
2203
2204bailout_error:
2205
2206 req->status = CTL_LUN_ERROR;
2207
2208 return (0);
2209}
2210
2211static int
2212ctl_be_block_modify_file(struct ctl_be_block_lun *be_lun,
2213 struct ctl_lun_req *req)
2214{
2215 struct vattr vattr;
2216 int error;
2217 struct ctl_lun_modify_params *params;
2218
2219 params = &req->reqdata.modify;
2220
2221 if (params->lun_size_bytes != 0) {
2222 be_lun->size_bytes = params->lun_size_bytes;
2223 } else {
2224 error = VOP_GETATTR(be_lun->vn, &vattr, curthread->td_ucred);
2225 if (error != 0) {
2226 snprintf(req->error_str, sizeof(req->error_str),
2227 "error calling VOP_GETATTR() for file %s",
2228 be_lun->dev_path);
2229 return (error);
2230 }
2231
2232 be_lun->size_bytes = vattr.va_size;
2233 }
2234
2235 return (0);
2236}
2237
2238static int
2239ctl_be_block_modify_dev(struct ctl_be_block_lun *be_lun,
2240 struct ctl_lun_req *req)
2241{
2242 struct cdev *dev;
2243 struct cdevsw *devsw;
2244 int error;
2245 struct ctl_lun_modify_params *params;
2246 uint64_t size_bytes;
2247
2248 params = &req->reqdata.modify;
2249
2250 dev = be_lun->vn->v_rdev;
2251 devsw = dev->si_devsw;
2252 if (!devsw->d_ioctl) {
2253 snprintf(req->error_str, sizeof(req->error_str),
2254 "%s: no d_ioctl for device %s!", __func__,
2255 be_lun->dev_path);
2256 return (ENODEV);
2257 }
2258
2259 error = devsw->d_ioctl(dev, DIOCGMEDIASIZE,
2260 (caddr_t)&size_bytes, FREAD,
2261 curthread);
2262 if (error) {
2263 snprintf(req->error_str, sizeof(req->error_str),
2264 "%s: error %d returned for DIOCGMEDIASIZE ioctl "
2265 "on %s!", __func__, error, be_lun->dev_path);
2266 return (error);
2267 }
2268
2269 if (params->lun_size_bytes != 0) {
2270 if (params->lun_size_bytes > size_bytes) {
2271 snprintf(req->error_str, sizeof(req->error_str),
2272 "%s: requested LUN size %ju > backing device "
2273 "size %ju", __func__,
2274 (uintmax_t)params->lun_size_bytes,
2275 (uintmax_t)size_bytes);
2276 return (EINVAL);
2277 }
2278
2279 be_lun->size_bytes = params->lun_size_bytes;
2280 } else {
2281 be_lun->size_bytes = size_bytes;
2282 }
2283
2284 return (0);
2285}
2286
2287static int
2288ctl_be_block_modify(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
2289{
2290 struct ctl_lun_modify_params *params;
2291 struct ctl_be_block_lun *be_lun;
2292 int error;
2293
2294 params = &req->reqdata.modify;
2295
2296 mtx_lock(&softc->lock);
2297
2298 be_lun = NULL;
2299
2300 STAILQ_FOREACH(be_lun, &softc->lun_list, links) {
2301 if (be_lun->ctl_be_lun.lun_id == params->lun_id)
2302 break;
2303 }
2304 mtx_unlock(&softc->lock);
2305
2306 if (be_lun == NULL) {
2307 snprintf(req->error_str, sizeof(req->error_str),
2308 "%s: LUN %u is not managed by the block backend",
2309 __func__, params->lun_id);
2310 goto bailout_error;
2311 }
2312
2313 if (params->lun_size_bytes != 0) {
2314 if (params->lun_size_bytes < be_lun->blocksize) {
2315 snprintf(req->error_str, sizeof(req->error_str),
2316 "%s: LUN size %ju < blocksize %u", __func__,
2317 params->lun_size_bytes, be_lun->blocksize);
2318 goto bailout_error;
2319 }
2320 }
2321
2322 vn_lock(be_lun->vn, LK_SHARED | LK_RETRY);
2323
2324 if (be_lun->vn->v_type == VREG)
2325 error = ctl_be_block_modify_file(be_lun, req);
2326 else
2327 error = ctl_be_block_modify_dev(be_lun, req);
2328
2329 VOP_UNLOCK(be_lun->vn, 0);
2330
2331 if (error != 0)
2332 goto bailout_error;
2333
2334 be_lun->size_blocks = be_lun->size_bytes >> be_lun->blocksize_shift;
2335
2336 /*
2337 * The maximum LBA is the size - 1.
2338 *
2339 * XXX: Note that this field is being updated without locking,
2340 * which might cause problems on 32-bit architectures.
2341 */
2342 be_lun->ctl_be_lun.maxlba = be_lun->size_blocks - 1;
2343 ctl_lun_capacity_changed(&be_lun->ctl_be_lun);
2344
2345 /* Tell the user the exact size we ended up using */
2346 params->lun_size_bytes = be_lun->size_bytes;
2347
2348 req->status = CTL_LUN_OK;
2349
2350 return (0);
2351
2352bailout_error:
2353 req->status = CTL_LUN_ERROR;
2354
2355 return (0);
2356}
2357
2358static void
2359ctl_be_block_lun_shutdown(void *be_lun)
2360{
2361 struct ctl_be_block_lun *lun;
2362 struct ctl_be_block_softc *softc;
2363
2364 lun = (struct ctl_be_block_lun *)be_lun;
2365
2366 softc = lun->softc;
2367
2368 mtx_lock(&softc->lock);
2369 lun->flags |= CTL_BE_BLOCK_LUN_UNCONFIGURED;
2370 if (lun->flags & CTL_BE_BLOCK_LUN_WAITING)
2371 wakeup(lun);
2372 mtx_unlock(&softc->lock);
2373
2374}
2375
2376static void
2377ctl_be_block_lun_config_status(void *be_lun, ctl_lun_config_status status)
2378{
2379 struct ctl_be_block_lun *lun;
2380 struct ctl_be_block_softc *softc;
2381
2382 lun = (struct ctl_be_block_lun *)be_lun;
2383 softc = lun->softc;
2384
2385 if (status == CTL_LUN_CONFIG_OK) {
2386 mtx_lock(&softc->lock);
2387 lun->flags &= ~CTL_BE_BLOCK_LUN_UNCONFIGURED;
2388 if (lun->flags & CTL_BE_BLOCK_LUN_WAITING)
2389 wakeup(lun);
2390 mtx_unlock(&softc->lock);
2391
2392 /*
2393 * We successfully added the LUN, attempt to enable it.
2394 */
2395 if (ctl_enable_lun(&lun->ctl_be_lun) != 0) {
2396 printf("%s: ctl_enable_lun() failed!\n", __func__);
2397 if (ctl_invalidate_lun(&lun->ctl_be_lun) != 0) {
2398 printf("%s: ctl_invalidate_lun() failed!\n",
2399 __func__);
2400 }
2401 }
2402
2403 return;
2404 }
2405
2406
2407 mtx_lock(&softc->lock);
2408 lun->flags &= ~CTL_BE_BLOCK_LUN_UNCONFIGURED;
2409 lun->flags |= CTL_BE_BLOCK_LUN_CONFIG_ERR;
2410 wakeup(lun);
2411 mtx_unlock(&softc->lock);
2412}
2413
2414
2415static int
2416ctl_be_block_config_write(union ctl_io *io)
2417{
2418 struct ctl_be_block_lun *be_lun;
2419 struct ctl_be_lun *ctl_be_lun;
2420 int retval;
2421
2422 retval = 0;
2423
2424 DPRINTF("entered\n");
2425
2426 ctl_be_lun = (struct ctl_be_lun *)io->io_hdr.ctl_private[
2427 CTL_PRIV_BACKEND_LUN].ptr;
2428 be_lun = (struct ctl_be_block_lun *)ctl_be_lun->be_lun;
2429
2430 switch (io->scsiio.cdb[0]) {
2431 case SYNCHRONIZE_CACHE:
2432 case SYNCHRONIZE_CACHE_16:
2433 case WRITE_SAME_10:
2434 case WRITE_SAME_16:
2435 case UNMAP:
2436 /*
2437 * The upper level CTL code will filter out any CDBs with
2438 * the immediate bit set and return the proper error.
2439 *
2440 * We don't really need to worry about what LBA range the
2441 * user asked to be synced out. When they issue a sync
2442 * cache command, we'll sync out the whole thing.
2443 */
2453 mtx_lock(&be_lun->lock);
2444 mtx_lock(&be_lun->queue_lock);
2454 STAILQ_INSERT_TAIL(&be_lun->config_write_queue, &io->io_hdr,
2455 links);
2445 STAILQ_INSERT_TAIL(&be_lun->config_write_queue, &io->io_hdr,
2446 links);
2456 mtx_unlock(&be_lun->lock);
2447 mtx_unlock(&be_lun->queue_lock);
2457 taskqueue_enqueue(be_lun->io_taskqueue, &be_lun->io_task);
2458 break;
2459 case START_STOP_UNIT: {
2460 struct scsi_start_stop_unit *cdb;
2461
2462 cdb = (struct scsi_start_stop_unit *)io->scsiio.cdb;
2463
2464 if (cdb->how & SSS_START)
2465 retval = ctl_start_lun(ctl_be_lun);
2466 else {
2467 retval = ctl_stop_lun(ctl_be_lun);
2468 /*
2469 * XXX KDM Copan-specific offline behavior.
2470 * Figure out a reasonable way to port this?
2471 */
2472#ifdef NEEDTOPORT
2473 if ((retval == 0)
2474 && (cdb->byte2 & SSS_ONOFFLINE))
2475 retval = ctl_lun_offline(ctl_be_lun);
2476#endif
2477 }
2478
2479 /*
2480 * In general, the above routines should not fail. They
2481 * just set state for the LUN. So we've got something
2482 * pretty wrong here if we can't start or stop the LUN.
2483 */
2484 if (retval != 0) {
2485 ctl_set_internal_failure(&io->scsiio,
2486 /*sks_valid*/ 1,
2487 /*retry_count*/ 0xf051);
2488 retval = CTL_RETVAL_COMPLETE;
2489 } else {
2490 ctl_set_success(&io->scsiio);
2491 }
2492 ctl_config_write_done(io);
2493 break;
2494 }
2495 default:
2496 ctl_set_invalid_opcode(&io->scsiio);
2497 ctl_config_write_done(io);
2498 retval = CTL_RETVAL_COMPLETE;
2499 break;
2500 }
2501
2502 return (retval);
2503
2504}
2505
2506static int
2507ctl_be_block_config_read(union ctl_io *io)
2508{
2509 return (0);
2510}
2511
2512static int
2513ctl_be_block_lun_info(void *be_lun, struct sbuf *sb)
2514{
2515 struct ctl_be_block_lun *lun;
2516 int retval;
2517
2518 lun = (struct ctl_be_block_lun *)be_lun;
2519 retval = 0;
2520
2521 retval = sbuf_printf(sb, "<num_threads>");
2522
2523 if (retval != 0)
2524 goto bailout;
2525
2526 retval = sbuf_printf(sb, "%d", lun->num_threads);
2527
2528 if (retval != 0)
2529 goto bailout;
2530
2531 retval = sbuf_printf(sb, "</num_threads>");
2532
2533bailout:
2534
2535 return (retval);
2536}
2537
2538int
2539ctl_be_block_init(void)
2540{
2541 struct ctl_be_block_softc *softc;
2542 int retval;
2543
2544 softc = &backend_block_softc;
2545 retval = 0;
2546
2448 taskqueue_enqueue(be_lun->io_taskqueue, &be_lun->io_task);
2449 break;
2450 case START_STOP_UNIT: {
2451 struct scsi_start_stop_unit *cdb;
2452
2453 cdb = (struct scsi_start_stop_unit *)io->scsiio.cdb;
2454
2455 if (cdb->how & SSS_START)
2456 retval = ctl_start_lun(ctl_be_lun);
2457 else {
2458 retval = ctl_stop_lun(ctl_be_lun);
2459 /*
2460 * XXX KDM Copan-specific offline behavior.
2461 * Figure out a reasonable way to port this?
2462 */
2463#ifdef NEEDTOPORT
2464 if ((retval == 0)
2465 && (cdb->byte2 & SSS_ONOFFLINE))
2466 retval = ctl_lun_offline(ctl_be_lun);
2467#endif
2468 }
2469
2470 /*
2471 * In general, the above routines should not fail. They
2472 * just set state for the LUN. So we've got something
2473 * pretty wrong here if we can't start or stop the LUN.
2474 */
2475 if (retval != 0) {
2476 ctl_set_internal_failure(&io->scsiio,
2477 /*sks_valid*/ 1,
2478 /*retry_count*/ 0xf051);
2479 retval = CTL_RETVAL_COMPLETE;
2480 } else {
2481 ctl_set_success(&io->scsiio);
2482 }
2483 ctl_config_write_done(io);
2484 break;
2485 }
2486 default:
2487 ctl_set_invalid_opcode(&io->scsiio);
2488 ctl_config_write_done(io);
2489 retval = CTL_RETVAL_COMPLETE;
2490 break;
2491 }
2492
2493 return (retval);
2494
2495}
2496
2497static int
2498ctl_be_block_config_read(union ctl_io *io)
2499{
2500 return (0);
2501}
2502
2503static int
2504ctl_be_block_lun_info(void *be_lun, struct sbuf *sb)
2505{
2506 struct ctl_be_block_lun *lun;
2507 int retval;
2508
2509 lun = (struct ctl_be_block_lun *)be_lun;
2510 retval = 0;
2511
2512 retval = sbuf_printf(sb, "<num_threads>");
2513
2514 if (retval != 0)
2515 goto bailout;
2516
2517 retval = sbuf_printf(sb, "%d", lun->num_threads);
2518
2519 if (retval != 0)
2520 goto bailout;
2521
2522 retval = sbuf_printf(sb, "</num_threads>");
2523
2524bailout:
2525
2526 return (retval);
2527}
2528
2529int
2530ctl_be_block_init(void)
2531{
2532 struct ctl_be_block_softc *softc;
2533 int retval;
2534
2535 softc = &backend_block_softc;
2536 retval = 0;
2537
2547 mtx_init(&softc->lock, "ctlblk", NULL, MTX_DEF);
2538 mtx_init(&softc->lock, "ctlblock", NULL, MTX_DEF);
2548 beio_zone = uma_zcreate("beio", sizeof(struct ctl_be_block_io),
2549 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
2550 STAILQ_INIT(&softc->disk_list);
2551 STAILQ_INIT(&softc->lun_list);
2552
2553 return (retval);
2554}
2539 beio_zone = uma_zcreate("beio", sizeof(struct ctl_be_block_io),
2540 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
2541 STAILQ_INIT(&softc->disk_list);
2542 STAILQ_INIT(&softc->lun_list);
2543
2544 return (retval);
2545}