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