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