1 /* 2 * Copyright (c) 2011-2014 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 65 int 66 hammer2_ioctl(hammer2_inode_t *ip, u_long com, void *data, int fflag, 67 struct ucred *cred) 68 { 69 int error; 70 71 /* 72 * Standard root cred checks, will be selectively ignored below 73 * for ioctls that do not require root creds. 74 */ 75 error = priv_check_cred(cred, PRIV_HAMMER_IOCTL, 0); 76 77 switch(com) { 78 case HAMMER2IOC_VERSION_GET: 79 error = hammer2_ioctl_version_get(ip, data); 80 break; 81 case HAMMER2IOC_RECLUSTER: 82 if (error == 0) 83 error = hammer2_ioctl_recluster(ip, data); 84 break; 85 case HAMMER2IOC_REMOTE_SCAN: 86 if (error == 0) 87 error = hammer2_ioctl_remote_scan(ip, data); 88 break; 89 case HAMMER2IOC_REMOTE_ADD: 90 if (error == 0) 91 error = hammer2_ioctl_remote_add(ip, data); 92 break; 93 case HAMMER2IOC_REMOTE_DEL: 94 if (error == 0) 95 error = hammer2_ioctl_remote_del(ip, data); 96 break; 97 case HAMMER2IOC_REMOTE_REP: 98 if (error == 0) 99 error = hammer2_ioctl_remote_rep(ip, data); 100 break; 101 case HAMMER2IOC_SOCKET_GET: 102 if (error == 0) 103 error = hammer2_ioctl_socket_get(ip, data); 104 break; 105 case HAMMER2IOC_SOCKET_SET: 106 if (error == 0) 107 error = hammer2_ioctl_socket_set(ip, data); 108 break; 109 case HAMMER2IOC_PFS_GET: 110 if (error == 0) 111 error = hammer2_ioctl_pfs_get(ip, data); 112 break; 113 case HAMMER2IOC_PFS_LOOKUP: 114 if (error == 0) 115 error = hammer2_ioctl_pfs_lookup(ip, data); 116 break; 117 case HAMMER2IOC_PFS_CREATE: 118 if (error == 0) 119 error = hammer2_ioctl_pfs_create(ip, data); 120 break; 121 case HAMMER2IOC_PFS_DELETE: 122 if (error == 0) 123 error = hammer2_ioctl_pfs_delete(ip, data); 124 break; 125 case HAMMER2IOC_PFS_SNAPSHOT: 126 if (error == 0) 127 error = hammer2_ioctl_pfs_snapshot(ip, data); 128 break; 129 case HAMMER2IOC_INODE_GET: 130 error = hammer2_ioctl_inode_get(ip, data); 131 break; 132 case HAMMER2IOC_INODE_SET: 133 if (error == 0) 134 error = hammer2_ioctl_inode_set(ip, data); 135 break; 136 /*case HAMMER2IOC_INODE_COMP_SET: 137 error = hammer2_ioctl_inode_comp_set(ip, data); 138 break; 139 case HAMMER2IOC_INODE_COMP_REC_SET: 140 error = hammer2_ioctl_inode_comp_rec_set(ip, data); 141 break; 142 case HAMMER2IOC_INODE_COMP_REC_SET2: 143 error = hammer2_ioctl_inode_comp_rec_set2(ip, data); 144 break;*/ 145 case HAMMER2IOC_DEBUG_DUMP: 146 error = hammer2_ioctl_debug_dump(ip); 147 break; 148 default: 149 error = EOPNOTSUPP; 150 break; 151 } 152 return (error); 153 } 154 155 /* 156 * Retrieve version and basic info 157 */ 158 static int 159 hammer2_ioctl_version_get(hammer2_inode_t *ip, void *data) 160 { 161 hammer2_mount_t *hmp = ip->pmp->iroot->cluster.focus->hmp; 162 hammer2_ioc_version_t *version = data; 163 164 version->version = hmp->voldata.version; 165 return 0; 166 } 167 168 static int 169 hammer2_ioctl_recluster(hammer2_inode_t *ip, void *data) 170 { 171 hammer2_ioc_recluster_t *recl = data; 172 struct file *fp; 173 hammer2_cluster_t *cluster; 174 int error; 175 176 fp = holdfp(curproc->p_fd, recl->fd, -1); 177 if (fp) { 178 kprintf("reconnect to cluster: "); 179 cluster = &ip->pmp->iroot->cluster; 180 if (cluster->nchains != 1 || cluster->focus == NULL) { 181 kprintf("not a local device mount\n"); 182 error = EINVAL; 183 } else { 184 hammer2_cluster_reconnect(cluster->focus->hmp, fp); 185 kprintf("ok\n"); 186 error = 0; 187 } 188 } else { 189 error = EINVAL; 190 } 191 return error; 192 } 193 194 /* 195 * Retrieve information about a remote 196 */ 197 static int 198 hammer2_ioctl_remote_scan(hammer2_inode_t *ip, void *data) 199 { 200 hammer2_mount_t *hmp = ip->pmp->iroot->cluster.focus->hmp; 201 hammer2_ioc_remote_t *remote = data; 202 int copyid = remote->copyid; 203 204 if (copyid < 0 || copyid >= HAMMER2_COPYID_COUNT) 205 return (EINVAL); 206 207 hammer2_voldata_lock(hmp); 208 remote->copy1 = hmp->voldata.copyinfo[copyid]; 209 hammer2_voldata_unlock(hmp); 210 211 /* 212 * Adjust nextid (GET only) 213 */ 214 while (++copyid < HAMMER2_COPYID_COUNT && 215 hmp->voldata.copyinfo[copyid].copyid == 0) { 216 ; 217 } 218 if (copyid == HAMMER2_COPYID_COUNT) 219 remote->nextid = -1; 220 else 221 remote->nextid = copyid; 222 223 return(0); 224 } 225 226 /* 227 * Add new remote entry 228 */ 229 static int 230 hammer2_ioctl_remote_add(hammer2_inode_t *ip, void *data) 231 { 232 hammer2_ioc_remote_t *remote = data; 233 hammer2_pfsmount_t *pmp = ip->pmp; 234 hammer2_mount_t *hmp; 235 int copyid = remote->copyid; 236 int error = 0; 237 238 if (copyid >= HAMMER2_COPYID_COUNT) 239 return (EINVAL); 240 241 hmp = pmp->iroot->cluster.focus->hmp; /* XXX */ 242 hammer2_voldata_lock(hmp); 243 if (copyid < 0) { 244 for (copyid = 1; copyid < HAMMER2_COPYID_COUNT; ++copyid) { 245 if (hmp->voldata.copyinfo[copyid].copyid == 0) 246 break; 247 } 248 if (copyid == HAMMER2_COPYID_COUNT) { 249 error = ENOSPC; 250 goto failed; 251 } 252 } 253 hammer2_voldata_modify(hmp); 254 remote->copy1.copyid = copyid; 255 hmp->voldata.copyinfo[copyid] = remote->copy1; 256 hammer2_volconf_update(hmp, copyid); 257 failed: 258 hammer2_voldata_unlock(hmp); 259 return (error); 260 } 261 262 /* 263 * Delete existing remote entry 264 */ 265 static int 266 hammer2_ioctl_remote_del(hammer2_inode_t *ip, void *data) 267 { 268 hammer2_ioc_remote_t *remote = data; 269 hammer2_pfsmount_t *pmp = ip->pmp; 270 hammer2_mount_t *hmp; 271 int copyid = remote->copyid; 272 int error = 0; 273 274 hmp = pmp->iroot->cluster.focus->hmp; /* XXX */ 275 if (copyid >= HAMMER2_COPYID_COUNT) 276 return (EINVAL); 277 remote->copy1.path[sizeof(remote->copy1.path) - 1] = 0; 278 hammer2_voldata_lock(hmp); 279 if (copyid < 0) { 280 for (copyid = 1; copyid < HAMMER2_COPYID_COUNT; ++copyid) { 281 if (hmp->voldata.copyinfo[copyid].copyid == 0) 282 continue; 283 if (strcmp(remote->copy1.path, 284 hmp->voldata.copyinfo[copyid].path) == 0) { 285 break; 286 } 287 } 288 if (copyid == HAMMER2_COPYID_COUNT) { 289 error = ENOENT; 290 goto failed; 291 } 292 } 293 hammer2_voldata_modify(hmp); 294 hmp->voldata.copyinfo[copyid].copyid = 0; 295 hammer2_volconf_update(hmp, copyid); 296 failed: 297 hammer2_voldata_unlock(hmp); 298 return (error); 299 } 300 301 /* 302 * Replace existing remote entry 303 */ 304 static int 305 hammer2_ioctl_remote_rep(hammer2_inode_t *ip, void *data) 306 { 307 hammer2_ioc_remote_t *remote = data; 308 hammer2_mount_t *hmp; 309 int copyid = remote->copyid; 310 311 hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */ 312 313 if (copyid < 0 || copyid >= HAMMER2_COPYID_COUNT) 314 return (EINVAL); 315 316 hammer2_voldata_lock(hmp); 317 hammer2_voldata_modify(hmp); 318 /*hammer2_volconf_update(hmp, copyid);*/ 319 hammer2_voldata_unlock(hmp); 320 321 return(0); 322 } 323 324 /* 325 * Retrieve communications socket 326 */ 327 static int 328 hammer2_ioctl_socket_get(hammer2_inode_t *ip, void *data) 329 { 330 return (EOPNOTSUPP); 331 } 332 333 /* 334 * Set communications socket for connection 335 */ 336 static int 337 hammer2_ioctl_socket_set(hammer2_inode_t *ip, void *data) 338 { 339 hammer2_ioc_remote_t *remote = data; 340 hammer2_mount_t *hmp; 341 int copyid = remote->copyid; 342 343 hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */ 344 if (copyid < 0 || copyid >= HAMMER2_COPYID_COUNT) 345 return (EINVAL); 346 347 hammer2_voldata_lock(hmp); 348 hammer2_voldata_unlock(hmp); 349 350 return(0); 351 } 352 353 /* 354 * Used to scan and retrieve PFS information. PFS's are directories under 355 * the super-root. 356 * 357 * To scan PFSs pass name_key=0. The function will scan for the next 358 * PFS and set all fields, as well as set name_next to the next key. 359 * When no PFSs remain, name_next is set to (hammer2_key_t)-1. 360 * 361 * To retrieve the PFS associated with the file descriptor, pass 362 * name_key set to (hammer2_key_t)-1. 363 */ 364 static int 365 hammer2_ioctl_pfs_get(hammer2_inode_t *ip, void *data) 366 { 367 const hammer2_inode_data_t *ripdata; 368 hammer2_mount_t *hmp; 369 hammer2_ioc_pfs_t *pfs; 370 hammer2_cluster_t *cparent; 371 hammer2_cluster_t *rcluster; 372 hammer2_cluster_t *cluster; 373 hammer2_key_t key_next; 374 int error; 375 int ddflag; 376 377 error = 0; 378 hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */ 379 pfs = data; 380 cparent = hammer2_inode_lock_ex(hmp->spmp->iroot); 381 rcluster = hammer2_inode_lock_ex(ip->pmp->iroot); 382 383 /* 384 * Search for the first key or specific key. Remember that keys 385 * can be returned in any order. 386 */ 387 if (pfs->name_key == 0) { 388 cluster = hammer2_cluster_lookup(cparent, &key_next, 389 0, (hammer2_key_t)-1, 390 0, &ddflag); 391 } else if (pfs->name_key == (hammer2_key_t)-1) { 392 ripdata = &hammer2_cluster_rdata(rcluster)->ipdata; 393 cluster = hammer2_cluster_lookup(cparent, &key_next, 394 ripdata->name_key, 395 ripdata->name_key, 396 0, &ddflag); 397 ripdata = NULL; /* safety */ 398 } else { 399 cluster = hammer2_cluster_lookup(cparent, &key_next, 400 pfs->name_key, pfs->name_key, 401 0, &ddflag); 402 } 403 hammer2_inode_unlock_ex(ip->pmp->iroot, rcluster); 404 405 while (cluster && 406 hammer2_cluster_type(cluster) != HAMMER2_BREF_TYPE_INODE) { 407 cluster = hammer2_cluster_next(cparent, cluster, &key_next, 408 key_next, (hammer2_key_t)-1, 409 0); 410 } 411 if (cluster) { 412 /* 413 * Load the data being returned by the ioctl. 414 */ 415 ripdata = &hammer2_cluster_rdata(cluster)->ipdata; 416 pfs->name_key = ripdata->name_key; 417 pfs->pfs_type = ripdata->pfs_type; 418 pfs->pfs_clid = ripdata->pfs_clid; 419 pfs->pfs_fsid = ripdata->pfs_fsid; 420 KKASSERT(ripdata->name_len < sizeof(pfs->name)); 421 bcopy(ripdata->filename, pfs->name, ripdata->name_len); 422 pfs->name[ripdata->name_len] = 0; 423 ripdata = NULL; /* safety */ 424 425 /* 426 * Calculate the next field 427 */ 428 do { 429 cluster = hammer2_cluster_next(cparent, cluster, 430 &key_next, 431 0, (hammer2_key_t)-1, 432 0); 433 } while (cluster && 434 hammer2_cluster_type(cluster) != 435 HAMMER2_BREF_TYPE_INODE); 436 if (cluster) { 437 ripdata = &hammer2_cluster_rdata(cluster)->ipdata; 438 pfs->name_next = ripdata->name_key; 439 hammer2_cluster_unlock(cluster); 440 } else { 441 pfs->name_next = (hammer2_key_t)-1; 442 } 443 } else { 444 pfs->name_next = (hammer2_key_t)-1; 445 error = ENOENT; 446 } 447 hammer2_inode_unlock_ex(hmp->spmp->iroot, cparent); 448 449 return (error); 450 } 451 452 /* 453 * Find a specific PFS by name 454 */ 455 static int 456 hammer2_ioctl_pfs_lookup(hammer2_inode_t *ip, void *data) 457 { 458 const hammer2_inode_data_t *ripdata; 459 hammer2_mount_t *hmp; 460 hammer2_ioc_pfs_t *pfs; 461 hammer2_cluster_t *cparent; 462 hammer2_cluster_t *cluster; 463 hammer2_key_t key_next; 464 hammer2_key_t lhc; 465 int error; 466 int ddflag; 467 size_t len; 468 469 error = 0; 470 hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */ 471 pfs = data; 472 cparent = hammer2_inode_lock_sh(hmp->spmp->iroot); 473 474 pfs->name[sizeof(pfs->name) - 1] = 0; 475 len = strlen(pfs->name); 476 lhc = hammer2_dirhash(pfs->name, len); 477 478 cluster = hammer2_cluster_lookup(cparent, &key_next, 479 lhc, lhc + HAMMER2_DIRHASH_LOMASK, 480 HAMMER2_LOOKUP_SHARED, &ddflag); 481 while (cluster) { 482 if (hammer2_cluster_type(cluster) == HAMMER2_BREF_TYPE_INODE) { 483 ripdata = &hammer2_cluster_rdata(cluster)->ipdata; 484 if (ripdata->name_len == len && 485 bcmp(ripdata->filename, pfs->name, len) == 0) { 486 break; 487 } 488 ripdata = NULL; /* safety */ 489 } 490 cluster = hammer2_cluster_next(cparent, cluster, &key_next, 491 key_next, 492 lhc + HAMMER2_DIRHASH_LOMASK, 493 HAMMER2_LOOKUP_SHARED); 494 } 495 496 /* 497 * Load the data being returned by the ioctl. 498 */ 499 if (cluster) { 500 ripdata = &hammer2_cluster_rdata(cluster)->ipdata; 501 pfs->name_key = ripdata->name_key; 502 pfs->pfs_type = ripdata->pfs_type; 503 pfs->pfs_clid = ripdata->pfs_clid; 504 pfs->pfs_fsid = ripdata->pfs_fsid; 505 ripdata = NULL; 506 507 hammer2_cluster_unlock(cluster); 508 } else { 509 error = ENOENT; 510 } 511 hammer2_inode_unlock_sh(hmp->spmp->iroot, cparent); 512 513 return (error); 514 } 515 516 /* 517 * Create a new PFS under the super-root 518 */ 519 static int 520 hammer2_ioctl_pfs_create(hammer2_inode_t *ip, void *data) 521 { 522 hammer2_inode_data_t *nipdata; 523 hammer2_mount_t *hmp; 524 hammer2_ioc_pfs_t *pfs; 525 hammer2_inode_t *nip; 526 hammer2_cluster_t *ncluster; 527 hammer2_trans_t trans; 528 int error; 529 530 hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */ 531 pfs = data; 532 nip = NULL; 533 534 if (pfs->name[0] == 0) 535 return(EINVAL); 536 pfs->name[sizeof(pfs->name) - 1] = 0; /* ensure 0-termination */ 537 538 hammer2_trans_init(&trans, ip->pmp, HAMMER2_TRANS_NEWINODE); 539 nip = hammer2_inode_create(&trans, hmp->spmp->iroot, NULL, NULL, 540 pfs->name, strlen(pfs->name), 541 &ncluster, &error); 542 if (error == 0) { 543 nipdata = hammer2_cluster_modify_ip(&trans, nip, ncluster, 0); 544 nipdata->pfs_type = pfs->pfs_type; 545 nipdata->pfs_clid = pfs->pfs_clid; 546 nipdata->pfs_fsid = pfs->pfs_fsid; 547 548 /* 549 * Do not allow compression on PFS's with the special name 550 * "boot", the boot loader can't decompress (yet). 551 */ 552 if (strcmp(pfs->name, "boot") == 0) 553 nipdata->comp_algo = HAMMER2_ENC_ALGO( 554 HAMMER2_COMP_AUTOZERO); 555 hammer2_cluster_modsync(ncluster); 556 hammer2_inode_unlock_ex(nip, ncluster); 557 } 558 hammer2_trans_done(&trans); 559 560 return (error); 561 } 562 563 /* 564 * Destroy an existing PFS under the super-root 565 */ 566 static int 567 hammer2_ioctl_pfs_delete(hammer2_inode_t *ip, void *data) 568 { 569 hammer2_mount_t *hmp; 570 hammer2_ioc_pfs_t *pfs = data; 571 hammer2_trans_t trans; 572 int error; 573 574 hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */ 575 hammer2_trans_init(&trans, ip->pmp, 0); 576 error = hammer2_unlink_file(&trans, hmp->spmp->iroot, 577 pfs->name, strlen(pfs->name), 578 2, NULL, NULL, -1); 579 hammer2_trans_done(&trans); 580 581 return (error); 582 } 583 584 static int 585 hammer2_ioctl_pfs_snapshot(hammer2_inode_t *ip, void *data) 586 { 587 hammer2_ioc_pfs_t *pfs = data; 588 hammer2_trans_t trans; 589 hammer2_cluster_t *cparent; 590 int error; 591 592 if (pfs->name[0] == 0) 593 return(EINVAL); 594 if (pfs->name[sizeof(pfs->name)-1] != 0) 595 return(EINVAL); 596 597 hammer2_vfs_sync(ip->pmp->mp, MNT_WAIT); 598 599 hammer2_trans_init(&trans, ip->pmp, 600 HAMMER2_TRANS_ISFLUSH | HAMMER2_TRANS_NEWINODE); 601 cparent = hammer2_inode_lock_ex(ip); 602 error = hammer2_cluster_snapshot(&trans, cparent, pfs); 603 hammer2_inode_unlock_ex(ip, cparent); 604 hammer2_trans_done(&trans); 605 606 return (error); 607 } 608 609 /* 610 * Retrieve the raw inode structure 611 */ 612 static int 613 hammer2_ioctl_inode_get(hammer2_inode_t *ip, void *data) 614 { 615 const hammer2_inode_data_t *ripdata; 616 hammer2_ioc_inode_t *ino; 617 hammer2_cluster_t *cparent; 618 619 ino = data; 620 621 cparent = hammer2_inode_lock_sh(ip); 622 ripdata = &hammer2_cluster_rdata(cparent)->ipdata; 623 ino->ip_data = *ripdata; 624 ino->kdata = ip; 625 hammer2_inode_unlock_sh(ip, cparent); 626 627 return (0); 628 } 629 630 /* 631 * Set various parameters in an inode which cannot be set through 632 * normal filesystem VNOPS. 633 */ 634 static int 635 hammer2_ioctl_inode_set(hammer2_inode_t *ip, void *data) 636 { 637 const hammer2_inode_data_t *ripdata; 638 hammer2_inode_data_t *wipdata; 639 hammer2_ioc_inode_t *ino = data; 640 hammer2_cluster_t *cparent; 641 hammer2_trans_t trans; 642 int error = 0; 643 int dosync = 0; 644 645 hammer2_trans_init(&trans, ip->pmp, 0); 646 cparent = hammer2_inode_lock_ex(ip); 647 ripdata = &hammer2_cluster_rdata(cparent)->ipdata; 648 649 if (ino->ip_data.check_algo != ripdata->check_algo) { 650 wipdata = hammer2_cluster_modify_ip(&trans, ip, cparent, 0); 651 wipdata->check_algo = ino->ip_data.check_algo; 652 ripdata = wipdata; /* safety */ 653 hammer2_cluster_setmethod_check(&trans, cparent, 654 wipdata->check_algo); 655 dosync = 1; 656 } 657 if (ino->ip_data.comp_algo != ripdata->comp_algo) { 658 wipdata = hammer2_cluster_modify_ip(&trans, ip, cparent, 0); 659 wipdata->comp_algo = ino->ip_data.comp_algo; 660 ripdata = wipdata; /* safety */ 661 dosync = 1; 662 } 663 ino->kdata = ip; 664 665 /* Ignore these flags for now...*/ 666 if (ino->flags & HAMMER2IOC_INODE_FLAG_IQUOTA) { 667 } 668 if (ino->flags & HAMMER2IOC_INODE_FLAG_DQUOTA) { 669 } 670 if (ino->flags & HAMMER2IOC_INODE_FLAG_COPIES) { 671 } 672 if (dosync) 673 hammer2_cluster_modsync(cparent); 674 hammer2_trans_done(&trans); 675 hammer2_inode_unlock_ex(ip, cparent); 676 677 return (error); 678 } 679 680 static 681 int 682 hammer2_ioctl_debug_dump(hammer2_inode_t *ip) 683 { 684 hammer2_chain_t *chain; 685 int count = 1000; 686 int i; 687 688 for (i = 0; i < ip->cluster.nchains; ++i) { 689 chain = ip->cluster.array[i]; 690 if (chain == NULL) 691 continue; 692 hammer2_dump_chain(chain, 0, &count, 'i'); 693 } 694 return 0; 695 } 696