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 int ddflag; 380 381 error = 0; 382 hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */ 383 pfs = data; 384 cparent = hammer2_inode_lock_ex(hmp->spmp->iroot); 385 rcluster = hammer2_inode_lock_ex(ip->pmp->iroot); 386 387 /* 388 * Search for the first key or specific key. Remember that keys 389 * can be returned in any order. 390 */ 391 if (pfs->name_key == 0) { 392 cluster = hammer2_cluster_lookup(cparent, &key_next, 393 0, (hammer2_key_t)-1, 394 0, &ddflag); 395 } else if (pfs->name_key == (hammer2_key_t)-1) { 396 ripdata = &hammer2_cluster_rdata(rcluster)->ipdata; 397 cluster = hammer2_cluster_lookup(cparent, &key_next, 398 ripdata->name_key, 399 ripdata->name_key, 400 0, &ddflag); 401 ripdata = NULL; /* safety */ 402 } else { 403 cluster = hammer2_cluster_lookup(cparent, &key_next, 404 pfs->name_key, pfs->name_key, 405 0, &ddflag); 406 } 407 hammer2_inode_unlock_ex(ip->pmp->iroot, rcluster); 408 409 while (cluster && 410 hammer2_cluster_type(cluster) != HAMMER2_BREF_TYPE_INODE) { 411 cluster = hammer2_cluster_next(cparent, cluster, &key_next, 412 key_next, (hammer2_key_t)-1, 413 0); 414 } 415 if (cluster) { 416 /* 417 * Load the data being returned by the ioctl. 418 */ 419 ripdata = &hammer2_cluster_rdata(cluster)->ipdata; 420 pfs->name_key = ripdata->name_key; 421 pfs->pfs_type = ripdata->pfs_type; 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 } else { 445 pfs->name_next = (hammer2_key_t)-1; 446 } 447 } else { 448 pfs->name_next = (hammer2_key_t)-1; 449 error = ENOENT; 450 } 451 hammer2_inode_unlock_ex(hmp->spmp->iroot, cparent); 452 453 return (error); 454 } 455 456 /* 457 * Find a specific PFS by name 458 */ 459 static int 460 hammer2_ioctl_pfs_lookup(hammer2_inode_t *ip, void *data) 461 { 462 const hammer2_inode_data_t *ripdata; 463 hammer2_dev_t *hmp; 464 hammer2_ioc_pfs_t *pfs; 465 hammer2_cluster_t *cparent; 466 hammer2_cluster_t *cluster; 467 hammer2_key_t key_next; 468 hammer2_key_t lhc; 469 int error; 470 int ddflag; 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_sh(hmp->spmp->iroot); 477 478 pfs->name[sizeof(pfs->name) - 1] = 0; 479 len = strlen(pfs->name); 480 lhc = hammer2_dirhash(pfs->name, len); 481 482 cluster = hammer2_cluster_lookup(cparent, &key_next, 483 lhc, lhc + HAMMER2_DIRHASH_LOMASK, 484 HAMMER2_LOOKUP_SHARED, &ddflag); 485 while (cluster) { 486 if (hammer2_cluster_type(cluster) == HAMMER2_BREF_TYPE_INODE) { 487 ripdata = &hammer2_cluster_rdata(cluster)->ipdata; 488 if (ripdata->name_len == len && 489 bcmp(ripdata->filename, pfs->name, len) == 0) { 490 break; 491 } 492 ripdata = NULL; /* safety */ 493 } 494 cluster = hammer2_cluster_next(cparent, cluster, &key_next, 495 key_next, 496 lhc + HAMMER2_DIRHASH_LOMASK, 497 HAMMER2_LOOKUP_SHARED); 498 } 499 500 /* 501 * Load the data being returned by the ioctl. 502 */ 503 if (cluster) { 504 ripdata = &hammer2_cluster_rdata(cluster)->ipdata; 505 pfs->name_key = ripdata->name_key; 506 pfs->pfs_type = ripdata->pfs_type; 507 pfs->pfs_clid = ripdata->pfs_clid; 508 pfs->pfs_fsid = ripdata->pfs_fsid; 509 ripdata = NULL; 510 511 hammer2_cluster_unlock(cluster); 512 } else { 513 error = ENOENT; 514 } 515 hammer2_inode_unlock_sh(hmp->spmp->iroot, cparent); 516 517 return (error); 518 } 519 520 /* 521 * Create a new PFS under the super-root 522 */ 523 static int 524 hammer2_ioctl_pfs_create(hammer2_inode_t *ip, void *data) 525 { 526 hammer2_inode_data_t *nipdata; 527 hammer2_dev_t *hmp; 528 hammer2_ioc_pfs_t *pfs; 529 hammer2_inode_t *nip; 530 hammer2_cluster_t *ncluster; 531 hammer2_trans_t trans; 532 hammer2_blockref_t bref; 533 int error; 534 535 hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */ 536 pfs = data; 537 nip = NULL; 538 539 if (pfs->name[0] == 0) 540 return(EINVAL); 541 pfs->name[sizeof(pfs->name) - 1] = 0; /* ensure 0-termination */ 542 543 if (hammer2_ioctl_pfs_lookup(ip, pfs) == 0) 544 return(EEXIST); 545 546 hammer2_trans_init(&trans, hmp->spmp, HAMMER2_TRANS_NEWINODE); 547 nip = hammer2_inode_create(&trans, hmp->spmp->iroot, NULL, NULL, 548 pfs->name, strlen(pfs->name), 549 &ncluster, 550 HAMMER2_INSERT_PFSROOT, &error); 551 if (error == 0) { 552 nipdata = hammer2_cluster_modify_ip(&trans, nip, ncluster, 0); 553 nipdata->pfs_type = pfs->pfs_type; 554 nipdata->pfs_clid = pfs->pfs_clid; 555 nipdata->pfs_fsid = pfs->pfs_fsid; 556 nipdata->op_flags |= HAMMER2_OPFLAG_PFSROOT; 557 558 /* 559 * Do not allow compression on PFS's with the special name 560 * "boot", the boot loader can't decompress (yet). 561 */ 562 if (strcmp(pfs->name, "boot") == 0) 563 nipdata->comp_algo = HAMMER2_ENC_ALGO( 564 HAMMER2_COMP_AUTOZERO); 565 hammer2_cluster_modsync(ncluster); 566 hammer2_cluster_bref(ncluster, &bref); 567 #if 1 568 kprintf("ADD LOCAL PFS (IOCTL): %s\n", nipdata->filename); 569 hammer2_pfsalloc(ncluster, nipdata, bref.mirror_tid); 570 /* XXX rescan */ 571 #endif 572 hammer2_inode_unlock_ex(nip, ncluster); 573 } 574 hammer2_trans_done(&trans); 575 576 return (error); 577 } 578 579 /* 580 * Destroy an existing PFS under the super-root 581 */ 582 static int 583 hammer2_ioctl_pfs_delete(hammer2_inode_t *ip, void *data) 584 { 585 hammer2_dev_t *hmp; 586 hammer2_ioc_pfs_t *pfs = data; 587 hammer2_trans_t trans; 588 int error; 589 590 hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */ 591 hammer2_trans_init(&trans, hmp->spmp, 0); 592 error = hammer2_unlink_file(&trans, hmp->spmp->iroot, 593 pfs->name, strlen(pfs->name), 594 2, NULL, NULL, -1); 595 hammer2_trans_done(&trans); 596 597 return (error); 598 } 599 600 static int 601 hammer2_ioctl_pfs_snapshot(hammer2_inode_t *ip, void *data) 602 { 603 hammer2_ioc_pfs_t *pfs = data; 604 hammer2_trans_t trans; 605 hammer2_cluster_t *cparent; 606 int error; 607 608 if (pfs->name[0] == 0) 609 return(EINVAL); 610 if (pfs->name[sizeof(pfs->name)-1] != 0) 611 return(EINVAL); 612 613 hammer2_vfs_sync(ip->pmp->mp, MNT_WAIT); 614 615 hammer2_trans_init(&trans, ip->pmp, 616 HAMMER2_TRANS_ISFLUSH | HAMMER2_TRANS_NEWINODE); 617 cparent = hammer2_inode_lock_ex(ip); 618 error = hammer2_cluster_snapshot(&trans, cparent, pfs); 619 hammer2_inode_unlock_ex(ip, cparent); 620 hammer2_trans_done(&trans); 621 622 return (error); 623 } 624 625 /* 626 * Retrieve the raw inode structure 627 */ 628 static int 629 hammer2_ioctl_inode_get(hammer2_inode_t *ip, void *data) 630 { 631 const hammer2_inode_data_t *ripdata; 632 hammer2_ioc_inode_t *ino; 633 hammer2_cluster_t *cparent; 634 635 ino = data; 636 637 cparent = hammer2_inode_lock_sh(ip); 638 ripdata = &hammer2_cluster_rdata(cparent)->ipdata; 639 ino->ip_data = *ripdata; 640 ino->kdata = ip; 641 hammer2_inode_unlock_sh(ip, cparent); 642 643 return (0); 644 } 645 646 /* 647 * Set various parameters in an inode which cannot be set through 648 * normal filesystem VNOPS. 649 */ 650 static int 651 hammer2_ioctl_inode_set(hammer2_inode_t *ip, void *data) 652 { 653 const hammer2_inode_data_t *ripdata; 654 hammer2_inode_data_t *wipdata; 655 hammer2_ioc_inode_t *ino = data; 656 hammer2_cluster_t *cparent; 657 hammer2_trans_t trans; 658 int error = 0; 659 int dosync = 0; 660 661 hammer2_trans_init(&trans, ip->pmp, 0); 662 cparent = hammer2_inode_lock_ex(ip); 663 ripdata = &hammer2_cluster_rdata(cparent)->ipdata; 664 665 if (ino->ip_data.check_algo != ripdata->check_algo) { 666 wipdata = hammer2_cluster_modify_ip(&trans, ip, cparent, 0); 667 wipdata->check_algo = ino->ip_data.check_algo; 668 ripdata = wipdata; /* safety */ 669 hammer2_cluster_setmethod_check(&trans, cparent, 670 wipdata->check_algo); 671 dosync = 1; 672 } 673 if (ino->ip_data.comp_algo != ripdata->comp_algo) { 674 wipdata = hammer2_cluster_modify_ip(&trans, ip, cparent, 0); 675 wipdata->comp_algo = ino->ip_data.comp_algo; 676 ripdata = wipdata; /* safety */ 677 dosync = 1; 678 } 679 ino->kdata = ip; 680 681 /* Ignore these flags for now...*/ 682 if (ino->flags & HAMMER2IOC_INODE_FLAG_IQUOTA) { 683 } 684 if (ino->flags & HAMMER2IOC_INODE_FLAG_DQUOTA) { 685 } 686 if (ino->flags & HAMMER2IOC_INODE_FLAG_COPIES) { 687 } 688 if (dosync) 689 hammer2_cluster_modsync(cparent); 690 hammer2_trans_done(&trans); 691 hammer2_inode_unlock_ex(ip, cparent); 692 693 return (error); 694 } 695 696 static 697 int 698 hammer2_ioctl_debug_dump(hammer2_inode_t *ip) 699 { 700 hammer2_chain_t *chain; 701 int count = 1000; 702 int i; 703 704 for (i = 0; i < ip->cluster.nchains; ++i) { 705 chain = ip->cluster.array[i].chain; 706 if (chain == NULL) 707 continue; 708 hammer2_dump_chain(chain, 0, &count, 'i'); 709 } 710 return 0; 711 } 712 713 static 714 int 715 hammer2_ioctl_bulkfree_scan(hammer2_inode_t *ip, void *data) 716 { 717 hammer2_ioc_bulkfree_t *bfi = data; 718 hammer2_dev_t *hmp = ip->pmp->iroot->cluster.focus->hmp; 719 int error; 720 721 /* XXX run local cluster targets only */ 722 error = hammer2_bulkfree_pass(hmp, bfi); 723 724 return error; 725 } 726