1 /* 2 * Copyright (c) 2011-2015 The DragonFly Project. All rights reserved. 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 45 static int hammer2_ioctl_version_get(hammer2_inode_t *ip, void *data); 46 static int hammer2_ioctl_recluster(hammer2_inode_t *ip, void *data); 47 static int hammer2_ioctl_remote_scan(hammer2_inode_t *ip, void *data); 48 static int hammer2_ioctl_remote_add(hammer2_inode_t *ip, void *data); 49 static int hammer2_ioctl_remote_del(hammer2_inode_t *ip, void *data); 50 static int hammer2_ioctl_remote_rep(hammer2_inode_t *ip, void *data); 51 static int hammer2_ioctl_socket_get(hammer2_inode_t *ip, void *data); 52 static int hammer2_ioctl_socket_set(hammer2_inode_t *ip, void *data); 53 static int hammer2_ioctl_pfs_get(hammer2_inode_t *ip, void *data); 54 static int hammer2_ioctl_pfs_lookup(hammer2_inode_t *ip, void *data); 55 static int hammer2_ioctl_pfs_create(hammer2_inode_t *ip, void *data); 56 static int hammer2_ioctl_pfs_snapshot(hammer2_inode_t *ip, void *data); 57 static int hammer2_ioctl_pfs_delete(hammer2_inode_t *ip, void *data); 58 static int hammer2_ioctl_inode_get(hammer2_inode_t *ip, void *data); 59 static int hammer2_ioctl_inode_set(hammer2_inode_t *ip, void *data); 60 static int hammer2_ioctl_debug_dump(hammer2_inode_t *ip); 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); 64 static int hammer2_ioctl_bulkfree_scan(hammer2_inode_t *ip, void *data); 65 66 int 67 hammer2_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) { 79 case HAMMER2IOC_VERSION_GET: 80 error = hammer2_ioctl_version_get(ip, data); 81 break; 82 case HAMMER2IOC_RECLUSTER: 83 if (error == 0) 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); 89 break; 90 case HAMMER2IOC_REMOTE_ADD: 91 if (error == 0) 92 error = hammer2_ioctl_remote_add(ip, data); 93 break; 94 case HAMMER2IOC_REMOTE_DEL: 95 if (error == 0) 96 error = hammer2_ioctl_remote_del(ip, data); 97 break; 98 case HAMMER2IOC_REMOTE_REP: 99 if (error == 0) 100 error = hammer2_ioctl_remote_rep(ip, data); 101 break; 102 case HAMMER2IOC_SOCKET_GET: 103 if (error == 0) 104 error = hammer2_ioctl_socket_get(ip, data); 105 break; 106 case HAMMER2IOC_SOCKET_SET: 107 if (error == 0) 108 error = hammer2_ioctl_socket_set(ip, data); 109 break; 110 case HAMMER2IOC_PFS_GET: 111 if (error == 0) 112 error = hammer2_ioctl_pfs_get(ip, data); 113 break; 114 case HAMMER2IOC_PFS_LOOKUP: 115 if (error == 0) 116 error = hammer2_ioctl_pfs_lookup(ip, data); 117 break; 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); 125 break; 126 case HAMMER2IOC_PFS_SNAPSHOT: 127 if (error == 0) 128 error = hammer2_ioctl_pfs_snapshot(ip, data); 129 break; 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; 137 case HAMMER2IOC_BULKFREE_SCAN: 138 error = hammer2_ioctl_bulkfree_scan(ip, data); 139 break; 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;*/ 149 case HAMMER2IOC_DEBUG_DUMP: 150 error = hammer2_ioctl_debug_dump(ip); 151 break; 152 default: 153 error = EOPNOTSUPP; 154 break; 155 } 156 return (error); 157 } 158 159 /* 160 * Retrieve version and basic info 161 */ 162 static int 163 hammer2_ioctl_version_get(hammer2_inode_t *ip, void *data) 164 { 165 hammer2_dev_t *hmp = ip->pmp->iroot->cluster.focus->hmp; 166 hammer2_ioc_version_t *version = data; 167 168 version->version = hmp->voldata.version; 169 return 0; 170 } 171 172 static int 173 hammer2_ioctl_recluster(hammer2_inode_t *ip, void *data) 174 { 175 hammer2_ioc_recluster_t *recl = data; 176 struct file *fp; 177 hammer2_cluster_t *cluster; 178 int error; 179 180 fp = holdfp(curproc->p_fd, recl->fd, -1); 181 if (fp) { 182 kprintf("reconnect to cluster: XXX "); 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 } 192 } else { 193 error = EINVAL; 194 } 195 return error; 196 } 197 198 /* 199 * Retrieve information about a remote 200 */ 201 static int 202 hammer2_ioctl_remote_scan(hammer2_inode_t *ip, void *data) 203 { 204 hammer2_dev_t *hmp = ip->pmp->iroot->cluster.focus->hmp; 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]; 213 hammer2_voldata_unlock(hmp); 214 215 /* 216 * Adjust nextid (GET only) 217 */ 218 while (++copyid < HAMMER2_COPYID_COUNT && 219 hmp->voldata.copyinfo[copyid].copyid == 0) { 220 ; 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 */ 233 static int 234 hammer2_ioctl_remote_add(hammer2_inode_t *ip, void *data) 235 { 236 hammer2_ioc_remote_t *remote = data; 237 hammer2_pfs_t *pmp = ip->pmp; 238 hammer2_dev_t *hmp; 239 int copyid = remote->copyid; 240 int error = 0; 241 242 if (copyid >= HAMMER2_COPYID_COUNT) 243 return (EINVAL); 244 245 hmp = pmp->iroot->cluster.focus->hmp; /* XXX */ 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 } 257 hammer2_voldata_modify(hmp); 258 remote->copy1.copyid = copyid; 259 hmp->voldata.copyinfo[copyid] = remote->copy1; 260 hammer2_volconf_update(hmp, copyid); 261 failed: 262 hammer2_voldata_unlock(hmp); 263 return (error); 264 } 265 266 /* 267 * Delete existing remote entry 268 */ 269 static int 270 hammer2_ioctl_remote_del(hammer2_inode_t *ip, void *data) 271 { 272 hammer2_ioc_remote_t *remote = data; 273 hammer2_pfs_t *pmp = ip->pmp; 274 hammer2_dev_t *hmp; 275 int copyid = remote->copyid; 276 int error = 0; 277 278 hmp = pmp->iroot->cluster.focus->hmp; /* XXX */ 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 } 297 hammer2_voldata_modify(hmp); 298 hmp->voldata.copyinfo[copyid].copyid = 0; 299 hammer2_volconf_update(hmp, copyid); 300 failed: 301 hammer2_voldata_unlock(hmp); 302 return (error); 303 } 304 305 /* 306 * Replace existing remote entry 307 */ 308 static int 309 hammer2_ioctl_remote_rep(hammer2_inode_t *ip, void *data) 310 { 311 hammer2_ioc_remote_t *remote = data; 312 hammer2_dev_t *hmp; 313 int copyid = remote->copyid; 314 315 hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */ 316 317 if (copyid < 0 || copyid >= HAMMER2_COPYID_COUNT) 318 return (EINVAL); 319 320 hammer2_voldata_lock(hmp); 321 hammer2_voldata_modify(hmp); 322 /*hammer2_volconf_update(hmp, copyid);*/ 323 hammer2_voldata_unlock(hmp); 324 325 return(0); 326 } 327 328 /* 329 * Retrieve communications socket 330 */ 331 static int 332 hammer2_ioctl_socket_get(hammer2_inode_t *ip, void *data) 333 { 334 return (EOPNOTSUPP); 335 } 336 337 /* 338 * Set communications socket for connection 339 */ 340 static int 341 hammer2_ioctl_socket_set(hammer2_inode_t *ip, void *data) 342 { 343 hammer2_ioc_remote_t *remote = data; 344 hammer2_dev_t *hmp; 345 int copyid = remote->copyid; 346 347 hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */ 348 if (copyid < 0 || copyid >= HAMMER2_COPYID_COUNT) 349 return (EINVAL); 350 351 hammer2_voldata_lock(hmp); 352 hammer2_voldata_unlock(hmp); 353 354 return(0); 355 } 356 357 /* 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. 367 */ 368 static int 369 hammer2_ioctl_pfs_get(hammer2_inode_t *ip, void *data) 370 { 371 const hammer2_inode_data_t *ripdata; 372 hammer2_dev_t *hmp; 373 hammer2_ioc_pfs_t *pfs; 374 hammer2_cluster_t *cparent; 375 hammer2_cluster_t *rcluster; 376 hammer2_cluster_t *cluster; 377 hammer2_key_t key_next; 378 int error; 379 380 error = 0; 381 hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */ 382 pfs = data; 383 cparent = hammer2_inode_lock(hmp->spmp->iroot, HAMMER2_RESOLVE_ALWAYS); 384 rcluster = hammer2_inode_lock(ip->pmp->iroot, HAMMER2_RESOLVE_ALWAYS); 385 386 /* 387 * Search for the first key or specific key. Remember that keys 388 * can be returned in any order. 389 */ 390 if (pfs->name_key == 0) { 391 cluster = hammer2_cluster_lookup(cparent, &key_next, 392 0, (hammer2_key_t)-1, 393 0); 394 } else if (pfs->name_key == (hammer2_key_t)-1) { 395 ripdata = &hammer2_cluster_rdata(rcluster)->ipdata; 396 cluster = hammer2_cluster_lookup(cparent, &key_next, 397 ripdata->name_key, 398 ripdata->name_key, 399 0); 400 ripdata = NULL; /* safety */ 401 } else { 402 cluster = hammer2_cluster_lookup(cparent, &key_next, 403 pfs->name_key, pfs->name_key, 404 0); 405 } 406 hammer2_inode_unlock(ip->pmp->iroot, rcluster); 407 408 while (cluster && 409 hammer2_cluster_type(cluster) != HAMMER2_BREF_TYPE_INODE) { 410 cluster = hammer2_cluster_next(cparent, cluster, &key_next, 411 key_next, (hammer2_key_t)-1, 412 0); 413 } 414 if (cluster) { 415 /* 416 * Load the data being returned by the ioctl. 417 */ 418 ripdata = &hammer2_cluster_rdata(cluster)->ipdata; 419 pfs->name_key = ripdata->name_key; 420 pfs->pfs_type = ripdata->pfs_type; 421 pfs->pfs_subtype = ripdata->pfs_subtype; 422 pfs->pfs_clid = ripdata->pfs_clid; 423 pfs->pfs_fsid = ripdata->pfs_fsid; 424 KKASSERT(ripdata->name_len < sizeof(pfs->name)); 425 bcopy(ripdata->filename, pfs->name, ripdata->name_len); 426 pfs->name[ripdata->name_len] = 0; 427 ripdata = NULL; /* safety */ 428 429 /* 430 * Calculate the next field 431 */ 432 do { 433 cluster = hammer2_cluster_next(cparent, cluster, 434 &key_next, 435 0, (hammer2_key_t)-1, 436 0); 437 } while (cluster && 438 hammer2_cluster_type(cluster) != 439 HAMMER2_BREF_TYPE_INODE); 440 if (cluster) { 441 ripdata = &hammer2_cluster_rdata(cluster)->ipdata; 442 pfs->name_next = ripdata->name_key; 443 hammer2_cluster_unlock(cluster); 444 hammer2_cluster_drop(cluster); 445 } else { 446 pfs->name_next = (hammer2_key_t)-1; 447 } 448 } else { 449 pfs->name_next = (hammer2_key_t)-1; 450 error = ENOENT; 451 } 452 hammer2_inode_unlock(hmp->spmp->iroot, cparent); 453 454 return (error); 455 } 456 457 /* 458 * Find a specific PFS by name 459 */ 460 static int 461 hammer2_ioctl_pfs_lookup(hammer2_inode_t *ip, void *data) 462 { 463 const hammer2_inode_data_t *ripdata; 464 hammer2_dev_t *hmp; 465 hammer2_ioc_pfs_t *pfs; 466 hammer2_cluster_t *cparent; 467 hammer2_cluster_t *cluster; 468 hammer2_key_t key_next; 469 hammer2_key_t lhc; 470 int error; 471 size_t len; 472 473 error = 0; 474 hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */ 475 pfs = data; 476 cparent = hammer2_inode_lock(hmp->spmp->iroot, HAMMER2_RESOLVE_ALWAYS | 477 HAMMER2_RESOLVE_SHARED); 478 479 pfs->name[sizeof(pfs->name) - 1] = 0; 480 len = strlen(pfs->name); 481 lhc = hammer2_dirhash(pfs->name, len); 482 483 cluster = hammer2_cluster_lookup(cparent, &key_next, 484 lhc, lhc + HAMMER2_DIRHASH_LOMASK, 485 HAMMER2_LOOKUP_SHARED); 486 while (cluster) { 487 if (hammer2_cluster_type(cluster) == HAMMER2_BREF_TYPE_INODE) { 488 ripdata = &hammer2_cluster_rdata(cluster)->ipdata; 489 if (ripdata->name_len == len && 490 bcmp(ripdata->filename, pfs->name, len) == 0) { 491 break; 492 } 493 ripdata = NULL; /* safety */ 494 } 495 cluster = hammer2_cluster_next(cparent, cluster, &key_next, 496 key_next, 497 lhc + HAMMER2_DIRHASH_LOMASK, 498 HAMMER2_LOOKUP_SHARED); 499 } 500 501 /* 502 * Load the data being returned by the ioctl. 503 */ 504 if (cluster) { 505 ripdata = &hammer2_cluster_rdata(cluster)->ipdata; 506 pfs->name_key = ripdata->name_key; 507 pfs->pfs_type = ripdata->pfs_type; 508 pfs->pfs_subtype = ripdata->pfs_subtype; 509 pfs->pfs_clid = ripdata->pfs_clid; 510 pfs->pfs_fsid = ripdata->pfs_fsid; 511 ripdata = NULL; 512 513 hammer2_cluster_unlock(cluster); 514 hammer2_cluster_drop(cluster); 515 } else { 516 error = ENOENT; 517 } 518 hammer2_inode_unlock(hmp->spmp->iroot, cparent); 519 520 return (error); 521 } 522 523 /* 524 * Create a new PFS under the super-root 525 */ 526 static int 527 hammer2_ioctl_pfs_create(hammer2_inode_t *ip, void *data) 528 { 529 hammer2_inode_data_t *nipdata; 530 hammer2_dev_t *hmp; 531 hammer2_ioc_pfs_t *pfs; 532 hammer2_inode_t *nip; 533 hammer2_cluster_t *ncluster; 534 hammer2_trans_t trans; 535 hammer2_blockref_t bref; 536 int error; 537 538 hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */ 539 pfs = data; 540 nip = NULL; 541 542 if (pfs->name[0] == 0) 543 return(EINVAL); 544 pfs->name[sizeof(pfs->name) - 1] = 0; /* ensure 0-termination */ 545 546 if (hammer2_ioctl_pfs_lookup(ip, pfs) == 0) 547 return(EEXIST); 548 549 hammer2_trans_init(&trans, hmp->spmp, HAMMER2_TRANS_NEWINODE); 550 nip = hammer2_inode_create(&trans, hmp->spmp->iroot, NULL, NULL, 551 pfs->name, strlen(pfs->name), 552 &ncluster, 553 HAMMER2_INSERT_PFSROOT, &error); 554 if (error == 0) { 555 nipdata = hammer2_cluster_modify_ip(&trans, nip, ncluster, 0); 556 nipdata->pfs_type = pfs->pfs_type; 557 nipdata->pfs_subtype = pfs->pfs_subtype; 558 nipdata->pfs_clid = pfs->pfs_clid; 559 nipdata->pfs_fsid = pfs->pfs_fsid; 560 nipdata->op_flags |= HAMMER2_OPFLAG_PFSROOT; 561 562 /* 563 * Do not allow compression on PFS's with the special name 564 * "boot", the boot loader can't decompress (yet). 565 */ 566 if (strcmp(pfs->name, "boot") == 0) 567 nipdata->comp_algo = HAMMER2_ENC_ALGO( 568 HAMMER2_COMP_AUTOZERO); 569 hammer2_cluster_modsync(ncluster); 570 hammer2_cluster_bref(ncluster, &bref); 571 #if 1 572 kprintf("ADD LOCAL PFS (IOCTL): %s\n", nipdata->filename); 573 hammer2_pfsalloc(ncluster, nipdata, bref.modify_tid); 574 /* XXX rescan */ 575 #endif 576 hammer2_inode_unlock(nip, ncluster); 577 } 578 hammer2_trans_done(&trans); 579 580 return (error); 581 } 582 583 /* 584 * Destroy an existing PFS under the super-root 585 */ 586 static int 587 hammer2_ioctl_pfs_delete(hammer2_inode_t *ip, void *data) 588 { 589 hammer2_dev_t *hmp; 590 hammer2_ioc_pfs_t *pfs = data; 591 hammer2_trans_t trans; 592 int error; 593 594 hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */ 595 hammer2_trans_init(&trans, hmp->spmp, 0); 596 error = hammer2_unlink_file(&trans, hmp->spmp->iroot, 597 pfs->name, strlen(pfs->name), 598 2, NULL, NULL, -1); 599 hammer2_trans_done(&trans); 600 601 return (error); 602 } 603 604 static int 605 hammer2_ioctl_pfs_snapshot(hammer2_inode_t *ip, void *data) 606 { 607 hammer2_ioc_pfs_t *pfs = data; 608 hammer2_trans_t trans; 609 hammer2_cluster_t *cparent; 610 int error; 611 612 if (pfs->name[0] == 0) 613 return(EINVAL); 614 if (pfs->name[sizeof(pfs->name)-1] != 0) 615 return(EINVAL); 616 617 hammer2_vfs_sync(ip->pmp->mp, MNT_WAIT); 618 619 hammer2_trans_init(&trans, ip->pmp, 620 HAMMER2_TRANS_ISFLUSH | HAMMER2_TRANS_NEWINODE); 621 cparent = hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS); 622 error = hammer2_cluster_snapshot(&trans, cparent, pfs); 623 hammer2_inode_unlock(ip, cparent); 624 hammer2_trans_done(&trans); 625 626 return (error); 627 } 628 629 /* 630 * Retrieve the raw inode structure 631 */ 632 static int 633 hammer2_ioctl_inode_get(hammer2_inode_t *ip, void *data) 634 { 635 const hammer2_inode_data_t *ripdata; 636 hammer2_ioc_inode_t *ino; 637 hammer2_cluster_t *cparent; 638 int error; 639 640 ino = data; 641 642 cparent = hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS | 643 HAMMER2_RESOLVE_SHARED); 644 if (cparent->error) { 645 error = EIO; 646 } else { 647 ripdata = &hammer2_cluster_rdata(cparent)->ipdata; 648 ino->ip_data = *ripdata; 649 ino->kdata = ip; 650 error = 0; 651 } 652 hammer2_inode_unlock(ip, cparent); 653 654 return error; 655 } 656 657 /* 658 * Set various parameters in an inode which cannot be set through 659 * normal filesystem VNOPS. 660 */ 661 static int 662 hammer2_ioctl_inode_set(hammer2_inode_t *ip, void *data) 663 { 664 const hammer2_inode_data_t *ripdata; 665 hammer2_inode_data_t *wipdata; 666 hammer2_ioc_inode_t *ino = data; 667 hammer2_cluster_t *cparent; 668 hammer2_trans_t trans; 669 int error = 0; 670 int dosync = 0; 671 672 hammer2_trans_init(&trans, ip->pmp, 0); 673 cparent = hammer2_inode_lock(ip, HAMMER2_RESOLVE_ALWAYS); 674 ripdata = &hammer2_cluster_rdata(cparent)->ipdata; 675 676 if (ino->ip_data.check_algo != ripdata->check_algo) { 677 wipdata = hammer2_cluster_modify_ip(&trans, ip, cparent, 0); 678 wipdata->check_algo = ino->ip_data.check_algo; 679 ripdata = wipdata; /* safety */ 680 hammer2_cluster_setmethod_check(&trans, cparent, 681 wipdata->check_algo); 682 dosync = 1; 683 } 684 if (ino->ip_data.comp_algo != ripdata->comp_algo) { 685 wipdata = hammer2_cluster_modify_ip(&trans, ip, cparent, 0); 686 wipdata->comp_algo = ino->ip_data.comp_algo; 687 ripdata = wipdata; /* safety */ 688 dosync = 1; 689 } 690 ino->kdata = ip; 691 692 /* Ignore these flags for now...*/ 693 if (ino->flags & HAMMER2IOC_INODE_FLAG_IQUOTA) { 694 } 695 if (ino->flags & HAMMER2IOC_INODE_FLAG_DQUOTA) { 696 } 697 if (ino->flags & HAMMER2IOC_INODE_FLAG_COPIES) { 698 } 699 if (dosync) 700 hammer2_cluster_modsync(cparent); 701 hammer2_trans_done(&trans); 702 hammer2_inode_unlock(ip, cparent); 703 704 return (error); 705 } 706 707 static 708 int 709 hammer2_ioctl_debug_dump(hammer2_inode_t *ip) 710 { 711 hammer2_chain_t *chain; 712 int count = 1000; 713 int i; 714 715 for (i = 0; i < ip->cluster.nchains; ++i) { 716 chain = ip->cluster.array[i].chain; 717 if (chain == NULL) 718 continue; 719 hammer2_dump_chain(chain, 0, &count, 'i'); 720 } 721 return 0; 722 } 723 724 static 725 int 726 hammer2_ioctl_bulkfree_scan(hammer2_inode_t *ip, void *data) 727 { 728 hammer2_ioc_bulkfree_t *bfi = data; 729 hammer2_dev_t *hmp = ip->pmp->iroot->cluster.focus->hmp; 730 int error; 731 732 /* XXX run local cluster targets only */ 733 error = hammer2_bulkfree_pass(hmp, bfi); 734 735 return error; 736 } 737