xref: /dflybsd-src/sys/vfs/hammer2/hammer2_iocom.c (revision 95bf987f4dc2309fd93b0cf0832ef6696d5a74c5)
1d157d4dcSMatthew Dillon /*
2d157d4dcSMatthew Dillon  * Copyright (c) 2011-2015 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/nlookup.h>
39d157d4dcSMatthew Dillon #include <sys/vnode.h>
40d157d4dcSMatthew Dillon #include <sys/mount.h>
41d157d4dcSMatthew Dillon #include <sys/fcntl.h>
42d157d4dcSMatthew Dillon #include <sys/buf.h>
43d157d4dcSMatthew Dillon #include <sys/uuid.h>
44d157d4dcSMatthew Dillon #include <sys/vfsops.h>
45d157d4dcSMatthew Dillon #include <sys/sysctl.h>
46d157d4dcSMatthew Dillon #include <sys/socket.h>
47d157d4dcSMatthew Dillon #include <sys/objcache.h>
48d157d4dcSMatthew Dillon 
49d157d4dcSMatthew Dillon #include <sys/proc.h>
50d157d4dcSMatthew Dillon #include <sys/namei.h>
51d157d4dcSMatthew Dillon #include <sys/mountctl.h>
52d157d4dcSMatthew Dillon #include <sys/dirent.h>
53d157d4dcSMatthew Dillon #include <sys/uio.h>
54d157d4dcSMatthew Dillon 
55d157d4dcSMatthew Dillon #include <sys/mutex.h>
56d157d4dcSMatthew Dillon #include <sys/mutex2.h>
57d157d4dcSMatthew Dillon 
58d157d4dcSMatthew Dillon #include "hammer2.h"
59d157d4dcSMatthew Dillon #include "hammer2_disk.h"
60d157d4dcSMatthew Dillon #include "hammer2_mount.h"
61d157d4dcSMatthew Dillon 
62d157d4dcSMatthew Dillon static int hammer2_rcvdmsg(kdmsg_msg_t *msg);
63d157d4dcSMatthew Dillon static void hammer2_autodmsg(kdmsg_msg_t *msg);
64d157d4dcSMatthew Dillon static int hammer2_lnk_span_reply(kdmsg_state_t *state, kdmsg_msg_t *msg);
65d157d4dcSMatthew Dillon 
66d157d4dcSMatthew Dillon void
67506bd6d1SMatthew Dillon hammer2_iocom_init(hammer2_dev_t *hmp)
68d157d4dcSMatthew Dillon {
69d157d4dcSMatthew Dillon 	/*
70d157d4dcSMatthew Dillon 	 * Automatic LNK_CONN
71d157d4dcSMatthew Dillon 	 * Automatic LNK_SPAN handling
72d157d4dcSMatthew Dillon 	 * No automatic LNK_SPAN generation (we generate multiple spans
73d157d4dcSMatthew Dillon 	 *				     ourselves).
74d157d4dcSMatthew Dillon 	 */
75d157d4dcSMatthew Dillon 	kdmsg_iocom_init(&hmp->iocom, hmp,
76d157d4dcSMatthew Dillon 			 KDMSG_IOCOMF_AUTOCONN |
77d157d4dcSMatthew Dillon 			 KDMSG_IOCOMF_AUTORXSPAN,
78d157d4dcSMatthew Dillon 			 hmp->mchain, hammer2_rcvdmsg);
79d157d4dcSMatthew Dillon }
80d157d4dcSMatthew Dillon 
81d157d4dcSMatthew Dillon void
82506bd6d1SMatthew Dillon hammer2_iocom_uninit(hammer2_dev_t *hmp)
83d157d4dcSMatthew Dillon {
843c198419SMatthew Dillon 	/* XXX chain depend deadlck? */
853c198419SMatthew Dillon 	if (hmp->iocom.mmsg)
863c198419SMatthew Dillon 		kdmsg_iocom_uninit(&hmp->iocom);
87d157d4dcSMatthew Dillon }
88d157d4dcSMatthew Dillon 
89d157d4dcSMatthew Dillon /*
90d157d4dcSMatthew Dillon  * Reconnect using the passed file pointer.  The caller must ref the
91d157d4dcSMatthew Dillon  * fp for us.
92d157d4dcSMatthew Dillon  */
93d157d4dcSMatthew Dillon void
94506bd6d1SMatthew Dillon hammer2_cluster_reconnect(hammer2_dev_t *hmp, struct file *fp)
95d157d4dcSMatthew Dillon {
96d157d4dcSMatthew Dillon 	/*
97d157d4dcSMatthew Dillon 	 * Closes old comm descriptor, kills threads, cleans up
98d157d4dcSMatthew Dillon 	 * states, then installs the new descriptor and creates
99d157d4dcSMatthew Dillon 	 * new threads.
100d157d4dcSMatthew Dillon 	 */
101d157d4dcSMatthew Dillon 	kdmsg_iocom_reconnect(&hmp->iocom, fp, "hammer2");
102d157d4dcSMatthew Dillon 
103d157d4dcSMatthew Dillon 	/*
1047750fd72SMatthew Dillon 	 * Setup LNK_CONN fields for autoinitiated state machine.  LNK_CONN
1057750fd72SMatthew Dillon 	 * does not have to be unique.  peer_id can be used to filter incoming
1067750fd72SMatthew Dillon 	 * LNK_SPANs automatically if desired (though we still need to check).
1077750fd72SMatthew Dillon 	 * peer_label typically identifies who we are and is not a filter.
108d157d4dcSMatthew Dillon 	 *
1097750fd72SMatthew Dillon 	 * Since we will be initiating multiple LNK_SPANs we cannot use
1107750fd72SMatthew Dillon 	 * AUTOTXSPAN, but we do use AUTORXSPAN so kdmsg tracks received
1117750fd72SMatthew Dillon 	 * LNK_SPANs, and we simply monitor those messages.
112d157d4dcSMatthew Dillon 	 */
1137750fd72SMatthew Dillon 	bzero(&hmp->iocom.auto_lnk_conn.peer_id,
1147750fd72SMatthew Dillon 	      sizeof(hmp->iocom.auto_lnk_conn.peer_id));
1157750fd72SMatthew Dillon 	/* hmp->iocom.auto_lnk_conn.peer_id = hmp->voldata.fsid; */
116d157d4dcSMatthew Dillon 	hmp->iocom.auto_lnk_conn.proto_version = DMSG_SPAN_PROTO_1;
117d157d4dcSMatthew Dillon #if 0
118d157d4dcSMatthew Dillon 	hmp->iocom.auto_lnk_conn.peer_type = hmp->voldata.peer_type;
119d157d4dcSMatthew Dillon #endif
120d157d4dcSMatthew Dillon 	hmp->iocom.auto_lnk_conn.peer_type = DMSG_PEER_HAMMER2;
121d157d4dcSMatthew Dillon 
122d157d4dcSMatthew Dillon 	/*
1237750fd72SMatthew Dillon 	 * We just want to receive LNK_SPANs related to HAMMER2 matching
1247750fd72SMatthew Dillon 	 * peer_id.
125d157d4dcSMatthew Dillon 	 */
126d157d4dcSMatthew Dillon 	hmp->iocom.auto_lnk_conn.peer_mask = 1LLU << DMSG_PEER_HAMMER2;
127d157d4dcSMatthew Dillon 
128d157d4dcSMatthew Dillon #if 0
129b0f58de8SMatthew Dillon 	switch (ipdata->meta.pfs_type) {
130d157d4dcSMatthew Dillon 	case DMSG_PFSTYPE_CLIENT:
131d157d4dcSMatthew Dillon 		hmp->iocom.auto_lnk_conn.peer_mask &=
132d157d4dcSMatthew Dillon 				~(1LLU << DMSG_PFSTYPE_CLIENT);
133d157d4dcSMatthew Dillon 		break;
134d157d4dcSMatthew Dillon 	default:
135d157d4dcSMatthew Dillon 		break;
136d157d4dcSMatthew Dillon 	}
137d157d4dcSMatthew Dillon #endif
138d157d4dcSMatthew Dillon 
1397750fd72SMatthew Dillon 	bzero(&hmp->iocom.auto_lnk_conn.peer_label,
1407750fd72SMatthew Dillon 	      sizeof(hmp->iocom.auto_lnk_conn.peer_label));
1417750fd72SMatthew Dillon 	ksnprintf(hmp->iocom.auto_lnk_conn.peer_label,
1427750fd72SMatthew Dillon 		  sizeof(hmp->iocom.auto_lnk_conn.peer_label),
1437750fd72SMatthew Dillon 		  "%s/%s",
1447750fd72SMatthew Dillon 		  hostname, "hammer2-mount");
145d157d4dcSMatthew Dillon 	kdmsg_iocom_autoinitiate(&hmp->iocom, hammer2_autodmsg);
146d157d4dcSMatthew Dillon }
147d157d4dcSMatthew Dillon 
148d157d4dcSMatthew Dillon static int
149d157d4dcSMatthew Dillon hammer2_rcvdmsg(kdmsg_msg_t *msg)
150d157d4dcSMatthew Dillon {
151d157d4dcSMatthew Dillon 	kprintf("RCVMSG %08x\n", msg->tcmd);
152d157d4dcSMatthew Dillon 
153d157d4dcSMatthew Dillon 	switch(msg->tcmd) {
154d157d4dcSMatthew Dillon 	case DMSG_DBG_SHELL:
155d157d4dcSMatthew Dillon 		/*
156d157d4dcSMatthew Dillon 		 * (non-transaction)
157d157d4dcSMatthew Dillon 		 * Execute shell command (not supported atm)
158d157d4dcSMatthew Dillon 		 */
159d157d4dcSMatthew Dillon 		kdmsg_msg_result(msg, DMSG_ERR_NOSUPP);
160d157d4dcSMatthew Dillon 		break;
161d157d4dcSMatthew Dillon 	case DMSG_DBG_SHELL | DMSGF_REPLY:
162d157d4dcSMatthew Dillon 		/*
163d157d4dcSMatthew Dillon 		 * (non-transaction)
164d157d4dcSMatthew Dillon 		 */
165d157d4dcSMatthew Dillon 		if (msg->aux_data) {
166d157d4dcSMatthew Dillon 			msg->aux_data[msg->aux_size - 1] = 0;
167d157d4dcSMatthew Dillon 			kprintf("HAMMER2 DBG: %s\n", msg->aux_data);
168d157d4dcSMatthew Dillon 		}
169d157d4dcSMatthew Dillon 		break;
170d157d4dcSMatthew Dillon 	default:
171d157d4dcSMatthew Dillon 		/*
172d157d4dcSMatthew Dillon 		 * Unsupported message received.  We only need to
173d157d4dcSMatthew Dillon 		 * reply if it's a transaction in order to close our end.
174d157d4dcSMatthew Dillon 		 * Ignore any one-way messages or any further messages
175d157d4dcSMatthew Dillon 		 * associated with the transaction.
176d157d4dcSMatthew Dillon 		 *
177d157d4dcSMatthew Dillon 		 * NOTE: This case also includes DMSG_LNK_ERROR messages
178d157d4dcSMatthew Dillon 		 *	 which might be one-way, replying to those would
179d157d4dcSMatthew Dillon 		 *	 cause an infinite ping-pong.
180d157d4dcSMatthew Dillon 		 */
181d157d4dcSMatthew Dillon 		if (msg->any.head.cmd & DMSGF_CREATE)
182d157d4dcSMatthew Dillon 			kdmsg_msg_reply(msg, DMSG_ERR_NOSUPP);
183d157d4dcSMatthew Dillon 		break;
184d157d4dcSMatthew Dillon 	}
185d157d4dcSMatthew Dillon 	return(0);
186d157d4dcSMatthew Dillon }
187d157d4dcSMatthew Dillon 
188d157d4dcSMatthew Dillon /*
189d157d4dcSMatthew Dillon  * This function is called after KDMSG has automatically handled processing
190d157d4dcSMatthew Dillon  * of a LNK layer message (typically CONN or SPAN).
191d157d4dcSMatthew Dillon  *
192d157d4dcSMatthew Dillon  * We tag off the LNK_CONN to trigger our LNK_VOLCONF messages which
193d157d4dcSMatthew Dillon  * advertises all available hammer2 super-root volumes.
194d157d4dcSMatthew Dillon  *
195d157d4dcSMatthew Dillon  * We collect span state
196d157d4dcSMatthew Dillon  */
197506bd6d1SMatthew Dillon static void hammer2_update_spans(hammer2_dev_t *hmp, kdmsg_state_t *state);
198d157d4dcSMatthew Dillon 
199d157d4dcSMatthew Dillon static void
200d157d4dcSMatthew Dillon hammer2_autodmsg(kdmsg_msg_t *msg)
201d157d4dcSMatthew Dillon {
202506bd6d1SMatthew Dillon 	hammer2_dev_t *hmp = msg->state->iocom->handle;
203d157d4dcSMatthew Dillon 	int copyid;
204d157d4dcSMatthew Dillon 
205d157d4dcSMatthew Dillon 	switch(msg->tcmd) {
206d157d4dcSMatthew Dillon 	case DMSG_LNK_CONN | DMSGF_CREATE:
207d157d4dcSMatthew Dillon 	case DMSG_LNK_CONN | DMSGF_CREATE | DMSGF_DELETE:
208d157d4dcSMatthew Dillon 	case DMSG_LNK_CONN | DMSGF_DELETE:
209d157d4dcSMatthew Dillon 		/*
210d157d4dcSMatthew Dillon 		 * NOTE: kern_dmsg will automatically issue a result,
211d157d4dcSMatthew Dillon 		 *       leaving the transaction open, for CREATEs,
212d157d4dcSMatthew Dillon 		 *	 and will automatically issue a terminating reply
213d157d4dcSMatthew Dillon 		 *	 for DELETEs.
214d157d4dcSMatthew Dillon 		 */
215d157d4dcSMatthew Dillon 		break;
216d157d4dcSMatthew Dillon 	case DMSG_LNK_CONN | DMSGF_CREATE | DMSGF_REPLY:
217d157d4dcSMatthew Dillon 	case DMSG_LNK_CONN | DMSGF_CREATE | DMSGF_DELETE | DMSGF_REPLY:
218d157d4dcSMatthew Dillon 		/*
219d157d4dcSMatthew Dillon 		 * Do a volume configuration dump when we receive a reply
220d157d4dcSMatthew Dillon 		 * to our auto-CONN (typically leaving the transaction open).
221d157d4dcSMatthew Dillon 		 */
222d157d4dcSMatthew Dillon 		if (msg->any.head.cmd & DMSGF_CREATE) {
223d157d4dcSMatthew Dillon 			kprintf("HAMMER2: VOLDATA DUMP\n");
224d157d4dcSMatthew Dillon 
225d157d4dcSMatthew Dillon 			/*
226d157d4dcSMatthew Dillon 			 * Dump the configuration stored in the volume header.
227d157d4dcSMatthew Dillon 			 * This will typically be import/export access rights,
228d157d4dcSMatthew Dillon 			 * master encryption keys (encrypted), etc.
229d157d4dcSMatthew Dillon 			 */
230d157d4dcSMatthew Dillon 			hammer2_voldata_lock(hmp);
231d157d4dcSMatthew Dillon 			copyid = 0;
232d157d4dcSMatthew Dillon 			while (copyid < HAMMER2_COPYID_COUNT) {
233d157d4dcSMatthew Dillon 				if (hmp->voldata.copyinfo[copyid].copyid)
234d157d4dcSMatthew Dillon 					hammer2_volconf_update(hmp, copyid);
235d157d4dcSMatthew Dillon 				++copyid;
236d157d4dcSMatthew Dillon 			}
237d157d4dcSMatthew Dillon 			hammer2_voldata_unlock(hmp);
238d157d4dcSMatthew Dillon 
239d157d4dcSMatthew Dillon 			kprintf("HAMMER2: INITIATE SPANs\n");
240d157d4dcSMatthew Dillon 			hammer2_update_spans(hmp, msg->state);
241d157d4dcSMatthew Dillon 		}
242d157d4dcSMatthew Dillon 		if ((msg->any.head.cmd & DMSGF_DELETE) &&
243d157d4dcSMatthew Dillon 		    msg->state && (msg->state->txcmd & DMSGF_DELETE) == 0) {
244d157d4dcSMatthew Dillon 			kprintf("HAMMER2: CONN WAS TERMINATED\n");
245d157d4dcSMatthew Dillon 		}
246d157d4dcSMatthew Dillon 		break;
247d157d4dcSMatthew Dillon 	case DMSG_LNK_SPAN | DMSGF_CREATE:
248d157d4dcSMatthew Dillon 		/*
249d157d4dcSMatthew Dillon 		 * Monitor SPANs and issue a result, leaving the SPAN open
250d157d4dcSMatthew Dillon 		 * if it is something we can use now or in the future.
251d157d4dcSMatthew Dillon 		 */
252d157d4dcSMatthew Dillon 		if (msg->any.lnk_span.peer_type != DMSG_PEER_HAMMER2) {
253d157d4dcSMatthew Dillon 			kdmsg_msg_reply(msg, 0);
254d157d4dcSMatthew Dillon 			break;
255d157d4dcSMatthew Dillon 		}
256d157d4dcSMatthew Dillon 		if (msg->any.lnk_span.proto_version != DMSG_SPAN_PROTO_1) {
257d157d4dcSMatthew Dillon 			kdmsg_msg_reply(msg, 0);
258d157d4dcSMatthew Dillon 			break;
259d157d4dcSMatthew Dillon 		}
2607750fd72SMatthew Dillon 		DMSG_TERMINATE_STRING(msg->any.lnk_span.peer_label);
261*95bf987fSMatthew Dillon 		if (hammer2_debug & 0x0100) {
2627750fd72SMatthew Dillon 			kprintf("H2 +RXSPAN cmd=%08x (%-20s) cl=",
263*95bf987fSMatthew Dillon 				msg->any.head.cmd,
264*95bf987fSMatthew Dillon 				msg->any.lnk_span.peer_label);
2657750fd72SMatthew Dillon 			printf_uuid(&msg->any.lnk_span.peer_id);
266d157d4dcSMatthew Dillon 			kprintf(" fs=");
2677750fd72SMatthew Dillon 			printf_uuid(&msg->any.lnk_span.pfs_id);
268d157d4dcSMatthew Dillon 			kprintf(" type=%d\n", msg->any.lnk_span.pfs_type);
269*95bf987fSMatthew Dillon 		}
270d157d4dcSMatthew Dillon 		kdmsg_msg_result(msg, 0);
271d157d4dcSMatthew Dillon 		break;
272d157d4dcSMatthew Dillon 	case DMSG_LNK_SPAN | DMSGF_DELETE:
273d157d4dcSMatthew Dillon 		/*
274d157d4dcSMatthew Dillon 		 * NOTE: kern_dmsg will automatically reply to DELETEs.
275d157d4dcSMatthew Dillon 		 */
276*95bf987fSMatthew Dillon 		if (hammer2_debug & 0x0100)
277d157d4dcSMatthew Dillon 			kprintf("H2 -RXSPAN\n");
278d157d4dcSMatthew Dillon 		break;
279d157d4dcSMatthew Dillon 	default:
280d157d4dcSMatthew Dillon 		break;
281d157d4dcSMatthew Dillon 	}
282d157d4dcSMatthew Dillon }
283d157d4dcSMatthew Dillon 
284d157d4dcSMatthew Dillon /*
285d157d4dcSMatthew Dillon  * Update LNK_SPAN state
286d157d4dcSMatthew Dillon  */
287d157d4dcSMatthew Dillon static void
288506bd6d1SMatthew Dillon hammer2_update_spans(hammer2_dev_t *hmp, kdmsg_state_t *state)
289d157d4dcSMatthew Dillon {
290d157d4dcSMatthew Dillon 	const hammer2_inode_data_t *ripdata;
29101d71aa5SMatthew Dillon 	hammer2_chain_t *parent;
29201d71aa5SMatthew Dillon 	hammer2_chain_t *chain;
293506bd6d1SMatthew Dillon 	hammer2_pfs_t *spmp;
294d157d4dcSMatthew Dillon 	hammer2_key_t key_next;
295d157d4dcSMatthew Dillon 	kdmsg_msg_t *rmsg;
296d157d4dcSMatthew Dillon 	size_t name_len;
29701d71aa5SMatthew Dillon 	int cache_index = -1;
298d157d4dcSMatthew Dillon 
299d157d4dcSMatthew Dillon 	/*
300d157d4dcSMatthew Dillon 	 * Lookup mount point under the media-localized super-root.
301d157d4dcSMatthew Dillon 	 *
302d157d4dcSMatthew Dillon 	 * cluster->pmp will incorrectly point to spmp and must be fixed
303d157d4dcSMatthew Dillon 	 * up later on.
304d157d4dcSMatthew Dillon 	 */
305d157d4dcSMatthew Dillon 	spmp = hmp->spmp;
306b7add675SMatthew Dillon 	hammer2_inode_lock(spmp->iroot, 0);
30701d71aa5SMatthew Dillon 
30801d71aa5SMatthew Dillon 	parent = hammer2_inode_chain(spmp->iroot, 0, HAMMER2_RESOLVE_ALWAYS);
30901d71aa5SMatthew Dillon 	chain = NULL;
31001d71aa5SMatthew Dillon 	if (parent == NULL)
31101d71aa5SMatthew Dillon 		goto done;
31201d71aa5SMatthew Dillon 	chain = hammer2_chain_lookup(&parent, &key_next,
31301d71aa5SMatthew Dillon 				     HAMMER2_KEY_MIN, HAMMER2_KEY_MAX,
31401d71aa5SMatthew Dillon 				     &cache_index,
315b8ba9690SMatthew Dillon 				     0);
31601d71aa5SMatthew Dillon 	while (chain) {
31701d71aa5SMatthew Dillon 		if (chain->bref.type != HAMMER2_BREF_TYPE_INODE)
318d157d4dcSMatthew Dillon 			continue;
31901d71aa5SMatthew Dillon 		ripdata = &chain->data->ipdata;
320d157d4dcSMatthew Dillon 		kprintf("UPDATE SPANS: %s\n", ripdata->filename);
321d157d4dcSMatthew Dillon 
322d157d4dcSMatthew Dillon 		rmsg = kdmsg_msg_alloc(&hmp->iocom.state0,
323d157d4dcSMatthew Dillon 				       DMSG_LNK_SPAN | DMSGF_CREATE,
324d157d4dcSMatthew Dillon 				       hammer2_lnk_span_reply, NULL);
325b0f58de8SMatthew Dillon 		rmsg->any.lnk_span.peer_id = ripdata->meta.pfs_clid;
326b0f58de8SMatthew Dillon 		rmsg->any.lnk_span.pfs_id = ripdata->meta.pfs_fsid;
327b0f58de8SMatthew Dillon 		rmsg->any.lnk_span.pfs_type = ripdata->meta.pfs_type;
328d157d4dcSMatthew Dillon 		rmsg->any.lnk_span.peer_type = DMSG_PEER_HAMMER2;
329d157d4dcSMatthew Dillon 		rmsg->any.lnk_span.proto_version = DMSG_SPAN_PROTO_1;
330b0f58de8SMatthew Dillon 		name_len = ripdata->meta.name_len;
3317750fd72SMatthew Dillon 		if (name_len >= sizeof(rmsg->any.lnk_span.peer_label))
3327750fd72SMatthew Dillon 			name_len = sizeof(rmsg->any.lnk_span.peer_label) - 1;
3337750fd72SMatthew Dillon 		bcopy(ripdata->filename,
3347750fd72SMatthew Dillon 		      rmsg->any.lnk_span.peer_label,
3357750fd72SMatthew Dillon 		      name_len);
336d157d4dcSMatthew Dillon 
337d157d4dcSMatthew Dillon 		kdmsg_msg_write(rmsg);
338d157d4dcSMatthew Dillon 
33901d71aa5SMatthew Dillon 		chain = hammer2_chain_next(&parent, chain, &key_next,
34001d71aa5SMatthew Dillon 					       key_next, HAMMER2_KEY_MAX,
34101d71aa5SMatthew Dillon 					       &cache_index,
342d157d4dcSMatthew Dillon 					       0);
343d157d4dcSMatthew Dillon 	}
344b7add675SMatthew Dillon 	hammer2_inode_unlock(spmp->iroot);
34501d71aa5SMatthew Dillon done:
34601d71aa5SMatthew Dillon 	if (chain) {
34701d71aa5SMatthew Dillon 		hammer2_chain_unlock(chain);
34801d71aa5SMatthew Dillon 		hammer2_chain_drop(chain);
34901d71aa5SMatthew Dillon 	}
35001d71aa5SMatthew Dillon 	if (parent) {
35101d71aa5SMatthew Dillon 		hammer2_chain_unlock(parent);
35201d71aa5SMatthew Dillon 		hammer2_chain_drop(parent);
353b7add675SMatthew Dillon 	}
354d157d4dcSMatthew Dillon }
355d157d4dcSMatthew Dillon 
356d157d4dcSMatthew Dillon static
357d157d4dcSMatthew Dillon int
358d157d4dcSMatthew Dillon hammer2_lnk_span_reply(kdmsg_state_t *state, kdmsg_msg_t *msg)
359d157d4dcSMatthew Dillon {
360d157d4dcSMatthew Dillon 	if ((state->txcmd & DMSGF_DELETE) == 0 &&
361d157d4dcSMatthew Dillon 	    (msg->any.head.cmd & DMSGF_DELETE)) {
362d157d4dcSMatthew Dillon 		kdmsg_msg_reply(msg, 0);
363d157d4dcSMatthew Dillon 	}
364d157d4dcSMatthew Dillon 	return 0;
365d157d4dcSMatthew Dillon }
366d157d4dcSMatthew Dillon 
367d157d4dcSMatthew Dillon /*
368d157d4dcSMatthew Dillon  * Volume configuration updates are passed onto the userland service
369d157d4dcSMatthew Dillon  * daemon via the open LNK_CONN transaction.
370d157d4dcSMatthew Dillon  */
371d157d4dcSMatthew Dillon void
372506bd6d1SMatthew Dillon hammer2_volconf_update(hammer2_dev_t *hmp, int index)
373d157d4dcSMatthew Dillon {
374d157d4dcSMatthew Dillon 	kdmsg_msg_t *msg;
375d157d4dcSMatthew Dillon 
376d157d4dcSMatthew Dillon 	/* XXX interlock against connection state termination */
377d157d4dcSMatthew Dillon 	kprintf("volconf update %p\n", hmp->iocom.conn_state);
378d157d4dcSMatthew Dillon 	if (hmp->iocom.conn_state) {
379d157d4dcSMatthew Dillon 		kprintf("TRANSMIT VOLCONF VIA OPEN CONN TRANSACTION\n");
380d157d4dcSMatthew Dillon 		msg = kdmsg_msg_alloc(hmp->iocom.conn_state,
381d157d4dcSMatthew Dillon 				      DMSG_LNK_HAMMER2_VOLCONF,
382d157d4dcSMatthew Dillon 				      NULL, NULL);
383d157d4dcSMatthew Dillon 		H2_LNK_VOLCONF(msg)->copy = hmp->voldata.copyinfo[index];
384d157d4dcSMatthew Dillon 		H2_LNK_VOLCONF(msg)->mediaid = hmp->voldata.fsid;
385d157d4dcSMatthew Dillon 		H2_LNK_VOLCONF(msg)->index = index;
386d157d4dcSMatthew Dillon 		kdmsg_msg_write(msg);
387d157d4dcSMatthew Dillon 	}
388d157d4dcSMatthew Dillon }
389