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