hammer2 - Refactor frontend part 14/many
[dragonfly.git] / sys / vfs / hammer2 / hammer2_ioctl.c
CommitLineData
2910a90c 1/*
3148f677 2 * Copyright (c) 2011-2015 The DragonFly Project. All rights reserved.
2910a90c
MD
3 *
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>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
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
17 * distribution.
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.
21 *
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
33 * SUCH DAMAGE.
34 */
35/*
36 * Ioctl Functions.
37 *
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.
41 */
42
43#include "hammer2.h"
44
ae183399 45static int hammer2_ioctl_version_get(hammer2_inode_t *ip, void *data);
1a34728c
MD
46static int hammer2_ioctl_recluster(hammer2_inode_t *ip, void *data);
47static int hammer2_ioctl_remote_scan(hammer2_inode_t *ip, void *data);
ae183399
MD
48static int hammer2_ioctl_remote_add(hammer2_inode_t *ip, void *data);
49static int hammer2_ioctl_remote_del(hammer2_inode_t *ip, void *data);
50static int hammer2_ioctl_remote_rep(hammer2_inode_t *ip, void *data);
51static int hammer2_ioctl_socket_get(hammer2_inode_t *ip, void *data);
52static int hammer2_ioctl_socket_set(hammer2_inode_t *ip, void *data);
53static int hammer2_ioctl_pfs_get(hammer2_inode_t *ip, void *data);
458ecb1b 54static int hammer2_ioctl_pfs_lookup(hammer2_inode_t *ip, void *data);
ae183399 55static int hammer2_ioctl_pfs_create(hammer2_inode_t *ip, void *data);
a864c5d9 56static int hammer2_ioctl_pfs_snapshot(hammer2_inode_t *ip, void *data);
ae183399 57static int hammer2_ioctl_pfs_delete(hammer2_inode_t *ip, void *data);
344d4f82
MD
58static int hammer2_ioctl_inode_get(hammer2_inode_t *ip, void *data);
59static int hammer2_ioctl_inode_set(hammer2_inode_t *ip, void *data);
03188ed8 60static int hammer2_ioctl_debug_dump(hammer2_inode_t *ip);
355d67fc
MD
61//static int hammer2_ioctl_inode_comp_set(hammer2_inode_t *ip, void *data);
62//static int hammer2_ioctl_inode_comp_rec_set(hammer2_inode_t *ip, void *data);
63//static int hammer2_ioctl_inode_comp_rec_set2(hammer2_inode_t *ip, void *data);
3148f677 64static int hammer2_ioctl_bulkfree_scan(hammer2_inode_t *ip, void *data);
2910a90c
MD
65
66int
67hammer2_ioctl(hammer2_inode_t *ip, u_long com, void *data, int fflag,
68 struct ucred *cred)
69{
70 int error;
71
72 /*
73 * Standard root cred checks, will be selectively ignored below
74 * for ioctls that do not require root creds.
75 */
76 error = priv_check_cred(cred, PRIV_HAMMER_IOCTL, 0);
77
78 switch(com) {
ae183399
MD
79 case HAMMER2IOC_VERSION_GET:
80 error = hammer2_ioctl_version_get(ip, data);
2910a90c 81 break;
1a34728c 82 case HAMMER2IOC_RECLUSTER:
2910a90c 83 if (error == 0)
1a34728c
MD
84 error = hammer2_ioctl_recluster(ip, data);
85 break;
86 case HAMMER2IOC_REMOTE_SCAN:
87 if (error == 0)
88 error = hammer2_ioctl_remote_scan(ip, data);
2910a90c 89 break;
ae183399 90 case HAMMER2IOC_REMOTE_ADD:
2910a90c 91 if (error == 0)
ae183399 92 error = hammer2_ioctl_remote_add(ip, data);
2910a90c 93 break;
ae183399 94 case HAMMER2IOC_REMOTE_DEL:
2910a90c 95 if (error == 0)
ae183399 96 error = hammer2_ioctl_remote_del(ip, data);
2910a90c 97 break;
ae183399 98 case HAMMER2IOC_REMOTE_REP:
2910a90c 99 if (error == 0)
ae183399 100 error = hammer2_ioctl_remote_rep(ip, data);
2910a90c 101 break;
ae183399 102 case HAMMER2IOC_SOCKET_GET:
2910a90c 103 if (error == 0)
ae183399 104 error = hammer2_ioctl_socket_get(ip, data);
2910a90c 105 break;
ae183399
MD
106 case HAMMER2IOC_SOCKET_SET:
107 if (error == 0)
108 error = hammer2_ioctl_socket_set(ip, data);
109 break;
110 case HAMMER2IOC_PFS_GET:
2910a90c 111 if (error == 0)
ae183399
MD
112 error = hammer2_ioctl_pfs_get(ip, data);
113 break;
458ecb1b
MD
114 case HAMMER2IOC_PFS_LOOKUP:
115 if (error == 0)
116 error = hammer2_ioctl_pfs_lookup(ip, data);
117 break;
ae183399
MD
118 case HAMMER2IOC_PFS_CREATE:
119 if (error == 0)
120 error = hammer2_ioctl_pfs_create(ip, data);
121 break;
122 case HAMMER2IOC_PFS_DELETE:
123 if (error == 0)
124 error = hammer2_ioctl_pfs_delete(ip, data);
2910a90c 125 break;
a864c5d9
MD
126 case HAMMER2IOC_PFS_SNAPSHOT:
127 if (error == 0)
128 error = hammer2_ioctl_pfs_snapshot(ip, data);
129 break;
344d4f82
MD
130 case HAMMER2IOC_INODE_GET:
131 error = hammer2_ioctl_inode_get(ip, data);
132 break;
133 case HAMMER2IOC_INODE_SET:
134 if (error == 0)
135 error = hammer2_ioctl_inode_set(ip, data);
136 break;
3148f677
MD
137 case HAMMER2IOC_BULKFREE_SCAN:
138 error = hammer2_ioctl_bulkfree_scan(ip, data);
139 break;
355d67fc
MD
140 /*case HAMMER2IOC_INODE_COMP_SET:
141 error = hammer2_ioctl_inode_comp_set(ip, data);
142 break;
143 case HAMMER2IOC_INODE_COMP_REC_SET:
144 error = hammer2_ioctl_inode_comp_rec_set(ip, data);
145 break;
146 case HAMMER2IOC_INODE_COMP_REC_SET2:
147 error = hammer2_ioctl_inode_comp_rec_set2(ip, data);
148 break;*/
03188ed8
MD
149 case HAMMER2IOC_DEBUG_DUMP:
150 error = hammer2_ioctl_debug_dump(ip);
151 break;
2910a90c
MD
152 default:
153 error = EOPNOTSUPP;
154 break;
155 }
156 return (error);
157}
158
159/*
160 * Retrieve version and basic info
161 */
162static int
ae183399 163hammer2_ioctl_version_get(hammer2_inode_t *ip, void *data)
2910a90c 164{
506bd6d1 165 hammer2_dev_t *hmp = ip->pmp->iroot->cluster.focus->hmp;
2910a90c
MD
166 hammer2_ioc_version_t *version = data;
167
168 version->version = hmp->voldata.version;
169 return 0;
170}
171
1a34728c
MD
172static int
173hammer2_ioctl_recluster(hammer2_inode_t *ip, void *data)
174{
175 hammer2_ioc_recluster_t *recl = data;
176 struct file *fp;
063639ba
MD
177 hammer2_cluster_t *cluster;
178 int error;
1a34728c
MD
179
180 fp = holdfp(curproc->p_fd, recl->fd, -1);
181 if (fp) {
fe73aa5d 182 kprintf("reconnect to cluster: XXX ");
063639ba
MD
183 cluster = &ip->pmp->iroot->cluster;
184 if (cluster->nchains != 1 || cluster->focus == NULL) {
185 kprintf("not a local device mount\n");
186 error = EINVAL;
187 } else {
188 hammer2_cluster_reconnect(cluster->focus->hmp, fp);
189 kprintf("ok\n");
190 error = 0;
191 }
1a34728c 192 } else {
063639ba 193 error = EINVAL;
1a34728c 194 }
063639ba 195 return error;
1a34728c
MD
196}
197
2910a90c
MD
198/*
199 * Retrieve information about a remote
200 */
201static int
1a34728c 202hammer2_ioctl_remote_scan(hammer2_inode_t *ip, void *data)
2910a90c 203{
506bd6d1 204 hammer2_dev_t *hmp = ip->pmp->iroot->cluster.focus->hmp;
2910a90c
MD
205 hammer2_ioc_remote_t *remote = data;
206 int copyid = remote->copyid;
207
208 if (copyid < 0 || copyid >= HAMMER2_COPYID_COUNT)
209 return (EINVAL);
210
211 hammer2_voldata_lock(hmp);
212 remote->copy1 = hmp->voldata.copyinfo[copyid];
50456506 213 hammer2_voldata_unlock(hmp);
2910a90c
MD
214
215 /*
216 * Adjust nextid (GET only)
217 */
218 while (++copyid < HAMMER2_COPYID_COUNT &&
219 hmp->voldata.copyinfo[copyid].copyid == 0) {
1a34728c 220 ;
2910a90c
MD
221 }
222 if (copyid == HAMMER2_COPYID_COUNT)
223 remote->nextid = -1;
224 else
225 remote->nextid = copyid;
226
227 return(0);
228}
229
230/*
231 * Add new remote entry
232 */
233static int
ae183399 234hammer2_ioctl_remote_add(hammer2_inode_t *ip, void *data)
2910a90c 235{
2910a90c 236 hammer2_ioc_remote_t *remote = data;
506bd6d1
MD
237 hammer2_pfs_t *pmp = ip->pmp;
238 hammer2_dev_t *hmp;
2910a90c
MD
239 int copyid = remote->copyid;
240 int error = 0;
241
242 if (copyid >= HAMMER2_COPYID_COUNT)
243 return (EINVAL);
244
58e43599 245 hmp = pmp->iroot->cluster.focus->hmp; /* XXX */
2910a90c
MD
246 hammer2_voldata_lock(hmp);
247 if (copyid < 0) {
248 for (copyid = 1; copyid < HAMMER2_COPYID_COUNT; ++copyid) {
249 if (hmp->voldata.copyinfo[copyid].copyid == 0)
250 break;
251 }
252 if (copyid == HAMMER2_COPYID_COUNT) {
253 error = ENOSPC;
254 goto failed;
255 }
256 }
50456506 257 hammer2_voldata_modify(hmp);
2910a90c
MD
258 remote->copy1.copyid = copyid;
259 hmp->voldata.copyinfo[copyid] = remote->copy1;
063639ba 260 hammer2_volconf_update(hmp, copyid);
2910a90c 261failed:
50456506 262 hammer2_voldata_unlock(hmp);
2910a90c
MD
263 return (error);
264}
265
266/*
267 * Delete existing remote entry
268 */
269static int
ae183399 270hammer2_ioctl_remote_del(hammer2_inode_t *ip, void *data)
2910a90c 271{
2910a90c 272 hammer2_ioc_remote_t *remote = data;
506bd6d1
MD
273 hammer2_pfs_t *pmp = ip->pmp;
274 hammer2_dev_t *hmp;
2910a90c
MD
275 int copyid = remote->copyid;
276 int error = 0;
277
58e43599 278 hmp = pmp->iroot->cluster.focus->hmp; /* XXX */
2910a90c
MD
279 if (copyid >= HAMMER2_COPYID_COUNT)
280 return (EINVAL);
281 remote->copy1.path[sizeof(remote->copy1.path) - 1] = 0;
282 hammer2_voldata_lock(hmp);
283 if (copyid < 0) {
284 for (copyid = 1; copyid < HAMMER2_COPYID_COUNT; ++copyid) {
285 if (hmp->voldata.copyinfo[copyid].copyid == 0)
286 continue;
287 if (strcmp(remote->copy1.path,
288 hmp->voldata.copyinfo[copyid].path) == 0) {
289 break;
290 }
291 }
292 if (copyid == HAMMER2_COPYID_COUNT) {
293 error = ENOENT;
294 goto failed;
295 }
296 }
50456506 297 hammer2_voldata_modify(hmp);
2910a90c 298 hmp->voldata.copyinfo[copyid].copyid = 0;
063639ba 299 hammer2_volconf_update(hmp, copyid);
2910a90c 300failed:
50456506 301 hammer2_voldata_unlock(hmp);
2910a90c
MD
302 return (error);
303}
304
305/*
306 * Replace existing remote entry
307 */
308static int
ae183399 309hammer2_ioctl_remote_rep(hammer2_inode_t *ip, void *data)
2910a90c 310{
2910a90c 311 hammer2_ioc_remote_t *remote = data;
506bd6d1 312 hammer2_dev_t *hmp;
2910a90c
MD
313 int copyid = remote->copyid;
314
58e43599 315 hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */
a5913bdf 316
2910a90c
MD
317 if (copyid < 0 || copyid >= HAMMER2_COPYID_COUNT)
318 return (EINVAL);
319
320 hammer2_voldata_lock(hmp);
50456506 321 hammer2_voldata_modify(hmp);
063639ba 322 /*hammer2_volconf_update(hmp, copyid);*/
50456506 323 hammer2_voldata_unlock(hmp);
2910a90c
MD
324
325 return(0);
326}
327
328/*
329 * Retrieve communications socket
330 */
331static int
ae183399 332hammer2_ioctl_socket_get(hammer2_inode_t *ip, void *data)
2910a90c
MD
333{
334 return (EOPNOTSUPP);
335}
336
337/*
338 * Set communications socket for connection
339 */
340static int
ae183399 341hammer2_ioctl_socket_set(hammer2_inode_t *ip, void *data)
2910a90c 342{
2910a90c 343 hammer2_ioc_remote_t *remote = data;
506bd6d1 344 hammer2_dev_t *hmp;
2910a90c
MD
345 int copyid = remote->copyid;
346
58e43599 347 hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */
2910a90c
MD
348 if (copyid < 0 || copyid >= HAMMER2_COPYID_COUNT)
349 return (EINVAL);
350
351 hammer2_voldata_lock(hmp);
50456506 352 hammer2_voldata_unlock(hmp);
2910a90c
MD
353
354 return(0);
355}
ae183399
MD
356
357/*
a864c5d9
MD
358 * Used to scan and retrieve PFS information. PFS's are directories under
359 * the super-root.
360 *
361 * To scan PFSs pass name_key=0. The function will scan for the next
362 * PFS and set all fields, as well as set name_next to the next key.
363 * When no PFSs remain, name_next is set to (hammer2_key_t)-1.
364 *
365 * To retrieve the PFS associated with the file descriptor, pass
366 * name_key set to (hammer2_key_t)-1.
ae183399
MD
367 */
368static int
369hammer2_ioctl_pfs_get(hammer2_inode_t *ip, void *data)
370{
bca9f8e6 371 const hammer2_inode_data_t *ripdata;
506bd6d1 372 hammer2_dev_t *hmp;
476d2aad 373 hammer2_ioc_pfs_t *pfs;
278ab2b2
MD
374 hammer2_cluster_t *cparent;
375 hammer2_cluster_t *rcluster;
376 hammer2_cluster_t *cluster;
1897c66e 377 hammer2_key_t key_next;
476d2aad 378 int error;
ae183399 379
476d2aad 380 error = 0;
58e43599 381 hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */
476d2aad 382 pfs = data;
159c3ca2
MD
383 hammer2_inode_lock(hmp->spmp->iroot, HAMMER2_RESOLVE_ALWAYS);
384 cparent = hammer2_inode_cluster(hmp->spmp->iroot,
385 HAMMER2_RESOLVE_ALWAYS);
386 hammer2_inode_lock(ip->pmp->iroot, HAMMER2_RESOLVE_ALWAYS);
387 rcluster = hammer2_inode_cluster(ip->pmp->iroot,
388 HAMMER2_RESOLVE_ALWAYS);
ae183399
MD
389
390 /*
391 * Search for the first key or specific key. Remember that keys
392 * can be returned in any order.
393 */
394 if (pfs->name_key == 0) {
278ab2b2
MD
395 cluster = hammer2_cluster_lookup(cparent, &key_next,
396 0, (hammer2_key_t)-1,
b8ba9690 397 0);
a864c5d9 398 } else if (pfs->name_key == (hammer2_key_t)-1) {
bca9f8e6 399 ripdata = &hammer2_cluster_rdata(rcluster)->ipdata;
278ab2b2 400 cluster = hammer2_cluster_lookup(cparent, &key_next,
b0f58de8
MD
401 ripdata->meta.name_key,
402 ripdata->meta.name_key,
b8ba9690 403 0);
bca9f8e6 404 ripdata = NULL; /* safety */
ae183399 405 } else {
278ab2b2
MD
406 cluster = hammer2_cluster_lookup(cparent, &key_next,
407 pfs->name_key, pfs->name_key,
b8ba9690 408 0);
ae183399 409 }
b93cc2e0 410 hammer2_inode_unlock(ip->pmp->iroot, rcluster);
9b6b3df4 411
278ab2b2
MD
412 while (cluster &&
413 hammer2_cluster_type(cluster) != HAMMER2_BREF_TYPE_INODE) {
414 cluster = hammer2_cluster_next(cparent, cluster, &key_next,
415 key_next, (hammer2_key_t)-1,
416 0);
ae183399 417 }
278ab2b2 418 if (cluster) {
ae183399
MD
419 /*
420 * Load the data being returned by the ioctl.
421 */
bca9f8e6 422 ripdata = &hammer2_cluster_rdata(cluster)->ipdata;
b0f58de8
MD
423 pfs->name_key = ripdata->meta.name_key;
424 pfs->pfs_type = ripdata->meta.pfs_type;
425 pfs->pfs_subtype = ripdata->meta.pfs_subtype;
426 pfs->pfs_clid = ripdata->meta.pfs_clid;
427 pfs->pfs_fsid = ripdata->meta.pfs_fsid;
428 KKASSERT(ripdata->meta.name_len < sizeof(pfs->name));
429 bcopy(ripdata->filename, pfs->name, ripdata->meta.name_len);
430 pfs->name[ripdata->meta.name_len] = 0;
bca9f8e6 431 ripdata = NULL; /* safety */
ae183399
MD
432
433 /*
434 * Calculate the next field
435 */
436 do {
278ab2b2
MD
437 cluster = hammer2_cluster_next(cparent, cluster,
438 &key_next,
439 0, (hammer2_key_t)-1,
440 0);
441 } while (cluster &&
442 hammer2_cluster_type(cluster) !=
443 HAMMER2_BREF_TYPE_INODE);
444 if (cluster) {
bca9f8e6 445 ripdata = &hammer2_cluster_rdata(cluster)->ipdata;
b0f58de8 446 pfs->name_next = ripdata->meta.name_key;
278ab2b2 447 hammer2_cluster_unlock(cluster);
e513e77e 448 hammer2_cluster_drop(cluster);
ae183399
MD
449 } else {
450 pfs->name_next = (hammer2_key_t)-1;
451 }
452 } else {
453 pfs->name_next = (hammer2_key_t)-1;
454 error = ENOENT;
455 }
b93cc2e0 456 hammer2_inode_unlock(hmp->spmp->iroot, cparent);
0dea3156 457
ae183399
MD
458 return (error);
459}
460
458ecb1b
MD
461/*
462 * Find a specific PFS by name
463 */
464static int
465hammer2_ioctl_pfs_lookup(hammer2_inode_t *ip, void *data)
466{
bca9f8e6 467 const hammer2_inode_data_t *ripdata;
506bd6d1 468 hammer2_dev_t *hmp;
476d2aad 469 hammer2_ioc_pfs_t *pfs;
278ab2b2
MD
470 hammer2_cluster_t *cparent;
471 hammer2_cluster_t *cluster;
1897c66e 472 hammer2_key_t key_next;
458ecb1b 473 hammer2_key_t lhc;
476d2aad 474 int error;
458ecb1b
MD
475 size_t len;
476
476d2aad 477 error = 0;
58e43599 478 hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */
476d2aad 479 pfs = data;
159c3ca2
MD
480 hammer2_inode_lock(hmp->spmp->iroot, HAMMER2_RESOLVE_ALWAYS |
481 HAMMER2_RESOLVE_SHARED);
482 cparent = hammer2_inode_cluster(hmp->spmp->iroot,
483 HAMMER2_RESOLVE_ALWAYS |
484 HAMMER2_RESOLVE_SHARED);
458ecb1b
MD
485
486 pfs->name[sizeof(pfs->name) - 1] = 0;
487 len = strlen(pfs->name);
488 lhc = hammer2_dirhash(pfs->name, len);
489
278ab2b2
MD
490 cluster = hammer2_cluster_lookup(cparent, &key_next,
491 lhc, lhc + HAMMER2_DIRHASH_LOMASK,
b8ba9690 492 HAMMER2_LOOKUP_SHARED);
278ab2b2
MD
493 while (cluster) {
494 if (hammer2_cluster_type(cluster) == HAMMER2_BREF_TYPE_INODE) {
bca9f8e6 495 ripdata = &hammer2_cluster_rdata(cluster)->ipdata;
b0f58de8 496 if (ripdata->meta.name_len == len &&
bca9f8e6 497 bcmp(ripdata->filename, pfs->name, len) == 0) {
278ab2b2
MD
498 break;
499 }
bca9f8e6 500 ripdata = NULL; /* safety */
458ecb1b 501 }
278ab2b2 502 cluster = hammer2_cluster_next(cparent, cluster, &key_next,
1897c66e
MD
503 key_next,
504 lhc + HAMMER2_DIRHASH_LOMASK,
278ab2b2 505 HAMMER2_LOOKUP_SHARED);
458ecb1b
MD
506 }
507
508 /*
509 * Load the data being returned by the ioctl.
510 */
278ab2b2 511 if (cluster) {
bca9f8e6 512 ripdata = &hammer2_cluster_rdata(cluster)->ipdata;
b0f58de8
MD
513 pfs->name_key = ripdata->meta.name_key;
514 pfs->pfs_type = ripdata->meta.pfs_type;
515 pfs->pfs_subtype = ripdata->meta.pfs_subtype;
516 pfs->pfs_clid = ripdata->meta.pfs_clid;
517 pfs->pfs_fsid = ripdata->meta.pfs_fsid;
bca9f8e6 518 ripdata = NULL;
458ecb1b 519
278ab2b2 520 hammer2_cluster_unlock(cluster);
e513e77e 521 hammer2_cluster_drop(cluster);
458ecb1b
MD
522 } else {
523 error = ENOENT;
524 }
b93cc2e0 525 hammer2_inode_unlock(hmp->spmp->iroot, cparent);
7bed8d7e 526
458ecb1b
MD
527 return (error);
528}
529
ae183399
MD
530/*
531 * Create a new PFS under the super-root
532 */
533static int
534hammer2_ioctl_pfs_create(hammer2_inode_t *ip, void *data)
535{
476d2aad 536 hammer2_inode_data_t *nipdata;
c603b86b 537 hammer2_chain_t *nchain;
506bd6d1 538 hammer2_dev_t *hmp;
476d2aad
MD
539 hammer2_ioc_pfs_t *pfs;
540 hammer2_inode_t *nip;
ae183399
MD
541 int error;
542
58e43599 543 hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */
476d2aad
MD
544 pfs = data;
545 nip = NULL;
546
a864c5d9
MD
547 if (pfs->name[0] == 0)
548 return(EINVAL);
ae183399 549 pfs->name[sizeof(pfs->name) - 1] = 0; /* ensure 0-termination */
10252dc7 550
3c198419
MD
551 if (hammer2_ioctl_pfs_lookup(ip, pfs) == 0)
552 return(EEXIST);
553
c603b86b
MD
554 hammer2_trans_init(hmp->spmp, 0);
555 nip = hammer2_inode_create(hmp->spmp->iroot, NULL, NULL,
556 pfs->name, strlen(pfs->name),
e12ae3a5 557 1, HAMMER2_OBJTYPE_DIRECTORY, 0,
c603b86b 558 HAMMER2_INSERT_PFSROOT, &error);
ae183399 559 if (error == 0) {
c603b86b
MD
560 hammer2_inode_modify(nip);
561 nchain = hammer2_inode_chain(nip, 0, HAMMER2_RESOLVE_ALWAYS);
562 hammer2_chain_modify(nchain, 0);
563 nipdata = &nchain->data->ipdata;
564
565 nip->meta.pfs_type = pfs->pfs_type;
566 nip->meta.pfs_subtype = pfs->pfs_subtype;
567 nip->meta.pfs_clid = pfs->pfs_clid;
568 nip->meta.pfs_fsid = pfs->pfs_fsid;
569 nip->meta.op_flags |= HAMMER2_OPFLAG_PFSROOT;
cdfd0a3e
MD
570
571 /*
27253552
MD
572 * Set default compression and check algorithm. This
573 * can be changed later.
574 *
cdfd0a3e
MD
575 * Do not allow compression on PFS's with the special name
576 * "boot", the boot loader can't decompress (yet).
577 */
c603b86b 578 nip->meta.comp_algo =
27253552 579 HAMMER2_ENC_ALGO(HAMMER2_COMP_NEWFS_DEFAULT);
c603b86b 580 nip->meta.check_algo =
27253552
MD
581 HAMMER2_ENC_ALGO( HAMMER2_CHECK_ISCSI32);
582
583 if (strcasecmp(pfs->name, "boot") == 0) {
c603b86b 584 nip->meta.comp_algo =
27253552
MD
585 HAMMER2_ENC_ALGO(HAMMER2_COMP_AUTOZERO);
586 }
c603b86b
MD
587#if 0
588 hammer2_blockref_t bref;
589 /* XXX new PFS needs to be rescanned / added */
590 bref = nchain->bref;
506bd6d1 591 kprintf("ADD LOCAL PFS (IOCTL): %s\n", nipdata->filename);
e513e77e 592 hammer2_pfsalloc(ncluster, nipdata, bref.modify_tid);
506bd6d1 593#endif
c603b86b
MD
594 /* XXX rescan */
595 hammer2_chain_unlock(nchain);
596 hammer2_chain_drop(nchain);
597
598 hammer2_inode_unlock(nip, NULL);
ae183399 599 }
c603b86b 600 hammer2_trans_done(hmp->spmp);
278ab2b2 601
ae183399
MD
602 return (error);
603}
604
605/*
606 * Destroy an existing PFS under the super-root
607 */
608static int
609hammer2_ioctl_pfs_delete(hammer2_inode_t *ip, void *data)
610{
ae183399 611 hammer2_ioc_pfs_t *pfs = data;
e12ae3a5
MD
612 hammer2_pfs_t *spmp;
613 hammer2_xop_unlink_t *xop;
614 hammer2_inode_t *dip;
ae183399
MD
615 int error;
616
e12ae3a5
MD
617 pfs->name[sizeof(pfs->name) - 1] = 0; /* ensure termination */
618
619 /* XXX */
620 spmp = ip->pmp->iroot->cluster.focus->hmp->spmp;
621 dip = spmp->iroot;
622 hammer2_trans_init(spmp, 0);
623 hammer2_inode_lock(dip, HAMMER2_RESOLVE_ALWAYS);
624
625 xop = &hammer2_xop_alloc(dip)->xop_unlink;
626 hammer2_xop_setname(&xop->head, pfs->name, strlen(pfs->name));
627 xop->isdir = 2;
628 xop->dopermanent = 1;
629 hammer2_xop_start(&xop->head, hammer2_xop_unlink);
630
631 error = hammer2_xop_collect(&xop->head, 0);
632
633 hammer2_inode_unlock(dip, NULL);
634 hammer2_trans_done(spmp);
a864c5d9
MD
635
636 return (error);
637}
638
639static int
640hammer2_ioctl_pfs_snapshot(hammer2_inode_t *ip, void *data)
641{
a864c5d9 642 hammer2_ioc_pfs_t *pfs = data;
278ab2b2 643 hammer2_cluster_t *cparent;
a864c5d9
MD
644 int error;
645
646 if (pfs->name[0] == 0)
647 return(EINVAL);
648 if (pfs->name[sizeof(pfs->name)-1] != 0)
649 return(EINVAL);
650
a7720be7
MD
651 hammer2_vfs_sync(ip->pmp->mp, MNT_WAIT);
652
c603b86b 653 hammer2_trans_init(ip->pmp, HAMMER2_TRANS_ISFLUSH);
159c3ca2
MD
654 hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS);
655 cparent = hammer2_inode_cluster(ip, HAMMER2_RESOLVE_ALWAYS);
c603b86b 656 error = hammer2_cluster_snapshot(cparent, pfs);
b93cc2e0 657 hammer2_inode_unlock(ip, cparent);
c603b86b 658 hammer2_trans_done(ip->pmp);
0dea3156 659
ae183399
MD
660 return (error);
661}
344d4f82
MD
662
663/*
664 * Retrieve the raw inode structure
665 */
666static int
667hammer2_ioctl_inode_get(hammer2_inode_t *ip, void *data)
668{
bca9f8e6 669 const hammer2_inode_data_t *ripdata;
6a5f4fe6 670 hammer2_ioc_inode_t *ino;
29cbd7e5 671 hammer2_cluster_t *cluster;
b93cc2e0 672 int error;
344d4f82 673
6a5f4fe6
MD
674 ino = data;
675
159c3ca2
MD
676 hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS |
677 HAMMER2_RESOLVE_SHARED);
678 cluster = hammer2_inode_cluster(ip, HAMMER2_RESOLVE_ALWAYS |
679 HAMMER2_RESOLVE_SHARED);
29cbd7e5 680 if (cluster->error) {
b93cc2e0
MD
681 error = EIO;
682 } else {
29cbd7e5 683 ripdata = &hammer2_cluster_rdata(cluster)->ipdata;
b93cc2e0
MD
684 ino->ip_data = *ripdata;
685 ino->kdata = ip;
29cbd7e5
MD
686 ino->data_count = cluster->focus->bref.data_count;
687 ino->inode_count = cluster->focus->bref.inode_count;
b93cc2e0
MD
688 error = 0;
689 }
29cbd7e5 690 hammer2_inode_unlock(ip, cluster);
0dea3156 691
b93cc2e0 692 return error;
344d4f82
MD
693}
694
f481450f
MD
695/*
696 * Set various parameters in an inode which cannot be set through
697 * normal filesystem VNOPS.
698 */
344d4f82
MD
699static int
700hammer2_ioctl_inode_set(hammer2_inode_t *ip, void *data)
701{
6a5f4fe6
MD
702 const hammer2_inode_data_t *ripdata;
703 hammer2_inode_data_t *wipdata;
344d4f82 704 hammer2_ioc_inode_t *ino = data;
278ab2b2 705 hammer2_cluster_t *cparent;
f481450f 706 int error = 0;
6a5f4fe6 707 int dosync = 0;
344d4f82 708
c603b86b 709 hammer2_trans_init(ip->pmp, 0);
159c3ca2
MD
710 hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS);
711 cparent = hammer2_inode_cluster(ip, HAMMER2_RESOLVE_ALWAYS);
bca9f8e6 712 ripdata = &hammer2_cluster_rdata(cparent)->ipdata;
f481450f 713
b0f58de8 714 if (ino->ip_data.meta.check_algo != ripdata->meta.check_algo) {
c603b86b 715 wipdata = hammer2_cluster_modify_ip(ip, cparent, 0);
b0f58de8 716 wipdata->meta.check_algo = ino->ip_data.meta.check_algo;
e07becf8 717 ripdata = wipdata; /* safety */
c603b86b 718 hammer2_cluster_setmethod_check(cparent,
b0f58de8 719 wipdata->meta.check_algo);
e07becf8
MD
720 dosync = 1;
721 }
b0f58de8 722 if (ino->ip_data.meta.comp_algo != ripdata->meta.comp_algo) {
c603b86b 723 wipdata = hammer2_cluster_modify_ip(ip, cparent, 0);
b0f58de8 724 wipdata->meta.comp_algo = ino->ip_data.meta.comp_algo;
6a5f4fe6
MD
725 ripdata = wipdata; /* safety */
726 dosync = 1;
f481450f 727 }
355d67fc
MD
728 ino->kdata = ip;
729
f481450f 730 /* Ignore these flags for now...*/
344d4f82
MD
731 if (ino->flags & HAMMER2IOC_INODE_FLAG_IQUOTA) {
732 }
733 if (ino->flags & HAMMER2IOC_INODE_FLAG_DQUOTA) {
734 }
735 if (ino->flags & HAMMER2IOC_INODE_FLAG_COPIES) {
736 }
6a5f4fe6
MD
737 if (dosync)
738 hammer2_cluster_modsync(cparent);
c603b86b 739 hammer2_trans_done(ip->pmp);
b93cc2e0 740 hammer2_inode_unlock(ip, cparent);
0dea3156 741
344d4f82
MD
742 return (error);
743}
03188ed8
MD
744
745static
746int
747hammer2_ioctl_debug_dump(hammer2_inode_t *ip)
748{
749 hammer2_chain_t *chain;
750 int count = 1000;
751 int i;
752
753 for (i = 0; i < ip->cluster.nchains; ++i) {
4b7e61e0 754 chain = ip->cluster.array[i].chain;
03188ed8
MD
755 if (chain == NULL)
756 continue;
757 hammer2_dump_chain(chain, 0, &count, 'i');
758 }
759 return 0;
760}
3148f677
MD
761
762static
763int
764hammer2_ioctl_bulkfree_scan(hammer2_inode_t *ip, void *data)
765{
766 hammer2_ioc_bulkfree_t *bfi = data;
506bd6d1 767 hammer2_dev_t *hmp = ip->pmp->iroot->cluster.focus->hmp;
3148f677
MD
768 int error;
769
770 /* XXX run local cluster targets only */
771 error = hammer2_bulkfree_pass(hmp, bfi);
772
773 return error;
774}