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