2 * Copyright (c) 2011-2012 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@dragonflybsd.org>
6 * by Venkatesh Srinivas <vsrinivas@dragonflybsd.org>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
18 * 3. Neither the name of The DragonFly Project nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific, prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * WARNING! The ioctl functions which manipulate the connection state need
39 * to be able to run without deadlock on the volume's chain lock.
40 * Most of these functions use a separate lock.
45 static int hammer2_ioctl_version_get(hammer2_inode_t *ip, void *data);
46 static int hammer2_ioctl_remote_get(hammer2_inode_t *ip, void *data);
47 static int hammer2_ioctl_remote_add(hammer2_inode_t *ip, void *data);
48 static int hammer2_ioctl_remote_del(hammer2_inode_t *ip, void *data);
49 static int hammer2_ioctl_remote_rep(hammer2_inode_t *ip, void *data);
50 static int hammer2_ioctl_socket_get(hammer2_inode_t *ip, void *data);
51 static int hammer2_ioctl_socket_set(hammer2_inode_t *ip, void *data);
52 static int hammer2_ioctl_pfs_get(hammer2_inode_t *ip, void *data);
53 static int hammer2_ioctl_pfs_create(hammer2_inode_t *ip, void *data);
54 static int hammer2_ioctl_pfs_delete(hammer2_inode_t *ip, void *data);
57 hammer2_ioctl(hammer2_inode_t *ip, u_long com, void *data, int fflag,
63 * Standard root cred checks, will be selectively ignored below
64 * for ioctls that do not require root creds.
66 error = priv_check_cred(cred, PRIV_HAMMER_IOCTL, 0);
69 case HAMMER2IOC_VERSION_GET:
70 error = hammer2_ioctl_version_get(ip, data);
72 case HAMMER2IOC_REMOTE_GET:
74 error = hammer2_ioctl_remote_get(ip, data);
76 case HAMMER2IOC_REMOTE_ADD:
78 error = hammer2_ioctl_remote_add(ip, data);
80 case HAMMER2IOC_REMOTE_DEL:
82 error = hammer2_ioctl_remote_del(ip, data);
84 case HAMMER2IOC_REMOTE_REP:
86 error = hammer2_ioctl_remote_rep(ip, data);
88 case HAMMER2IOC_SOCKET_GET:
90 error = hammer2_ioctl_socket_get(ip, data);
92 case HAMMER2IOC_SOCKET_SET:
94 error = hammer2_ioctl_socket_set(ip, data);
96 case HAMMER2IOC_PFS_GET:
98 error = hammer2_ioctl_pfs_get(ip, data);
100 case HAMMER2IOC_PFS_CREATE:
102 error = hammer2_ioctl_pfs_create(ip, data);
104 case HAMMER2IOC_PFS_DELETE:
106 error = hammer2_ioctl_pfs_delete(ip, data);
116 * Retrieve version and basic info
119 hammer2_ioctl_version_get(hammer2_inode_t *ip, void *data)
121 hammer2_mount_t *hmp = ip->hmp;
122 hammer2_ioc_version_t *version = data;
124 version->version = hmp->voldata.version;
129 * Retrieve information about a remote
132 hammer2_ioctl_remote_get(hammer2_inode_t *ip, void *data)
134 hammer2_mount_t *hmp = ip->hmp;
135 hammer2_ioc_remote_t *remote = data;
136 int copyid = remote->copyid;
138 if (copyid < 0 || copyid >= HAMMER2_COPYID_COUNT)
141 hammer2_voldata_lock(hmp);
142 remote->copy1 = hmp->voldata.copyinfo[copyid];
143 hammer2_voldata_unlock(hmp);
146 * Adjust nextid (GET only)
148 while (++copyid < HAMMER2_COPYID_COUNT &&
149 hmp->voldata.copyinfo[copyid].copyid == 0) {
152 if (copyid == HAMMER2_COPYID_COUNT)
155 remote->nextid = copyid;
161 * Add new remote entry
164 hammer2_ioctl_remote_add(hammer2_inode_t *ip, void *data)
166 hammer2_mount_t *hmp = ip->hmp;
167 hammer2_ioc_remote_t *remote = data;
168 int copyid = remote->copyid;
171 if (copyid >= HAMMER2_COPYID_COUNT)
174 hammer2_voldata_lock(hmp);
176 for (copyid = 1; copyid < HAMMER2_COPYID_COUNT; ++copyid) {
177 if (hmp->voldata.copyinfo[copyid].copyid == 0)
180 if (copyid == HAMMER2_COPYID_COUNT) {
185 hammer2_modify_volume(hmp);
186 kprintf("copyid %d\n", copyid);
187 remote->copy1.copyid = copyid;
188 hmp->voldata.copyinfo[copyid] = remote->copy1;
190 hammer2_voldata_unlock(hmp);
195 * Delete existing remote entry
198 hammer2_ioctl_remote_del(hammer2_inode_t *ip, void *data)
200 hammer2_mount_t *hmp = ip->hmp;
201 hammer2_ioc_remote_t *remote = data;
202 int copyid = remote->copyid;
205 if (copyid >= HAMMER2_COPYID_COUNT)
207 remote->copy1.path[sizeof(remote->copy1.path) - 1] = 0;
208 hammer2_voldata_lock(hmp);
210 for (copyid = 1; copyid < HAMMER2_COPYID_COUNT; ++copyid) {
211 if (hmp->voldata.copyinfo[copyid].copyid == 0)
213 if (strcmp(remote->copy1.path,
214 hmp->voldata.copyinfo[copyid].path) == 0) {
218 if (copyid == HAMMER2_COPYID_COUNT) {
223 hammer2_modify_volume(hmp);
224 hmp->voldata.copyinfo[copyid].copyid = 0;
226 hammer2_voldata_unlock(hmp);
231 * Replace existing remote entry
234 hammer2_ioctl_remote_rep(hammer2_inode_t *ip, void *data)
236 hammer2_mount_t *hmp = ip->hmp;
237 hammer2_ioc_remote_t *remote = data;
238 int copyid = remote->copyid;
240 if (copyid < 0 || copyid >= HAMMER2_COPYID_COUNT)
243 hammer2_voldata_lock(hmp);
244 hammer2_voldata_unlock(hmp);
250 * Retrieve communications socket
253 hammer2_ioctl_socket_get(hammer2_inode_t *ip, void *data)
259 * Set communications socket for connection
262 hammer2_ioctl_socket_set(hammer2_inode_t *ip, void *data)
264 hammer2_mount_t *hmp = ip->hmp;
265 hammer2_ioc_remote_t *remote = data;
266 int copyid = remote->copyid;
268 if (copyid < 0 || copyid >= HAMMER2_COPYID_COUNT)
271 hammer2_voldata_lock(hmp);
272 hammer2_voldata_unlock(hmp);
278 * Used to scan PFSs, which are directories under the super-root.
281 hammer2_ioctl_pfs_get(hammer2_inode_t *ip, void *data)
283 hammer2_mount_t *hmp = ip->hmp;
284 hammer2_ioc_pfs_t *pfs = data;
285 hammer2_chain_t *parent;
286 hammer2_chain_t *chain;
287 hammer2_inode_t *xip;
290 parent = hmp->schain;
291 error = hammer2_chain_lock(hmp, parent, HAMMER2_RESOLVE_ALWAYS);
296 * Search for the first key or specific key. Remember that keys
297 * can be returned in any order.
299 if (pfs->name_key == 0) {
300 chain = hammer2_chain_lookup(hmp, &parent,
301 0, (hammer2_key_t)-1, 0);
303 chain = hammer2_chain_lookup(hmp, &parent,
304 pfs->name_key, pfs->name_key, 0);
306 while (chain && chain->bref.type != HAMMER2_BREF_TYPE_INODE) {
307 chain = hammer2_chain_next(hmp, &parent, chain,
308 0, (hammer2_key_t)-1, 0);
312 * Load the data being returned by the ioctl.
315 pfs->name_key = xip->ip_data.name_key;
316 pfs->pfs_type = xip->ip_data.pfs_type;
317 pfs->pfs_id = xip->ip_data.pfs_id;
318 pfs->pfs_fsid = xip->ip_data.pfs_fsid;
319 KKASSERT(xip->ip_data.name_len < sizeof(pfs->name));
320 bcopy(xip->ip_data.filename, pfs->name,
321 xip->ip_data.name_len);
322 pfs->name[xip->ip_data.name_len] = 0;
325 * Calculate the next field
328 chain = hammer2_chain_next(hmp, &parent, chain,
329 0, (hammer2_key_t)-1, 0);
330 } while (chain && chain->bref.type != HAMMER2_BREF_TYPE_INODE);
332 pfs->name_next = chain->u.ip->ip_data.name_key;
333 hammer2_chain_unlock(hmp, chain);
335 pfs->name_next = (hammer2_key_t)-1;
338 pfs->name_next = (hammer2_key_t)-1;
342 hammer2_chain_unlock(hmp, parent);
347 * Create a new PFS under the super-root
350 hammer2_ioctl_pfs_create(hammer2_inode_t *ip, void *data)
352 hammer2_mount_t *hmp = ip->hmp;
353 hammer2_ioc_pfs_t *pfs = data;
354 hammer2_inode_t *nip = NULL;
357 pfs->name[sizeof(pfs->name) - 1] = 0; /* ensure 0-termination */
358 error = hammer2_inode_create(hmp->schain->u.ip, NULL, NULL,
359 pfs->name, strlen(pfs->name),
362 hammer2_chain_modify(hmp, &nip->chain, 0);
363 nip->ip_data.pfs_type = pfs->pfs_type;
364 nip->ip_data.pfs_id = pfs->pfs_id;
365 nip->ip_data.pfs_fsid = pfs->pfs_fsid;
366 hammer2_chain_unlock(hmp, &nip->chain);
372 * Destroy an existing PFS under the super-root
375 hammer2_ioctl_pfs_delete(hammer2_inode_t *ip, void *data)
377 hammer2_mount_t *hmp = ip->hmp;
378 hammer2_ioc_pfs_t *pfs = data;
381 error = hammer2_unlink_file(hmp->schain->u.ip,
382 pfs->name, strlen(pfs->name),