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