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