xref: /dragonfly/sys/kern/subr_diskiocom.c (revision 5bd45597)
1185ace93SMatthew Dillon /*
2185ace93SMatthew Dillon  * Copyright (c) 2012 The DragonFly Project.  All rights reserved.
3185ace93SMatthew Dillon  *
4185ace93SMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
5185ace93SMatthew Dillon  * by Matthew Dillon <dillon@backplane.com>
6185ace93SMatthew Dillon  *
7185ace93SMatthew Dillon  * Redistribution and use in source and binary forms, with or without
8185ace93SMatthew Dillon  * modification, are permitted provided that the following conditions
9185ace93SMatthew Dillon  * are met:
10185ace93SMatthew Dillon  *
11185ace93SMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
12185ace93SMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
13185ace93SMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
14185ace93SMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
15185ace93SMatthew Dillon  *    the documentation and/or other materials provided with the
16185ace93SMatthew Dillon  *    distribution.
17185ace93SMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
18185ace93SMatthew Dillon  *    contributors may be used to endorse or promote products derived
19185ace93SMatthew Dillon  *    from this software without specific, prior written permission.
20185ace93SMatthew Dillon  *
21185ace93SMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22185ace93SMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23185ace93SMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24185ace93SMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25185ace93SMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26185ace93SMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27185ace93SMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28185ace93SMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29185ace93SMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30185ace93SMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31185ace93SMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32185ace93SMatthew Dillon  * SUCH DAMAGE.
33185ace93SMatthew Dillon  */
34185ace93SMatthew Dillon #include <sys/param.h>
35185ace93SMatthew Dillon #include <sys/systm.h>
36185ace93SMatthew Dillon #include <sys/kernel.h>
37185ace93SMatthew Dillon #include <sys/proc.h>
38185ace93SMatthew Dillon #include <sys/sysctl.h>
39185ace93SMatthew Dillon #include <sys/buf.h>
40185ace93SMatthew Dillon #include <sys/conf.h>
41185ace93SMatthew Dillon #include <sys/disklabel.h>
42185ace93SMatthew Dillon #include <sys/disklabel32.h>
43185ace93SMatthew Dillon #include <sys/disklabel64.h>
44185ace93SMatthew Dillon #include <sys/diskslice.h>
45185ace93SMatthew Dillon #include <sys/diskmbr.h>
46185ace93SMatthew Dillon #include <sys/disk.h>
47185ace93SMatthew Dillon #include <sys/malloc.h>
48185ace93SMatthew Dillon #include <sys/device.h>
49185ace93SMatthew Dillon #include <sys/devfs.h>
50185ace93SMatthew Dillon #include <sys/thread.h>
51185ace93SMatthew Dillon #include <sys/queue.h>
52185ace93SMatthew Dillon #include <sys/lock.h>
538d6d37b8SMatthew Dillon #include <sys/stat.h>
54185ace93SMatthew Dillon #include <sys/uuid.h>
55185ace93SMatthew Dillon #include <sys/dmsg.h>
56185ace93SMatthew Dillon 
57185ace93SMatthew Dillon #include <sys/buf2.h>
58185ace93SMatthew Dillon #include <sys/msgport2.h>
59185ace93SMatthew Dillon 
608d6d37b8SMatthew Dillon struct dios_open {
618d6d37b8SMatthew Dillon 	int	openrd;
628d6d37b8SMatthew Dillon 	int	openwr;
638d6d37b8SMatthew Dillon };
648d6d37b8SMatthew Dillon 
658d6d37b8SMatthew Dillon struct dios_io {
668d6d37b8SMatthew Dillon 	int	count;
678d6d37b8SMatthew Dillon 	int	eof;
681a2a529dSMatthew Dillon 	kdmsg_data_t data;
698d6d37b8SMatthew Dillon };
708d6d37b8SMatthew Dillon 
71185ace93SMatthew Dillon static MALLOC_DEFINE(M_DMSG_DISK, "dmsg_disk", "disk dmsg");
72185ace93SMatthew Dillon 
7345c1a24bSMatthew Dillon static int blk_active;
7445c1a24bSMatthew Dillon SYSCTL_INT(_debug, OID_AUTO, blk_active, CTLFLAG_RW, &blk_active, 0,
7545c1a24bSMatthew Dillon            "Number of active iocom IOs");
7645c1a24bSMatthew Dillon 
77185ace93SMatthew Dillon static int disk_iocom_reconnect(struct disk *dp, struct file *fp);
7803d99ea4SMatthew Dillon static int disk_rcvdmsg(kdmsg_msg_t *msg);
79185ace93SMatthew Dillon 
808d6d37b8SMatthew Dillon static void disk_blk_open(struct disk *dp, kdmsg_msg_t *msg);
818d6d37b8SMatthew Dillon static void disk_blk_read(struct disk *dp, kdmsg_msg_t *msg);
828d6d37b8SMatthew Dillon static void disk_blk_write(struct disk *dp, kdmsg_msg_t *msg);
838d6d37b8SMatthew Dillon static void disk_blk_flush(struct disk *dp, kdmsg_msg_t *msg);
848d6d37b8SMatthew Dillon static void disk_blk_freeblks(struct disk *dp, kdmsg_msg_t *msg);
858d6d37b8SMatthew Dillon static void diskiodone(struct bio *bio);
868d6d37b8SMatthew Dillon 
87185ace93SMatthew Dillon void
disk_iocom_init(struct disk * dp)88185ace93SMatthew Dillon disk_iocom_init(struct disk *dp)
89185ace93SMatthew Dillon {
9003d99ea4SMatthew Dillon 	kdmsg_iocom_init(&dp->d_iocom, dp,
9103d99ea4SMatthew Dillon 			 KDMSG_IOCOMF_AUTOCONN |
928e226bc8SMatthew Dillon 			 KDMSG_IOCOMF_AUTORXSPAN |
931b8eded1SMatthew Dillon 			 KDMSG_IOCOMF_AUTOTXSPAN,
9403d99ea4SMatthew Dillon 			 M_DMSG_DISK, disk_rcvdmsg);
95185ace93SMatthew Dillon }
96185ace93SMatthew Dillon 
97185ace93SMatthew Dillon void
disk_iocom_update(struct disk * dp)98185ace93SMatthew Dillon disk_iocom_update(struct disk *dp)
99185ace93SMatthew Dillon {
100185ace93SMatthew Dillon }
101185ace93SMatthew Dillon 
102185ace93SMatthew Dillon void
disk_iocom_uninit(struct disk * dp)103185ace93SMatthew Dillon disk_iocom_uninit(struct disk *dp)
104185ace93SMatthew Dillon {
105185ace93SMatthew Dillon 	kdmsg_iocom_uninit(&dp->d_iocom);
106185ace93SMatthew Dillon }
107185ace93SMatthew Dillon 
108185ace93SMatthew Dillon int
disk_iocom_ioctl(struct disk * dp,u_long cmd,void * data)109f4668135SSepherosa Ziehau disk_iocom_ioctl(struct disk *dp, u_long cmd, void *data)
110185ace93SMatthew Dillon {
111185ace93SMatthew Dillon 	struct file *fp;
112185ace93SMatthew Dillon 	struct disk_ioc_recluster *recl;
113185ace93SMatthew Dillon 	int error;
114185ace93SMatthew Dillon 
115185ace93SMatthew Dillon 	switch(cmd) {
116185ace93SMatthew Dillon 	case DIOCRECLUSTER:
117185ace93SMatthew Dillon 		recl = data;
11835949930SMatthew Dillon 		fp = holdfp(curthread, recl->fd, -1);
119185ace93SMatthew Dillon 		if (fp) {
120185ace93SMatthew Dillon 			error = disk_iocom_reconnect(dp, fp);
121185ace93SMatthew Dillon 		} else {
122185ace93SMatthew Dillon 			error = EINVAL;
123185ace93SMatthew Dillon 		}
124185ace93SMatthew Dillon 		break;
125185ace93SMatthew Dillon 	default:
126185ace93SMatthew Dillon 		error = EOPNOTSUPP;
127185ace93SMatthew Dillon 		break;
128185ace93SMatthew Dillon 	}
129185ace93SMatthew Dillon 	return error;
130185ace93SMatthew Dillon }
131185ace93SMatthew Dillon 
132185ace93SMatthew Dillon static
133185ace93SMatthew Dillon int
disk_iocom_reconnect(struct disk * dp,struct file * fp)134185ace93SMatthew Dillon disk_iocom_reconnect(struct disk *dp, struct file *fp)
135185ace93SMatthew Dillon {
136185ace93SMatthew Dillon 	char devname[64];
137185ace93SMatthew Dillon 
138185ace93SMatthew Dillon 	ksnprintf(devname, sizeof(devname), "%s%d",
139185ace93SMatthew Dillon 		  dev_dname(dp->d_rawdev), dkunit(dp->d_rawdev));
140185ace93SMatthew Dillon 
141185ace93SMatthew Dillon 	kdmsg_iocom_reconnect(&dp->d_iocom, fp, devname);
142185ace93SMatthew Dillon 
14303d99ea4SMatthew Dillon 	dp->d_iocom.auto_lnk_conn.proto_version = DMSG_SPAN_PROTO_1;
14403d99ea4SMatthew Dillon 	dp->d_iocom.auto_lnk_conn.peer_type = DMSG_PEER_BLOCK;
14503d99ea4SMatthew Dillon 	dp->d_iocom.auto_lnk_conn.peer_mask = 1LLU << DMSG_PEER_BLOCK;
1467750fd72SMatthew Dillon 	dp->d_iocom.auto_lnk_conn.peer_mask = (uint64_t)-1;
1477750fd72SMatthew Dillon #if 0
14803d99ea4SMatthew Dillon 	if (dp->d_info.d_serialno) {
1497750fd72SMatthew Dillon 		ksnprintf(dp->d_iocom.auto_lnk_conn.peer_label,
1507750fd72SMatthew Dillon 			  sizeof(dp->d_iocom.auto_lnk_conn.peer_label),
1517750fd72SMatthew Dillon 			  "%s/%s", hostname, dp->d_info.d_serialno);
1527750fd72SMatthew Dillon 	} else {
1537750fd72SMatthew Dillon 		ksnprintf(dp->d_iocom.auto_lnk_conn.peer_label,
1547750fd72SMatthew Dillon 			  sizeof(dp->d_iocom.auto_lnk_conn.peer_label),
1557750fd72SMatthew Dillon 			  "%s/%s", hostname, devname);
15603d99ea4SMatthew Dillon 	}
1577750fd72SMatthew Dillon #endif
1587750fd72SMatthew Dillon 	ksnprintf(dp->d_iocom.auto_lnk_conn.peer_label,
1597750fd72SMatthew Dillon 		  sizeof(dp->d_iocom.auto_lnk_conn.peer_label),
1607750fd72SMatthew Dillon 		  "%s/%s", hostname, devname);
16103d99ea4SMatthew Dillon 
16203d99ea4SMatthew Dillon 	dp->d_iocom.auto_lnk_span.proto_version = DMSG_SPAN_PROTO_1;
16303d99ea4SMatthew Dillon 	dp->d_iocom.auto_lnk_span.peer_type = DMSG_PEER_BLOCK;
16403d99ea4SMatthew Dillon 	dp->d_iocom.auto_lnk_span.media.block.bytes =
16503d99ea4SMatthew Dillon 						dp->d_info.d_media_size;
16603d99ea4SMatthew Dillon 	dp->d_iocom.auto_lnk_span.media.block.blksize =
16703d99ea4SMatthew Dillon 						dp->d_info.d_media_blksize;
1687750fd72SMatthew Dillon 	ksnprintf(dp->d_iocom.auto_lnk_span.peer_label,
1697750fd72SMatthew Dillon 		  sizeof(dp->d_iocom.auto_lnk_span.peer_label),
1707750fd72SMatthew Dillon 		  "%s", dp->d_iocom.auto_lnk_conn.peer_label);
17103d99ea4SMatthew Dillon 	if (dp->d_info.d_serialno) {
1727750fd72SMatthew Dillon 		ksnprintf(dp->d_iocom.auto_lnk_span.pfs_label,
1737750fd72SMatthew Dillon 			  sizeof(dp->d_iocom.auto_lnk_span.pfs_label),
17403d99ea4SMatthew Dillon 			  "%s", dp->d_info.d_serialno);
1757750fd72SMatthew Dillon 	} else {
1767750fd72SMatthew Dillon 		/*
1777750fd72SMatthew Dillon 		 * If no serial number is available generate a dummy serial
1787750fd72SMatthew Dillon 		 * number from the host and device name and pray.  This will
1797750fd72SMatthew Dillon 		 * allow e.g. /dev/vn* to look meaningful on a remote machine.
1807750fd72SMatthew Dillon 		 */
1817750fd72SMatthew Dillon 		ksnprintf(dp->d_iocom.auto_lnk_span.pfs_label,
1827750fd72SMatthew Dillon 			  sizeof(dp->d_iocom.auto_lnk_span.pfs_label),
1837750fd72SMatthew Dillon 			  "%s.%s", hostname, devname);
18403d99ea4SMatthew Dillon 	}
18503d99ea4SMatthew Dillon 
18603d99ea4SMatthew Dillon 	kdmsg_iocom_autoinitiate(&dp->d_iocom, NULL);
187185ace93SMatthew Dillon 
188185ace93SMatthew Dillon 	return (0);
189185ace93SMatthew Dillon }
190185ace93SMatthew Dillon 
19159b728a7SSascha Wildner static int
disk_rcvdmsg(kdmsg_msg_t * msg)19203d99ea4SMatthew Dillon disk_rcvdmsg(kdmsg_msg_t *msg)
193185ace93SMatthew Dillon {
1941b8eded1SMatthew Dillon 	struct disk *dp = msg->state->iocom->handle;
195185ace93SMatthew Dillon 
1968d6d37b8SMatthew Dillon 	/*
1978d6d37b8SMatthew Dillon 	 * Handle debug messages (these might not be in transactions)
1988d6d37b8SMatthew Dillon 	 */
1998d6d37b8SMatthew Dillon 	switch(msg->any.head.cmd & DMSGF_CMDSWMASK) {
200185ace93SMatthew Dillon 	case DMSG_DBG_SHELL:
201185ace93SMatthew Dillon 		/*
202185ace93SMatthew Dillon 		 * Execute shell command (not supported atm)
203185ace93SMatthew Dillon 		 */
204185ace93SMatthew Dillon 		kdmsg_msg_reply(msg, DMSG_ERR_NOSUPP);
2058d6d37b8SMatthew Dillon 		return(0);
206185ace93SMatthew Dillon 	case DMSG_DBG_SHELL | DMSGF_REPLY:
207185ace93SMatthew Dillon 		if (msg->aux_data) {
208185ace93SMatthew Dillon 			msg->aux_data[msg->aux_size - 1] = 0;
20903d99ea4SMatthew Dillon 			kprintf("diskiocom: DEBUGMSG: %s\n", msg->aux_data);
210185ace93SMatthew Dillon 		}
2118d6d37b8SMatthew Dillon 		return(0);
2128d6d37b8SMatthew Dillon 	}
2138d6d37b8SMatthew Dillon 
2148d6d37b8SMatthew Dillon 	/*
215d34b92afSMatthew Dillon 	 * All remaining messages must be in a transaction.
216d34b92afSMatthew Dillon 	 *
217d34b92afSMatthew Dillon 	 * NOTE!  We currently don't care if the transaction is just
218d34b92afSMatthew Dillon 	 *	  the span transaction (for disk probes) or if it is the
219d34b92afSMatthew Dillon 	 *	  BLK_OPEN transaction.
2208d6d37b8SMatthew Dillon 	 *
2218d6d37b8SMatthew Dillon 	 * NOTE!  We are switching on the first message's command.  The
2228d6d37b8SMatthew Dillon 	 *	  actual message command within the transaction may be
2238d6d37b8SMatthew Dillon 	 *	  different (if streaming within a transaction).
2248d6d37b8SMatthew Dillon 	 */
2251b8eded1SMatthew Dillon 	if (msg->state == &msg->state->iocom->state0) {
226185ace93SMatthew Dillon 		kdmsg_msg_reply(msg, DMSG_ERR_NOSUPP);
2278d6d37b8SMatthew Dillon 		return(0);
2288d6d37b8SMatthew Dillon 	}
2298d6d37b8SMatthew Dillon 
2308d6d37b8SMatthew Dillon 	switch(msg->state->rxcmd & DMSGF_CMDSWMASK) {
2318d6d37b8SMatthew Dillon 	case DMSG_BLK_OPEN:
2328d6d37b8SMatthew Dillon 		disk_blk_open(dp, msg);
2338d6d37b8SMatthew Dillon 		break;
2348d6d37b8SMatthew Dillon 	case DMSG_BLK_READ:
235d34b92afSMatthew Dillon 		/*
236d34b92afSMatthew Dillon 		 * not reached normally but leave in for completeness
237d34b92afSMatthew Dillon 		 */
2388d6d37b8SMatthew Dillon 		disk_blk_read(dp, msg);
2398d6d37b8SMatthew Dillon 		break;
2408d6d37b8SMatthew Dillon 	case DMSG_BLK_WRITE:
2418d6d37b8SMatthew Dillon 		disk_blk_write(dp, msg);
2428d6d37b8SMatthew Dillon 		break;
2438d6d37b8SMatthew Dillon 	case DMSG_BLK_FLUSH:
2448d6d37b8SMatthew Dillon 		disk_blk_flush(dp, msg);
2458d6d37b8SMatthew Dillon 		break;
2468d6d37b8SMatthew Dillon 	case DMSG_BLK_FREEBLKS:
2478d6d37b8SMatthew Dillon 		disk_blk_freeblks(dp, msg);
2488d6d37b8SMatthew Dillon 		break;
2498d6d37b8SMatthew Dillon 	default:
2508d6d37b8SMatthew Dillon 		if ((msg->any.head.cmd & DMSGF_REPLY) == 0) {
2518d6d37b8SMatthew Dillon 			if (msg->any.head.cmd & DMSGF_DELETE)
2528d6d37b8SMatthew Dillon 				kdmsg_msg_reply(msg, DMSG_ERR_NOSUPP);
2538d6d37b8SMatthew Dillon 			else
2548d6d37b8SMatthew Dillon 				kdmsg_msg_result(msg, DMSG_ERR_NOSUPP);
2558d6d37b8SMatthew Dillon 		}
256185ace93SMatthew Dillon 		break;
257185ace93SMatthew Dillon 	}
258185ace93SMatthew Dillon 	return (0);
259185ace93SMatthew Dillon }
2608d6d37b8SMatthew Dillon 
2618d6d37b8SMatthew Dillon static
2628d6d37b8SMatthew Dillon void
disk_blk_open(struct disk * dp,kdmsg_msg_t * msg)2638d6d37b8SMatthew Dillon disk_blk_open(struct disk *dp, kdmsg_msg_t *msg)
2648d6d37b8SMatthew Dillon {
2658d6d37b8SMatthew Dillon 	struct dios_open *openst;
2668d6d37b8SMatthew Dillon 	int error = DMSG_ERR_NOSUPP;
2678d6d37b8SMatthew Dillon 	int fflags;
2688d6d37b8SMatthew Dillon 
2698d6d37b8SMatthew Dillon 	openst = msg->state->any.any;
2708d6d37b8SMatthew Dillon 	if ((msg->any.head.cmd & DMSGF_CMDSWMASK) == DMSG_BLK_OPEN) {
2718d6d37b8SMatthew Dillon 		if (openst == NULL) {
2728d6d37b8SMatthew Dillon 			openst = kmalloc(sizeof(*openst), M_DEVBUF,
2738d6d37b8SMatthew Dillon 						M_WAITOK | M_ZERO);
2748d6d37b8SMatthew Dillon 			msg->state->any.any = openst;
2758d6d37b8SMatthew Dillon 		}
2768d6d37b8SMatthew Dillon 		fflags = 0;
2778d6d37b8SMatthew Dillon 		if (msg->any.blk_open.modes & DMSG_BLKOPEN_RD)
2788d6d37b8SMatthew Dillon 			fflags = FREAD;
2798d6d37b8SMatthew Dillon 		if (msg->any.blk_open.modes & DMSG_BLKOPEN_WR)
2808d6d37b8SMatthew Dillon 			fflags |= FWRITE;
281*5bd45597SMatthew Dillon 		error = dev_dopen(dp->d_rawdev, fflags, S_IFCHR,
282*5bd45597SMatthew Dillon 				  proc0.p_ucred, NULL, NULL);
2838d6d37b8SMatthew Dillon 		if (error) {
2848d6d37b8SMatthew Dillon 			error = DMSG_ERR_IO;
2858d6d37b8SMatthew Dillon 		} else {
2868d6d37b8SMatthew Dillon 			if (msg->any.blk_open.modes & DMSG_BLKOPEN_RD)
2878d6d37b8SMatthew Dillon 				++openst->openrd;
2888d6d37b8SMatthew Dillon 			if (msg->any.blk_open.modes & DMSG_BLKOPEN_WR)
2898d6d37b8SMatthew Dillon 				++openst->openwr;
2908d6d37b8SMatthew Dillon 		}
2918d6d37b8SMatthew Dillon 	}
292d30cab67SMatthew Dillon #if 0
2938d6d37b8SMatthew Dillon 	if ((msg->any.head.cmd & DMSGF_CMDSWMASK) == DMSG_BLK_CLOSE &&
2948d6d37b8SMatthew Dillon 	    openst) {
2958d6d37b8SMatthew Dillon 		fflags = 0;
2968d6d37b8SMatthew Dillon 		if ((msg->any.blk_open.modes & DMSG_BLKOPEN_RD) &&
2978d6d37b8SMatthew Dillon 		    openst->openrd) {
2988d6d37b8SMatthew Dillon 			fflags = FREAD;
2998d6d37b8SMatthew Dillon 		}
3008d6d37b8SMatthew Dillon 		if ((msg->any.blk_open.modes & DMSG_BLKOPEN_WR) &&
3018d6d37b8SMatthew Dillon 		    openst->openwr) {
3028d6d37b8SMatthew Dillon 			fflags |= FWRITE;
3038d6d37b8SMatthew Dillon 		}
304ce486e08SMarkus Pfeiffer 		error = dev_dclose(dp->d_rawdev, fflags, S_IFCHR, NULL);
3058d6d37b8SMatthew Dillon 		if (error) {
3068d6d37b8SMatthew Dillon 			error = DMSG_ERR_IO;
3078d6d37b8SMatthew Dillon 		} else {
3088d6d37b8SMatthew Dillon 			if (msg->any.blk_open.modes & DMSG_BLKOPEN_RD)
3098d6d37b8SMatthew Dillon 				--openst->openrd;
3108d6d37b8SMatthew Dillon 			if (msg->any.blk_open.modes & DMSG_BLKOPEN_WR)
3118d6d37b8SMatthew Dillon 				--openst->openwr;
3128d6d37b8SMatthew Dillon 		}
3138d6d37b8SMatthew Dillon 	}
314d30cab67SMatthew Dillon #endif
3158d6d37b8SMatthew Dillon 	if (msg->any.head.cmd & DMSGF_DELETE) {
3168d6d37b8SMatthew Dillon 		if (openst) {
3178d6d37b8SMatthew Dillon 			while (openst->openrd && openst->openwr) {
3188d6d37b8SMatthew Dillon 				--openst->openrd;
3198d6d37b8SMatthew Dillon 				--openst->openwr;
320ce486e08SMarkus Pfeiffer 				dev_dclose(dp->d_rawdev, FREAD|FWRITE, S_IFCHR, NULL);
3218d6d37b8SMatthew Dillon 			}
3228d6d37b8SMatthew Dillon 			while (openst->openrd) {
3238d6d37b8SMatthew Dillon 				--openst->openrd;
324ce486e08SMarkus Pfeiffer 				dev_dclose(dp->d_rawdev, FREAD, S_IFCHR, NULL);
3258d6d37b8SMatthew Dillon 			}
3268d6d37b8SMatthew Dillon 			while (openst->openwr) {
3278d6d37b8SMatthew Dillon 				--openst->openwr;
328ce486e08SMarkus Pfeiffer 				dev_dclose(dp->d_rawdev, FWRITE, S_IFCHR, NULL);
3298d6d37b8SMatthew Dillon 			}
3308d6d37b8SMatthew Dillon 			kfree(openst, M_DEVBUF);
3318d6d37b8SMatthew Dillon 			msg->state->any.any = NULL;
3328d6d37b8SMatthew Dillon 		}
3338d6d37b8SMatthew Dillon 		kdmsg_msg_reply(msg, error);
3348d6d37b8SMatthew Dillon 	} else {
3358d6d37b8SMatthew Dillon 		kdmsg_msg_result(msg, error);
3368d6d37b8SMatthew Dillon 	}
3378d6d37b8SMatthew Dillon }
3388d6d37b8SMatthew Dillon 
3398d6d37b8SMatthew Dillon static
3408d6d37b8SMatthew Dillon void
disk_blk_read(struct disk * dp,kdmsg_msg_t * msg)3418d6d37b8SMatthew Dillon disk_blk_read(struct disk *dp, kdmsg_msg_t *msg)
3428d6d37b8SMatthew Dillon {
3438d6d37b8SMatthew Dillon 	struct dios_io *iost;
3448d6d37b8SMatthew Dillon 	struct buf *bp;
3458d6d37b8SMatthew Dillon 	struct bio *bio;
3468d6d37b8SMatthew Dillon 	int error = DMSG_ERR_NOSUPP;
3478d6d37b8SMatthew Dillon 	int reterr = 1;
3488d6d37b8SMatthew Dillon 
3498d6d37b8SMatthew Dillon 	/*
3508d6d37b8SMatthew Dillon 	 * Only DMSG_BLK_READ commands imply read ops.
3518d6d37b8SMatthew Dillon 	 */
3528d6d37b8SMatthew Dillon 	iost = msg->state->any.any;
3538d6d37b8SMatthew Dillon 	if ((msg->any.head.cmd & DMSGF_CMDSWMASK) == DMSG_BLK_READ) {
3548d6d37b8SMatthew Dillon 		if (msg->any.blk_read.bytes < DEV_BSIZE ||
3558d6d37b8SMatthew Dillon 		    msg->any.blk_read.bytes > MAXPHYS) {
3568d6d37b8SMatthew Dillon 			error = DMSG_ERR_PARAM;
3578d6d37b8SMatthew Dillon 			goto done;
3588d6d37b8SMatthew Dillon 		}
3598d6d37b8SMatthew Dillon 		if (iost == NULL) {
3608d6d37b8SMatthew Dillon 			iost = kmalloc(sizeof(*iost), M_DEVBUF,
3618d6d37b8SMatthew Dillon 				       M_WAITOK | M_ZERO);
3628d6d37b8SMatthew Dillon 			msg->state->any.any = iost;
3638d6d37b8SMatthew Dillon 		}
3648d6d37b8SMatthew Dillon 		reterr = 0;
365bf20632cSMatthew Dillon 		bp = getpbuf_mem(NULL);
366bf20632cSMatthew Dillon 		KKASSERT(msg->any.blk_read.bytes <= bp->b_bufsize);
3678d6d37b8SMatthew Dillon 		bio = &bp->b_bio1;
3688d6d37b8SMatthew Dillon 		bp->b_cmd = BUF_CMD_READ;
3698d6d37b8SMatthew Dillon 		bp->b_bcount = msg->any.blk_read.bytes;
3708d6d37b8SMatthew Dillon 		bp->b_resid = bp->b_bcount;
3718d6d37b8SMatthew Dillon 		bio->bio_offset = msg->any.blk_read.offset;
3728d6d37b8SMatthew Dillon 		bio->bio_caller_info1.ptr = msg->state;
3738d6d37b8SMatthew Dillon 		bio->bio_done = diskiodone;
3748d6d37b8SMatthew Dillon 
37545c1a24bSMatthew Dillon 		/* kdmsg_state_hold(msg->state); */
37645c1a24bSMatthew Dillon 		atomic_add_int(&blk_active, 1);
3778d6d37b8SMatthew Dillon 		atomic_add_int(&iost->count, 1);
3788d6d37b8SMatthew Dillon 		if (msg->any.head.cmd & DMSGF_DELETE)
3798d6d37b8SMatthew Dillon 			iost->eof = 1;
3808d6d37b8SMatthew Dillon 		BUF_KERNPROC(bp);
3818d6d37b8SMatthew Dillon 		dev_dstrategy(dp->d_rawdev, bio);
3828d6d37b8SMatthew Dillon 	}
3838d6d37b8SMatthew Dillon done:
3848d6d37b8SMatthew Dillon 	if (reterr) {
3858d6d37b8SMatthew Dillon 		if (msg->any.head.cmd & DMSGF_DELETE) {
3868d6d37b8SMatthew Dillon 			if (iost && iost->count == 0) {
3878d6d37b8SMatthew Dillon 				kfree(iost, M_DEVBUF);
3888d6d37b8SMatthew Dillon 				msg->state->any.any = NULL;
3898d6d37b8SMatthew Dillon 			}
3908d6d37b8SMatthew Dillon 			kdmsg_msg_reply(msg, error);
3918d6d37b8SMatthew Dillon 		} else {
3928d6d37b8SMatthew Dillon 			kdmsg_msg_result(msg, error);
3938d6d37b8SMatthew Dillon 		}
3948d6d37b8SMatthew Dillon 	}
3958d6d37b8SMatthew Dillon }
3968d6d37b8SMatthew Dillon 
3978d6d37b8SMatthew Dillon static
3988d6d37b8SMatthew Dillon void
disk_blk_write(struct disk * dp,kdmsg_msg_t * msg)3998d6d37b8SMatthew Dillon disk_blk_write(struct disk *dp, kdmsg_msg_t *msg)
4008d6d37b8SMatthew Dillon {
4018d6d37b8SMatthew Dillon 	struct dios_io *iost;
4028d6d37b8SMatthew Dillon 	struct buf *bp;
4038d6d37b8SMatthew Dillon 	struct bio *bio;
4048d6d37b8SMatthew Dillon 	int error = DMSG_ERR_NOSUPP;
4058d6d37b8SMatthew Dillon 	int reterr = 1;
4068d6d37b8SMatthew Dillon 
4078d6d37b8SMatthew Dillon 	/*
4088d6d37b8SMatthew Dillon 	 * Only DMSG_BLK_WRITE commands imply read ops.
4098d6d37b8SMatthew Dillon 	 */
4108d6d37b8SMatthew Dillon 	iost = msg->state->any.any;
4118d6d37b8SMatthew Dillon 	if ((msg->any.head.cmd & DMSGF_CMDSWMASK) == DMSG_BLK_WRITE) {
4128d6d37b8SMatthew Dillon 		if (msg->any.blk_write.bytes < DEV_BSIZE ||
4138d6d37b8SMatthew Dillon 		    msg->any.blk_write.bytes > MAXPHYS) {
4148d6d37b8SMatthew Dillon 			error = DMSG_ERR_PARAM;
4158d6d37b8SMatthew Dillon 			goto done;
4168d6d37b8SMatthew Dillon 		}
4178d6d37b8SMatthew Dillon 		if (iost == NULL) {
4188d6d37b8SMatthew Dillon 			iost = kmalloc(sizeof(*iost), M_DEVBUF,
4198d6d37b8SMatthew Dillon 				       M_WAITOK | M_ZERO);
4208d6d37b8SMatthew Dillon 			msg->state->any.any = iost;
4218d6d37b8SMatthew Dillon 		}
4228d6d37b8SMatthew Dillon 
4238d6d37b8SMatthew Dillon 		/*
4248d6d37b8SMatthew Dillon 		 * Issue WRITE.  Short data implies zeros.  Try to optimize
4258d6d37b8SMatthew Dillon 		 * the buffer cache buffer for the case where we can just
4268d6d37b8SMatthew Dillon 		 * use the message's data pointer.
4278d6d37b8SMatthew Dillon 		 */
4288d6d37b8SMatthew Dillon 		reterr = 0;
4298d6d37b8SMatthew Dillon 		if (msg->aux_size >= msg->any.blk_write.bytes)
4308d6d37b8SMatthew Dillon 			bp = getpbuf(NULL);
4318d6d37b8SMatthew Dillon 		else
432bf20632cSMatthew Dillon 			bp = getpbuf_mem(NULL);
433bf20632cSMatthew Dillon 		KKASSERT(msg->any.blk_write.bytes <= bp->b_bufsize);
4348d6d37b8SMatthew Dillon 		bio = &bp->b_bio1;
4358d6d37b8SMatthew Dillon 		bp->b_cmd = BUF_CMD_WRITE;
4368d6d37b8SMatthew Dillon 		bp->b_bcount = msg->any.blk_write.bytes;
4378d6d37b8SMatthew Dillon 		bp->b_resid = bp->b_bcount;
4388d6d37b8SMatthew Dillon 		if (msg->aux_size >= msg->any.blk_write.bytes) {
4398d6d37b8SMatthew Dillon 			bp->b_data = msg->aux_data;
4401a2a529dSMatthew Dillon 			kdmsg_detach_aux_data(msg, &iost->data);
4418d6d37b8SMatthew Dillon 		} else {
4428d6d37b8SMatthew Dillon 			bcopy(msg->aux_data, bp->b_data, msg->aux_size);
4438d6d37b8SMatthew Dillon 			bzero(bp->b_data + msg->aux_size,
4448d6d37b8SMatthew Dillon 			      msg->any.blk_write.bytes - msg->aux_size);
4451a2a529dSMatthew Dillon 			bzero(&iost->data, sizeof(iost->data));
4468d6d37b8SMatthew Dillon 		}
4478d6d37b8SMatthew Dillon 		bio->bio_offset = msg->any.blk_write.offset;
4488d6d37b8SMatthew Dillon 		bio->bio_caller_info1.ptr = msg->state;
4498d6d37b8SMatthew Dillon 		bio->bio_done = diskiodone;
4508d6d37b8SMatthew Dillon 
45145c1a24bSMatthew Dillon 		/* kdmsg_state_hold(msg->state); */
45245c1a24bSMatthew Dillon 		atomic_add_int(&blk_active, 1);
4538d6d37b8SMatthew Dillon 		atomic_add_int(&iost->count, 1);
4548d6d37b8SMatthew Dillon 		if (msg->any.head.cmd & DMSGF_DELETE)
4558d6d37b8SMatthew Dillon 			iost->eof = 1;
4568d6d37b8SMatthew Dillon 		BUF_KERNPROC(bp);
4578d6d37b8SMatthew Dillon 		dev_dstrategy(dp->d_rawdev, bio);
4588d6d37b8SMatthew Dillon 	}
4598d6d37b8SMatthew Dillon done:
4608d6d37b8SMatthew Dillon 	if (reterr) {
4618d6d37b8SMatthew Dillon 		if (msg->any.head.cmd & DMSGF_DELETE) {
4628d6d37b8SMatthew Dillon 			if (iost && iost->count == 0) {
4638d6d37b8SMatthew Dillon 				kfree(iost, M_DEVBUF);
4648d6d37b8SMatthew Dillon 				msg->state->any.any = NULL;
4658d6d37b8SMatthew Dillon 			}
4668d6d37b8SMatthew Dillon 			kdmsg_msg_reply(msg, error);
4678d6d37b8SMatthew Dillon 		} else {
4688d6d37b8SMatthew Dillon 			kdmsg_msg_result(msg, error);
4698d6d37b8SMatthew Dillon 		}
4708d6d37b8SMatthew Dillon 	}
4718d6d37b8SMatthew Dillon }
4728d6d37b8SMatthew Dillon 
4738d6d37b8SMatthew Dillon static
4748d6d37b8SMatthew Dillon void
disk_blk_flush(struct disk * dp,kdmsg_msg_t * msg)4758d6d37b8SMatthew Dillon disk_blk_flush(struct disk *dp, kdmsg_msg_t *msg)
4768d6d37b8SMatthew Dillon {
4778d6d37b8SMatthew Dillon 	struct dios_io *iost;
4788d6d37b8SMatthew Dillon 	struct buf *bp;
4798d6d37b8SMatthew Dillon 	struct bio *bio;
4808d6d37b8SMatthew Dillon 	int error = DMSG_ERR_NOSUPP;
4818d6d37b8SMatthew Dillon 	int reterr = 1;
4828d6d37b8SMatthew Dillon 
4838d6d37b8SMatthew Dillon 	/*
4848d6d37b8SMatthew Dillon 	 * Only DMSG_BLK_FLUSH commands imply read ops.
4858d6d37b8SMatthew Dillon 	 */
4868d6d37b8SMatthew Dillon 	iost = msg->state->any.any;
4878d6d37b8SMatthew Dillon 	if ((msg->any.head.cmd & DMSGF_CMDSWMASK) == DMSG_BLK_FLUSH) {
4888d6d37b8SMatthew Dillon 		if (iost == NULL) {
4898d6d37b8SMatthew Dillon 			iost = kmalloc(sizeof(*iost), M_DEVBUF,
4908d6d37b8SMatthew Dillon 				       M_WAITOK | M_ZERO);
4918d6d37b8SMatthew Dillon 			msg->state->any.any = iost;
4928d6d37b8SMatthew Dillon 		}
4938d6d37b8SMatthew Dillon 		reterr = 0;
4948d6d37b8SMatthew Dillon 		bp = getpbuf(NULL);
4958d6d37b8SMatthew Dillon 		bio = &bp->b_bio1;
4968d6d37b8SMatthew Dillon 		bp->b_cmd = BUF_CMD_FLUSH;
4978d6d37b8SMatthew Dillon 		bp->b_bcount = msg->any.blk_flush.bytes;
4988d6d37b8SMatthew Dillon 		bp->b_resid = 0;
4998d6d37b8SMatthew Dillon 		bio->bio_offset = msg->any.blk_flush.offset;
5008d6d37b8SMatthew Dillon 		bio->bio_caller_info1.ptr = msg->state;
5018d6d37b8SMatthew Dillon 		bio->bio_done = diskiodone;
5028d6d37b8SMatthew Dillon 
50345c1a24bSMatthew Dillon 		/* kdmsg_state_hold(msg->state); */
50445c1a24bSMatthew Dillon 		atomic_add_int(&blk_active, 1);
5058d6d37b8SMatthew Dillon 		atomic_add_int(&iost->count, 1);
5068d6d37b8SMatthew Dillon 		if (msg->any.head.cmd & DMSGF_DELETE)
5078d6d37b8SMatthew Dillon 			iost->eof = 1;
5088d6d37b8SMatthew Dillon 		BUF_KERNPROC(bp);
5098d6d37b8SMatthew Dillon 		dev_dstrategy(dp->d_rawdev, bio);
5108d6d37b8SMatthew Dillon 	}
5118d6d37b8SMatthew Dillon 	if (reterr) {
5128d6d37b8SMatthew Dillon 		if (msg->any.head.cmd & DMSGF_DELETE) {
5138d6d37b8SMatthew Dillon 			if (iost && iost->count == 0) {
5148d6d37b8SMatthew Dillon 				kfree(iost, M_DEVBUF);
5158d6d37b8SMatthew Dillon 				msg->state->any.any = NULL;
5168d6d37b8SMatthew Dillon 			}
5178d6d37b8SMatthew Dillon 			kdmsg_msg_reply(msg, error);
5188d6d37b8SMatthew Dillon 		} else {
5198d6d37b8SMatthew Dillon 			kdmsg_msg_result(msg, error);
5208d6d37b8SMatthew Dillon 		}
5218d6d37b8SMatthew Dillon 	}
5228d6d37b8SMatthew Dillon }
5238d6d37b8SMatthew Dillon 
5248d6d37b8SMatthew Dillon static
5258d6d37b8SMatthew Dillon void
disk_blk_freeblks(struct disk * dp,kdmsg_msg_t * msg)5268d6d37b8SMatthew Dillon disk_blk_freeblks(struct disk *dp, kdmsg_msg_t *msg)
5278d6d37b8SMatthew Dillon {
5288d6d37b8SMatthew Dillon 	struct dios_io *iost;
5298d6d37b8SMatthew Dillon 	struct buf *bp;
5308d6d37b8SMatthew Dillon 	struct bio *bio;
5318d6d37b8SMatthew Dillon 	int error = DMSG_ERR_NOSUPP;
5328d6d37b8SMatthew Dillon 	int reterr = 1;
5338d6d37b8SMatthew Dillon 
5348d6d37b8SMatthew Dillon 	/*
5358d6d37b8SMatthew Dillon 	 * Only DMSG_BLK_FREEBLKS commands imply read ops.
5368d6d37b8SMatthew Dillon 	 */
5378d6d37b8SMatthew Dillon 	iost = msg->state->any.any;
5388d6d37b8SMatthew Dillon 	if ((msg->any.head.cmd & DMSGF_CMDSWMASK) == DMSG_BLK_FREEBLKS) {
5398d6d37b8SMatthew Dillon 		if (iost == NULL) {
5408d6d37b8SMatthew Dillon 			iost = kmalloc(sizeof(*iost), M_DEVBUF,
5418d6d37b8SMatthew Dillon 				       M_WAITOK | M_ZERO);
5428d6d37b8SMatthew Dillon 			msg->state->any.any = iost;
5438d6d37b8SMatthew Dillon 		}
5448d6d37b8SMatthew Dillon 		reterr = 0;
5458d6d37b8SMatthew Dillon 		bp = getpbuf(NULL);
5468d6d37b8SMatthew Dillon 		bio = &bp->b_bio1;
5478d6d37b8SMatthew Dillon 		bp->b_cmd = BUF_CMD_FREEBLKS;
5488d6d37b8SMatthew Dillon 		bp->b_bcount = msg->any.blk_freeblks.bytes;
5498d6d37b8SMatthew Dillon 		bp->b_resid = 0;
5508d6d37b8SMatthew Dillon 		bio->bio_offset = msg->any.blk_freeblks.offset;
5518d6d37b8SMatthew Dillon 		bio->bio_caller_info1.ptr = msg->state;
5528d6d37b8SMatthew Dillon 		bio->bio_done = diskiodone;
5538d6d37b8SMatthew Dillon 
55445c1a24bSMatthew Dillon 		/* kdmsg_state_hold(msg->state); */
55545c1a24bSMatthew Dillon 		atomic_add_int(&blk_active, 1);
5568d6d37b8SMatthew Dillon 		atomic_add_int(&iost->count, 1);
5578d6d37b8SMatthew Dillon 		if (msg->any.head.cmd & DMSGF_DELETE)
5588d6d37b8SMatthew Dillon 			iost->eof = 1;
5598d6d37b8SMatthew Dillon 		BUF_KERNPROC(bp);
5608d6d37b8SMatthew Dillon 		dev_dstrategy(dp->d_rawdev, bio);
5618d6d37b8SMatthew Dillon 	}
5628d6d37b8SMatthew Dillon 	if (reterr) {
5638d6d37b8SMatthew Dillon 		if (msg->any.head.cmd & DMSGF_DELETE) {
5648d6d37b8SMatthew Dillon 			if (iost && iost->count == 0) {
5658d6d37b8SMatthew Dillon 				kfree(iost, M_DEVBUF);
5668d6d37b8SMatthew Dillon 				msg->state->any.any = NULL;
5678d6d37b8SMatthew Dillon 			}
5688d6d37b8SMatthew Dillon 			kdmsg_msg_reply(msg, error);
5698d6d37b8SMatthew Dillon 		} else {
5708d6d37b8SMatthew Dillon 			kdmsg_msg_result(msg, error);
5718d6d37b8SMatthew Dillon 		}
5728d6d37b8SMatthew Dillon 	}
5738d6d37b8SMatthew Dillon }
5748d6d37b8SMatthew Dillon 
5758d6d37b8SMatthew Dillon static
5768d6d37b8SMatthew Dillon void
diskiodone(struct bio * bio)5778d6d37b8SMatthew Dillon diskiodone(struct bio *bio)
5788d6d37b8SMatthew Dillon {
5798d6d37b8SMatthew Dillon 	struct buf *bp = bio->bio_buf;
5808d6d37b8SMatthew Dillon 	kdmsg_state_t *state = bio->bio_caller_info1.ptr;
5818d6d37b8SMatthew Dillon 	kdmsg_msg_t *rmsg;
5828d6d37b8SMatthew Dillon 	struct dios_io *iost = state->any.any;
5838d6d37b8SMatthew Dillon 	int error;
5848d6d37b8SMatthew Dillon 	int resid = 0;
5858d6d37b8SMatthew Dillon 	int bytes;
5868d6d37b8SMatthew Dillon 	uint32_t cmd;
5878d6d37b8SMatthew Dillon 	void *data;
5888d6d37b8SMatthew Dillon 
5898d6d37b8SMatthew Dillon 	cmd = DMSG_LNK_ERROR;
5908d6d37b8SMatthew Dillon 	data = NULL;
5918d6d37b8SMatthew Dillon 	bytes = 0;
5928d6d37b8SMatthew Dillon 
5938d6d37b8SMatthew Dillon 	switch(bp->b_cmd) {
5948d6d37b8SMatthew Dillon 	case BUF_CMD_READ:
5958d6d37b8SMatthew Dillon 		cmd = DMSG_LNK_ERROR;
5968d6d37b8SMatthew Dillon 		data = bp->b_data;
5978d6d37b8SMatthew Dillon 		bytes = bp->b_bcount;
5988d6d37b8SMatthew Dillon 		/* fall through */
5998d6d37b8SMatthew Dillon 	case BUF_CMD_WRITE:
6008d6d37b8SMatthew Dillon 		if (bp->b_flags & B_ERROR) {
6018d6d37b8SMatthew Dillon 			error = bp->b_error;
6028d6d37b8SMatthew Dillon 		} else {
6038d6d37b8SMatthew Dillon 			error = 0;
6048d6d37b8SMatthew Dillon 			resid = bp->b_resid;
6058d6d37b8SMatthew Dillon 		}
6061a2a529dSMatthew Dillon 		kdmsg_free_aux_data(&iost->data);
6078d6d37b8SMatthew Dillon 		break;
6088d6d37b8SMatthew Dillon 	case BUF_CMD_FLUSH:
6098d6d37b8SMatthew Dillon 	case BUF_CMD_FREEBLKS:
6108d6d37b8SMatthew Dillon 		if (bp->b_flags & B_ERROR)
6118d6d37b8SMatthew Dillon 			error = bp->b_error;
6128d6d37b8SMatthew Dillon 		else
6138d6d37b8SMatthew Dillon 			error = 0;
6148d6d37b8SMatthew Dillon 		break;
6158d6d37b8SMatthew Dillon 	default:
6168d6d37b8SMatthew Dillon 		panic("diskiodone: Unknown bio cmd = %d\n",
6178d6d37b8SMatthew Dillon 		      bio->bio_buf->b_cmd);
6185a78b06aSMatthew Dillon 		error = 0;	/* avoid compiler warning */
6198d6d37b8SMatthew Dillon 		break;		/* NOT REACHED */
6208d6d37b8SMatthew Dillon 	}
6218d6d37b8SMatthew Dillon 
6228d6d37b8SMatthew Dillon 	/*
6235a78b06aSMatthew Dillon 	 * Convert error to DMSG_ERR_* code.
6245a78b06aSMatthew Dillon 	 */
6255a78b06aSMatthew Dillon 	if (error)
6265a78b06aSMatthew Dillon 		error = DMSG_ERR_IO;
6275a78b06aSMatthew Dillon 
6285a78b06aSMatthew Dillon 	/*
6298d6d37b8SMatthew Dillon 	 * Convert LNK_ERROR or BLK_ERROR if non-zero resid.  READS will
6308d6d37b8SMatthew Dillon 	 * have already converted cmd to BLK_ERROR and set up data to return.
6318d6d37b8SMatthew Dillon 	 */
6328d6d37b8SMatthew Dillon 	if (resid && cmd == DMSG_LNK_ERROR)
6338d6d37b8SMatthew Dillon 		cmd = DMSG_BLK_ERROR;
6348d6d37b8SMatthew Dillon 	/* XXX txcmd is delayed so this won't work for streaming */
6358d6d37b8SMatthew Dillon 	if ((state->txcmd & DMSGF_CREATE) == 0)	/* assume serialized */
6368d6d37b8SMatthew Dillon 		cmd |= DMSGF_CREATE;
6378d6d37b8SMatthew Dillon 	if (iost->eof) {
6388d6d37b8SMatthew Dillon 		if (atomic_fetchadd_int(&iost->count, -1) == 1)
6398d6d37b8SMatthew Dillon 			cmd |= DMSGF_DELETE;
6408d6d37b8SMatthew Dillon 	} else {
6418d6d37b8SMatthew Dillon 		atomic_add_int(&iost->count, -1);
6428d6d37b8SMatthew Dillon 	}
64345c1a24bSMatthew Dillon 	atomic_add_int(&blk_active, -1);
6448d6d37b8SMatthew Dillon 	cmd |= DMSGF_REPLY;
6458d6d37b8SMatthew Dillon 
6468d6d37b8SMatthew Dillon 	/*
6478d6d37b8SMatthew Dillon 	 * Allocate a basic or extended reply.  Be careful not to populate
6488d6d37b8SMatthew Dillon 	 * extended header fields unless we allocated an extended reply.
6498d6d37b8SMatthew Dillon 	 */
6501b8eded1SMatthew Dillon 	rmsg = kdmsg_msg_alloc(state, cmd, NULL, 0);
6518d6d37b8SMatthew Dillon 	if (data) {
6528d6d37b8SMatthew Dillon 		rmsg->aux_data = kmalloc(bytes, state->iocom->mmsg, M_INTWAIT);
6538d6d37b8SMatthew Dillon 		rmsg->aux_size = bytes;
6548d6d37b8SMatthew Dillon 		rmsg->flags |= KDMSG_FLAG_AUXALLOC;
6558d6d37b8SMatthew Dillon 		bcopy(data, rmsg->aux_data, bytes);
6568d6d37b8SMatthew Dillon 	}
6578d6d37b8SMatthew Dillon 	rmsg->any.blk_error.head.error = error;
6588d6d37b8SMatthew Dillon 	if ((cmd & DMSGF_BASECMDMASK) == DMSG_BLK_ERROR)
6598d6d37b8SMatthew Dillon 		rmsg->any.blk_error.resid = resid;
6608d6d37b8SMatthew Dillon 	bio->bio_caller_info1.ptr = NULL;
6618d6d37b8SMatthew Dillon 	/* kdmsg_state_drop(state); */
6628d6d37b8SMatthew Dillon 	kdmsg_msg_write(rmsg);
6638d6d37b8SMatthew Dillon 	if (bp->b_flags & B_PAGING) {
664bf20632cSMatthew Dillon 		relpbuf(bp, NULL);
6658d6d37b8SMatthew Dillon 	} else {
6668d6d37b8SMatthew Dillon 		bp->b_flags |= B_INVAL | B_AGE;
667bf20632cSMatthew Dillon 		relpbuf(bp, NULL);
6688d6d37b8SMatthew Dillon 	}
6698d6d37b8SMatthew Dillon }
670