xref: /netbsd-src/sys/ufs/chfs/chfs_vfsops.c (revision 9ea3b23dafd978027b28369eda07bf00fb169b23)
1*9ea3b23dShannken /*	$NetBSD: chfs_vfsops.c,v 1.23 2022/03/19 13:53:32 hannken Exp $	*/
2288addd0Sahoka 
3288addd0Sahoka /*-
4288addd0Sahoka  * Copyright (c) 2010 Department of Software Engineering,
5288addd0Sahoka  *		      University of Szeged, Hungary
6288addd0Sahoka  * Copyright (C) 2010 Tamas Toth <ttoth@inf.u-szeged.hu>
7288addd0Sahoka  * Copyright (C) 2010 Adam Hoka <ahoka@NetBSD.org>
8288addd0Sahoka  * All rights reserved.
9288addd0Sahoka  *
10288addd0Sahoka  * This code is derived from software contributed to The NetBSD Foundation
11288addd0Sahoka  * by the Department of Software Engineering, University of Szeged, Hungary
12288addd0Sahoka  *
13288addd0Sahoka  * Redistribution and use in source and binary forms, with or without
14288addd0Sahoka  * modification, are permitted provided that the following conditions
15288addd0Sahoka  * are met:
16288addd0Sahoka  * 1. Redistributions of source code must retain the above copyright
17288addd0Sahoka  *    notice, this list of conditions and the following disclaimer.
18288addd0Sahoka  * 2. Redistributions in binary form must reproduce the above copyright
19288addd0Sahoka  *    notice, this list of conditions and the following disclaimer in the
20288addd0Sahoka  *    documentation and/or other materials provided with the distribution.
21288addd0Sahoka  *
22288addd0Sahoka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23288addd0Sahoka  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24288addd0Sahoka  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25288addd0Sahoka  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26288addd0Sahoka  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27288addd0Sahoka  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28288addd0Sahoka  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29288addd0Sahoka  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30288addd0Sahoka  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31288addd0Sahoka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32288addd0Sahoka  * SUCH DAMAGE.
33288addd0Sahoka  */
34288addd0Sahoka 
35288addd0Sahoka #include <sys/cdefs.h>
36288addd0Sahoka 
37288addd0Sahoka #include <sys/param.h>
38288addd0Sahoka #include <sys/types.h>
39288addd0Sahoka #include <sys/kmem.h>
40288addd0Sahoka #include <sys/mount.h>
41288addd0Sahoka #include <sys/stat.h>
42288addd0Sahoka #include <sys/systm.h>
43288addd0Sahoka #include <sys/proc.h>
44288addd0Sahoka #include <sys/module.h>
45288addd0Sahoka #include <sys/namei.h>
46288addd0Sahoka #include <sys/fcntl.h>
47288addd0Sahoka #include <sys/conf.h>
48288addd0Sahoka #include <sys/buf.h>
49288addd0Sahoka //XXX needed just for debugging
50288addd0Sahoka #include <sys/fstrans.h>
51288addd0Sahoka #include <sys/sleepq.h>
52288addd0Sahoka #include <sys/lockdebug.h>
53288addd0Sahoka #include <sys/ktrace.h>
54288addd0Sahoka 
559fc45356Sriastradh #include <uvm/uvm_extern.h>
569fc45356Sriastradh 
57288addd0Sahoka #include <ufs/ufs/dir.h>
58288addd0Sahoka #include <ufs/ufs/ufs_extern.h>
59288addd0Sahoka #include <miscfs/genfs/genfs.h>
60288addd0Sahoka #include <miscfs/genfs/genfs_node.h>
61288addd0Sahoka #include <miscfs/specfs/specdev.h>
62288addd0Sahoka #include "chfs.h"
63288addd0Sahoka #include "chfs_args.h"
64288addd0Sahoka 
65288addd0Sahoka /* --------------------------------------------------------------------- */
66288addd0Sahoka /* functions */
67288addd0Sahoka 
68288addd0Sahoka static int chfs_mount(struct mount *, const char *, void *, size_t *);
69288addd0Sahoka static int chfs_unmount(struct mount *, int);
70c2e9cb94Sad static int chfs_root(struct mount *, int, struct vnode **);
71ba1d531eShannken static int chfs_loadvnode(struct mount *, struct vnode *,
72ba1d531eShannken     const void *, size_t, const void **);
73c2e9cb94Sad static int chfs_vget(struct mount *, ino_t, int, struct vnode **);
74c2e9cb94Sad static int chfs_fhtovp(struct mount *, struct fid *, int, struct vnode **);
75288addd0Sahoka static int chfs_vptofh(struct vnode *, struct fid *, size_t *);
76288addd0Sahoka static int chfs_start(struct mount *, int);
77288addd0Sahoka static int chfs_statvfs(struct mount *, struct statvfs *);
78288addd0Sahoka static int chfs_sync(struct mount *, int, kauth_cred_t);
79288addd0Sahoka static void chfs_init(void);
80288addd0Sahoka static void chfs_reinit(void);
81288addd0Sahoka static void chfs_done(void);
82288addd0Sahoka static int chfs_snapshot(struct mount *, struct vnode *,
83288addd0Sahoka     struct timespec *);
84288addd0Sahoka 
85288addd0Sahoka /* --------------------------------------------------------------------- */
86288addd0Sahoka /* structures */
87288addd0Sahoka 
88288addd0Sahoka int
chfs_gop_alloc(struct vnode * vp,off_t off,off_t len,int flags,kauth_cred_t cred)89288addd0Sahoka chfs_gop_alloc(struct vnode *vp, off_t off, off_t len,  int flags,
90288addd0Sahoka     kauth_cred_t cred)
91288addd0Sahoka {
92288addd0Sahoka 	return (0);
93288addd0Sahoka }
94288addd0Sahoka 
95288addd0Sahoka const struct genfs_ops chfs_genfsops = {
96288addd0Sahoka 	.gop_size = genfs_size,
97288addd0Sahoka 	.gop_alloc = chfs_gop_alloc,
98288addd0Sahoka 	.gop_write = genfs_gop_write,
99288addd0Sahoka 	.gop_markupdate = ufs_gop_markupdate,
100e406c140Schs 	.gop_putrange = genfs_gop_putrange,
101288addd0Sahoka };
102288addd0Sahoka 
103288addd0Sahoka struct pool chfs_inode_pool;
104288addd0Sahoka 
105288addd0Sahoka /* for looking up the major for flash */
106288addd0Sahoka extern const struct cdevsw flash_cdevsw;
107288addd0Sahoka 
108288addd0Sahoka /* --------------------------------------------------------------------- */
109288addd0Sahoka 
110288addd0Sahoka static int
chfs_mount(struct mount * mp,const char * path,void * data,size_t * data_len)111288addd0Sahoka chfs_mount(struct mount *mp,
112288addd0Sahoka     const char *path, void *data, size_t *data_len)
113288addd0Sahoka {
114288addd0Sahoka 	struct lwp *l = curlwp;
115288addd0Sahoka 	struct nameidata nd;
116288addd0Sahoka 	struct pathbuf *pb;
117288addd0Sahoka 	struct vnode *devvp = NULL;
118288addd0Sahoka 	struct ufs_args *args = data;
119288addd0Sahoka 	struct ufsmount *ump = NULL;
120288addd0Sahoka 	struct chfs_mount *chmp;
121288addd0Sahoka 	int err = 0;
122288addd0Sahoka 	int xflags;
123288addd0Sahoka 
124288addd0Sahoka 	dbg("mount()\n");
125288addd0Sahoka 
12623f76b6dSmaxv 	if (args == NULL)
12723f76b6dSmaxv 		return EINVAL;
128288addd0Sahoka 	if (*data_len < sizeof *args)
129288addd0Sahoka 		return EINVAL;
130288addd0Sahoka 
131288addd0Sahoka 	if (mp->mnt_flag & MNT_GETARGS) {
132288addd0Sahoka 		ump = VFSTOUFS(mp);
133288addd0Sahoka 		if (ump == NULL)
134288addd0Sahoka 			return EIO;
135288addd0Sahoka 		memset(args, 0, sizeof *args);
136288addd0Sahoka 		args->fspec = NULL;
137288addd0Sahoka 		*data_len = sizeof *args;
138288addd0Sahoka 		return 0;
139288addd0Sahoka 	}
140288addd0Sahoka 
141288addd0Sahoka 	if (mp->mnt_flag & MNT_UPDATE) {
142288addd0Sahoka 		/* XXX: There is no support yet to update file system
143288addd0Sahoka 		 * settings.  Should be added. */
144288addd0Sahoka 
145288addd0Sahoka 		return ENODEV;
146288addd0Sahoka 	}
147288addd0Sahoka 
148288addd0Sahoka 	if (args->fspec != NULL) {
149288addd0Sahoka 		err = pathbuf_copyin(args->fspec, &pb);
150288addd0Sahoka 		if (err) {
151288addd0Sahoka 			return err;
152288addd0Sahoka 		}
153bca84b9eSttoth 		/* Look up the name and verify that it's sane. */
154288addd0Sahoka 		NDINIT(&nd, LOOKUP, FOLLOW, pb);
155f694e9caSchristos 		err = namei(&nd);
15612c7ae02Smaxv 		pathbuf_destroy(pb);
157f694e9caSchristos 		if (err)
158f694e9caSchristos 			return err;
159288addd0Sahoka 		devvp = nd.ni_vp;
160288addd0Sahoka 
161bca84b9eSttoth 		/* Be sure this is a valid block device */
162288addd0Sahoka 		if (devvp->v_type != VBLK)
163288addd0Sahoka 			err = ENOTBLK;
164288addd0Sahoka 		else if (bdevsw_lookup(devvp->v_rdev) == NULL)
165288addd0Sahoka 			err = ENXIO;
166288addd0Sahoka 	}
167288addd0Sahoka 
168288addd0Sahoka 	if (err) {
169288addd0Sahoka 		vrele(devvp);
170288addd0Sahoka 		return (err);
171288addd0Sahoka 	}
172288addd0Sahoka 
173288addd0Sahoka 	if (mp->mnt_flag & MNT_RDONLY)
174288addd0Sahoka 		xflags = FREAD;
175288addd0Sahoka 	else
176288addd0Sahoka 		xflags = FREAD|FWRITE;
177288addd0Sahoka 
178288addd0Sahoka 	err = VOP_OPEN(devvp, xflags, FSCRED);
179288addd0Sahoka 	if (err)
180288addd0Sahoka 		goto fail;
181288addd0Sahoka 
182bca84b9eSttoth 	/* call CHFS mount function */
183288addd0Sahoka 	err = chfs_mountfs(devvp, mp);
184288addd0Sahoka 	if (err) {
185288addd0Sahoka 		vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
186288addd0Sahoka 		(void)VOP_CLOSE(devvp, xflags, NOCRED);
187288addd0Sahoka 		VOP_UNLOCK(devvp);
188288addd0Sahoka 		goto fail;
189288addd0Sahoka 	}
190bca84b9eSttoth 
191288addd0Sahoka 	ump = VFSTOUFS(mp);
192288addd0Sahoka 	chmp = ump->um_chfs;
193288addd0Sahoka 
194288addd0Sahoka 	vfs_getnewfsid(mp);
195288addd0Sahoka 	chmp->chm_fsmp = mp;
196288addd0Sahoka 
197288addd0Sahoka 	return set_statvfs_info(path,
198288addd0Sahoka 	    UIO_USERSPACE, args->fspec,
199288addd0Sahoka 	    UIO_USERSPACE, mp->mnt_op->vfs_name, mp, l);
200288addd0Sahoka 
201288addd0Sahoka fail:
202288addd0Sahoka 	vrele(devvp);
203288addd0Sahoka 	return (err);
204288addd0Sahoka }
205288addd0Sahoka 
206bca84b9eSttoth /* chfs_mountfs - init CHFS */
207288addd0Sahoka int
chfs_mountfs(struct vnode * devvp,struct mount * mp)208288addd0Sahoka chfs_mountfs(struct vnode *devvp, struct mount *mp)
209288addd0Sahoka {
210288addd0Sahoka 	struct lwp *l = curlwp;
211288addd0Sahoka 	kauth_cred_t cred;
212288addd0Sahoka 	devmajor_t flash_major;
213288addd0Sahoka 	dev_t dev;
214288addd0Sahoka 	struct ufsmount* ump = NULL;
215288addd0Sahoka 	struct chfs_mount* chmp;
216288addd0Sahoka 	struct vnode *vp;
217288addd0Sahoka 	int err = 0;
218288addd0Sahoka 
219288addd0Sahoka 	dbg("mountfs()\n");
220288addd0Sahoka 
221288addd0Sahoka 	dev = devvp->v_rdev;
222288addd0Sahoka 	cred = l ? l->l_cred : NOCRED;
223288addd0Sahoka 
224288addd0Sahoka 	/* Flush out any old buffers remaining from a previous use. */
225288addd0Sahoka 	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
226288addd0Sahoka 	err = vinvalbuf(devvp, V_SAVE, cred, l, 0, 0);
227288addd0Sahoka 	VOP_UNLOCK(devvp);
228288addd0Sahoka 	if (err)
22981f0ddf5Sriastradh 		goto fail0;
230288addd0Sahoka 
231bca84b9eSttoth 	/* Setup device. */
232288addd0Sahoka 	flash_major = cdevsw_lookup_major(&flash_cdevsw);
233288addd0Sahoka 
234288addd0Sahoka 	if (devvp->v_type != VBLK)
235288addd0Sahoka 		err = ENOTBLK;
236288addd0Sahoka 	else if (bdevsw_lookup(dev) == NULL)
237288addd0Sahoka 		err = ENXIO;
238288addd0Sahoka 	else if (major(dev) != flash_major) {
239288addd0Sahoka 		dbg("major(dev): %d, flash_major: %d\n",
240288addd0Sahoka 		    major(dev), flash_major);
241288addd0Sahoka 		err = ENODEV;
242288addd0Sahoka 	}
24381f0ddf5Sriastradh 	if (err)
24481f0ddf5Sriastradh 		goto fail0;
245288addd0Sahoka 
246bca84b9eSttoth 	/* Connect CHFS to UFS. */
247f1d428afSrmind 	ump = kmem_zalloc(sizeof(struct ufsmount), KM_SLEEP);
248f1d428afSrmind 
249288addd0Sahoka 	ump->um_fstype = UFS1;
250f1d428afSrmind 	ump->um_chfs = kmem_zalloc(sizeof(struct chfs_mount), KM_SLEEP);
251288addd0Sahoka 	mutex_init(&ump->um_lock, MUTEX_DEFAULT, IPL_NONE);
252288addd0Sahoka 
253288addd0Sahoka 	chmp = ump->um_chfs;
254288addd0Sahoka 
255bca84b9eSttoth 	/* Initialize erase block handler. */
256288addd0Sahoka 	chmp->chm_ebh = kmem_alloc(sizeof(struct chfs_ebh), KM_SLEEP);
257288addd0Sahoka 
258288addd0Sahoka 	dbg("[]opening flash: %u\n", (unsigned int)devvp->v_rdev);
259288addd0Sahoka 	err = ebh_open(chmp->chm_ebh, devvp->v_rdev);
260288addd0Sahoka 	if (err) {
261288addd0Sahoka 		dbg("error while opening flash\n");
26281f0ddf5Sriastradh 		goto fail1;
263288addd0Sahoka 	}
264288addd0Sahoka 
265288addd0Sahoka 	//TODO check flash sizes
266288addd0Sahoka 
267bca84b9eSttoth 	/* Initialize vnode cache's hashtable and eraseblock array. */
268288addd0Sahoka 	chmp->chm_gbl_version = 0;
269288addd0Sahoka 	chmp->chm_vnocache_hash = chfs_vnocache_hash_init();
270288addd0Sahoka 
271288addd0Sahoka 	chmp->chm_blocks = kmem_zalloc(chmp->chm_ebh->peb_nr *
272288addd0Sahoka 	    sizeof(struct chfs_eraseblock), KM_SLEEP);
273288addd0Sahoka 
274bca84b9eSttoth 	/* Initialize mutexes. */
275288addd0Sahoka 	mutex_init(&chmp->chm_lock_mountfields, MUTEX_DEFAULT, IPL_NONE);
276288addd0Sahoka 	mutex_init(&chmp->chm_lock_sizes, MUTEX_DEFAULT, IPL_NONE);
277288addd0Sahoka 	mutex_init(&chmp->chm_lock_vnocache, MUTEX_DEFAULT, IPL_NONE);
278288addd0Sahoka 
279bca84b9eSttoth 	/* Initialize read/write contants. (from UFS) */
280288addd0Sahoka 	chmp->chm_fs_bmask = -4096;
281288addd0Sahoka 	chmp->chm_fs_bsize = 4096;
282288addd0Sahoka 	chmp->chm_fs_qbmask = 4095;
283288addd0Sahoka 	chmp->chm_fs_bshift = 12;
284288addd0Sahoka 	chmp->chm_fs_fmask = -2048;
285288addd0Sahoka 	chmp->chm_fs_qfmask = 2047;
286288addd0Sahoka 
287bca84b9eSttoth 	/* Initialize writebuffer. */
288288addd0Sahoka 	chmp->chm_wbuf_pagesize = chmp->chm_ebh->flash_if->page_size;
289288addd0Sahoka 	dbg("wbuf size: %zu\n", chmp->chm_wbuf_pagesize);
290288addd0Sahoka 	chmp->chm_wbuf = kmem_alloc(chmp->chm_wbuf_pagesize, KM_SLEEP);
291288addd0Sahoka 	rw_init(&chmp->chm_lock_wbuf);
292288addd0Sahoka 
293bca84b9eSttoth 	/* Initialize queues. */
294288addd0Sahoka 	TAILQ_INIT(&chmp->chm_free_queue);
295288addd0Sahoka 	TAILQ_INIT(&chmp->chm_clean_queue);
296288addd0Sahoka 	TAILQ_INIT(&chmp->chm_dirty_queue);
297288addd0Sahoka 	TAILQ_INIT(&chmp->chm_very_dirty_queue);
298288addd0Sahoka 	TAILQ_INIT(&chmp->chm_erasable_pending_wbuf_queue);
299288addd0Sahoka 	TAILQ_INIT(&chmp->chm_erase_pending_queue);
300288addd0Sahoka 
301bca84b9eSttoth 	/* Initialize flash-specific constants. */
302288addd0Sahoka 	chfs_calc_trigger_levels(chmp);
303288addd0Sahoka 
304bca84b9eSttoth 	/* Initialize sizes. */
305288addd0Sahoka 	chmp->chm_nr_free_blocks = 0;
306288addd0Sahoka 	chmp->chm_nr_erasable_blocks = 0;
307288addd0Sahoka 	chmp->chm_max_vno = 2;
308288addd0Sahoka 	chmp->chm_checked_vno = 2;
309288addd0Sahoka 	chmp->chm_unchecked_size = 0;
310288addd0Sahoka 	chmp->chm_used_size = 0;
311288addd0Sahoka 	chmp->chm_dirty_size = 0;
312288addd0Sahoka 	chmp->chm_wasted_size = 0;
313288addd0Sahoka 	chmp->chm_free_size = chmp->chm_ebh->eb_size * chmp->chm_ebh->peb_nr;
314bca84b9eSttoth 
315bca84b9eSttoth 	/* Build filesystem. */
316288addd0Sahoka 	err = chfs_build_filesystem(chmp);
317288addd0Sahoka 
318288addd0Sahoka 	if (err) {
319bca84b9eSttoth 		/* Armageddon and return. */
320f1d428afSrmind 		err = EIO;
32181f0ddf5Sriastradh 		goto fail2;
322288addd0Sahoka 	}
323288addd0Sahoka 
324bca84b9eSttoth 	/* Initialize UFS. */
325288addd0Sahoka 	mp->mnt_data = ump;
326288addd0Sahoka 	mp->mnt_stat.f_fsidx.__fsid_val[0] = (long)dev;
327288addd0Sahoka 	mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_CHFS);
328288addd0Sahoka 	mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
329288addd0Sahoka 	mp->mnt_stat.f_namemax = MAXNAMLEN;
330288addd0Sahoka 	mp->mnt_flag |= MNT_LOCAL;
331288addd0Sahoka 	mp->mnt_fs_bshift = PAGE_SHIFT;
332288addd0Sahoka 	mp->mnt_dev_bshift = DEV_BSHIFT;
333288addd0Sahoka 	mp->mnt_iflag |= IMNT_MPSAFE;
334288addd0Sahoka 	ump->um_flags = 0;
335288addd0Sahoka 	ump->um_mountp = mp;
336288addd0Sahoka 	ump->um_dev = dev;
337288addd0Sahoka 	ump->um_devvp = devvp;
338288addd0Sahoka 	ump->um_maxfilesize = 1048512 * 1024;
339288addd0Sahoka 
340bca84b9eSttoth 	/* Allocate the root vnode. */
341c2e9cb94Sad 	err = VFS_VGET(mp, CHFS_ROOTINO, LK_EXCLUSIVE, &vp);
342288addd0Sahoka 	if (err) {
343288addd0Sahoka 		dbg("error: %d while allocating root node\n", err);
344288addd0Sahoka 		return err;
345288addd0Sahoka 	}
346288addd0Sahoka 	vput(vp);
347288addd0Sahoka 
348bca84b9eSttoth 	/* Start GC. */
349288addd0Sahoka 	chfs_gc_thread_start(chmp);
350288addd0Sahoka 	mutex_enter(&chmp->chm_lock_mountfields);
351288addd0Sahoka 	chfs_gc_trigger(chmp);
352288addd0Sahoka 	mutex_exit(&chmp->chm_lock_mountfields);
353288addd0Sahoka 
3543881f4f3Shannken 	spec_node_setmountedfs(devvp, mp);
355288addd0Sahoka 	return 0;
356bca84b9eSttoth 
35781f0ddf5Sriastradh fail2:
35881f0ddf5Sriastradh 	KASSERT(TAILQ_EMPTY(&chmp->chm_erase_pending_queue));
35981f0ddf5Sriastradh 	KASSERT(TAILQ_EMPTY(&chmp->chm_erasable_pending_wbuf_queue));
36081f0ddf5Sriastradh 	KASSERT(TAILQ_EMPTY(&chmp->chm_very_dirty_queue));
36181f0ddf5Sriastradh 	KASSERT(TAILQ_EMPTY(&chmp->chm_dirty_queue));
36281f0ddf5Sriastradh 	KASSERT(TAILQ_EMPTY(&chmp->chm_clean_queue));
36381f0ddf5Sriastradh 	KASSERT(TAILQ_EMPTY(&chmp->chm_free_queue));
36481f0ddf5Sriastradh 	rw_destroy(&chmp->chm_lock_wbuf);
36581f0ddf5Sriastradh 	kmem_free(chmp->chm_wbuf, chmp->chm_wbuf_pagesize);
36681f0ddf5Sriastradh 	mutex_destroy(&chmp->chm_lock_vnocache);
36781f0ddf5Sriastradh 	mutex_destroy(&chmp->chm_lock_sizes);
36881f0ddf5Sriastradh 	mutex_destroy(&chmp->chm_lock_mountfields);
36981f0ddf5Sriastradh 	kmem_free(chmp->chm_blocks, chmp->chm_ebh->peb_nr *
37081f0ddf5Sriastradh 	    sizeof(struct chfs_eraseblock));
37181f0ddf5Sriastradh 	chfs_vnocache_hash_destroy(chmp->chm_vnocache_hash);
37281f0ddf5Sriastradh 	ebh_close(chmp->chm_ebh);
37381f0ddf5Sriastradh 
37481f0ddf5Sriastradh fail1:
375f1d428afSrmind 	kmem_free(chmp->chm_ebh, sizeof(struct chfs_ebh));
37681f0ddf5Sriastradh 	mutex_destroy(&ump->um_lock);
377f1d428afSrmind 	kmem_free(chmp, sizeof(struct chfs_mount));
378f1d428afSrmind 	kmem_free(ump, sizeof(struct ufsmount));
37981f0ddf5Sriastradh 
38081f0ddf5Sriastradh fail0:
38181f0ddf5Sriastradh 	KASSERT(err);
382f1d428afSrmind 	return err;
383288addd0Sahoka }
384288addd0Sahoka 
385288addd0Sahoka /* --------------------------------------------------------------------- */
386288addd0Sahoka 
387288addd0Sahoka static int
chfs_unmount(struct mount * mp,int mntflags)388288addd0Sahoka chfs_unmount(struct mount *mp, int mntflags)
389288addd0Sahoka {
390288addd0Sahoka 	int flags = 0, i = 0;
391288addd0Sahoka 	struct ufsmount *ump;
392288addd0Sahoka 	struct chfs_mount *chmp;
393288addd0Sahoka 
394288addd0Sahoka 	if (mntflags & MNT_FORCE)
395288addd0Sahoka 		flags |= FORCECLOSE;
396288addd0Sahoka 
397288addd0Sahoka 	dbg("[START]\n");
398288addd0Sahoka 
399288addd0Sahoka 	ump = VFSTOUFS(mp);
400288addd0Sahoka 	chmp = ump->um_chfs;
401288addd0Sahoka 
402bca84b9eSttoth 	/* Stop GC. */
403288addd0Sahoka 	chfs_gc_thread_stop(chmp);
404288addd0Sahoka 
405bca84b9eSttoth 	/* Flush everyt buffer. */
406288addd0Sahoka 	(void)vflush(mp, NULLVP, flags);
407288addd0Sahoka 
408288addd0Sahoka 	if (chmp->chm_wbuf_len) {
409288addd0Sahoka 		mutex_enter(&chmp->chm_lock_mountfields);
410288addd0Sahoka 		chfs_flush_pending_wbuf(chmp);
411288addd0Sahoka 		mutex_exit(&chmp->chm_lock_mountfields);
412288addd0Sahoka 	}
413288addd0Sahoka 
414bca84b9eSttoth 	/* Free node references. */
415288addd0Sahoka 	for (i = 0; i < chmp->chm_ebh->peb_nr; i++) {
416288addd0Sahoka 		chfs_free_node_refs(&chmp->chm_blocks[i]);
417288addd0Sahoka 	}
418288addd0Sahoka 
419bca84b9eSttoth 	/* Destroy vnode cache hashtable. */
420288addd0Sahoka 	chfs_vnocache_hash_destroy(chmp->chm_vnocache_hash);
421288addd0Sahoka 
422bca84b9eSttoth 	/* Close eraseblock handler. */
423288addd0Sahoka 	ebh_close(chmp->chm_ebh);
424288addd0Sahoka 
425bca84b9eSttoth 	/* Destroy mutexes. */
426288addd0Sahoka 	rw_destroy(&chmp->chm_lock_wbuf);
427288addd0Sahoka 	mutex_destroy(&chmp->chm_lock_vnocache);
428288addd0Sahoka 	mutex_destroy(&chmp->chm_lock_sizes);
429288addd0Sahoka 	mutex_destroy(&chmp->chm_lock_mountfields);
430288addd0Sahoka 
431bca84b9eSttoth 	/* Unmount UFS. */
432288addd0Sahoka 	if (ump->um_devvp->v_type != VBAD) {
4333881f4f3Shannken 		spec_node_setmountedfs(ump->um_devvp, NULL);
434288addd0Sahoka 	}
435288addd0Sahoka 	vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
436288addd0Sahoka 	(void)VOP_CLOSE(ump->um_devvp, FREAD|FWRITE, NOCRED);
437288addd0Sahoka 	vput(ump->um_devvp);
438288addd0Sahoka 
439288addd0Sahoka 	mutex_destroy(&ump->um_lock);
440288addd0Sahoka 
441bca84b9eSttoth 	/* Everything done. */
442f1d428afSrmind 	kmem_free(ump, sizeof(struct ufsmount));
443288addd0Sahoka 	mp->mnt_data = NULL;
444288addd0Sahoka 	mp->mnt_flag &= ~MNT_LOCAL;
445288addd0Sahoka 	dbg("[END]\n");
446288addd0Sahoka 	return (0);
447288addd0Sahoka }
448288addd0Sahoka 
449288addd0Sahoka /* --------------------------------------------------------------------- */
450288addd0Sahoka 
451288addd0Sahoka static int
chfs_root(struct mount * mp,int lktype,struct vnode ** vpp)452c2e9cb94Sad chfs_root(struct mount *mp, int lktype, struct vnode **vpp)
453288addd0Sahoka {
454288addd0Sahoka 	struct vnode *vp;
455288addd0Sahoka 	int error;
456288addd0Sahoka 
457c2e9cb94Sad 	if ((error = VFS_VGET(mp, (ino_t)UFS_ROOTINO, lktype, &vp)) != 0)
458288addd0Sahoka 		return error;
459288addd0Sahoka 	*vpp = vp;
460288addd0Sahoka 	return 0;
461288addd0Sahoka }
462288addd0Sahoka 
463288addd0Sahoka /* --------------------------------------------------------------------- */
464288addd0Sahoka 
465288addd0Sahoka extern rb_tree_ops_t frag_rbtree_ops;
466288addd0Sahoka 
467288addd0Sahoka static int
chfs_loadvnode(struct mount * mp,struct vnode * vp,const void * key,size_t key_len,const void ** new_key)468ba1d531eShannken chfs_loadvnode(struct mount *mp, struct vnode *vp,
469ba1d531eShannken     const void *key, size_t key_len, const void **new_key)
470288addd0Sahoka {
471288addd0Sahoka 	struct chfs_mount *chmp;
472288addd0Sahoka 	struct chfs_inode *ip;
473288addd0Sahoka 	struct ufsmount *ump;
474288addd0Sahoka 	dev_t dev;
475288addd0Sahoka 	int error;
476288addd0Sahoka 	struct chfs_vnode_cache* chvc = NULL;
477288addd0Sahoka 	struct chfs_node_ref* nref = NULL;
478288addd0Sahoka 	struct buf *bp;
479ba1d531eShannken 	ino_t ino;
480ba1d531eShannken 
481ba1d531eShannken 	KASSERT(key_len == sizeof(ino));
482ba1d531eShannken 	memcpy(&ino, key, key_len);
483288addd0Sahoka 
484f9d6d5cbSagc 	dbg("vget() | ino: %llu\n", (unsigned long long)ino);
485288addd0Sahoka 
486288addd0Sahoka 	ump = VFSTOUFS(mp);
487288addd0Sahoka 	dev = ump->um_dev;
488288addd0Sahoka 
489288addd0Sahoka 	ip = pool_get(&chfs_inode_pool, PR_WAITOK);
490288addd0Sahoka 
491bca84b9eSttoth 	/* Initialize vnode/inode. */
492288addd0Sahoka 	memset(ip, 0, sizeof(*ip));
493288addd0Sahoka 	ip->vp = vp;
494288addd0Sahoka 	ip->ump = ump;
495288addd0Sahoka 	ip->chmp = chmp = ump->um_chfs;
496288addd0Sahoka 	ip->dev = dev;
497288addd0Sahoka 	ip->ino = ino;
498288addd0Sahoka 
499288addd0Sahoka 	rb_tree_init(&ip->fragtree, &frag_rbtree_ops);
500288addd0Sahoka 
501ba1d531eShannken 	vp->v_tag = VT_CHFS;
502ba1d531eShannken 	vp->v_op = chfs_vnodeop_p;
503ba1d531eShannken 	if (ino == CHFS_ROOTINO)
504ba1d531eShannken 		vp->v_vflag |= VV_ROOT;
505ba1d531eShannken 	vp->v_data = ip;
506288addd0Sahoka 
507bca84b9eSttoth 	/* Set root inode. */
508288addd0Sahoka 	if (ino == CHFS_ROOTINO) {
509288addd0Sahoka 		dbg("SETROOT\n");
510288addd0Sahoka 		vp->v_type = VDIR;
5114024b549Sttoth 		ip->ch_type = CHT_DIR;
512288addd0Sahoka 		ip->mode = IFMT | IEXEC | IWRITE | IREAD;
513288addd0Sahoka 		ip->iflag |= (IN_ACCESS | IN_CHANGE | IN_UPDATE);
514288addd0Sahoka 		chfs_update(vp, NULL, NULL, UPDATE_WAIT);
515288addd0Sahoka 		TAILQ_INIT(&ip->dents);
516288addd0Sahoka 		chfs_set_vnode_size(vp, 512);
517288addd0Sahoka 	}
518288addd0Sahoka 
519288addd0Sahoka 	mutex_enter(&chmp->chm_lock_vnocache);
520288addd0Sahoka 	chvc = chfs_vnode_cache_get(chmp, ino);
521288addd0Sahoka 	mutex_exit(&chmp->chm_lock_vnocache);
522288addd0Sahoka 	if (!chvc) {
523288addd0Sahoka 		dbg("!chvc\n");
524bca84b9eSttoth 		/* Initialize the corresponding vnode cache. */
525288addd0Sahoka 		/* XXX, we cant alloc under a lock, refactor this! */
526288addd0Sahoka 		chvc = chfs_vnode_cache_alloc(ino);
527288addd0Sahoka 		mutex_enter(&chmp->chm_lock_vnocache);
528288addd0Sahoka 		if (ino == CHFS_ROOTINO) {
529288addd0Sahoka 			chvc->nlink = 2;
530288addd0Sahoka 			chvc->pvno = CHFS_ROOTINO;
5313fae61eeSttoth 			chvc->state = VNO_STATE_CHECKEDABSENT;
532288addd0Sahoka 		}
533288addd0Sahoka 		chfs_vnode_cache_add(chmp, chvc);
534288addd0Sahoka 		mutex_exit(&chmp->chm_lock_vnocache);
535288addd0Sahoka 
536288addd0Sahoka 		ip->chvc = chvc;
537288addd0Sahoka 		TAILQ_INIT(&ip->dents);
538288addd0Sahoka 	} else {
539288addd0Sahoka 		dbg("chvc\n");
540288addd0Sahoka 		ip->chvc = chvc;
541bca84b9eSttoth 		/* We had a vnode cache, the node is already on flash, so read it */
542288addd0Sahoka 		if (ino == CHFS_ROOTINO) {
543288addd0Sahoka 			chvc->pvno = CHFS_ROOTINO;
544288addd0Sahoka 			TAILQ_INIT(&chvc->scan_dirents);
545288addd0Sahoka 		} else {
546288addd0Sahoka 			chfs_readvnode(mp, ino, &vp);
547288addd0Sahoka 		}
548288addd0Sahoka 
549288addd0Sahoka 		mutex_enter(&chmp->chm_lock_mountfields);
550bca84b9eSttoth 		/* Initialize type specific things. */
551ba1d531eShannken 		error = 0;
5524024b549Sttoth 		switch (ip->ch_type) {
5534024b549Sttoth 		case CHT_DIR:
554bca84b9eSttoth 			/* Read every dirent. */
555288addd0Sahoka 			nref = chvc->dirents;
556288addd0Sahoka 			while (nref &&
557288addd0Sahoka 			    (struct chfs_vnode_cache *)nref != chvc) {
558288addd0Sahoka 				chfs_readdirent(mp, nref, ip);
559288addd0Sahoka 				nref = nref->nref_next;
560288addd0Sahoka 			}
561288addd0Sahoka 			chfs_set_vnode_size(vp, 512);
562288addd0Sahoka 			break;
5634024b549Sttoth 		case CHT_REG:
564bca84b9eSttoth 			/* FALLTHROUGH */
5654024b549Sttoth 		case CHT_SOCK:
566bca84b9eSttoth 			/* Collect data. */
567f9d6d5cbSagc 			dbg("read_inode_internal | ino: %llu\n",
568f9d6d5cbSagc 				(unsigned long long)ip->ino);
569288addd0Sahoka 			error = chfs_read_inode(chmp, ip);
570288addd0Sahoka 			break;
5714024b549Sttoth 		case CHT_LNK:
572bca84b9eSttoth 			/* Collect data. */
573f9d6d5cbSagc 			dbg("read_inode_internal | ino: %llu\n",
574f9d6d5cbSagc 				(unsigned long long)ip->ino);
575288addd0Sahoka 			error = chfs_read_inode_internal(chmp, ip);
576ba1d531eShannken 			if (error)
577ba1d531eShannken 				break;
578288addd0Sahoka 
579bca84b9eSttoth 			/* Set link. */
580f9d6d5cbSagc 			dbg("size: %llu\n", (unsigned long long)ip->size);
581288addd0Sahoka 			bp = getiobuf(vp, true);
582288addd0Sahoka 			bp->b_blkno = 0;
583288addd0Sahoka 			bp->b_bufsize = bp->b_resid =
584288addd0Sahoka 			    bp->b_bcount = ip->size;
585288addd0Sahoka 			bp->b_data = kmem_alloc(ip->size, KM_SLEEP);
586288addd0Sahoka 			chfs_read_data(chmp, vp, bp);
587288addd0Sahoka 			if (!ip->target)
588288addd0Sahoka 				ip->target = kmem_alloc(ip->size,
589288addd0Sahoka 				    KM_SLEEP);
590288addd0Sahoka 			memcpy(ip->target, bp->b_data, ip->size);
591288addd0Sahoka 			kmem_free(bp->b_data, ip->size);
592288addd0Sahoka 			putiobuf(bp);
593288addd0Sahoka 
594288addd0Sahoka 			break;
5954024b549Sttoth 		case CHT_CHR:
596bca84b9eSttoth 			/* FALLTHROUGH */
5974024b549Sttoth 		case CHT_BLK:
598bca84b9eSttoth 			/* FALLTHROUGH */
5994024b549Sttoth 		case CHT_FIFO:
600bca84b9eSttoth 			/* Collect data. */
601f9d6d5cbSagc 			dbg("read_inode_internal | ino: %llu\n",
602f9d6d5cbSagc 				(unsigned long long)ip->ino);
603288addd0Sahoka 			error = chfs_read_inode_internal(chmp, ip);
604ba1d531eShannken 			if (error)
605ba1d531eShannken 				break;
606288addd0Sahoka 
607bca84b9eSttoth 			/* Set device. */
608288addd0Sahoka 			bp = getiobuf(vp, true);
609288addd0Sahoka 			bp->b_blkno = 0;
610288addd0Sahoka 			bp->b_bufsize = bp->b_resid =
611288addd0Sahoka 			    bp->b_bcount = sizeof(dev_t);
612288addd0Sahoka 			bp->b_data = kmem_alloc(sizeof(dev_t), KM_SLEEP);
613288addd0Sahoka 			chfs_read_data(chmp, vp, bp);
614288addd0Sahoka 			memcpy(&ip->rdev,
615288addd0Sahoka 			    bp->b_data, sizeof(dev_t));
616288addd0Sahoka 			kmem_free(bp->b_data, sizeof(dev_t));
617288addd0Sahoka 			putiobuf(bp);
618bca84b9eSttoth 			/* Set specific operations. */
6194024b549Sttoth 			if (ip->ch_type == CHT_FIFO) {
620288addd0Sahoka 				vp->v_op = chfs_fifoop_p;
6214024b549Sttoth 			} else {
622288addd0Sahoka 				vp->v_op = chfs_specop_p;
623288addd0Sahoka 				spec_node_init(vp, ip->rdev);
624288addd0Sahoka 			}
625288addd0Sahoka 
626288addd0Sahoka 		    break;
6274024b549Sttoth 		case CHT_BLANK:
628bca84b9eSttoth 			/* FALLTHROUGH */
6294024b549Sttoth 		case CHT_BAD:
630288addd0Sahoka 			break;
631288addd0Sahoka 		}
632288addd0Sahoka 		mutex_exit(&chmp->chm_lock_mountfields);
633ba1d531eShannken 		if (error) {
634ba1d531eShannken 			vp->v_data = NULL;
635ba1d531eShannken 			KASSERT(TAILQ_FIRST(&ip->dents) == NULL);
636ba1d531eShannken 			pool_put(&chfs_inode_pool, ip);
637ba1d531eShannken 			return error;
638ba1d531eShannken 		}
639288addd0Sahoka 
640288addd0Sahoka 	}
641288addd0Sahoka 
642a5effc3cSmsaitoh 	/* Finish inode initialization. */
643ba1d531eShannken 	ip->ch_type = VTTOCHT(vp->v_type);
644288addd0Sahoka 	ip->devvp = ump->um_devvp;
645288addd0Sahoka 	vref(ip->devvp);
646288addd0Sahoka 
647ba1d531eShannken 	genfs_node_init(vp, &chfs_genfsops);
648288addd0Sahoka 	uvm_vnp_setsize(vp, ip->size);
649ba1d531eShannken 
650ba1d531eShannken 	*new_key = &ip->ino;
651288addd0Sahoka 
652288addd0Sahoka 	return 0;
653288addd0Sahoka }
654288addd0Sahoka 
655288addd0Sahoka /* --------------------------------------------------------------------- */
656288addd0Sahoka 
657288addd0Sahoka static int
chfs_vget(struct mount * mp,ino_t ino,int lktype,struct vnode ** vpp)658c2e9cb94Sad chfs_vget(struct mount *mp, ino_t ino, int lktype, struct vnode **vpp)
659ba1d531eShannken {
660ba1d531eShannken 	int error;
661ba1d531eShannken 
662ba1d531eShannken 	error = vcache_get(mp, &ino, sizeof(ino), vpp);
663ba1d531eShannken 	if (error)
664ba1d531eShannken 		return error;
665ba1d531eShannken 
666c2e9cb94Sad 	error = vn_lock(*vpp, lktype);
667ba1d531eShannken 	if (error) {
668ba1d531eShannken 		vrele(*vpp);
669ba1d531eShannken 		*vpp = NULL;
670ba1d531eShannken 		return error;
671ba1d531eShannken 	}
672ba1d531eShannken 
673ba1d531eShannken 	return 0;
674ba1d531eShannken }
675ba1d531eShannken 
676ba1d531eShannken /* --------------------------------------------------------------------- */
677ba1d531eShannken 
678ba1d531eShannken 
679ba1d531eShannken static int
chfs_fhtovp(struct mount * mp,struct fid * fhp,int lktype,struct vnode ** vpp)680c2e9cb94Sad chfs_fhtovp(struct mount *mp, struct fid *fhp, int lktype, struct vnode **vpp)
681288addd0Sahoka {
682288addd0Sahoka 	return ENODEV;
683288addd0Sahoka }
684288addd0Sahoka 
685288addd0Sahoka /* --------------------------------------------------------------------- */
686288addd0Sahoka 
687288addd0Sahoka static int
chfs_vptofh(struct vnode * vp,struct fid * fhp,size_t * fh_size)688288addd0Sahoka chfs_vptofh(struct vnode *vp, struct fid *fhp, size_t *fh_size)
689288addd0Sahoka {
690288addd0Sahoka 	return ENODEV;
691288addd0Sahoka }
692288addd0Sahoka 
693288addd0Sahoka /* --------------------------------------------------------------------- */
694288addd0Sahoka 
695288addd0Sahoka static int
chfs_start(struct mount * mp,int flags)696288addd0Sahoka chfs_start(struct mount *mp, int flags)
697288addd0Sahoka {
698288addd0Sahoka 	return 0;
699288addd0Sahoka }
700288addd0Sahoka 
701288addd0Sahoka /* --------------------------------------------------------------------- */
702288addd0Sahoka 
703288addd0Sahoka static int
chfs_statvfs(struct mount * mp,struct statvfs * sbp)704288addd0Sahoka chfs_statvfs(struct mount *mp, struct statvfs *sbp)
705288addd0Sahoka {
706288addd0Sahoka  	struct chfs_mount *chmp;
707288addd0Sahoka 	struct ufsmount *ump;
708288addd0Sahoka 	dbg("statvfs\n");
709288addd0Sahoka 
710288addd0Sahoka 	ump = VFSTOUFS(mp);
711288addd0Sahoka 	chmp = ump->um_chfs;
712288addd0Sahoka 
713288addd0Sahoka 	sbp->f_flag   = mp->mnt_flag;
714288addd0Sahoka 	sbp->f_bsize  = chmp->chm_ebh->eb_size;
715288addd0Sahoka 	sbp->f_frsize = chmp->chm_ebh->eb_size;
716288addd0Sahoka 	sbp->f_iosize = chmp->chm_ebh->eb_size;
717288addd0Sahoka 
718288addd0Sahoka 	sbp->f_blocks = chmp->chm_ebh->peb_nr;
719288addd0Sahoka 	sbp->f_files  = 0;
720288addd0Sahoka 	sbp->f_bavail = chmp->chm_nr_free_blocks - chmp->chm_resv_blocks_write;
721288addd0Sahoka 
722288addd0Sahoka 	sbp->f_bfree = chmp->chm_nr_free_blocks;
723288addd0Sahoka 	sbp->f_bresvd = chmp->chm_resv_blocks_write;
724288addd0Sahoka 
725288addd0Sahoka 	/* FFS specific */
726288addd0Sahoka 	sbp->f_ffree  = 0;
727288addd0Sahoka 	sbp->f_favail = 0;
728288addd0Sahoka 	sbp->f_fresvd = 0;
729288addd0Sahoka 
730288addd0Sahoka 	copy_statvfs_info(sbp, mp);
731288addd0Sahoka 
732288addd0Sahoka 	return 0;
733288addd0Sahoka }
734288addd0Sahoka 
735288addd0Sahoka /* --------------------------------------------------------------------- */
736288addd0Sahoka 
737288addd0Sahoka static int
chfs_sync(struct mount * mp,int waitfor,kauth_cred_t uc)738288addd0Sahoka chfs_sync(struct mount *mp, int waitfor,
739288addd0Sahoka     kauth_cred_t uc)
740288addd0Sahoka {
741288addd0Sahoka 	return 0;
742288addd0Sahoka }
743288addd0Sahoka 
744288addd0Sahoka /* --------------------------------------------------------------------- */
745288addd0Sahoka 
746288addd0Sahoka static void
chfs_init(void)747288addd0Sahoka chfs_init(void)
748288addd0Sahoka {
749bca84b9eSttoth 	/* Initialize pools and inode hash. */
750288addd0Sahoka 	chfs_alloc_pool_caches();
751288addd0Sahoka 	pool_init(&chfs_inode_pool, sizeof(struct chfs_inode), 0, 0, 0,
752288addd0Sahoka 	    "chfsinopl", &pool_allocator_nointr, IPL_NONE);
753288addd0Sahoka 	ufs_init();
754288addd0Sahoka }
755288addd0Sahoka 
756288addd0Sahoka /* --------------------------------------------------------------------- */
757288addd0Sahoka 
758288addd0Sahoka static void
chfs_reinit(void)759288addd0Sahoka chfs_reinit(void)
760288addd0Sahoka {
761288addd0Sahoka 	ufs_reinit();
762288addd0Sahoka }
763288addd0Sahoka 
764288addd0Sahoka /* --------------------------------------------------------------------- */
765288addd0Sahoka 
766288addd0Sahoka static void
chfs_done(void)767288addd0Sahoka chfs_done(void)
768288addd0Sahoka {
769288addd0Sahoka 	ufs_done();
770288addd0Sahoka 	pool_destroy(&chfs_inode_pool);
771288addd0Sahoka 	chfs_destroy_pool_caches();
772288addd0Sahoka }
773288addd0Sahoka 
774288addd0Sahoka /* --------------------------------------------------------------------- */
775288addd0Sahoka 
776288addd0Sahoka static int
chfs_snapshot(struct mount * mp,struct vnode * vp,struct timespec * ctime)777288addd0Sahoka chfs_snapshot(struct mount *mp, struct vnode *vp,
778288addd0Sahoka     struct timespec *ctime)
779288addd0Sahoka {
780288addd0Sahoka 	return ENODEV;
781288addd0Sahoka }
782288addd0Sahoka 
783288addd0Sahoka /* --------------------------------------------------------------------- */
784288addd0Sahoka 
785288addd0Sahoka /*
786288addd0Sahoka  * chfs vfs operations.
787288addd0Sahoka  */
788288addd0Sahoka 
789288addd0Sahoka extern const struct vnodeopv_desc chfs_fifoop_opv_desc;
790288addd0Sahoka extern const struct vnodeopv_desc chfs_specop_opv_desc;
791288addd0Sahoka extern const struct vnodeopv_desc chfs_vnodeop_opv_desc;
792288addd0Sahoka 
793288addd0Sahoka const struct vnodeopv_desc * const chfs_vnodeopv_descs[] = {
794288addd0Sahoka 	&chfs_fifoop_opv_desc,
795288addd0Sahoka 	&chfs_specop_opv_desc,
796288addd0Sahoka 	&chfs_vnodeop_opv_desc,
797288addd0Sahoka 	NULL,
798288addd0Sahoka };
799288addd0Sahoka 
800288addd0Sahoka struct vfsops chfs_vfsops = {
8016d285189Shannken 	.vfs_name = MOUNT_CHFS,
8026d285189Shannken 	.vfs_min_mount_data = sizeof (struct chfs_args),
8036d285189Shannken 	.vfs_mount = chfs_mount,
8046d285189Shannken 	.vfs_start = chfs_start,
8056d285189Shannken 	.vfs_unmount = chfs_unmount,
8066d285189Shannken 	.vfs_root = chfs_root,
8076d285189Shannken 	.vfs_quotactl = ufs_quotactl,
8086d285189Shannken 	.vfs_statvfs = chfs_statvfs,
8096d285189Shannken 	.vfs_sync = chfs_sync,
8106d285189Shannken 	.vfs_vget = chfs_vget,
811ba1d531eShannken 	.vfs_loadvnode = chfs_loadvnode,
8126d285189Shannken 	.vfs_fhtovp = chfs_fhtovp,
8136d285189Shannken 	.vfs_vptofh = chfs_vptofh,
8146d285189Shannken 	.vfs_init = chfs_init,
8156d285189Shannken 	.vfs_reinit = chfs_reinit,
8166d285189Shannken 	.vfs_done = chfs_done,
8176d285189Shannken 	.vfs_snapshot = chfs_snapshot,
8186d285189Shannken 	.vfs_extattrctl = vfs_stdextattrctl,
819326db3aaShannken 	.vfs_suspendctl = genfs_suspendctl,
8206d285189Shannken 	.vfs_renamelock_enter = genfs_renamelock_enter,
8216d285189Shannken 	.vfs_renamelock_exit = genfs_renamelock_exit,
8226d285189Shannken 	.vfs_fsync = (void *)eopnotsupp,
8236d285189Shannken 	.vfs_opv_descs = chfs_vnodeopv_descs
824288addd0Sahoka };
825288addd0Sahoka 
826bca84b9eSttoth /* For using CHFS as a module. */
82731dfde78Spgoyette 
82831dfde78Spgoyette MODULE(MODULE_CLASS_VFS, chfs, "ufs,flash");
82931dfde78Spgoyette 
830288addd0Sahoka static int
chfs_modcmd(modcmd_t cmd,void * arg)831288addd0Sahoka chfs_modcmd(modcmd_t cmd, void *arg)
832288addd0Sahoka {
833288addd0Sahoka 	switch (cmd) {
834288addd0Sahoka 	case MODULE_CMD_INIT:
835288addd0Sahoka 		return vfs_attach(&chfs_vfsops);
836288addd0Sahoka 	case MODULE_CMD_FINI:
837288addd0Sahoka 		return vfs_detach(&chfs_vfsops);
838288addd0Sahoka 	default:
839288addd0Sahoka 		return ENOTTY;
840288addd0Sahoka 	}
841288addd0Sahoka }
842