1 /* 2 * Copyright (c) 2012 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/kernel.h> 37 #include <sys/proc.h> 38 #include <sys/sysctl.h> 39 #include <sys/buf.h> 40 #include <sys/conf.h> 41 #include <sys/disklabel.h> 42 #include <sys/disklabel32.h> 43 #include <sys/disklabel64.h> 44 #include <sys/diskslice.h> 45 #include <sys/diskmbr.h> 46 #include <sys/disk.h> 47 #include <sys/malloc.h> 48 #include <sys/device.h> 49 #include <sys/devfs.h> 50 #include <sys/thread.h> 51 #include <sys/queue.h> 52 #include <sys/lock.h> 53 #include <sys/uuid.h> 54 55 #include <sys/dmsg.h> 56 57 #include <sys/buf2.h> 58 #include <sys/mplock2.h> 59 #include <sys/msgport2.h> 60 #include <sys/thread2.h> 61 62 static MALLOC_DEFINE(M_DMSG_DISK, "dmsg_disk", "disk dmsg"); 63 64 static int disk_iocom_reconnect(struct disk *dp, struct file *fp); 65 static int disk_msg_conn_reply(kdmsg_state_t *state, kdmsg_msg_t *msg); 66 static int disk_msg_span_reply(kdmsg_state_t *state, kdmsg_msg_t *msg); 67 68 void 69 disk_iocom_init(struct disk *dp) 70 { 71 kdmsg_iocom_init(&dp->d_iocom, dp, M_DMSG_DISK, 72 disk_lnk_rcvmsg, 73 disk_dbg_rcvmsg, 74 disk_adhoc_input); 75 } 76 77 void 78 disk_iocom_update(struct disk *dp) 79 { 80 } 81 82 void 83 disk_iocom_uninit(struct disk *dp) 84 { 85 kdmsg_iocom_uninit(&dp->d_iocom); 86 } 87 88 int 89 disk_iocom_ioctl(struct disk *dp, int cmd, void *data) 90 { 91 struct file *fp; 92 struct disk_ioc_recluster *recl; 93 int error; 94 95 switch(cmd) { 96 case DIOCRECLUSTER: 97 recl = data; 98 fp = holdfp(curproc->p_fd, recl->fd, -1); 99 if (fp) { 100 error = disk_iocom_reconnect(dp, fp); 101 } else { 102 error = EINVAL; 103 } 104 break; 105 default: 106 error = EOPNOTSUPP; 107 break; 108 } 109 return error; 110 } 111 112 static 113 int 114 disk_iocom_reconnect(struct disk *dp, struct file *fp) 115 { 116 kdmsg_msg_t *msg; 117 char devname[64]; 118 119 ksnprintf(devname, sizeof(devname), "%s%d", 120 dev_dname(dp->d_rawdev), dkunit(dp->d_rawdev)); 121 122 kdmsg_iocom_reconnect(&dp->d_iocom, fp, devname); 123 124 msg = kdmsg_msg_alloc(&dp->d_iocom.router, DMSG_LNK_CONN | DMSGF_CREATE, 125 disk_msg_conn_reply, dp); 126 msg->any.lnk_conn.pfs_type = 0; 127 msg->any.lnk_conn.proto_version = DMSG_SPAN_PROTO_1; 128 msg->any.lnk_conn.peer_type = DMSG_PEER_BLOCK; 129 msg->any.lnk_conn.peer_mask = 1LLU << DMSG_PEER_BLOCK; 130 131 ksnprintf(msg->any.lnk_conn.cl_label, 132 sizeof(msg->any.lnk_conn.cl_label), 133 "%s/%s", hostname, devname); 134 dp->d_iocom.conn_state = msg->state; 135 kdmsg_msg_write(msg); 136 137 return (0); 138 } 139 140 /* 141 * Received reply to our LNK_CONN transaction, indicating LNK_SPAN support. 142 * Issue LNK_SPAN. 143 */ 144 static 145 int 146 disk_msg_conn_reply(kdmsg_state_t *state, kdmsg_msg_t *msg) 147 { 148 struct disk *dp = state->any.any; 149 kdmsg_msg_t *rmsg; 150 151 if (msg->any.head.cmd & DMSGF_CREATE) { 152 kprintf("DISK LNK_CONN received reply\n"); 153 rmsg = kdmsg_msg_alloc(&dp->d_iocom.router, 154 DMSG_LNK_SPAN | DMSGF_CREATE, 155 disk_msg_span_reply, dp); 156 rmsg->any.lnk_span.pfs_type = 0; 157 rmsg->any.lnk_span.proto_version = DMSG_SPAN_PROTO_1; 158 rmsg->any.lnk_span.peer_type = DMSG_PEER_BLOCK; 159 160 ksnprintf(rmsg->any.lnk_span.cl_label, 161 sizeof(rmsg->any.lnk_span.cl_label), 162 "%s/%s%d", 163 hostname, 164 dev_dname(dp->d_rawdev), 165 dkunit(dp->d_rawdev)); 166 kdmsg_msg_write(rmsg); 167 } 168 if ((state->txcmd & DMSGF_DELETE) == 0 && 169 (msg->any.head.cmd & DMSGF_DELETE)) { 170 kprintf("DISK LNK_CONN terminated by remote\n"); 171 dp->d_iocom.conn_state = NULL; 172 kdmsg_msg_reply(msg, 0); 173 } 174 return(0); 175 } 176 177 /* 178 * Reply to our LNK_SPAN. The transaction is left open. 179 */ 180 static 181 int 182 disk_msg_span_reply(kdmsg_state_t *state, kdmsg_msg_t *msg) 183 { 184 /*struct disk *dp = state->any.any;*/ 185 186 kprintf("DISK LNK_SPAN reply received\n"); 187 if ((state->txcmd & DMSGF_DELETE) == 0 && 188 (msg->any.head.cmd & DMSGF_DELETE)) { 189 kdmsg_msg_reply(msg, 0); 190 } 191 return (0); 192 } 193 194 int 195 disk_lnk_rcvmsg(kdmsg_msg_t *msg) 196 { 197 /*struct disk *dp = msg->router->iocom->handle;*/ 198 199 switch(msg->any.head.cmd & DMSGF_TRANSMASK) { 200 case DMSG_LNK_CONN | DMSGF_CREATE: 201 /* 202 * reply & leave trans open 203 */ 204 kprintf("DISK CONN RECEIVE - (just ignore it)\n"); 205 kdmsg_msg_result(msg, 0); 206 break; 207 case DMSG_LNK_SPAN | DMSGF_CREATE: 208 kprintf("DISK SPAN RECEIVE - ADDED FROM CLUSTER\n"); 209 break; 210 case DMSG_LNK_SPAN | DMSGF_DELETE: 211 kprintf("DISK SPAN RECEIVE - DELETED FROM CLUSTER\n"); 212 break; 213 default: 214 break; 215 } 216 return (0); 217 } 218 219 int 220 disk_dbg_rcvmsg(kdmsg_msg_t *msg) 221 { 222 /*struct disk *dp = msg->router->iocom->handle;*/ 223 224 switch(msg->any.head.cmd & DMSGF_CMDSWMASK) { 225 case DMSG_DBG_SHELL: 226 /* 227 * Execute shell command (not supported atm) 228 */ 229 kdmsg_msg_reply(msg, DMSG_ERR_NOSUPP); 230 break; 231 case DMSG_DBG_SHELL | DMSGF_REPLY: 232 if (msg->aux_data) { 233 msg->aux_data[msg->aux_size - 1] = 0; 234 kprintf("DEBUGMSG: %s\n", msg->aux_data); 235 } 236 break; 237 default: 238 kdmsg_msg_reply(msg, DMSG_ERR_NOSUPP); 239 break; 240 } 241 return (0); 242 } 243 244 int 245 disk_adhoc_input(kdmsg_msg_t *msg) 246 { 247 struct disk *dp = msg->router->iocom->handle; 248 249 kprintf("DISK ADHOC INPUT %s%d\n", 250 dev_dname(dp->d_rawdev), dkunit(dp->d_rawdev)); 251 252 return (0); 253 } 254