xref: /dflybsd-src/sys/vfs/hammer2/hammer2_iocom.c (revision c12cfc4ad07eb9a5d7d3b0c346f718520ed82b99)
1d157d4dcSMatthew Dillon /*
268b321c1SMatthew Dillon  * Copyright (c) 2011-2018 The DragonFly Project.  All rights reserved.
3d157d4dcSMatthew Dillon  *
4d157d4dcSMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
5d157d4dcSMatthew Dillon  * by Matthew Dillon <dillon@backplane.com>
6d157d4dcSMatthew Dillon  * by Daniel Flores (GSOC 2013 - mentored by Matthew Dillon, compression)
7d157d4dcSMatthew Dillon  *
8d157d4dcSMatthew Dillon  * Redistribution and use in source and binary forms, with or without
9d157d4dcSMatthew Dillon  * modification, are permitted provided that the following conditions
10d157d4dcSMatthew Dillon  * are met:
11d157d4dcSMatthew Dillon  *
12d157d4dcSMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
13d157d4dcSMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
14d157d4dcSMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
15d157d4dcSMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
16d157d4dcSMatthew Dillon  *    the documentation and/or other materials provided with the
17d157d4dcSMatthew Dillon  *    distribution.
18d157d4dcSMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
19d157d4dcSMatthew Dillon  *    contributors may be used to endorse or promote products derived
20d157d4dcSMatthew Dillon  *    from this software without specific, prior written permission.
21d157d4dcSMatthew Dillon  *
22d157d4dcSMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23d157d4dcSMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24d157d4dcSMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25d157d4dcSMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
26d157d4dcSMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27d157d4dcSMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
28d157d4dcSMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29d157d4dcSMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30d157d4dcSMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31d157d4dcSMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32d157d4dcSMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33d157d4dcSMatthew Dillon  * SUCH DAMAGE.
34d157d4dcSMatthew Dillon  */
35d157d4dcSMatthew Dillon #include <sys/param.h>
36d157d4dcSMatthew Dillon #include <sys/systm.h>
37d157d4dcSMatthew Dillon #include <sys/kernel.h>
38d157d4dcSMatthew Dillon #include <sys/mount.h>
39d157d4dcSMatthew Dillon #include <sys/uuid.h>
40d157d4dcSMatthew Dillon #include <sys/socket.h>
41d157d4dcSMatthew Dillon #include <sys/proc.h>
42*c12cfc4aSTomohiro Kusumi #include <sys/file.h>
43d157d4dcSMatthew Dillon 
44d157d4dcSMatthew Dillon #include "hammer2.h"
45d157d4dcSMatthew Dillon 
46d157d4dcSMatthew Dillon static int hammer2_rcvdmsg(kdmsg_msg_t *msg);
47d157d4dcSMatthew Dillon static void hammer2_autodmsg(kdmsg_msg_t *msg);
48d157d4dcSMatthew Dillon static int hammer2_lnk_span_reply(kdmsg_state_t *state, kdmsg_msg_t *msg);
49d157d4dcSMatthew Dillon 
50d157d4dcSMatthew Dillon void
hammer2_iocom_init(hammer2_dev_t * hmp)51506bd6d1SMatthew Dillon hammer2_iocom_init(hammer2_dev_t *hmp)
52d157d4dcSMatthew Dillon {
53d157d4dcSMatthew Dillon 	/*
54d157d4dcSMatthew Dillon 	 * Automatic LNK_CONN
55d157d4dcSMatthew Dillon 	 * Automatic LNK_SPAN handling
56d157d4dcSMatthew Dillon 	 * No automatic LNK_SPAN generation (we generate multiple spans
57d157d4dcSMatthew Dillon 	 *				     ourselves).
58d157d4dcSMatthew Dillon 	 */
59d157d4dcSMatthew Dillon 	kdmsg_iocom_init(&hmp->iocom, hmp,
60d157d4dcSMatthew Dillon 			 KDMSG_IOCOMF_AUTOCONN |
61d157d4dcSMatthew Dillon 			 KDMSG_IOCOMF_AUTORXSPAN,
62e9dbfea1SMatthew Dillon 			 hmp->mmsg, hammer2_rcvdmsg);
63d157d4dcSMatthew Dillon }
64d157d4dcSMatthew Dillon 
65d157d4dcSMatthew Dillon void
hammer2_iocom_uninit(hammer2_dev_t * hmp)66506bd6d1SMatthew Dillon hammer2_iocom_uninit(hammer2_dev_t *hmp)
67d157d4dcSMatthew Dillon {
683c198419SMatthew Dillon 	/* XXX chain depend deadlck? */
693c198419SMatthew Dillon 	if (hmp->iocom.mmsg)
703c198419SMatthew Dillon 		kdmsg_iocom_uninit(&hmp->iocom);
71d157d4dcSMatthew Dillon }
72d157d4dcSMatthew Dillon 
73d157d4dcSMatthew Dillon /*
74d157d4dcSMatthew Dillon  * Reconnect using the passed file pointer.  The caller must ref the
75d157d4dcSMatthew Dillon  * fp for us.
76d157d4dcSMatthew Dillon  */
77d157d4dcSMatthew Dillon void
hammer2_cluster_reconnect(hammer2_dev_t * hmp,struct file * fp)78506bd6d1SMatthew Dillon hammer2_cluster_reconnect(hammer2_dev_t *hmp, struct file *fp)
79d157d4dcSMatthew Dillon {
80d157d4dcSMatthew Dillon 	/*
81d157d4dcSMatthew Dillon 	 * Closes old comm descriptor, kills threads, cleans up
82d157d4dcSMatthew Dillon 	 * states, then installs the new descriptor and creates
83d157d4dcSMatthew Dillon 	 * new threads.
84d157d4dcSMatthew Dillon 	 */
85d157d4dcSMatthew Dillon 	kdmsg_iocom_reconnect(&hmp->iocom, fp, "hammer2");
86d157d4dcSMatthew Dillon 
87d157d4dcSMatthew Dillon 	/*
887750fd72SMatthew Dillon 	 * Setup LNK_CONN fields for autoinitiated state machine.  LNK_CONN
897750fd72SMatthew Dillon 	 * does not have to be unique.  peer_id can be used to filter incoming
907750fd72SMatthew Dillon 	 * LNK_SPANs automatically if desired (though we still need to check).
917750fd72SMatthew Dillon 	 * peer_label typically identifies who we are and is not a filter.
92d157d4dcSMatthew Dillon 	 *
937750fd72SMatthew Dillon 	 * Since we will be initiating multiple LNK_SPANs we cannot use
947750fd72SMatthew Dillon 	 * AUTOTXSPAN, but we do use AUTORXSPAN so kdmsg tracks received
957750fd72SMatthew Dillon 	 * LNK_SPANs, and we simply monitor those messages.
96d157d4dcSMatthew Dillon 	 */
977750fd72SMatthew Dillon 	bzero(&hmp->iocom.auto_lnk_conn.peer_id,
987750fd72SMatthew Dillon 	      sizeof(hmp->iocom.auto_lnk_conn.peer_id));
997750fd72SMatthew Dillon 	/* hmp->iocom.auto_lnk_conn.peer_id = hmp->voldata.fsid; */
100d157d4dcSMatthew Dillon 	hmp->iocom.auto_lnk_conn.proto_version = DMSG_SPAN_PROTO_1;
101d157d4dcSMatthew Dillon #if 0
102d157d4dcSMatthew Dillon 	hmp->iocom.auto_lnk_conn.peer_type = hmp->voldata.peer_type;
103d157d4dcSMatthew Dillon #endif
104d157d4dcSMatthew Dillon 	hmp->iocom.auto_lnk_conn.peer_type = DMSG_PEER_HAMMER2;
105d157d4dcSMatthew Dillon 
106d157d4dcSMatthew Dillon 	/*
1077750fd72SMatthew Dillon 	 * We just want to receive LNK_SPANs related to HAMMER2 matching
1087750fd72SMatthew Dillon 	 * peer_id.
109d157d4dcSMatthew Dillon 	 */
110d157d4dcSMatthew Dillon 	hmp->iocom.auto_lnk_conn.peer_mask = 1LLU << DMSG_PEER_HAMMER2;
111d157d4dcSMatthew Dillon 
112d157d4dcSMatthew Dillon #if 0
113b0f58de8SMatthew Dillon 	switch (ipdata->meta.pfs_type) {
114d157d4dcSMatthew Dillon 	case DMSG_PFSTYPE_CLIENT:
115d157d4dcSMatthew Dillon 		hmp->iocom.auto_lnk_conn.peer_mask &=
116d157d4dcSMatthew Dillon 				~(1LLU << DMSG_PFSTYPE_CLIENT);
117d157d4dcSMatthew Dillon 		break;
118d157d4dcSMatthew Dillon 	default:
119d157d4dcSMatthew Dillon 		break;
120d157d4dcSMatthew Dillon 	}
121d157d4dcSMatthew Dillon #endif
122d157d4dcSMatthew Dillon 
1237750fd72SMatthew Dillon 	bzero(&hmp->iocom.auto_lnk_conn.peer_label,
1247750fd72SMatthew Dillon 	      sizeof(hmp->iocom.auto_lnk_conn.peer_label));
1257750fd72SMatthew Dillon 	ksnprintf(hmp->iocom.auto_lnk_conn.peer_label,
1267750fd72SMatthew Dillon 		  sizeof(hmp->iocom.auto_lnk_conn.peer_label),
1277750fd72SMatthew Dillon 		  "%s/%s",
1287750fd72SMatthew Dillon 		  hostname, "hammer2-mount");
129d157d4dcSMatthew Dillon 	kdmsg_iocom_autoinitiate(&hmp->iocom, hammer2_autodmsg);
130d157d4dcSMatthew Dillon }
131d157d4dcSMatthew Dillon 
132d157d4dcSMatthew Dillon static int
hammer2_rcvdmsg(kdmsg_msg_t * msg)133d157d4dcSMatthew Dillon hammer2_rcvdmsg(kdmsg_msg_t *msg)
134d157d4dcSMatthew Dillon {
135d157d4dcSMatthew Dillon 	kprintf("RCVMSG %08x\n", msg->tcmd);
136d157d4dcSMatthew Dillon 
137d157d4dcSMatthew Dillon 	switch(msg->tcmd) {
138d157d4dcSMatthew Dillon 	case DMSG_DBG_SHELL:
139d157d4dcSMatthew Dillon 		/*
140d157d4dcSMatthew Dillon 		 * (non-transaction)
141d157d4dcSMatthew Dillon 		 * Execute shell command (not supported atm)
142d157d4dcSMatthew Dillon 		 */
143d157d4dcSMatthew Dillon 		kdmsg_msg_result(msg, DMSG_ERR_NOSUPP);
144d157d4dcSMatthew Dillon 		break;
145d157d4dcSMatthew Dillon 	case DMSG_DBG_SHELL | DMSGF_REPLY:
146d157d4dcSMatthew Dillon 		/*
147d157d4dcSMatthew Dillon 		 * (non-transaction)
148d157d4dcSMatthew Dillon 		 */
149d157d4dcSMatthew Dillon 		if (msg->aux_data) {
150d157d4dcSMatthew Dillon 			msg->aux_data[msg->aux_size - 1] = 0;
151d157d4dcSMatthew Dillon 			kprintf("HAMMER2 DBG: %s\n", msg->aux_data);
152d157d4dcSMatthew Dillon 		}
153d157d4dcSMatthew Dillon 		break;
154d157d4dcSMatthew Dillon 	default:
155d157d4dcSMatthew Dillon 		/*
156d157d4dcSMatthew Dillon 		 * Unsupported message received.  We only need to
157d157d4dcSMatthew Dillon 		 * reply if it's a transaction in order to close our end.
158d157d4dcSMatthew Dillon 		 * Ignore any one-way messages or any further messages
159d157d4dcSMatthew Dillon 		 * associated with the transaction.
160d157d4dcSMatthew Dillon 		 *
161d157d4dcSMatthew Dillon 		 * NOTE: This case also includes DMSG_LNK_ERROR messages
162d157d4dcSMatthew Dillon 		 *	 which might be one-way, replying to those would
163d157d4dcSMatthew Dillon 		 *	 cause an infinite ping-pong.
164d157d4dcSMatthew Dillon 		 */
165d157d4dcSMatthew Dillon 		if (msg->any.head.cmd & DMSGF_CREATE)
166d157d4dcSMatthew Dillon 			kdmsg_msg_reply(msg, DMSG_ERR_NOSUPP);
167d157d4dcSMatthew Dillon 		break;
168d157d4dcSMatthew Dillon 	}
169d157d4dcSMatthew Dillon 	return(0);
170d157d4dcSMatthew Dillon }
171d157d4dcSMatthew Dillon 
172d157d4dcSMatthew Dillon /*
173d157d4dcSMatthew Dillon  * This function is called after KDMSG has automatically handled processing
174d157d4dcSMatthew Dillon  * of a LNK layer message (typically CONN or SPAN).
175d157d4dcSMatthew Dillon  *
176c4421f07SMatthew Dillon  * We trampoline off LNK_CONN (link level connection advertising the presence
177c4421f07SMatthew Dillon  * of H2 partitions) to generate LNK_HAMMER2_VOLCONF's from the vol->copyinfo[]
178c4421f07SMatthew Dillon  * array in the volume header, and to generate LNK_SPANs advertising all PFSs
179c4421f07SMatthew Dillon  * available from that volume.  Currently the VOLCONFs go through the motions
180c4421f07SMatthew Dillon  * but are otherwise ignored.
181d157d4dcSMatthew Dillon  *
182c4421f07SMatthew Dillon  * We collect LNK_SPAN state for hammer2 peers and turn those into 'remote'
183c4421f07SMatthew Dillon  * PFSs which look similar to local (direct storage) PFSs.  These PFSs are
184c4421f07SMatthew Dillon  * merged with local PFSs and may be mounted locally or merged with other
185c4421f07SMatthew Dillon  * elements that might or might not include local cluster components (local
186c4421f07SMatthew Dillon  * PFSs).  If you wish to ensure that a mandatory PFS rendezvous is present
187c4421f07SMatthew Dillon  * even without network connectivity you would normally just create a dummy
188c4421f07SMatthew Dillon  * local PFS configured as PFSTYPE_CACHE (that can be small and ram-backed).
189c4421f07SMatthew Dillon  *
190c4421f07SMatthew Dillon  * Remote PFSs are object-based and operate using an (inode,key) DMSG API
191c4421f07SMatthew Dillon  * instead of hammer2_chain's + direct I/O.  A high level XOP API is employed
192c4421f07SMatthew Dillon  * to retain integrity across operations such as rename()s.
193d157d4dcSMatthew Dillon  */
194506bd6d1SMatthew Dillon static void hammer2_update_spans(hammer2_dev_t *hmp, kdmsg_state_t *state);
195d157d4dcSMatthew Dillon 
196d157d4dcSMatthew Dillon static void
hammer2_autodmsg(kdmsg_msg_t * msg)197d157d4dcSMatthew Dillon hammer2_autodmsg(kdmsg_msg_t *msg)
198d157d4dcSMatthew Dillon {
199506bd6d1SMatthew Dillon 	hammer2_dev_t *hmp = msg->state->iocom->handle;
200d157d4dcSMatthew Dillon 	int copyid;
201d157d4dcSMatthew Dillon 
202d157d4dcSMatthew Dillon 	switch(msg->tcmd) {
203d157d4dcSMatthew Dillon 	case DMSG_LNK_CONN | DMSGF_CREATE:
204d157d4dcSMatthew Dillon 	case DMSG_LNK_CONN | DMSGF_CREATE | DMSGF_DELETE:
205d157d4dcSMatthew Dillon 	case DMSG_LNK_CONN | DMSGF_DELETE:
206d157d4dcSMatthew Dillon 		/*
207d157d4dcSMatthew Dillon 		 * NOTE: kern_dmsg will automatically issue a result,
208d157d4dcSMatthew Dillon 		 *       leaving the transaction open, for CREATEs,
209d157d4dcSMatthew Dillon 		 *	 and will automatically issue a terminating reply
210d157d4dcSMatthew Dillon 		 *	 for DELETEs.
211d157d4dcSMatthew Dillon 		 */
212d157d4dcSMatthew Dillon 		break;
213d157d4dcSMatthew Dillon 	case DMSG_LNK_CONN | DMSGF_CREATE | DMSGF_REPLY:
214d157d4dcSMatthew Dillon 	case DMSG_LNK_CONN | DMSGF_CREATE | DMSGF_DELETE | DMSGF_REPLY:
215d157d4dcSMatthew Dillon 		/*
216d157d4dcSMatthew Dillon 		 * Do a volume configuration dump when we receive a reply
217d157d4dcSMatthew Dillon 		 * to our auto-CONN (typically leaving the transaction open).
218d157d4dcSMatthew Dillon 		 */
219d157d4dcSMatthew Dillon 		if (msg->any.head.cmd & DMSGF_CREATE) {
220d157d4dcSMatthew Dillon 			kprintf("HAMMER2: VOLDATA DUMP\n");
221d157d4dcSMatthew Dillon 
222d157d4dcSMatthew Dillon 			/*
223d157d4dcSMatthew Dillon 			 * Dump the configuration stored in the volume header.
224d157d4dcSMatthew Dillon 			 * This will typically be import/export access rights,
225d157d4dcSMatthew Dillon 			 * master encryption keys (encrypted), etc.
226d157d4dcSMatthew Dillon 			 */
227d157d4dcSMatthew Dillon 			hammer2_voldata_lock(hmp);
228d157d4dcSMatthew Dillon 			copyid = 0;
229d157d4dcSMatthew Dillon 			while (copyid < HAMMER2_COPYID_COUNT) {
230d157d4dcSMatthew Dillon 				if (hmp->voldata.copyinfo[copyid].copyid)
231d157d4dcSMatthew Dillon 					hammer2_volconf_update(hmp, copyid);
232d157d4dcSMatthew Dillon 				++copyid;
233d157d4dcSMatthew Dillon 			}
234d157d4dcSMatthew Dillon 			hammer2_voldata_unlock(hmp);
235d157d4dcSMatthew Dillon 
236d157d4dcSMatthew Dillon 			kprintf("HAMMER2: INITIATE SPANs\n");
237d157d4dcSMatthew Dillon 			hammer2_update_spans(hmp, msg->state);
238d157d4dcSMatthew Dillon 		}
239d157d4dcSMatthew Dillon 		if ((msg->any.head.cmd & DMSGF_DELETE) &&
240d157d4dcSMatthew Dillon 		    msg->state && (msg->state->txcmd & DMSGF_DELETE) == 0) {
241d157d4dcSMatthew Dillon 			kprintf("HAMMER2: CONN WAS TERMINATED\n");
242d157d4dcSMatthew Dillon 		}
243d157d4dcSMatthew Dillon 		break;
244d157d4dcSMatthew Dillon 	case DMSG_LNK_SPAN | DMSGF_CREATE:
245d157d4dcSMatthew Dillon 		/*
246d157d4dcSMatthew Dillon 		 * Monitor SPANs and issue a result, leaving the SPAN open
247d157d4dcSMatthew Dillon 		 * if it is something we can use now or in the future.
248d157d4dcSMatthew Dillon 		 */
249d157d4dcSMatthew Dillon 		if (msg->any.lnk_span.peer_type != DMSG_PEER_HAMMER2) {
250d157d4dcSMatthew Dillon 			kdmsg_msg_reply(msg, 0);
251d157d4dcSMatthew Dillon 			break;
252d157d4dcSMatthew Dillon 		}
253d157d4dcSMatthew Dillon 		if (msg->any.lnk_span.proto_version != DMSG_SPAN_PROTO_1) {
254d157d4dcSMatthew Dillon 			kdmsg_msg_reply(msg, 0);
255d157d4dcSMatthew Dillon 			break;
256d157d4dcSMatthew Dillon 		}
2577750fd72SMatthew Dillon 		DMSG_TERMINATE_STRING(msg->any.lnk_span.peer_label);
25895bf987fSMatthew Dillon 		if (hammer2_debug & 0x0100) {
2597750fd72SMatthew Dillon 			kprintf("H2 +RXSPAN cmd=%08x (%-20s) cl=",
26095bf987fSMatthew Dillon 				msg->any.head.cmd,
26195bf987fSMatthew Dillon 				msg->any.lnk_span.peer_label);
2627750fd72SMatthew Dillon 			printf_uuid(&msg->any.lnk_span.peer_id);
263d157d4dcSMatthew Dillon 			kprintf(" fs=");
2647750fd72SMatthew Dillon 			printf_uuid(&msg->any.lnk_span.pfs_id);
265d157d4dcSMatthew Dillon 			kprintf(" type=%d\n", msg->any.lnk_span.pfs_type);
26695bf987fSMatthew Dillon 		}
267d157d4dcSMatthew Dillon 		kdmsg_msg_result(msg, 0);
268d157d4dcSMatthew Dillon 		break;
269d157d4dcSMatthew Dillon 	case DMSG_LNK_SPAN | DMSGF_DELETE:
270d157d4dcSMatthew Dillon 		/*
271d157d4dcSMatthew Dillon 		 * NOTE: kern_dmsg will automatically reply to DELETEs.
272d157d4dcSMatthew Dillon 		 */
27395bf987fSMatthew Dillon 		if (hammer2_debug & 0x0100)
274d157d4dcSMatthew Dillon 			kprintf("H2 -RXSPAN\n");
275d157d4dcSMatthew Dillon 		break;
276d157d4dcSMatthew Dillon 	default:
277d157d4dcSMatthew Dillon 		break;
278d157d4dcSMatthew Dillon 	}
279d157d4dcSMatthew Dillon }
280d157d4dcSMatthew Dillon 
281d157d4dcSMatthew Dillon /*
282d157d4dcSMatthew Dillon  * Update LNK_SPAN state
283d157d4dcSMatthew Dillon  */
284d157d4dcSMatthew Dillon static void
hammer2_update_spans(hammer2_dev_t * hmp,kdmsg_state_t * state)285506bd6d1SMatthew Dillon hammer2_update_spans(hammer2_dev_t *hmp, kdmsg_state_t *state)
286d157d4dcSMatthew Dillon {
287d157d4dcSMatthew Dillon 	const hammer2_inode_data_t *ripdata;
28801d71aa5SMatthew Dillon 	hammer2_chain_t *parent;
28901d71aa5SMatthew Dillon 	hammer2_chain_t *chain;
290506bd6d1SMatthew Dillon 	hammer2_pfs_t *spmp;
291d157d4dcSMatthew Dillon 	hammer2_key_t key_next;
292d157d4dcSMatthew Dillon 	kdmsg_msg_t *rmsg;
293d157d4dcSMatthew Dillon 	size_t name_len;
294c8c0a18aSMatthew Dillon 	int error;
295d157d4dcSMatthew Dillon 
296d157d4dcSMatthew Dillon 	/*
297d157d4dcSMatthew Dillon 	 * Lookup mount point under the media-localized super-root.
298d157d4dcSMatthew Dillon 	 *
299d157d4dcSMatthew Dillon 	 * cluster->pmp will incorrectly point to spmp and must be fixed
300d157d4dcSMatthew Dillon 	 * up later on.
301d157d4dcSMatthew Dillon 	 */
302d157d4dcSMatthew Dillon 	spmp = hmp->spmp;
303b7add675SMatthew Dillon 	hammer2_inode_lock(spmp->iroot, 0);
304c8c0a18aSMatthew Dillon 	error = 0;
30501d71aa5SMatthew Dillon 
30601d71aa5SMatthew Dillon 	parent = hammer2_inode_chain(spmp->iroot, 0, HAMMER2_RESOLVE_ALWAYS);
30701d71aa5SMatthew Dillon 	chain = NULL;
30801d71aa5SMatthew Dillon 	if (parent == NULL)
30901d71aa5SMatthew Dillon 		goto done;
31001d71aa5SMatthew Dillon 	chain = hammer2_chain_lookup(&parent, &key_next,
31101d71aa5SMatthew Dillon 				     HAMMER2_KEY_MIN, HAMMER2_KEY_MAX,
312c8c0a18aSMatthew Dillon 				     &error, 0);
31301d71aa5SMatthew Dillon 	while (chain) {
31401d71aa5SMatthew Dillon 		if (chain->bref.type != HAMMER2_BREF_TYPE_INODE)
315d157d4dcSMatthew Dillon 			continue;
31601d71aa5SMatthew Dillon 		ripdata = &chain->data->ipdata;
31739a93972SMatthew Dillon #if 0
318d157d4dcSMatthew Dillon 		kprintf("UPDATE SPANS: %s\n", ripdata->filename);
31939a93972SMatthew Dillon #endif
320d157d4dcSMatthew Dillon 
321d157d4dcSMatthew Dillon 		rmsg = kdmsg_msg_alloc(&hmp->iocom.state0,
322d157d4dcSMatthew Dillon 				       DMSG_LNK_SPAN | DMSGF_CREATE,
323d157d4dcSMatthew Dillon 				       hammer2_lnk_span_reply, NULL);
324b0f58de8SMatthew Dillon 		rmsg->any.lnk_span.peer_id = ripdata->meta.pfs_clid;
325b0f58de8SMatthew Dillon 		rmsg->any.lnk_span.pfs_id = ripdata->meta.pfs_fsid;
326b0f58de8SMatthew Dillon 		rmsg->any.lnk_span.pfs_type = ripdata->meta.pfs_type;
327d157d4dcSMatthew Dillon 		rmsg->any.lnk_span.peer_type = DMSG_PEER_HAMMER2;
328d157d4dcSMatthew Dillon 		rmsg->any.lnk_span.proto_version = DMSG_SPAN_PROTO_1;
329b0f58de8SMatthew Dillon 		name_len = ripdata->meta.name_len;
3307750fd72SMatthew Dillon 		if (name_len >= sizeof(rmsg->any.lnk_span.peer_label))
3317750fd72SMatthew Dillon 			name_len = sizeof(rmsg->any.lnk_span.peer_label) - 1;
3327750fd72SMatthew Dillon 		bcopy(ripdata->filename,
3337750fd72SMatthew Dillon 		      rmsg->any.lnk_span.peer_label,
3347750fd72SMatthew Dillon 		      name_len);
335d157d4dcSMatthew Dillon 
336d157d4dcSMatthew Dillon 		kdmsg_msg_write(rmsg);
337d157d4dcSMatthew Dillon 
33801d71aa5SMatthew Dillon 		chain = hammer2_chain_next(&parent, chain, &key_next,
33901d71aa5SMatthew Dillon 					       key_next, HAMMER2_KEY_MAX,
340c8c0a18aSMatthew Dillon 					       &error, 0);
341d157d4dcSMatthew Dillon 	}
342b7add675SMatthew Dillon 	hammer2_inode_unlock(spmp->iroot);
343c8c0a18aSMatthew Dillon 	/* XXX do something with error */
34401d71aa5SMatthew Dillon done:
34501d71aa5SMatthew Dillon 	if (chain) {
34601d71aa5SMatthew Dillon 		hammer2_chain_unlock(chain);
34701d71aa5SMatthew Dillon 		hammer2_chain_drop(chain);
34801d71aa5SMatthew Dillon 	}
34901d71aa5SMatthew Dillon 	if (parent) {
35001d71aa5SMatthew Dillon 		hammer2_chain_unlock(parent);
35101d71aa5SMatthew Dillon 		hammer2_chain_drop(parent);
352b7add675SMatthew Dillon 	}
353d157d4dcSMatthew Dillon }
354d157d4dcSMatthew Dillon 
355d157d4dcSMatthew Dillon static
356d157d4dcSMatthew Dillon int
hammer2_lnk_span_reply(kdmsg_state_t * state,kdmsg_msg_t * msg)357d157d4dcSMatthew Dillon hammer2_lnk_span_reply(kdmsg_state_t *state, kdmsg_msg_t *msg)
358d157d4dcSMatthew Dillon {
359d157d4dcSMatthew Dillon 	if ((state->txcmd & DMSGF_DELETE) == 0 &&
360d157d4dcSMatthew Dillon 	    (msg->any.head.cmd & DMSGF_DELETE)) {
361d157d4dcSMatthew Dillon 		kdmsg_msg_reply(msg, 0);
362d157d4dcSMatthew Dillon 	}
363d157d4dcSMatthew Dillon 	return 0;
364d157d4dcSMatthew Dillon }
365d157d4dcSMatthew Dillon 
366d157d4dcSMatthew Dillon /*
367d157d4dcSMatthew Dillon  * Volume configuration updates are passed onto the userland service
368d157d4dcSMatthew Dillon  * daemon via the open LNK_CONN transaction.
369d157d4dcSMatthew Dillon  */
370d157d4dcSMatthew Dillon void
hammer2_volconf_update(hammer2_dev_t * hmp,int index)371506bd6d1SMatthew Dillon hammer2_volconf_update(hammer2_dev_t *hmp, int index)
372d157d4dcSMatthew Dillon {
373d157d4dcSMatthew Dillon 	kdmsg_msg_t *msg;
374d157d4dcSMatthew Dillon 
375d157d4dcSMatthew Dillon 	/* XXX interlock against connection state termination */
376d157d4dcSMatthew Dillon 	kprintf("volconf update %p\n", hmp->iocom.conn_state);
377d157d4dcSMatthew Dillon 	if (hmp->iocom.conn_state) {
378d157d4dcSMatthew Dillon 		kprintf("TRANSMIT VOLCONF VIA OPEN CONN TRANSACTION\n");
379d157d4dcSMatthew Dillon 		msg = kdmsg_msg_alloc(hmp->iocom.conn_state,
380d157d4dcSMatthew Dillon 				      DMSG_LNK_HAMMER2_VOLCONF,
381d157d4dcSMatthew Dillon 				      NULL, NULL);
382d157d4dcSMatthew Dillon 		H2_LNK_VOLCONF(msg)->copy = hmp->voldata.copyinfo[index];
383d157d4dcSMatthew Dillon 		H2_LNK_VOLCONF(msg)->mediaid = hmp->voldata.fsid;
384d157d4dcSMatthew Dillon 		H2_LNK_VOLCONF(msg)->index = index;
385d157d4dcSMatthew Dillon 		kdmsg_msg_write(msg);
386d157d4dcSMatthew Dillon 	}
387d157d4dcSMatthew Dillon }
388