1 /* $NetBSD: nilfs_vfsops.c,v 1.27 2021/09/16 22:19:11 andvar Exp $ */ 2 3 /* 4 * Copyright (c) 2008, 2009 Reinoud Zandijk 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 */ 28 29 #include <sys/cdefs.h> 30 #ifndef lint 31 __KERNEL_RCSID(0, "$NetBSD: nilfs_vfsops.c,v 1.27 2021/09/16 22:19:11 andvar Exp $"); 32 #endif /* not lint */ 33 34 35 #if defined(_KERNEL_OPT) 36 #include "opt_compat_netbsd.h" 37 #endif 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/sysctl.h> 42 #include <sys/namei.h> 43 #include <sys/proc.h> 44 #include <sys/kernel.h> 45 #include <sys/vnode.h> 46 #include <miscfs/genfs/genfs.h> 47 #include <miscfs/specfs/specdev.h> 48 #include <sys/mount.h> 49 #include <sys/buf.h> 50 #include <sys/file.h> 51 #include <sys/device.h> 52 #include <sys/disklabel.h> 53 #include <sys/ioctl.h> 54 #include <sys/malloc.h> 55 #include <sys/dirent.h> 56 #include <sys/stat.h> 57 #include <sys/conf.h> 58 #include <sys/kauth.h> 59 #include <sys/module.h> 60 61 #include <fs/nilfs/nilfs_mount.h> 62 #include <sys/dirhash.h> 63 64 65 #include "nilfs.h" 66 #include "nilfs_subr.h" 67 #include "nilfs_bswap.h" 68 69 MODULE(MODULE_CLASS_VFS, nilfs, NULL); 70 71 #define VTOI(vnode) ((struct nilfs_node *) vnode->v_data) 72 73 /* verbose levels of the nilfs filingsystem */ 74 int nilfs_verbose = NILFS_DEBUGGING; 75 76 /* malloc regions */ 77 MALLOC_JUSTDEFINE(M_NILFSMNT, "NILFS mount", "NILFS mount structures"); 78 MALLOC_JUSTDEFINE(M_NILFSTEMP, "NILFS temp", "NILFS scrap space"); 79 struct pool nilfs_node_pool; 80 81 /* globals */ 82 struct _nilfs_devices nilfs_devices; 83 84 /* supported functions predefined */ 85 VFS_PROTOS(nilfs); 86 87 88 /* --------------------------------------------------------------------- */ 89 90 /* 91 * Genfs interfacing 92 * 93 * static const struct genfs_ops nilfs_genfsops = { 94 * .gop_size = genfs_size, 95 * size of transfers 96 * .gop_alloc = nilfs_gop_alloc, 97 * allocate len bytes at offset 98 * .gop_write = genfs_gop_write, 99 * putpages interface code 100 * .gop_markupdate = nilfs_gop_markupdate, 101 * set update/modify flags etc. 102 * } 103 */ 104 105 /* 106 * Callback from genfs to allocate len bytes at offset off; only called when 107 * filling up gaps in the allocation. 108 */ 109 static int 110 nilfs_gop_alloc(struct vnode *vp, off_t off, 111 off_t len, int flags, kauth_cred_t cred) 112 { 113 DPRINTF(NOTIMPL, ("nilfs_gop_alloc not implemented\n")); 114 DPRINTF(ALLOC, ("nilfs_gop_alloc called for %"PRIu64" bytes\n", len)); 115 116 return 0; 117 } 118 119 120 /* 121 * callback from genfs to update our flags 122 */ 123 static void 124 nilfs_gop_markupdate(struct vnode *vp, int flags) 125 { 126 struct nilfs_node *nilfs_node = VTOI(vp); 127 u_long mask = 0; 128 129 if ((flags & GOP_UPDATE_ACCESSED) != 0) { 130 mask = IN_ACCESS; 131 } 132 if ((flags & GOP_UPDATE_MODIFIED) != 0) { 133 if (vp->v_type == VREG) { 134 mask |= IN_CHANGE | IN_UPDATE; 135 } else { 136 mask |= IN_MODIFY; 137 } 138 } 139 if (mask) { 140 nilfs_node->i_flags |= mask; 141 } 142 } 143 144 145 static const struct genfs_ops nilfs_genfsops = { 146 .gop_size = genfs_size, 147 .gop_alloc = nilfs_gop_alloc, 148 .gop_write = genfs_gop_write_rwmap, 149 .gop_markupdate = nilfs_gop_markupdate, 150 .gop_putrange = genfs_gop_putrange, 151 }; 152 153 /* --------------------------------------------------------------------- */ 154 155 /* predefine vnode-op list descriptor */ 156 extern const struct vnodeopv_desc nilfs_vnodeop_opv_desc; 157 158 const struct vnodeopv_desc * const nilfs_vnodeopv_descs[] = { 159 &nilfs_vnodeop_opv_desc, 160 NULL, 161 }; 162 163 164 /* vfsops descriptor linked in as anchor point for the filingsystem */ 165 struct vfsops nilfs_vfsops = { 166 .vfs_name = MOUNT_NILFS, 167 .vfs_min_mount_data = sizeof (struct nilfs_args), 168 .vfs_mount = nilfs_mount, 169 .vfs_start = nilfs_start, 170 .vfs_unmount = nilfs_unmount, 171 .vfs_root = nilfs_root, 172 .vfs_quotactl = (void *)eopnotsupp, 173 .vfs_statvfs = nilfs_statvfs, 174 .vfs_sync = nilfs_sync, 175 .vfs_vget = nilfs_vget, 176 .vfs_loadvnode = nilfs_loadvnode, 177 .vfs_fhtovp = nilfs_fhtovp, 178 .vfs_vptofh = nilfs_vptofh, 179 .vfs_init = nilfs_init, 180 .vfs_reinit = nilfs_reinit, 181 .vfs_done = nilfs_done, 182 .vfs_mountroot = nilfs_mountroot, 183 .vfs_snapshot = nilfs_snapshot, 184 .vfs_extattrctl = vfs_stdextattrctl, 185 .vfs_suspendctl = genfs_suspendctl, 186 .vfs_renamelock_enter = genfs_renamelock_enter, 187 .vfs_renamelock_exit = genfs_renamelock_exit, 188 .vfs_fsync = (void *)eopnotsupp, 189 .vfs_opv_descs = nilfs_vnodeopv_descs 190 }; 191 192 /* --------------------------------------------------------------------- */ 193 194 /* file system starts here */ 195 void 196 nilfs_init(void) 197 { 198 size_t size; 199 200 /* setup memory types */ 201 malloc_type_attach(M_NILFSMNT); 202 malloc_type_attach(M_NILFSTEMP); 203 204 /* init device lists */ 205 SLIST_INIT(&nilfs_devices); 206 207 /* init node pools */ 208 size = sizeof(struct nilfs_node); 209 pool_init(&nilfs_node_pool, size, 0, 0, 0, 210 "nilfs_node_pool", NULL, IPL_NONE); 211 } 212 213 214 void 215 nilfs_reinit(void) 216 { 217 /* nothing to do */ 218 } 219 220 221 void 222 nilfs_done(void) 223 { 224 /* remove pools */ 225 pool_destroy(&nilfs_node_pool); 226 227 malloc_type_detach(M_NILFSMNT); 228 malloc_type_detach(M_NILFSTEMP); 229 } 230 231 /* 232 * If running a DEBUG kernel, provide an easy way to set the debug flags when 233 * running into a problem. 234 */ 235 #define NILFS_VERBOSE_SYSCTLOPT 1 236 237 SYSCTL_SETUP(nilfs_sysctl_setup, "nilfs sysctl") 238 { 239 const struct sysctlnode *node; 240 241 /* 242 * XXX the "30" below could be dynamic, thereby eliminating one 243 * more instance of the "number to vfs" mapping problem, but 244 * "30" is the order as taken from sys/mount.h 245 */ 246 sysctl_createv(clog, 0, NULL, &node, 247 CTLFLAG_PERMANENT, 248 CTLTYPE_NODE, "nilfs", 249 SYSCTL_DESCR("NTT's NILFSv2"), 250 NULL, 0, NULL, 0, 251 CTL_VFS, 30, CTL_EOL); 252 #ifdef DEBUG 253 sysctl_createv(clog, 0, NULL, &node, 254 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 255 CTLTYPE_INT, "verbose", 256 SYSCTL_DESCR("Bitmask for filesystem debugging"), 257 NULL, 0, &nilfs_verbose, 0, 258 CTL_VFS, 30, NILFS_VERBOSE_SYSCTLOPT, CTL_EOL); 259 #endif 260 } 261 262 static int 263 nilfs_modcmd(modcmd_t cmd, void *arg) 264 { 265 int error; 266 267 switch (cmd) { 268 case MODULE_CMD_INIT: 269 error = vfs_attach(&nilfs_vfsops); 270 if (error != 0) 271 break; 272 break; 273 case MODULE_CMD_FINI: 274 error = vfs_detach(&nilfs_vfsops); 275 if (error != 0) 276 break; 277 break; 278 default: 279 error = ENOTTY; 280 break; 281 } 282 283 return (error); 284 } 285 286 /* --------------------------------------------------------------------- */ 287 288 int 289 nilfs_mountroot(void) 290 { 291 return EOPNOTSUPP; 292 } 293 294 /* --------------------------------------------------------------------- */ 295 296 /* system nodes */ 297 static int 298 nilfs_create_system_nodes(struct nilfs_device *nilfsdev) 299 { 300 int error; 301 302 error = nilfs_get_node_raw(nilfsdev, NULL, NILFS_DAT_INO, 303 &nilfsdev->super_root.sr_dat, &nilfsdev->dat_node); 304 if (error) 305 goto errorout; 306 307 error = nilfs_get_node_raw(nilfsdev, NULL, NILFS_CPFILE_INO, 308 &nilfsdev->super_root.sr_cpfile, &nilfsdev->cp_node); 309 if (error) 310 goto errorout; 311 312 error = nilfs_get_node_raw(nilfsdev, NULL, NILFS_SUFILE_INO, 313 &nilfsdev->super_root.sr_sufile, &nilfsdev->su_node); 314 if (error) 315 goto errorout; 316 317 return 0; 318 errorout: 319 nilfs_dispose_node(&nilfsdev->dat_node); 320 nilfs_dispose_node(&nilfsdev->cp_node); 321 nilfs_dispose_node(&nilfsdev->su_node); 322 323 return error; 324 } 325 326 327 static void 328 nilfs_release_system_nodes(struct nilfs_device *nilfsdev) 329 { 330 if (!nilfsdev) 331 return; 332 if (nilfsdev->refcnt > 0) 333 return; 334 335 nilfs_dispose_node(&nilfsdev->dat_node); 336 nilfs_dispose_node(&nilfsdev->cp_node); 337 nilfs_dispose_node(&nilfsdev->su_node); 338 } 339 340 341 /* --------------------------------------------------------------------- */ 342 343 static int 344 nilfs_check_superblock_crc(struct nilfs_super_block *super) 345 { 346 uint32_t super_crc, comp_crc; 347 348 /* check super block magic */ 349 if (nilfs_rw16(super->s_magic) != NILFS_SUPER_MAGIC) 350 return 0; 351 352 /* preserve crc */ 353 super_crc = nilfs_rw32(super->s_sum); 354 355 /* calculate */ 356 super->s_sum = 0; 357 comp_crc = crc32_le(nilfs_rw32(super->s_crc_seed), 358 (uint8_t *) super, nilfs_rw16(super->s_bytes)); 359 360 /* restore */ 361 super->s_sum = nilfs_rw32(super_crc); 362 363 /* check CRC */ 364 return (super_crc == comp_crc); 365 } 366 367 368 369 static int 370 nilfs_read_superblock(struct nilfs_device *nilfsdev) 371 { 372 struct nilfs_super_block *super, tmp_super; 373 struct buf *bp; 374 uint64_t sb1off, sb2off; 375 uint64_t last_cno1, last_cno2; 376 uint64_t dev_blk; 377 int dev_bsize, dev_blks; 378 int sb1ok, sb2ok, swp; 379 int error; 380 381 sb1off = NILFS_SB_OFFSET_BYTES; 382 sb2off = NILFS_SB2_OFFSET_BYTES(nilfsdev->devsize); 383 384 dev_bsize = 1 << nilfsdev->devvp->v_mount->mnt_fs_bshift; 385 386 /* read our superblock regardless of backing device blocksize */ 387 dev_blk = 0; 388 dev_blks = (sb1off + dev_bsize -1)/dev_bsize; 389 error = bread(nilfsdev->devvp, dev_blk, dev_blks * dev_bsize, 0, &bp); 390 if (error) { 391 return error; 392 } 393 394 /* copy read-in super block at the offset */ 395 super = &nilfsdev->super; 396 memcpy(super, (uint8_t *) bp->b_data + NILFS_SB_OFFSET_BYTES, 397 sizeof(struct nilfs_super_block)); 398 brelse(bp, BC_AGE); 399 400 /* read our 2nd superblock regardless of backing device blocksize */ 401 dev_blk = sb2off / dev_bsize; 402 dev_blks = 2; /* assumption max one dev_bsize */ 403 error = bread(nilfsdev->devvp, dev_blk, dev_blks * dev_bsize, 0, &bp); 404 if (error) { 405 return error; 406 } 407 408 /* copy read-in superblock2 at the offset */ 409 super = &nilfsdev->super2; 410 memcpy(super, (uint8_t *) bp->b_data + NILFS_SB_OFFSET_BYTES, 411 sizeof(struct nilfs_super_block)); 412 brelse(bp, BC_AGE); 413 414 sb1ok = nilfs_check_superblock_crc(&nilfsdev->super); 415 sb2ok = nilfs_check_superblock_crc(&nilfsdev->super2); 416 417 last_cno1 = nilfs_rw64(nilfsdev->super.s_last_cno); 418 last_cno2 = nilfs_rw64(nilfsdev->super2.s_last_cno); 419 swp = sb2ok && (last_cno2 > last_cno1); 420 421 if (swp) { 422 printf("nilfs warning: broken superblock, using spare\n"); 423 tmp_super = nilfsdev->super2; 424 nilfsdev->super2 = nilfsdev->super; /* why preserve? */ 425 nilfsdev->super = tmp_super; 426 } 427 428 if (!sb1ok && !sb2ok) { 429 printf("nilfs: no valid superblocks found\n"); 430 return EINVAL; 431 } 432 433 return 0; 434 } 435 436 437 /* XXX NOTHING from the system nodes should need to be written here */ 438 static void 439 nilfs_unmount_base(struct nilfs_device *nilfsdev) 440 { 441 int error __diagused; 442 443 if (!nilfsdev) 444 return; 445 446 /* remove all our information */ 447 error = vinvalbuf(nilfsdev->devvp, 0, FSCRED, curlwp, 0, 0); 448 KASSERT(error == 0); 449 450 /* release the device's system nodes */ 451 nilfs_release_system_nodes(nilfsdev); 452 453 /* TODO writeout super_block? */ 454 } 455 456 457 static int 458 nilfs_mount_base(struct nilfs_device *nilfsdev, 459 struct mount *mp, struct nilfs_args *args) 460 { 461 struct lwp *l = curlwp; 462 uint64_t last_pseg, last_cno, last_seq; 463 uint32_t log_blocksize; 464 int error; 465 466 /* flush out any old buffers remaining from a previous use. */ 467 if ((error = vinvalbuf(nilfsdev->devvp, V_SAVE, l->l_cred, l, 0, 0))) 468 return error; 469 470 /* read in our superblock */ 471 error = nilfs_read_superblock(nilfsdev); 472 if (error) { 473 printf("nilfs_mount: can't read in super block : %d\n", error); 474 return error; 475 } 476 477 /* get our blocksize */ 478 log_blocksize = nilfs_rw32(nilfsdev->super.s_log_block_size); 479 nilfsdev->blocksize = (uint64_t) 1 << (log_blocksize + 10); 480 /* TODO check superblock's blocksize limits */ 481 482 /* calculate dat structure parameters */ 483 nilfs_calc_mdt_consts(nilfsdev, &nilfsdev->dat_mdt, 484 nilfs_rw16(nilfsdev->super.s_dat_entry_size)); 485 nilfs_calc_mdt_consts(nilfsdev, &nilfsdev->ifile_mdt, 486 nilfs_rw16(nilfsdev->super.s_inode_size)); 487 488 DPRINTF(VOLUMES, ("nilfs_mount: accepted super block\n")); 489 490 /* search for the super root and roll forward when needed */ 491 nilfs_search_super_root(nilfsdev); 492 493 nilfsdev->mount_state = nilfs_rw16(nilfsdev->super.s_state); 494 if (nilfsdev->mount_state != NILFS_VALID_FS) { 495 printf("FS is seriously damaged, needs repairing\n"); 496 printf("aborting mount\n"); 497 return EINVAL; 498 } 499 500 /* 501 * FS should be ok now. The superblock and the last segsum could be 502 * updated from the repair so extract running values again. 503 */ 504 last_pseg = nilfs_rw64(nilfsdev->super.s_last_pseg); /*blknr */ 505 last_cno = nilfs_rw64(nilfsdev->super.s_last_cno); 506 last_seq = nilfs_rw64(nilfsdev->super.s_last_seq); 507 508 nilfsdev->last_seg_seq = last_seq; 509 nilfsdev->last_seg_num = nilfs_get_segnum_of_block(nilfsdev, last_pseg); 510 nilfsdev->next_seg_num = nilfs_get_segnum_of_block(nilfsdev, 511 nilfs_rw64(nilfsdev->last_segsum.ss_next)); 512 nilfsdev->last_cno = last_cno; 513 514 DPRINTF(VOLUMES, ("nilfs_mount: accepted super root\n")); 515 516 /* create system vnodes for DAT, CP and SEGSUM */ 517 error = nilfs_create_system_nodes(nilfsdev); 518 if (error) 519 nilfs_unmount_base(nilfsdev); 520 return error; 521 } 522 523 524 static void 525 nilfs_unmount_device(struct nilfs_device *nilfsdev) 526 { 527 int error; 528 529 /* is there anything? */ 530 if (nilfsdev == NULL) 531 return; 532 533 /* remove the device only if we're the last reference */ 534 nilfsdev->refcnt--; 535 if (nilfsdev->refcnt >= 1) 536 return; 537 538 /* unmount our base */ 539 nilfs_unmount_base(nilfsdev); 540 541 /* remove from our device list */ 542 SLIST_REMOVE(&nilfs_devices, nilfsdev, nilfs_device, next_device); 543 544 /* close device */ 545 DPRINTF(VOLUMES, ("closing device\n")); 546 547 /* remove our mount reference before closing device */ 548 spec_node_setmountedfs(nilfsdev->devvp, NULL); 549 550 /* devvp is still locked by us */ 551 vn_lock(nilfsdev->devvp, LK_EXCLUSIVE | LK_RETRY); 552 error = VOP_CLOSE(nilfsdev->devvp, FREAD | FWRITE, NOCRED); 553 if (error) 554 printf("Error during closure of device! error %d, " 555 "device might stay locked\n", error); 556 DPRINTF(VOLUMES, ("device close ok\n")); 557 558 /* clear our mount reference and release device node */ 559 vput(nilfsdev->devvp); 560 561 /* free our device info */ 562 cv_destroy(&nilfsdev->sync_cv); 563 free(nilfsdev, M_NILFSMNT); 564 } 565 566 567 static int 568 nilfs_check_mounts(struct nilfs_device *nilfsdev, struct mount *mp, 569 struct nilfs_args *args) 570 { 571 struct nilfs_mount *ump; 572 uint64_t last_cno; 573 574 /* no double-mounting of the same checkpoint */ 575 STAILQ_FOREACH(ump, &nilfsdev->mounts, next_mount) { 576 if (ump->mount_args.cpno == args->cpno) 577 return EBUSY; 578 } 579 580 /* allow readonly mounts without questioning here */ 581 if (mp->mnt_flag & MNT_RDONLY) 582 return 0; 583 584 /* readwrite mount you want */ 585 STAILQ_FOREACH(ump, &nilfsdev->mounts, next_mount) { 586 /* only one RW mount on this device! */ 587 if ((ump->vfs_mountp->mnt_flag & MNT_RDONLY)==0) 588 return EROFS; 589 /* RDONLY on last mountpoint is device busy */ 590 last_cno = nilfs_rw64(ump->nilfsdev->super.s_last_cno); 591 if (ump->mount_args.cpno == last_cno) 592 return EBUSY; 593 } 594 595 /* OK for now */ 596 return 0; 597 } 598 599 600 static int 601 nilfs_mount_device(struct vnode *devvp, struct mount *mp, struct nilfs_args *args, 602 struct nilfs_device **nilfsdev_p) 603 { 604 uint64_t psize; 605 unsigned secsize; 606 struct nilfs_device *nilfsdev; 607 struct lwp *l = curlwp; 608 int openflags, accessmode, error; 609 610 DPRINTF(VOLUMES, ("Mounting NILFS device\n")); 611 612 /* lookup device in our nilfs_mountpoints */ 613 *nilfsdev_p = NULL; 614 SLIST_FOREACH(nilfsdev, &nilfs_devices, next_device) 615 if (nilfsdev->devvp == devvp) 616 break; 617 618 if (nilfsdev) { 619 DPRINTF(VOLUMES, ("device already mounted\n")); 620 error = nilfs_check_mounts(nilfsdev, mp, args); 621 if (error) 622 return error; 623 nilfsdev->refcnt++; 624 *nilfsdev_p = nilfsdev; 625 return 0; 626 } 627 628 DPRINTF(VOLUMES, ("no previous mounts on this device, mounting device\n")); 629 630 /* check if its a block device specified */ 631 if (devvp->v_type != VBLK) { 632 vrele(devvp); 633 return ENOTBLK; 634 } 635 if (bdevsw_lookup(devvp->v_rdev) == NULL) { 636 vrele(devvp); 637 return ENXIO; 638 } 639 640 /* 641 * If mount by non-root, then verify that user has necessary 642 * permissions on the device. 643 */ 644 accessmode = VREAD; 645 if ((mp->mnt_flag & MNT_RDONLY) == 0) 646 accessmode |= VWRITE; 647 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 648 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT, 649 KAUTH_REQ_SYSTEM_MOUNT_DEVICE, mp, devvp, KAUTH_ARG(accessmode)); 650 VOP_UNLOCK(devvp); 651 if (error) { 652 vrele(devvp); 653 return error; 654 } 655 656 /* 657 * Open device read-write; TODO how about upgrading later when needed? 658 */ 659 openflags = FREAD | FWRITE; 660 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 661 error = VOP_OPEN(devvp, openflags, FSCRED); 662 VOP_UNLOCK(devvp); 663 if (error) { 664 vrele(devvp); 665 return error; 666 } 667 668 /* opened ok, try mounting */ 669 nilfsdev = malloc(sizeof(*nilfsdev), M_NILFSMNT, M_WAITOK | M_ZERO); 670 671 /* initialise */ 672 nilfsdev->refcnt = 1; 673 nilfsdev->devvp = devvp; 674 nilfsdev->uncomitted_bl = 0; 675 cv_init(&nilfsdev->sync_cv, "nilfssyn"); 676 STAILQ_INIT(&nilfsdev->mounts); 677 678 /* register nilfs_device in list */ 679 SLIST_INSERT_HEAD(&nilfs_devices, nilfsdev, next_device); 680 681 /* get our device's size */ 682 error = getdisksize(devvp, &psize, &secsize); 683 if (error) { 684 /* remove all our information */ 685 nilfs_unmount_device(nilfsdev); 686 return EINVAL; 687 } 688 689 nilfsdev->devsize = psize * secsize; 690 691 /* connect to the head for most recent files XXX really pass mp and args? */ 692 error = nilfs_mount_base(nilfsdev, mp, args); 693 if (error) { 694 /* remove all our information */ 695 nilfs_unmount_device(nilfsdev); 696 return EINVAL; 697 } 698 699 *nilfsdev_p = nilfsdev; 700 DPRINTF(VOLUMES, ("NILFS device mounted ok\n")); 701 702 return 0; 703 } 704 705 706 static int 707 nilfs_mount_checkpoint(struct nilfs_mount *ump) 708 { 709 struct nilfs_cpfile_header *cphdr; 710 struct nilfs_checkpoint *cp; 711 struct nilfs_inode ifile_inode; 712 struct nilfs_node *cp_node; 713 struct buf *bp; 714 uint64_t ncp, nsn, fcpno, blocknr, last_cno; 715 uint32_t off, dlen; 716 int cp_per_block, error; 717 718 DPRINTF(VOLUMES, ("mount_nilfs: trying to mount checkpoint number " 719 "%"PRIu64"\n", ump->mount_args.cpno)); 720 721 cp_node = ump->nilfsdev->cp_node; 722 723 /* get cpfile header from 1st block of cp file */ 724 error = nilfs_bread(cp_node, 0, 0, &bp); 725 if (error) 726 return error; 727 cphdr = (struct nilfs_cpfile_header *) bp->b_data; 728 ncp = nilfs_rw64(cphdr->ch_ncheckpoints); 729 nsn = nilfs_rw64(cphdr->ch_nsnapshots); 730 731 brelse(bp, BC_AGE); 732 733 DPRINTF(VOLUMES, ("mount_nilfs: checkpoint header read in\n")); 734 DPRINTF(VOLUMES, ("\tNumber of checkpoints %"PRIu64"\n", ncp)); 735 DPRINTF(VOLUMES, ("\tNumber of snapshots %"PRIu64"\n", nsn)); 736 #ifndef NILFS_DEBUG 737 __USE(ncp); 738 __USE(nsn); 739 #endif 740 741 /* read in our specified checkpoint */ 742 dlen = nilfs_rw16(ump->nilfsdev->super.s_checkpoint_size); 743 cp_per_block = ump->nilfsdev->blocksize / dlen; 744 745 fcpno = ump->mount_args.cpno + NILFS_CPFILE_FIRST_CHECKPOINT_OFFSET -1; 746 blocknr = fcpno / cp_per_block; 747 off = (fcpno % cp_per_block) * dlen; 748 749 error = nilfs_bread(cp_node, blocknr, 0, &bp); 750 if (error) { 751 printf("mount_nilfs: couldn't read cp block %"PRIu64"\n", 752 fcpno); 753 return EINVAL; 754 } 755 756 /* needs to be a valid checkpoint */ 757 cp = (struct nilfs_checkpoint *) ((uint8_t *) bp->b_data + off); 758 if (cp->cp_flags & NILFS_CHECKPOINT_INVALID) { 759 printf("mount_nilfs: checkpoint marked invalid\n"); 760 brelse(bp, BC_AGE); 761 return EINVAL; 762 } 763 764 /* is this really the checkpoint we want? */ 765 if (nilfs_rw64(cp->cp_cno) != ump->mount_args.cpno) { 766 printf("mount_nilfs: checkpoint file corrupt? " 767 "expected cpno %"PRIu64", found cpno %"PRIu64"\n", 768 ump->mount_args.cpno, nilfs_rw64(cp->cp_cno)); 769 brelse(bp, BC_AGE); 770 return EINVAL; 771 } 772 773 /* check if its a snapshot ! */ 774 last_cno = nilfs_rw64(ump->nilfsdev->super.s_last_cno); 775 if (ump->mount_args.cpno != last_cno) { 776 /* only allow snapshots if not mounting on the last cp */ 777 if ((cp->cp_flags & NILFS_CHECKPOINT_SNAPSHOT) == 0) { 778 printf( "mount_nilfs: checkpoint %"PRIu64" is not a " 779 "snapshot\n", ump->mount_args.cpno); 780 brelse(bp, BC_AGE); 781 return EINVAL; 782 } 783 } 784 785 ifile_inode = cp->cp_ifile_inode; 786 brelse(bp, BC_AGE); 787 788 /* get ifile inode */ 789 error = nilfs_get_node_raw(ump->nilfsdev, NULL, NILFS_IFILE_INO, 790 &ifile_inode, &ump->ifile_node); 791 if (error) { 792 printf("mount_nilfs: can't read ifile node\n"); 793 return EINVAL; 794 } 795 796 /* get root node? */ 797 798 return 0; 799 } 800 801 802 static int 803 nilfs_stop_writing(struct nilfs_mount *ump) 804 { 805 /* readonly mounts won't write */ 806 if (ump->vfs_mountp->mnt_flag & MNT_RDONLY) 807 return 0; 808 809 DPRINTF(CALL, ("nilfs_stop_writing called for RW mount\n")); 810 811 /* TODO writeout super_block? */ 812 /* XXX no support for writing yet anyway */ 813 return 0; 814 } 815 816 817 /* --------------------------------------------------------------------- */ 818 819 820 821 #define MPFREE(a, lst) \ 822 if ((a)) free((a), lst); 823 static void 824 free_nilfs_mountinfo(struct mount *mp) 825 { 826 struct nilfs_mount *ump = VFSTONILFS(mp); 827 828 if (ump == NULL) 829 return; 830 831 MPFREE(ump, M_NILFSMNT); 832 } 833 #undef MPFREE 834 835 int 836 nilfs_mount(struct mount *mp, const char *path, 837 void *data, size_t *data_len) 838 { 839 struct nilfs_args *args = data; 840 struct nilfs_device *nilfsdev; 841 struct nilfs_mount *ump; 842 struct vnode *devvp; 843 int error; 844 845 DPRINTF(VFSCALL, ("nilfs_mount called\n")); 846 847 if (args == NULL) 848 return EINVAL; 849 if (*data_len < sizeof *args) 850 return EINVAL; 851 852 if (mp->mnt_flag & MNT_GETARGS) { 853 /* request for the mount arguments */ 854 ump = VFSTONILFS(mp); 855 if (ump == NULL) 856 return EINVAL; 857 *args = ump->mount_args; 858 *data_len = sizeof *args; 859 return 0; 860 } 861 862 /* check/translate struct version */ 863 if (args->version != 1) { 864 printf("mount_nilfs: unrecognized argument structure version\n"); 865 return EINVAL; 866 } 867 /* TODO sanity checking other mount arguments */ 868 869 /* handle request for updating mount parameters */ 870 if (mp->mnt_flag & MNT_UPDATE) { 871 /* TODO can't update my mountpoint yet */ 872 return EOPNOTSUPP; 873 } 874 875 /* lookup name to get its vnode */ 876 error = namei_simple_user(args->fspec, NSM_FOLLOW_NOEMULROOT, &devvp); 877 if (error) 878 return error; 879 880 #ifdef DEBUG 881 if (nilfs_verbose & NILFS_DEBUG_VOLUMES) 882 vprint("NILFS mount, trying to mount \n", devvp); 883 #endif 884 885 error = nilfs_mount_device(devvp, mp, args, &nilfsdev); 886 if (error) 887 return error; 888 889 /* 890 * Create a nilfs_mount on the specified checkpoint. Note that only 891 * ONE RW mount point can exist and it needs to have the highest 892 * checkpoint nr. If mounting RW and its not on the last checkpoint we 893 * need to invalidate all checkpoints that follow!!! This is an 894 * advanced option. 895 */ 896 897 /* setup basic mountpoint structure */ 898 mp->mnt_data = NULL; 899 mp->mnt_stat.f_fsidx.__fsid_val[0] = (uint32_t) devvp->v_rdev; 900 mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_NILFS); 901 mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0]; 902 mp->mnt_stat.f_namemax = NILFS_NAME_LEN; 903 mp->mnt_flag |= MNT_LOCAL; 904 905 /* XXX can't enable MPSAFE yet since genfs barfs on bad CV */ 906 // mp->mnt_iflag |= IMNT_MPSAFE; 907 908 /* set our dev and fs units */ 909 mp->mnt_dev_bshift = nilfs_rw32(nilfsdev->super.s_log_block_size) + 10; 910 mp->mnt_fs_bshift = mp->mnt_dev_bshift; 911 912 /* allocate nilfs part of mount structure; malloc always succeeds */ 913 ump = malloc(sizeof(struct nilfs_mount), M_NILFSMNT, M_WAITOK | M_ZERO); 914 915 /* set up linkage */ 916 mp->mnt_data = ump; 917 ump->vfs_mountp = mp; 918 ump->nilfsdev = nilfsdev; 919 920 #if 0 921 #ifndef NILFS_READWRITE 922 /* force read-only for now */ 923 if ((mp->mnt_flag & MNT_RDONLY) == 0) { 924 printf( "Enable kernel/module option NILFS_READWRITE for " 925 "writing, downgrading access to read-only\n"); 926 mp->mnt_flag |= MNT_RDONLY; 927 } 928 #endif 929 #endif 930 931 /* DONT register our nilfs mountpoint on our vfs mountpoint */ 932 spec_node_setmountedfs(devvp, NULL); 933 #if 0 934 if (spec_node_getmountedfs(devvp) == NULL) 935 spec_node_setmountedfs(devvp, mp); 936 if ((mp->mnt_flag & MNT_RDONLY) == 0) 937 spec_node_setmountedfs(devvp, mp); 938 #endif 939 940 /* add our mountpoint */ 941 STAILQ_INSERT_TAIL(&nilfsdev->mounts, ump, next_mount); 942 943 /* get our selected checkpoint */ 944 if (args->cpno == 0) 945 args->cpno = nilfsdev->last_cno; 946 args->cpno = MIN(args->cpno, nilfsdev->last_cno); 947 948 /* setting up other parameters */ 949 ump->mount_args = *args; 950 error = nilfs_mount_checkpoint(ump); 951 if (error) { 952 nilfs_unmount(mp, MNT_FORCE); 953 return error; 954 } 955 956 /* set VFS info */ 957 error = set_statvfs_info(path, UIO_USERSPACE, args->fspec, UIO_USERSPACE, 958 mp->mnt_op->vfs_name, mp, curlwp); 959 if (error) { 960 nilfs_unmount(mp, MNT_FORCE); 961 return error; 962 } 963 964 /* successfully mounted */ 965 DPRINTF(VOLUMES, ("nilfs_mount() successful\n")); 966 967 return 0; 968 } 969 970 /* --------------------------------------------------------------------- */ 971 972 973 /* remove our mountpoint and if its the last reference, remove our device */ 974 int 975 nilfs_unmount(struct mount *mp, int mntflags) 976 { 977 struct nilfs_device *nilfsdev; 978 struct nilfs_mount *ump; 979 int error, flags; 980 981 DPRINTF(VFSCALL, ("nilfs_umount called\n")); 982 983 ump = VFSTONILFS(mp); 984 if (!ump) 985 panic("NILFS unmount: empty ump\n"); 986 nilfsdev = ump->nilfsdev; 987 988 /* 989 * Flush all nodes associated to this mountpoint. 990 */ 991 flags = (mntflags & MNT_FORCE) ? FORCECLOSE : 0; 992 if ((error = vflush(mp, NULLVP, flags)) != 0) 993 return error; 994 995 /* if we're the write mount, we ought to close the writing session */ 996 error = nilfs_stop_writing(ump); 997 if (error) 998 return error; 999 1000 nilfs_dispose_node(&ump->ifile_node); 1001 1002 /* remove our mount point */ 1003 STAILQ_REMOVE(&nilfsdev->mounts, ump, nilfs_mount, next_mount); 1004 free_nilfs_mountinfo(mp); 1005 1006 /* free ump struct references */ 1007 mp->mnt_data = NULL; 1008 mp->mnt_flag &= ~MNT_LOCAL; 1009 1010 /* unmount the device itself when we're the last one */ 1011 nilfs_unmount_device(nilfsdev); 1012 1013 DPRINTF(VOLUMES, ("Fin unmount\n")); 1014 return error; 1015 } 1016 1017 /* --------------------------------------------------------------------- */ 1018 1019 int 1020 nilfs_start(struct mount *mp, int flags) 1021 { 1022 /* do we have to do something here? */ 1023 return 0; 1024 } 1025 1026 /* --------------------------------------------------------------------- */ 1027 1028 int 1029 nilfs_root(struct mount *mp, int lktype, struct vnode **vpp) 1030 { 1031 uint64_t ino = NILFS_ROOT_INO; 1032 int error; 1033 1034 DPRINTF(NODE, ("nilfs_root called\n")); 1035 1036 error = vcache_get(mp, &ino, sizeof(ino), vpp); 1037 if (error == 0) { 1038 error = vn_lock(*vpp, lktype); 1039 if (error) { 1040 vrele(*vpp); 1041 *vpp = NULL; 1042 return error; 1043 } 1044 } 1045 KASSERT(error != 0 || ((*vpp)->v_vflag & VV_ROOT)); 1046 1047 DPRINTF(NODE, ("nilfs_root finished\n")); 1048 return error; 1049 } 1050 1051 /* --------------------------------------------------------------------- */ 1052 1053 int 1054 nilfs_statvfs(struct mount *mp, struct statvfs *sbp) 1055 { 1056 struct nilfs_mount *ump = VFSTONILFS(mp); 1057 uint32_t blocksize; 1058 1059 DPRINTF(VFSCALL, ("nilfs_statvfs called\n")); 1060 1061 blocksize = ump->nilfsdev->blocksize; 1062 sbp->f_flag = mp->mnt_flag; 1063 sbp->f_bsize = blocksize; 1064 sbp->f_frsize = blocksize; 1065 sbp->f_iosize = blocksize; 1066 1067 copy_statvfs_info(sbp, mp); 1068 return 0; 1069 } 1070 1071 /* --------------------------------------------------------------------- */ 1072 1073 int 1074 nilfs_sync(struct mount *mp, int waitfor, kauth_cred_t cred) 1075 { 1076 // struct nilfs_mount *ump = VFSTONILFS(mp); 1077 1078 DPRINTF(VFSCALL, ("nilfs_sync called\n")); 1079 /* if called when mounted readonly, just ignore */ 1080 if (mp->mnt_flag & MNT_RDONLY) 1081 return 0; 1082 1083 DPRINTF(VFSCALL, ("end of nilfs_sync()\n")); 1084 1085 return 0; 1086 } 1087 1088 /* --------------------------------------------------------------------- */ 1089 1090 /* 1091 * Get vnode for the file system type specific file id ino for the fs. Its 1092 * used for reference to files by unique ID and for NFSv3. 1093 * (optional) TODO lookup why some sources state NFSv3 1094 */ 1095 int 1096 nilfs_vget(struct mount *mp, ino_t ino, int lktype, 1097 struct vnode **vpp) 1098 { 1099 DPRINTF(NOTIMPL, ("nilfs_vget called\n")); 1100 return EOPNOTSUPP; 1101 } 1102 1103 /* --------------------------------------------------------------------- */ 1104 1105 /* 1106 * Read an inode from disk and initialize this vnode / inode pair. 1107 * Caller assures no other thread will try to load this inode. 1108 */ 1109 int 1110 nilfs_loadvnode(struct mount *mp, struct vnode *vp, 1111 const void *key, size_t key_len, const void **new_key) 1112 { 1113 uint64_t ino; 1114 struct nilfs_device *nilfsdev; 1115 struct nilfs_inode inode, *entry; 1116 struct nilfs_node *node; 1117 struct nilfs_mount *ump; 1118 struct buf *bp; 1119 uint64_t ivblocknr; 1120 uint32_t entry_in_block; 1121 int error; 1122 extern int (**nilfs_vnodeop_p)(void *); 1123 1124 KASSERT(key_len == sizeof(ino)); 1125 memcpy(&ino, key, key_len); 1126 1127 ump = VFSTONILFS(mp); 1128 1129 /* create new inode; XXX check could be handier */ 1130 if ((ino < NILFS_USER_INO) && (ino != NILFS_ROOT_INO)) { 1131 printf("nilfs_get_node: system ino %"PRIu64" not in mount " 1132 "point!\n", ino); 1133 return ENOENT; 1134 } 1135 1136 /* lookup inode in the ifile */ 1137 DPRINTF(NODE, ("lookup ino %"PRIu64"\n", ino)); 1138 1139 /* lookup inode structure in mountpoints ifile */ 1140 nilfsdev = ump->nilfsdev; 1141 nilfs_mdt_trans(&nilfsdev->ifile_mdt, ino, &ivblocknr, &entry_in_block); 1142 1143 error = nilfs_bread(ump->ifile_node, ivblocknr, 0, &bp); 1144 if (error) 1145 return ENOENT; 1146 1147 /* get inode entry */ 1148 entry = (struct nilfs_inode *) bp->b_data + entry_in_block; 1149 inode = *entry; 1150 brelse(bp, BC_AGE); 1151 1152 /* get node */ 1153 error = nilfs_get_node_raw(ump->nilfsdev, ump, ino, &inode, &node); 1154 if (error) 1155 return error; 1156 1157 vp->v_type = IFTOVT(inode.i_mode); 1158 switch (vp->v_type) { 1159 case VREG: 1160 case VDIR: 1161 case VLNK: 1162 break; 1163 /* other types not yet supported. */ 1164 default: 1165 vp->v_type = VNON; 1166 nilfs_dispose_node(&node); 1167 return ENXIO; 1168 } 1169 1170 vp->v_tag = VT_NILFS; 1171 vp->v_op = nilfs_vnodeop_p; 1172 vp->v_data = node; 1173 node->vnode = vp; 1174 1175 /* initialise genfs */ 1176 genfs_node_init(vp, &nilfs_genfsops); 1177 1178 /* check if we're fetching the root */ 1179 if (ino == NILFS_ROOT_INO) 1180 vp->v_vflag |= VV_ROOT; 1181 1182 uvm_vnp_setsize(vp, nilfs_rw64(inode.i_size)); 1183 *new_key = &node->ino; 1184 1185 return 0; 1186 1187 } 1188 1189 /* --------------------------------------------------------------------- */ 1190 1191 /* 1192 * Lookup vnode for file handle specified 1193 */ 1194 int 1195 nilfs_fhtovp(struct mount *mp, struct fid *fhp, int lktype, 1196 struct vnode **vpp) 1197 { 1198 DPRINTF(NOTIMPL, ("nilfs_fhtovp called\n")); 1199 return EOPNOTSUPP; 1200 } 1201 1202 /* --------------------------------------------------------------------- */ 1203 1204 /* 1205 * Create an unique file handle. Its structure is opaque and won't be used by 1206 * other subsystems. It should uniquely identify the file in the filingsystem 1207 * and enough information to know if a file has been removed and/or resources 1208 * have been recycled. 1209 */ 1210 int 1211 nilfs_vptofh(struct vnode *vp, struct fid *fid, 1212 size_t *fh_size) 1213 { 1214 DPRINTF(NOTIMPL, ("nilfs_vptofh called\n")); 1215 return EOPNOTSUPP; 1216 } 1217 1218 /* --------------------------------------------------------------------- */ 1219 1220 /* 1221 * Create a file system snapshot at the specified timestamp. 1222 */ 1223 int 1224 nilfs_snapshot(struct mount *mp, struct vnode *vp, 1225 struct timespec *tm) 1226 { 1227 DPRINTF(NOTIMPL, ("nilfs_snapshot called\n")); 1228 return EOPNOTSUPP; 1229 } 1230 1231 /* --------------------------------------------------------------------- */ 1232