chfs_vfsops.c revision 1.4
1/* $NetBSD: chfs_vfsops.c,v 1.4 2012/04/30 22:51:28 rmind Exp $ */ 2 3/*- 4 * Copyright (c) 2010 Department of Software Engineering, 5 * University of Szeged, Hungary 6 * Copyright (C) 2010 Tamas Toth <ttoth@inf.u-szeged.hu> 7 * Copyright (C) 2010 Adam Hoka <ahoka@NetBSD.org> 8 * All rights reserved. 9 * 10 * This code is derived from software contributed to The NetBSD Foundation 11 * by the Department of Software Engineering, University of Szeged, Hungary 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35#include <sys/cdefs.h> 36 37#include <sys/param.h> 38#include <sys/types.h> 39#include <sys/kmem.h> 40#include <sys/mount.h> 41#include <sys/stat.h> 42#include <sys/systm.h> 43#include <sys/proc.h> 44#include <sys/module.h> 45#include <sys/namei.h> 46#include <sys/malloc.h> 47#include <sys/fcntl.h> 48#include <sys/conf.h> 49#include <sys/buf.h> 50//XXX needed just for debugging 51#include <sys/fstrans.h> 52#include <sys/sleepq.h> 53#include <sys/lockdebug.h> 54#include <sys/ktrace.h> 55 56#include <uvm/uvm.h> 57#include <uvm/uvm_pager.h> 58#include <ufs/ufs/dir.h> 59//#include <ufs/ufs/inode.h> 60#include <ufs/ufs/ufs_extern.h> 61#include <miscfs/genfs/genfs.h> 62#include <miscfs/genfs/genfs_node.h> 63#include <miscfs/specfs/specdev.h> 64//#include </root/xipffs/netbsd.chfs/chfs.h> 65//#include </root/xipffs/netbsd.chfs/chfs_args.h> 66#include "chfs.h" 67#include "chfs_args.h" 68 69MODULE(MODULE_CLASS_VFS, chfs, "flash"); 70 71/* --------------------------------------------------------------------- */ 72/* functions */ 73 74static int chfs_mount(struct mount *, const char *, void *, size_t *); 75static int chfs_unmount(struct mount *, int); 76static int chfs_root(struct mount *, struct vnode **); 77static int chfs_vget(struct mount *, ino_t, struct vnode **); 78static int chfs_fhtovp(struct mount *, struct fid *, struct vnode **); 79static int chfs_vptofh(struct vnode *, struct fid *, size_t *); 80static int chfs_start(struct mount *, int); 81static int chfs_statvfs(struct mount *, struct statvfs *); 82static int chfs_sync(struct mount *, int, kauth_cred_t); 83static void chfs_init(void); 84static void chfs_reinit(void); 85static void chfs_done(void); 86static int chfs_snapshot(struct mount *, struct vnode *, 87 struct timespec *); 88 89/* --------------------------------------------------------------------- */ 90/* structures */ 91 92int 93chfs_gop_alloc(struct vnode *vp, off_t off, off_t len, int flags, 94 kauth_cred_t cred) 95{ 96 return (0); 97} 98 99const struct genfs_ops chfs_genfsops = { 100 .gop_size = genfs_size, 101 .gop_alloc = chfs_gop_alloc, 102 .gop_write = genfs_gop_write, 103 .gop_markupdate = ufs_gop_markupdate, 104}; 105 106/* 107static const struct ufs_ops chfs_ufsops = { 108 .uo_itimes = chfs_itimes, 109 .uo_update = chfs_update, 110}; 111*/ 112 113struct pool chfs_inode_pool; 114 115/* for looking up the major for flash */ 116extern const struct cdevsw flash_cdevsw; 117 118/* --------------------------------------------------------------------- */ 119 120static int 121chfs_mount(struct mount *mp, 122 const char *path, void *data, size_t *data_len) 123{ 124 struct lwp *l = curlwp; 125 struct nameidata nd; 126 struct pathbuf *pb; 127 struct vnode *devvp = NULL; 128 struct ufs_args *args = data; 129 struct ufsmount *ump = NULL; 130 struct chfs_mount *chmp; 131 int err = 0; 132 int xflags; 133 134 dbg("mount()\n"); 135 136 if (*data_len < sizeof *args) 137 return EINVAL; 138 139 if (mp->mnt_flag & MNT_GETARGS) { 140 ump = VFSTOUFS(mp); 141 if (ump == NULL) 142 return EIO; 143 memset(args, 0, sizeof *args); 144 args->fspec = NULL; 145 *data_len = sizeof *args; 146 return 0; 147 } 148 149 if (mp->mnt_flag & MNT_UPDATE) { 150 /* XXX: There is no support yet to update file system 151 * settings. Should be added. */ 152 153 return ENODEV; 154 } 155 156 if (args->fspec != NULL) { 157 err = pathbuf_copyin(args->fspec, &pb); 158 if (err) { 159 return err; 160 } 161 /* 162 * Look up the name and verify that it's sane. 163 */ 164 NDINIT(&nd, LOOKUP, FOLLOW, pb); 165 if ((err = namei(&nd)) != 0 ) 166 return (err); 167 devvp = nd.ni_vp; 168 169 /* 170 * Be sure this is a valid block device 171 */ 172 if (devvp->v_type != VBLK) 173 err = ENOTBLK; 174 else if (bdevsw_lookup(devvp->v_rdev) == NULL) 175 err = ENXIO; 176 } 177 178 if (err) { 179 vrele(devvp); 180 return (err); 181 } 182 183 if (mp->mnt_flag & MNT_RDONLY) 184 xflags = FREAD; 185 else 186 xflags = FREAD|FWRITE; 187 188 err = VOP_OPEN(devvp, xflags, FSCRED); 189 if (err) 190 goto fail; 191 192 193 err = chfs_mountfs(devvp, mp); 194 if (err) { 195 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 196 (void)VOP_CLOSE(devvp, xflags, NOCRED); 197 VOP_UNLOCK(devvp); 198 goto fail; 199 } 200 ump = VFSTOUFS(mp); 201 chmp = ump->um_chfs; 202 203 vfs_getnewfsid(mp); 204 chmp->chm_fsmp = mp; 205 206 return set_statvfs_info(path, 207 UIO_USERSPACE, args->fspec, 208 UIO_USERSPACE, mp->mnt_op->vfs_name, mp, l); 209 210fail: 211 vrele(devvp); 212 return (err); 213} 214 215 216int 217chfs_mountfs(struct vnode *devvp, struct mount *mp) 218{ 219 struct lwp *l = curlwp; 220 struct proc *p; 221 kauth_cred_t cred; 222 devmajor_t flash_major; 223 dev_t dev; 224 struct ufsmount* ump = NULL; 225 struct chfs_mount* chmp; 226 struct vnode *vp; 227 int err = 0; 228 229 dbg("mountfs()\n"); 230 231 dev = devvp->v_rdev; 232 p = l ? l->l_proc : NULL; 233 cred = l ? l->l_cred : NOCRED; 234 235 /* Flush out any old buffers remaining from a previous use. */ 236 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 237 err = vinvalbuf(devvp, V_SAVE, cred, l, 0, 0); 238 VOP_UNLOCK(devvp); 239 if (err) 240 return (err); 241 242 flash_major = cdevsw_lookup_major(&flash_cdevsw); 243 244 if (devvp->v_type != VBLK) 245 err = ENOTBLK; 246 else if (bdevsw_lookup(dev) == NULL) 247 err = ENXIO; 248 else if (major(dev) != flash_major) { 249 dbg("major(dev): %d, flash_major: %d\n", 250 major(dev), flash_major); 251 err = ENODEV; 252 } 253 if (err) { 254 vrele(devvp); 255 return (err); 256 } 257 258 ump = kmem_zalloc(sizeof(struct ufsmount), KM_SLEEP); 259 260 ump->um_fstype = UFS1; 261 //ump->um_ops = &chfs_ufsops; 262 ump->um_chfs = kmem_zalloc(sizeof(struct chfs_mount), KM_SLEEP); 263 mutex_init(&ump->um_lock, MUTEX_DEFAULT, IPL_NONE); 264 265 /* Get superblock and set flash device number */ 266 chmp = ump->um_chfs; 267 268 chmp->chm_ebh = kmem_alloc(sizeof(struct chfs_ebh), KM_SLEEP); 269 270 dbg("[]opening flash: %u\n", (unsigned int)devvp->v_rdev); 271 err = ebh_open(chmp->chm_ebh, devvp->v_rdev); 272 if (err) { 273 dbg("error while opening flash\n"); 274 goto fail; 275 } 276 277 //TODO check flash sizes 278 279 chmp->chm_gbl_version = 0; 280 chmp->chm_vnocache_hash = chfs_vnocache_hash_init(); 281 282 chmp->chm_blocks = kmem_zalloc(chmp->chm_ebh->peb_nr * 283 sizeof(struct chfs_eraseblock), KM_SLEEP); 284 285 mutex_init(&chmp->chm_lock_mountfields, MUTEX_DEFAULT, IPL_NONE); 286 mutex_init(&chmp->chm_lock_sizes, MUTEX_DEFAULT, IPL_NONE); 287 mutex_init(&chmp->chm_lock_vnocache, MUTEX_DEFAULT, IPL_NONE); 288 289 //XXX 290 chmp->chm_fs_bmask = -4096; 291 chmp->chm_fs_bsize = 4096; 292 chmp->chm_fs_qbmask = 4095; 293 chmp->chm_fs_bshift = 12; 294 chmp->chm_fs_fmask = -2048; 295 chmp->chm_fs_qfmask = 2047; 296 297 chmp->chm_wbuf_pagesize = chmp->chm_ebh->flash_if->page_size; 298 dbg("wbuf size: %zu\n", chmp->chm_wbuf_pagesize); 299 chmp->chm_wbuf = kmem_alloc(chmp->chm_wbuf_pagesize, KM_SLEEP); 300 rw_init(&chmp->chm_lock_wbuf); 301 302 //init queues 303 TAILQ_INIT(&chmp->chm_free_queue); 304 TAILQ_INIT(&chmp->chm_clean_queue); 305 TAILQ_INIT(&chmp->chm_dirty_queue); 306 TAILQ_INIT(&chmp->chm_very_dirty_queue); 307 TAILQ_INIT(&chmp->chm_erasable_pending_wbuf_queue); 308 TAILQ_INIT(&chmp->chm_erase_pending_queue); 309 310 chfs_calc_trigger_levels(chmp); 311 312 chmp->chm_nr_free_blocks = 0; 313 chmp->chm_nr_erasable_blocks = 0; 314 chmp->chm_max_vno = 2; 315 chmp->chm_checked_vno = 2; 316 chmp->chm_unchecked_size = 0; 317 chmp->chm_used_size = 0; 318 chmp->chm_dirty_size = 0; 319 chmp->chm_wasted_size = 0; 320 chmp->chm_free_size = chmp->chm_ebh->eb_size * chmp->chm_ebh->peb_nr; 321 err = chfs_build_filesystem(chmp); 322 323 if (err) { 324 chfs_vnocache_hash_destroy(chmp->chm_vnocache_hash); 325 ebh_close(chmp->chm_ebh); 326 err = EIO; 327 goto fail; 328 } 329 330 mp->mnt_data = ump; 331 mp->mnt_stat.f_fsidx.__fsid_val[0] = (long)dev; 332 mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_CHFS); 333 mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0]; 334 mp->mnt_stat.f_namemax = MAXNAMLEN; 335 mp->mnt_flag |= MNT_LOCAL; 336 mp->mnt_fs_bshift = PAGE_SHIFT; 337 mp->mnt_dev_bshift = DEV_BSHIFT; 338 mp->mnt_iflag |= IMNT_MPSAFE; 339 ump->um_flags = 0; 340 ump->um_mountp = mp; 341 ump->um_dev = dev; 342 ump->um_devvp = devvp; 343 ump->um_maxfilesize = 1048512 * 1024; 344 /*TODO fill these fields 345 ump->um_nindir = 346 ump->um_lognindir = 347 ump->um_bptrtodb = 348 ump->um_seqinc = 349 ump->um_maxsymlinklen = 350 ump->um_dirblksiz = 351 ump->um_maxfilesize = 352 */ 353 354 /* 355 * Allocate the root vnode. 356 */ 357 err = VFS_VGET(mp, CHFS_ROOTINO, &vp); 358 if (err) { 359 dbg("error: %d while allocating root node\n", err); 360 return err; 361 } 362 vput(vp); 363 364 chfs_gc_thread_start(chmp); 365 mutex_enter(&chmp->chm_lock_mountfields); 366 chfs_gc_trigger(chmp); 367 mutex_exit(&chmp->chm_lock_mountfields); 368 369 devvp->v_specmountpoint = mp; 370 return 0; 371fail: 372 kmem_free(chmp->chm_ebh, sizeof(struct chfs_ebh)); 373 kmem_free(chmp, sizeof(struct chfs_mount)); 374 kmem_free(ump, sizeof(struct ufsmount)); 375 return err; 376} 377 378/* --------------------------------------------------------------------- */ 379 380/* ARGSUSED2 */ 381static int 382chfs_unmount(struct mount *mp, int mntflags) 383{ 384 int flags = 0, i = 0; 385 struct ufsmount *ump; 386 struct chfs_mount *chmp; 387// struct chfs_vnode_cache *vc, *next; 388 389 if (mntflags & MNT_FORCE) 390 flags |= FORCECLOSE; 391 392 dbg("[START]\n"); 393 394 ump = VFSTOUFS(mp); 395 chmp = ump->um_chfs; 396 397 chfs_gc_thread_stop(chmp); 398 399 (void)vflush(mp, NULLVP, flags); 400 401 if (chmp->chm_wbuf_len) { 402 mutex_enter(&chmp->chm_lock_mountfields); 403 chfs_flush_pending_wbuf(chmp); 404 mutex_exit(&chmp->chm_lock_mountfields); 405 } 406 407 for (i = 0; i < chmp->chm_ebh->peb_nr; i++) { 408 chfs_free_node_refs(&chmp->chm_blocks[i]); 409 } 410 411 chfs_vnocache_hash_destroy(chmp->chm_vnocache_hash); 412 413 ebh_close(chmp->chm_ebh); 414 415 rw_destroy(&chmp->chm_lock_wbuf); 416 mutex_destroy(&chmp->chm_lock_vnocache); 417 mutex_destroy(&chmp->chm_lock_sizes); 418 mutex_destroy(&chmp->chm_lock_mountfields); 419 420 if (ump->um_devvp->v_type != VBAD) { 421 ump->um_devvp->v_specmountpoint = NULL; 422 } 423 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY); 424 (void)VOP_CLOSE(ump->um_devvp, FREAD|FWRITE, NOCRED); 425 vput(ump->um_devvp); 426 427 mutex_destroy(&ump->um_lock); 428 429 //kmem_free(ump->um_chfs, sizeof(struct chfs_mount)); 430 kmem_free(ump, sizeof(struct ufsmount)); 431 mp->mnt_data = NULL; 432 mp->mnt_flag &= ~MNT_LOCAL; 433 dbg("[END]\n"); 434 return (0); 435} 436 437/* --------------------------------------------------------------------- */ 438 439static int 440chfs_root(struct mount *mp, struct vnode **vpp) 441{ 442 struct vnode *vp; 443 int error; 444 445 if ((error = VFS_VGET(mp, (ino_t)ROOTINO, &vp)) != 0) 446 return error; 447 *vpp = vp; 448 return 0; 449} 450 451/* --------------------------------------------------------------------- */ 452 453extern rb_tree_ops_t frag_rbtree_ops; 454 455static int 456chfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) 457{ 458 struct chfs_mount *chmp; 459 struct chfs_inode *ip; 460 struct ufsmount *ump; 461 struct vnode *vp; 462 dev_t dev; 463 int error; 464 struct chfs_vnode_cache* chvc = NULL; 465 struct chfs_node_ref* nref = NULL; 466 struct buf *bp; 467 468 dbg("vget() | ino: %llu\n", (unsigned long long)ino); 469 470 ump = VFSTOUFS(mp); 471 dev = ump->um_dev; 472retry: 473 if (!vpp) { 474 vpp = kmem_alloc(sizeof(struct vnode*), KM_SLEEP); 475 } 476 477 if ((*vpp = chfs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL) { 478 return 0; 479 } 480 481 /* Allocate a new vnode/inode. */ 482 if ((error = getnewvnode(VT_CHFS, 483 mp, chfs_vnodeop_p, NULL, &vp)) != 0) { 484 *vpp = NULL; 485 return (error); 486 } 487 ip = pool_get(&chfs_inode_pool, PR_WAITOK); 488 489 mutex_enter(&chfs_hashlock); 490 if ((*vpp = chfs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL) { 491 mutex_exit(&chfs_hashlock); 492 ungetnewvnode(vp); 493 pool_put(&chfs_inode_pool, ip); 494 goto retry; 495 } 496 497 vp->v_vflag |= VV_LOCKSWORK; 498 499 memset(ip, 0, sizeof(*ip)); 500 vp->v_data = ip; 501 ip->vp = vp; 502 ip->ch_type = VTTOCHT(vp->v_type); 503 ip->ump = ump; 504 ip->chmp = chmp = ump->um_chfs; 505 ip->dev = dev; 506 ip->ino = ino; 507 vp->v_mount = mp; 508 genfs_node_init(vp, &chfs_genfsops); 509 510 rb_tree_init(&ip->fragtree, &frag_rbtree_ops); 511 //mutex_init(&ip->inode_lock, MUTEX_DEFAULT, IPL_NONE); 512 513 chfs_ihashins(ip); 514 mutex_exit(&chfs_hashlock); 515 516 // set root inode 517 if (ino == CHFS_ROOTINO) { 518 dbg("SETROOT\n"); 519 vp->v_vflag |= VV_ROOT; 520 vp->v_type = VDIR; 521 ip->ch_type = CHT_DIR; 522 ip->mode = IFMT | IEXEC | IWRITE | IREAD; 523 ip->iflag |= (IN_ACCESS | IN_CHANGE | IN_UPDATE); 524 chfs_update(vp, NULL, NULL, UPDATE_WAIT); 525// ip->dents = NULL; XXXTAILQ 526 TAILQ_INIT(&ip->dents); 527 chfs_set_vnode_size(vp, 512); 528 } 529 530 // set vnode cache 531 mutex_enter(&chmp->chm_lock_vnocache); 532 chvc = chfs_vnode_cache_get(chmp, ino); 533 mutex_exit(&chmp->chm_lock_vnocache); 534 if (!chvc) { 535 dbg("!chvc\n"); 536 /* XXX, we cant alloc under a lock, refactor this! */ 537 chvc = chfs_vnode_cache_alloc(ino); 538 mutex_enter(&chmp->chm_lock_vnocache); 539 if (ino == CHFS_ROOTINO) { 540 chvc->nlink = 2; 541 chvc->pvno = CHFS_ROOTINO; 542 chfs_vnode_cache_set_state(chmp, 543 chvc, VNO_STATE_CHECKEDABSENT); 544 } 545 chfs_vnode_cache_add(chmp, chvc); 546 mutex_exit(&chmp->chm_lock_vnocache); 547 548 ip->chvc = chvc; 549 TAILQ_INIT(&ip->dents); 550 } else { 551 dbg("chvc\n"); 552 ip->chvc = chvc; 553 // if we have a vnode cache, the node is already on flash, so read it 554 if (ino == CHFS_ROOTINO) { 555 chvc->pvno = CHFS_ROOTINO; 556 TAILQ_INIT(&chvc->scan_dirents); 557 } else { 558 chfs_readvnode(mp, ino, &vp); 559 } 560 561 mutex_enter(&chmp->chm_lock_mountfields); 562 // init type specific things 563 switch (ip->ch_type) { 564 case CHT_DIR: 565 nref = chvc->dirents; 566 while (nref && 567 (struct chfs_vnode_cache *)nref != chvc) { 568 chfs_readdirent(mp, nref, ip); 569 nref = nref->nref_next; 570 } 571 chfs_set_vnode_size(vp, 512); 572 break; 573 case CHT_REG: 574 case CHT_SOCK: 575 //build the fragtree of the vnode 576 dbg("read_inode_internal | ino: %llu\n", 577 (unsigned long long)ip->ino); 578 error = chfs_read_inode(chmp, ip); 579 if (error) { 580 vput(vp); 581 *vpp = NULL; 582 mutex_exit(&chmp->chm_lock_mountfields); 583 return (error); 584 } 585 break; 586 case CHT_LNK: 587 //build the fragtree of the vnode 588 dbg("read_inode_internal | ino: %llu\n", 589 (unsigned long long)ip->ino); 590 error = chfs_read_inode_internal(chmp, ip); 591 if (error) { 592 vput(vp); 593 *vpp = NULL; 594 mutex_exit(&chmp->chm_lock_mountfields); 595 return (error); 596 } 597 598 dbg("size: %llu\n", (unsigned long long)ip->size); 599 bp = getiobuf(vp, true); 600 bp->b_blkno = 0; 601 bp->b_bufsize = bp->b_resid = 602 bp->b_bcount = ip->size; 603 bp->b_data = kmem_alloc(ip->size, KM_SLEEP); 604 chfs_read_data(chmp, vp, bp); 605 if (!ip->target) 606 ip->target = kmem_alloc(ip->size, 607 KM_SLEEP); 608 memcpy(ip->target, bp->b_data, ip->size); 609 kmem_free(bp->b_data, ip->size); 610 putiobuf(bp); 611 612 break; 613 case CHT_CHR: 614 case CHT_BLK: 615 case CHT_FIFO: 616 //build the fragtree of the vnode 617 dbg("read_inode_internal | ino: %llu\n", 618 (unsigned long long)ip->ino); 619 error = chfs_read_inode_internal(chmp, ip); 620 if (error) { 621 vput(vp); 622 *vpp = NULL; 623 mutex_exit(&chmp->chm_lock_mountfields); 624 return (error); 625 } 626 627 bp = getiobuf(vp, true); 628 bp->b_blkno = 0; 629 bp->b_bufsize = bp->b_resid = 630 bp->b_bcount = sizeof(dev_t); 631 bp->b_data = kmem_alloc(sizeof(dev_t), KM_SLEEP); 632 chfs_read_data(chmp, vp, bp); 633 memcpy(&ip->rdev, 634 bp->b_data, sizeof(dev_t)); 635 kmem_free(bp->b_data, sizeof(dev_t)); 636 putiobuf(bp); 637 if (ip->ch_type == CHT_FIFO) { 638 vp->v_op = chfs_fifoop_p; 639 } else { 640 vp->v_op = chfs_specop_p; 641 spec_node_init(vp, ip->rdev); 642 } 643 644 break; 645 case CHT_BLANK: 646 case CHT_BAD: 647 break; 648 } 649 mutex_exit(&chmp->chm_lock_mountfields); 650 651 } 652 653 /* finish inode initalization */ 654 ip->devvp = ump->um_devvp; 655 vref(ip->devvp); 656 657 uvm_vnp_setsize(vp, ip->size); 658 *vpp = vp; 659 660 return 0; 661} 662 663/* --------------------------------------------------------------------- */ 664 665static int 666chfs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) 667{ 668 return ENODEV; 669} 670 671/* --------------------------------------------------------------------- */ 672 673static int 674chfs_vptofh(struct vnode *vp, struct fid *fhp, size_t *fh_size) 675{ 676 return ENODEV; 677} 678 679/* --------------------------------------------------------------------- */ 680 681static int 682chfs_start(struct mount *mp, int flags) 683{ 684 return 0; 685} 686 687/* --------------------------------------------------------------------- */ 688 689/* ARGSUSED2 */ 690static int 691chfs_statvfs(struct mount *mp, struct statvfs *sbp) 692{ 693 struct chfs_mount *chmp; 694 struct ufsmount *ump; 695 dbg("statvfs\n"); 696 697 ump = VFSTOUFS(mp); 698 chmp = ump->um_chfs; 699 700 sbp->f_flag = mp->mnt_flag; 701 sbp->f_bsize = chmp->chm_ebh->eb_size; 702 sbp->f_frsize = chmp->chm_ebh->eb_size; 703 sbp->f_iosize = chmp->chm_ebh->eb_size; 704 705 sbp->f_blocks = chmp->chm_ebh->peb_nr; 706 sbp->f_files = 0; 707 sbp->f_bavail = chmp->chm_nr_free_blocks - chmp->chm_resv_blocks_write; 708#if 0 709 printf("chmp->chm_nr_free_blocks: %jd\n", 710 (intmax_t )chmp->chm_nr_free_blocks); 711 printf("chmp->chm_resv_blocks_write: %jd\n", 712 (intmax_t) chmp->chm_resv_blocks_write); 713 printf("chmp->chm_ebh->peb_nr: %jd\n", 714 (intmax_t) chmp->chm_ebh->peb_nr); 715#endif 716 717 sbp->f_bfree = chmp->chm_nr_free_blocks; 718 sbp->f_bresvd = chmp->chm_resv_blocks_write; 719 720 /* FFS specific */ 721 sbp->f_ffree = 0; 722 sbp->f_favail = 0; 723 sbp->f_fresvd = 0; 724 725 copy_statvfs_info(sbp, mp); 726 727 return 0; 728} 729 730/* --------------------------------------------------------------------- */ 731 732/* ARGSUSED0 */ 733static int 734chfs_sync(struct mount *mp, int waitfor, 735 kauth_cred_t uc) 736{ 737 return 0; 738} 739 740/* --------------------------------------------------------------------- */ 741 742static void 743chfs_init(void) 744{ 745 chfs_alloc_pool_caches(); 746 chfs_ihashinit(); 747 pool_init(&chfs_inode_pool, sizeof(struct chfs_inode), 0, 0, 0, 748 "chfsinopl", &pool_allocator_nointr, IPL_NONE); 749 ufs_init(); 750} 751 752/* --------------------------------------------------------------------- */ 753 754static void 755chfs_reinit(void) 756{ 757 chfs_ihashreinit(); 758 ufs_reinit(); 759} 760 761/* --------------------------------------------------------------------- */ 762 763static void 764chfs_done(void) 765{ 766 ufs_done(); 767 chfs_ihashdone(); 768 pool_destroy(&chfs_inode_pool); 769 chfs_destroy_pool_caches(); 770} 771 772/* --------------------------------------------------------------------- */ 773 774static int 775chfs_snapshot(struct mount *mp, struct vnode *vp, 776 struct timespec *ctime) 777{ 778 return ENODEV; 779} 780 781/* --------------------------------------------------------------------- */ 782 783/* 784 * chfs vfs operations. 785 */ 786 787extern const struct vnodeopv_desc chfs_fifoop_opv_desc; 788extern const struct vnodeopv_desc chfs_specop_opv_desc; 789extern const struct vnodeopv_desc chfs_vnodeop_opv_desc; 790 791const struct vnodeopv_desc * const chfs_vnodeopv_descs[] = { 792 &chfs_fifoop_opv_desc, 793 &chfs_specop_opv_desc, 794 &chfs_vnodeop_opv_desc, 795 NULL, 796}; 797 798struct vfsops chfs_vfsops = { 799 MOUNT_CHFS, /* vfs_name */ 800 sizeof (struct chfs_args), 801 chfs_mount, /* vfs_mount */ 802 chfs_start, /* vfs_start */ 803 chfs_unmount, /* vfs_unmount */ 804 chfs_root, /* vfs_root */ 805 ufs_quotactl, /* vfs_quotactl */ 806 chfs_statvfs, /* vfs_statvfs */ 807 chfs_sync, /* vfs_sync */ 808 chfs_vget, /* vfs_vget */ 809 chfs_fhtovp, /* vfs_fhtovp */ 810 chfs_vptofh, /* vfs_vptofh */ 811 chfs_init, /* vfs_init */ 812 chfs_reinit, /* vfs_reinit */ 813 chfs_done, /* vfs_done */ 814 NULL, /* vfs_mountroot */ 815 chfs_snapshot, /* vfs_snapshot */ 816 vfs_stdextattrctl, /* vfs_extattrctl */ 817 (void *)eopnotsupp, /* vfs_suspendctl */ 818 genfs_renamelock_enter, 819 genfs_renamelock_exit, 820 (void *)eopnotsupp, 821 chfs_vnodeopv_descs, 822 0, /* vfs_refcount */ 823 { NULL, NULL }, 824}; 825 826static int 827chfs_modcmd(modcmd_t cmd, void *arg) 828{ 829 switch (cmd) { 830 case MODULE_CMD_INIT: 831 return vfs_attach(&chfs_vfsops); 832 case MODULE_CMD_FINI: 833 return vfs_detach(&chfs_vfsops); 834 default: 835 return ENOTTY; 836 } 837} 838