xref: /netbsd-src/sys/fs/nilfs/nilfs_vfsops.c (revision b58602814f44cdb10d1ce70b9ef75bf29672fcc0)
1*b5860281Sandvar /* $NetBSD: nilfs_vfsops.c,v 1.27 2021/09/16 22:19:11 andvar Exp $ */
269a586f2Sreinoud 
369a586f2Sreinoud /*
469a586f2Sreinoud  * Copyright (c) 2008, 2009 Reinoud Zandijk
569a586f2Sreinoud  * All rights reserved.
669a586f2Sreinoud  *
769a586f2Sreinoud  * Redistribution and use in source and binary forms, with or without
869a586f2Sreinoud  * modification, are permitted provided that the following conditions
969a586f2Sreinoud  * are met:
1069a586f2Sreinoud  * 1. Redistributions of source code must retain the above copyright
1169a586f2Sreinoud  *    notice, this list of conditions and the following disclaimer.
1269a586f2Sreinoud  * 2. Redistributions in binary form must reproduce the above copyright
1369a586f2Sreinoud  *    notice, this list of conditions and the following disclaimer in the
1469a586f2Sreinoud  *    documentation and/or other materials provided with the distribution.
1569a586f2Sreinoud  *
1669a586f2Sreinoud  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1769a586f2Sreinoud  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1869a586f2Sreinoud  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1969a586f2Sreinoud  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2069a586f2Sreinoud  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2169a586f2Sreinoud  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2269a586f2Sreinoud  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2369a586f2Sreinoud  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2469a586f2Sreinoud  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2569a586f2Sreinoud  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2669a586f2Sreinoud  *
2769a586f2Sreinoud  */
2869a586f2Sreinoud 
2969a586f2Sreinoud #include <sys/cdefs.h>
3069a586f2Sreinoud #ifndef lint
31*b5860281Sandvar __KERNEL_RCSID(0, "$NetBSD: nilfs_vfsops.c,v 1.27 2021/09/16 22:19:11 andvar Exp $");
3269a586f2Sreinoud #endif /* not lint */
3369a586f2Sreinoud 
3469a586f2Sreinoud 
3569a586f2Sreinoud #if defined(_KERNEL_OPT)
3669a586f2Sreinoud #include "opt_compat_netbsd.h"
3769a586f2Sreinoud #endif
3869a586f2Sreinoud 
3969a586f2Sreinoud #include <sys/param.h>
4069a586f2Sreinoud #include <sys/systm.h>
4169a586f2Sreinoud #include <sys/sysctl.h>
4269a586f2Sreinoud #include <sys/namei.h>
4369a586f2Sreinoud #include <sys/proc.h>
4469a586f2Sreinoud #include <sys/kernel.h>
4569a586f2Sreinoud #include <sys/vnode.h>
4669a586f2Sreinoud #include <miscfs/genfs/genfs.h>
4769a586f2Sreinoud #include <miscfs/specfs/specdev.h>
4869a586f2Sreinoud #include <sys/mount.h>
4969a586f2Sreinoud #include <sys/buf.h>
5069a586f2Sreinoud #include <sys/file.h>
5169a586f2Sreinoud #include <sys/device.h>
5269a586f2Sreinoud #include <sys/disklabel.h>
5369a586f2Sreinoud #include <sys/ioctl.h>
5469a586f2Sreinoud #include <sys/malloc.h>
5569a586f2Sreinoud #include <sys/dirent.h>
5669a586f2Sreinoud #include <sys/stat.h>
5769a586f2Sreinoud #include <sys/conf.h>
5869a586f2Sreinoud #include <sys/kauth.h>
5969a586f2Sreinoud #include <sys/module.h>
6069a586f2Sreinoud 
6169a586f2Sreinoud #include <fs/nilfs/nilfs_mount.h>
6269a586f2Sreinoud #include <sys/dirhash.h>
6369a586f2Sreinoud 
6469a586f2Sreinoud 
6569a586f2Sreinoud #include "nilfs.h"
6669a586f2Sreinoud #include "nilfs_subr.h"
6769a586f2Sreinoud #include "nilfs_bswap.h"
6869a586f2Sreinoud 
6969a586f2Sreinoud MODULE(MODULE_CLASS_VFS, nilfs, NULL);
7069a586f2Sreinoud 
7169a586f2Sreinoud #define VTOI(vnode) ((struct nilfs_node *) vnode->v_data)
7269a586f2Sreinoud 
7369a586f2Sreinoud /* verbose levels of the nilfs filingsystem */
7469a586f2Sreinoud int nilfs_verbose = NILFS_DEBUGGING;
7569a586f2Sreinoud 
7669a586f2Sreinoud /* malloc regions */
7769a586f2Sreinoud MALLOC_JUSTDEFINE(M_NILFSMNT,   "NILFS mount",	"NILFS mount structures");
7869a586f2Sreinoud MALLOC_JUSTDEFINE(M_NILFSTEMP,  "NILFS temp",	"NILFS scrap space");
7969a586f2Sreinoud struct pool nilfs_node_pool;
8069a586f2Sreinoud 
8169a586f2Sreinoud /* globals */
8269a586f2Sreinoud struct _nilfs_devices nilfs_devices;
8369a586f2Sreinoud 
8469a586f2Sreinoud /* supported functions predefined */
8569a586f2Sreinoud VFS_PROTOS(nilfs);
8669a586f2Sreinoud 
8769a586f2Sreinoud 
8869a586f2Sreinoud /* --------------------------------------------------------------------- */
8969a586f2Sreinoud 
90668c7daaShannken /*
91668c7daaShannken  * Genfs interfacing
92668c7daaShannken  *
93668c7daaShannken  * static const struct genfs_ops nilfs_genfsops = {
94668c7daaShannken  * 	.gop_size = genfs_size,
95668c7daaShannken  * 		size of transfers
96668c7daaShannken  * 	.gop_alloc = nilfs_gop_alloc,
97668c7daaShannken  * 		allocate len bytes at offset
98668c7daaShannken  * 	.gop_write = genfs_gop_write,
99668c7daaShannken  * 		putpages interface code
100668c7daaShannken  * 	.gop_markupdate = nilfs_gop_markupdate,
101668c7daaShannken  * 		set update/modify flags etc.
102668c7daaShannken  * }
103668c7daaShannken  */
104668c7daaShannken 
105668c7daaShannken /*
106668c7daaShannken  * Callback from genfs to allocate len bytes at offset off; only called when
107668c7daaShannken  * filling up gaps in the allocation.
108668c7daaShannken  */
109668c7daaShannken static int
nilfs_gop_alloc(struct vnode * vp,off_t off,off_t len,int flags,kauth_cred_t cred)110668c7daaShannken nilfs_gop_alloc(struct vnode *vp, off_t off,
111668c7daaShannken     off_t len, int flags, kauth_cred_t cred)
112668c7daaShannken {
113668c7daaShannken 	DPRINTF(NOTIMPL, ("nilfs_gop_alloc not implemented\n"));
114668c7daaShannken 	DPRINTF(ALLOC, ("nilfs_gop_alloc called for %"PRIu64" bytes\n", len));
115668c7daaShannken 
116668c7daaShannken 	return 0;
117668c7daaShannken }
118668c7daaShannken 
119668c7daaShannken 
120668c7daaShannken /*
121668c7daaShannken  * callback from genfs to update our flags
122668c7daaShannken  */
123668c7daaShannken static void
nilfs_gop_markupdate(struct vnode * vp,int flags)124668c7daaShannken nilfs_gop_markupdate(struct vnode *vp, int flags)
125668c7daaShannken {
126668c7daaShannken 	struct nilfs_node *nilfs_node = VTOI(vp);
127668c7daaShannken 	u_long mask = 0;
128668c7daaShannken 
129668c7daaShannken 	if ((flags & GOP_UPDATE_ACCESSED) != 0) {
130668c7daaShannken 		mask = IN_ACCESS;
131668c7daaShannken 	}
132668c7daaShannken 	if ((flags & GOP_UPDATE_MODIFIED) != 0) {
133668c7daaShannken 		if (vp->v_type == VREG) {
134668c7daaShannken 			mask |= IN_CHANGE | IN_UPDATE;
135668c7daaShannken 		} else {
136668c7daaShannken 			mask |= IN_MODIFY;
137668c7daaShannken 		}
138668c7daaShannken 	}
139668c7daaShannken 	if (mask) {
140668c7daaShannken 		nilfs_node->i_flags |= mask;
141668c7daaShannken 	}
142668c7daaShannken }
143668c7daaShannken 
144668c7daaShannken 
145668c7daaShannken static const struct genfs_ops nilfs_genfsops = {
146668c7daaShannken 	.gop_size = genfs_size,
147668c7daaShannken 	.gop_alloc = nilfs_gop_alloc,
148668c7daaShannken 	.gop_write = genfs_gop_write_rwmap,
149668c7daaShannken 	.gop_markupdate = nilfs_gop_markupdate,
150e406c140Schs 	.gop_putrange = genfs_gop_putrange,
151668c7daaShannken };
152668c7daaShannken 
153668c7daaShannken /* --------------------------------------------------------------------- */
154668c7daaShannken 
15569a586f2Sreinoud /* predefine vnode-op list descriptor */
15669a586f2Sreinoud extern const struct vnodeopv_desc nilfs_vnodeop_opv_desc;
15769a586f2Sreinoud 
15869a586f2Sreinoud const struct vnodeopv_desc * const nilfs_vnodeopv_descs[] = {
15969a586f2Sreinoud 	&nilfs_vnodeop_opv_desc,
16069a586f2Sreinoud 	NULL,
16169a586f2Sreinoud };
16269a586f2Sreinoud 
16369a586f2Sreinoud 
16469a586f2Sreinoud /* vfsops descriptor linked in as anchor point for the filingsystem */
16569a586f2Sreinoud struct vfsops nilfs_vfsops = {
1666d285189Shannken 	.vfs_name = MOUNT_NILFS,
1676d285189Shannken 	.vfs_min_mount_data = sizeof (struct nilfs_args),
1686d285189Shannken 	.vfs_mount = nilfs_mount,
1696d285189Shannken 	.vfs_start = nilfs_start,
1706d285189Shannken 	.vfs_unmount = nilfs_unmount,
1716d285189Shannken 	.vfs_root = nilfs_root,
1726d285189Shannken 	.vfs_quotactl = (void *)eopnotsupp,
1736d285189Shannken 	.vfs_statvfs = nilfs_statvfs,
1746d285189Shannken 	.vfs_sync = nilfs_sync,
1756d285189Shannken 	.vfs_vget = nilfs_vget,
176668c7daaShannken 	.vfs_loadvnode = nilfs_loadvnode,
1776d285189Shannken 	.vfs_fhtovp = nilfs_fhtovp,
1786d285189Shannken 	.vfs_vptofh = nilfs_vptofh,
1796d285189Shannken 	.vfs_init = nilfs_init,
1806d285189Shannken 	.vfs_reinit = nilfs_reinit,
1816d285189Shannken 	.vfs_done = nilfs_done,
1826d285189Shannken 	.vfs_mountroot = nilfs_mountroot,
1836d285189Shannken 	.vfs_snapshot = nilfs_snapshot,
1846d285189Shannken 	.vfs_extattrctl = vfs_stdextattrctl,
185326db3aaShannken 	.vfs_suspendctl = genfs_suspendctl,
1866d285189Shannken 	.vfs_renamelock_enter = genfs_renamelock_enter,
1876d285189Shannken 	.vfs_renamelock_exit = genfs_renamelock_exit,
1886d285189Shannken 	.vfs_fsync = (void *)eopnotsupp,
1896d285189Shannken 	.vfs_opv_descs = nilfs_vnodeopv_descs
19069a586f2Sreinoud };
19169a586f2Sreinoud 
19269a586f2Sreinoud /* --------------------------------------------------------------------- */
19369a586f2Sreinoud 
19469a586f2Sreinoud /* file system starts here */
19569a586f2Sreinoud void
nilfs_init(void)19669a586f2Sreinoud nilfs_init(void)
19769a586f2Sreinoud {
19869a586f2Sreinoud 	size_t size;
19969a586f2Sreinoud 
20069a586f2Sreinoud 	/* setup memory types */
20169a586f2Sreinoud 	malloc_type_attach(M_NILFSMNT);
20269a586f2Sreinoud 	malloc_type_attach(M_NILFSTEMP);
20369a586f2Sreinoud 
20469a586f2Sreinoud 	/* init device lists */
20569a586f2Sreinoud 	SLIST_INIT(&nilfs_devices);
20669a586f2Sreinoud 
20769a586f2Sreinoud 	/* init node pools */
20869a586f2Sreinoud 	size = sizeof(struct nilfs_node);
20969a586f2Sreinoud 	pool_init(&nilfs_node_pool, size, 0, 0, 0,
21069a586f2Sreinoud 		"nilfs_node_pool", NULL, IPL_NONE);
21169a586f2Sreinoud }
21269a586f2Sreinoud 
21369a586f2Sreinoud 
21469a586f2Sreinoud void
nilfs_reinit(void)21569a586f2Sreinoud nilfs_reinit(void)
21669a586f2Sreinoud {
21769a586f2Sreinoud 	/* nothing to do */
21869a586f2Sreinoud }
21969a586f2Sreinoud 
22069a586f2Sreinoud 
22169a586f2Sreinoud void
nilfs_done(void)22269a586f2Sreinoud nilfs_done(void)
22369a586f2Sreinoud {
22469a586f2Sreinoud 	/* remove pools */
22569a586f2Sreinoud 	pool_destroy(&nilfs_node_pool);
22669a586f2Sreinoud 
22769a586f2Sreinoud 	malloc_type_detach(M_NILFSMNT);
22869a586f2Sreinoud 	malloc_type_detach(M_NILFSTEMP);
22969a586f2Sreinoud }
23069a586f2Sreinoud 
23169a586f2Sreinoud /*
23269a586f2Sreinoud  * If running a DEBUG kernel, provide an easy way to set the debug flags when
23369a586f2Sreinoud  * running into a problem.
23469a586f2Sreinoud  */
23569a586f2Sreinoud #define NILFS_VERBOSE_SYSCTLOPT        1
23669a586f2Sreinoud 
2379120d451Spgoyette SYSCTL_SETUP(nilfs_sysctl_setup, "nilfs sysctl")
2389120d451Spgoyette {
2399120d451Spgoyette 	const struct sysctlnode *node;
2409120d451Spgoyette 
2419120d451Spgoyette 	/*
2429120d451Spgoyette 	 * XXX the "30" below could be dynamic, thereby eliminating one
2439120d451Spgoyette 	 * more instance of the "number to vfs" mapping problem, but
2449120d451Spgoyette 	 * "30" is the order as taken from sys/mount.h
2459120d451Spgoyette 	 */
2469120d451Spgoyette 	sysctl_createv(clog, 0, NULL, &node,
2479120d451Spgoyette 		       CTLFLAG_PERMANENT,
2489120d451Spgoyette 		       CTLTYPE_NODE, "nilfs",
2499120d451Spgoyette 		       SYSCTL_DESCR("NTT's NILFSv2"),
2509120d451Spgoyette 		       NULL, 0, NULL, 0,
2519120d451Spgoyette 		       CTL_VFS, 30, CTL_EOL);
2529120d451Spgoyette #ifdef DEBUG
2539120d451Spgoyette 	sysctl_createv(clog, 0, NULL, &node,
2549120d451Spgoyette 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
2559120d451Spgoyette 		       CTLTYPE_INT, "verbose",
2569120d451Spgoyette 		       SYSCTL_DESCR("Bitmask for filesystem debugging"),
2579120d451Spgoyette 		       NULL, 0, &nilfs_verbose, 0,
2589120d451Spgoyette 		       CTL_VFS, 30, NILFS_VERBOSE_SYSCTLOPT, CTL_EOL);
2599120d451Spgoyette #endif
2609120d451Spgoyette }
2619120d451Spgoyette 
26269a586f2Sreinoud static int
nilfs_modcmd(modcmd_t cmd,void * arg)26369a586f2Sreinoud nilfs_modcmd(modcmd_t cmd, void *arg)
26469a586f2Sreinoud {
26569a586f2Sreinoud 	int error;
26669a586f2Sreinoud 
26769a586f2Sreinoud 	switch (cmd) {
26869a586f2Sreinoud 	case MODULE_CMD_INIT:
26969a586f2Sreinoud 		error = vfs_attach(&nilfs_vfsops);
27069a586f2Sreinoud 		if (error != 0)
27169a586f2Sreinoud 			break;
27269a586f2Sreinoud 		break;
27369a586f2Sreinoud 	case MODULE_CMD_FINI:
27469a586f2Sreinoud 		error = vfs_detach(&nilfs_vfsops);
27569a586f2Sreinoud 		if (error != 0)
27669a586f2Sreinoud 			break;
27769a586f2Sreinoud 		break;
27869a586f2Sreinoud 	default:
27969a586f2Sreinoud 		error = ENOTTY;
28069a586f2Sreinoud 		break;
28169a586f2Sreinoud 	}
28269a586f2Sreinoud 
28369a586f2Sreinoud 	return (error);
28469a586f2Sreinoud }
28569a586f2Sreinoud 
28669a586f2Sreinoud /* --------------------------------------------------------------------- */
28769a586f2Sreinoud 
28869a586f2Sreinoud int
nilfs_mountroot(void)28969a586f2Sreinoud nilfs_mountroot(void)
29069a586f2Sreinoud {
29169a586f2Sreinoud 	return EOPNOTSUPP;
29269a586f2Sreinoud }
29369a586f2Sreinoud 
29469a586f2Sreinoud /* --------------------------------------------------------------------- */
29569a586f2Sreinoud 
29669a586f2Sreinoud /* system nodes */
29769a586f2Sreinoud static int
nilfs_create_system_nodes(struct nilfs_device * nilfsdev)29869a586f2Sreinoud nilfs_create_system_nodes(struct nilfs_device *nilfsdev)
29969a586f2Sreinoud {
30069a586f2Sreinoud 	int error;
30169a586f2Sreinoud 
30269a586f2Sreinoud 	error = nilfs_get_node_raw(nilfsdev, NULL, NILFS_DAT_INO,
30369a586f2Sreinoud 		&nilfsdev->super_root.sr_dat, &nilfsdev->dat_node);
30469a586f2Sreinoud 	if (error)
30569a586f2Sreinoud 		goto errorout;
30669a586f2Sreinoud 
30769a586f2Sreinoud 	error = nilfs_get_node_raw(nilfsdev, NULL, NILFS_CPFILE_INO,
30869a586f2Sreinoud 		&nilfsdev->super_root.sr_cpfile, &nilfsdev->cp_node);
30969a586f2Sreinoud 	if (error)
31069a586f2Sreinoud 		goto errorout;
31169a586f2Sreinoud 
31269a586f2Sreinoud 	error = nilfs_get_node_raw(nilfsdev, NULL, NILFS_SUFILE_INO,
31369a586f2Sreinoud 		&nilfsdev->super_root.sr_sufile, &nilfsdev->su_node);
31469a586f2Sreinoud 	if (error)
31569a586f2Sreinoud 		goto errorout;
31669a586f2Sreinoud 
31769a586f2Sreinoud 	return 0;
31869a586f2Sreinoud errorout:
31969a586f2Sreinoud 	nilfs_dispose_node(&nilfsdev->dat_node);
32069a586f2Sreinoud 	nilfs_dispose_node(&nilfsdev->cp_node);
32169a586f2Sreinoud 	nilfs_dispose_node(&nilfsdev->su_node);
32269a586f2Sreinoud 
32369a586f2Sreinoud 	return error;
32469a586f2Sreinoud }
32569a586f2Sreinoud 
32669a586f2Sreinoud 
32769a586f2Sreinoud static void
nilfs_release_system_nodes(struct nilfs_device * nilfsdev)32869a586f2Sreinoud nilfs_release_system_nodes(struct nilfs_device *nilfsdev)
32969a586f2Sreinoud {
33069a586f2Sreinoud 	if (!nilfsdev)
33169a586f2Sreinoud 		return;
33269a586f2Sreinoud 	if (nilfsdev->refcnt > 0)
33369a586f2Sreinoud 		return;
33469a586f2Sreinoud 
33569a586f2Sreinoud 	nilfs_dispose_node(&nilfsdev->dat_node);
33669a586f2Sreinoud 	nilfs_dispose_node(&nilfsdev->cp_node);
33769a586f2Sreinoud 	nilfs_dispose_node(&nilfsdev->su_node);
33869a586f2Sreinoud }
33969a586f2Sreinoud 
34069a586f2Sreinoud 
34169a586f2Sreinoud /* --------------------------------------------------------------------- */
34269a586f2Sreinoud 
34369a586f2Sreinoud static int
nilfs_check_superblock_crc(struct nilfs_super_block * super)34469a586f2Sreinoud nilfs_check_superblock_crc(struct nilfs_super_block *super)
34569a586f2Sreinoud {
34669a586f2Sreinoud 	uint32_t super_crc, comp_crc;
34769a586f2Sreinoud 
34869a586f2Sreinoud 	/* check super block magic */
34969a586f2Sreinoud 	if (nilfs_rw16(super->s_magic) != NILFS_SUPER_MAGIC)
35069a586f2Sreinoud 		return 0;
35169a586f2Sreinoud 
35269a586f2Sreinoud 	/* preserve crc */
35369a586f2Sreinoud 	super_crc  = nilfs_rw32(super->s_sum);
35469a586f2Sreinoud 
35569a586f2Sreinoud 	/* calculate */
35669a586f2Sreinoud 	super->s_sum = 0;
35769a586f2Sreinoud 	comp_crc = crc32_le(nilfs_rw32(super->s_crc_seed),
35869a586f2Sreinoud 		(uint8_t *) super, nilfs_rw16(super->s_bytes));
35969a586f2Sreinoud 
36069a586f2Sreinoud 	/* restore */
36169a586f2Sreinoud 	super->s_sum = nilfs_rw32(super_crc);
36269a586f2Sreinoud 
36369a586f2Sreinoud 	/* check CRC */
36469a586f2Sreinoud 	return (super_crc == comp_crc);
36569a586f2Sreinoud }
36669a586f2Sreinoud 
36769a586f2Sreinoud 
36869a586f2Sreinoud 
36969a586f2Sreinoud static int
nilfs_read_superblock(struct nilfs_device * nilfsdev)37069a586f2Sreinoud nilfs_read_superblock(struct nilfs_device *nilfsdev)
37169a586f2Sreinoud {
37269a586f2Sreinoud 	struct nilfs_super_block *super, tmp_super;
37369a586f2Sreinoud 	struct buf *bp;
37469a586f2Sreinoud 	uint64_t sb1off, sb2off;
375bb702d32Sreinoud 	uint64_t last_cno1, last_cno2;
37669a586f2Sreinoud 	uint64_t dev_blk;
37769a586f2Sreinoud 	int dev_bsize, dev_blks;
37869a586f2Sreinoud 	int sb1ok, sb2ok, swp;
37969a586f2Sreinoud 	int error;
38069a586f2Sreinoud 
38169a586f2Sreinoud 	sb1off = NILFS_SB_OFFSET_BYTES;
38269a586f2Sreinoud 	sb2off = NILFS_SB2_OFFSET_BYTES(nilfsdev->devsize);
38369a586f2Sreinoud 
38469a586f2Sreinoud 	dev_bsize = 1 << nilfsdev->devvp->v_mount->mnt_fs_bshift;
38569a586f2Sreinoud 
38669a586f2Sreinoud 	/* read our superblock regardless of backing device blocksize */
38769a586f2Sreinoud 	dev_blk   = 0;
38869a586f2Sreinoud 	dev_blks  = (sb1off + dev_bsize -1)/dev_bsize;
3896e392401Smaxv 	error = bread(nilfsdev->devvp, dev_blk, dev_blks * dev_bsize, 0, &bp);
39069a586f2Sreinoud 	if (error) {
39169a586f2Sreinoud 		return error;
39269a586f2Sreinoud 	}
39369a586f2Sreinoud 
39469a586f2Sreinoud 	/* copy read-in super block at the offset */
39569a586f2Sreinoud 	super = &nilfsdev->super;
39669a586f2Sreinoud 	memcpy(super, (uint8_t *) bp->b_data + NILFS_SB_OFFSET_BYTES,
39769a586f2Sreinoud 		sizeof(struct nilfs_super_block));
39869a586f2Sreinoud 	brelse(bp, BC_AGE);
39969a586f2Sreinoud 
40069a586f2Sreinoud 	/* read our 2nd superblock regardless of backing device blocksize */
40169a586f2Sreinoud 	dev_blk   = sb2off / dev_bsize;
40269a586f2Sreinoud 	dev_blks  = 2;		/* assumption max one dev_bsize */
4036e392401Smaxv 	error = bread(nilfsdev->devvp, dev_blk, dev_blks * dev_bsize, 0, &bp);
40469a586f2Sreinoud 	if (error) {
40569a586f2Sreinoud 		return error;
40669a586f2Sreinoud 	}
40769a586f2Sreinoud 
40869a586f2Sreinoud 	/* copy read-in superblock2 at the offset */
40969a586f2Sreinoud 	super = &nilfsdev->super2;
41069a586f2Sreinoud 	memcpy(super, (uint8_t *) bp->b_data + NILFS_SB_OFFSET_BYTES,
41169a586f2Sreinoud 		sizeof(struct nilfs_super_block));
41269a586f2Sreinoud 	brelse(bp, BC_AGE);
41369a586f2Sreinoud 
41469a586f2Sreinoud 	sb1ok = nilfs_check_superblock_crc(&nilfsdev->super);
41569a586f2Sreinoud 	sb2ok = nilfs_check_superblock_crc(&nilfsdev->super2);
41669a586f2Sreinoud 
417bb702d32Sreinoud 	last_cno1 = nilfs_rw64(nilfsdev->super.s_last_cno);
418bb702d32Sreinoud 	last_cno2 = nilfs_rw64(nilfsdev->super2.s_last_cno);
419bb702d32Sreinoud 	swp = sb2ok && (last_cno2 > last_cno1);
42069a586f2Sreinoud 
42169a586f2Sreinoud 	if (swp) {
42269a586f2Sreinoud 		printf("nilfs warning: broken superblock, using spare\n");
42369a586f2Sreinoud 		tmp_super = nilfsdev->super2;
42469a586f2Sreinoud 		nilfsdev->super2 = nilfsdev->super;	/* why preserve? */
42569a586f2Sreinoud 		nilfsdev->super  = tmp_super;
42669a586f2Sreinoud 	}
42769a586f2Sreinoud 
42869a586f2Sreinoud 	if (!sb1ok && !sb2ok) {
42969a586f2Sreinoud 		printf("nilfs: no valid superblocks found\n");
43069a586f2Sreinoud 		return EINVAL;
43169a586f2Sreinoud 	}
43269a586f2Sreinoud 
43369a586f2Sreinoud 	return 0;
43469a586f2Sreinoud }
43569a586f2Sreinoud 
43669a586f2Sreinoud 
43769a586f2Sreinoud /* XXX NOTHING from the system nodes should need to be written here */
43869a586f2Sreinoud static void
nilfs_unmount_base(struct nilfs_device * nilfsdev)43969a586f2Sreinoud nilfs_unmount_base(struct nilfs_device *nilfsdev)
44069a586f2Sreinoud {
441c77065c1Smrg 	int error __diagused;
44269a586f2Sreinoud 
44369a586f2Sreinoud 	if (!nilfsdev)
44469a586f2Sreinoud 		return;
44569a586f2Sreinoud 
44669a586f2Sreinoud 	/* remove all our information */
44769a586f2Sreinoud 	error = vinvalbuf(nilfsdev->devvp, 0, FSCRED, curlwp, 0, 0);
44869a586f2Sreinoud 	KASSERT(error == 0);
44969a586f2Sreinoud 
45069a586f2Sreinoud 	/* release the device's system nodes */
45169a586f2Sreinoud 	nilfs_release_system_nodes(nilfsdev);
45269a586f2Sreinoud 
45369a586f2Sreinoud 	/* TODO writeout super_block? */
45469a586f2Sreinoud }
45569a586f2Sreinoud 
45669a586f2Sreinoud 
45769a586f2Sreinoud static int
nilfs_mount_base(struct nilfs_device * nilfsdev,struct mount * mp,struct nilfs_args * args)45869a586f2Sreinoud nilfs_mount_base(struct nilfs_device *nilfsdev,
45969a586f2Sreinoud 		struct mount *mp, struct nilfs_args *args)
46069a586f2Sreinoud {
46169a586f2Sreinoud 	struct lwp *l = curlwp;
46269a586f2Sreinoud 	uint64_t last_pseg, last_cno, last_seq;
46369a586f2Sreinoud 	uint32_t log_blocksize;
46469a586f2Sreinoud 	int error;
46569a586f2Sreinoud 
46669a586f2Sreinoud 	/* flush out any old buffers remaining from a previous use. */
46769a586f2Sreinoud 	if ((error = vinvalbuf(nilfsdev->devvp, V_SAVE, l->l_cred, l, 0, 0)))
46869a586f2Sreinoud 		return error;
46969a586f2Sreinoud 
47069a586f2Sreinoud 	/* read in our superblock */
47169a586f2Sreinoud 	error = nilfs_read_superblock(nilfsdev);
47269a586f2Sreinoud 	if (error) {
47369a586f2Sreinoud 		printf("nilfs_mount: can't read in super block : %d\n", error);
47469a586f2Sreinoud 		return error;
47569a586f2Sreinoud 	}
47669a586f2Sreinoud 
47769a586f2Sreinoud 	/* get our blocksize */
47869a586f2Sreinoud 	log_blocksize = nilfs_rw32(nilfsdev->super.s_log_block_size);
47969a586f2Sreinoud 	nilfsdev->blocksize   = (uint64_t) 1 << (log_blocksize + 10);
48069a586f2Sreinoud 	/* TODO check superblock's blocksize limits */
48169a586f2Sreinoud 
48269a586f2Sreinoud 	/* calculate dat structure parameters */
48369a586f2Sreinoud 	nilfs_calc_mdt_consts(nilfsdev, &nilfsdev->dat_mdt,
48469a586f2Sreinoud 			nilfs_rw16(nilfsdev->super.s_dat_entry_size));
48569a586f2Sreinoud 	nilfs_calc_mdt_consts(nilfsdev, &nilfsdev->ifile_mdt,
48669a586f2Sreinoud 			nilfs_rw16(nilfsdev->super.s_inode_size));
48769a586f2Sreinoud 
48869a586f2Sreinoud 	DPRINTF(VOLUMES, ("nilfs_mount: accepted super block\n"));
48969a586f2Sreinoud 
49069a586f2Sreinoud 	/* search for the super root and roll forward when needed */
49169a586f2Sreinoud 	nilfs_search_super_root(nilfsdev);
49269a586f2Sreinoud 
49369a586f2Sreinoud 	nilfsdev->mount_state = nilfs_rw16(nilfsdev->super.s_state);
49469a586f2Sreinoud 	if (nilfsdev->mount_state != NILFS_VALID_FS) {
49569a586f2Sreinoud 		printf("FS is seriously damaged, needs repairing\n");
49669a586f2Sreinoud 		printf("aborting mount\n");
49769a586f2Sreinoud 		return EINVAL;
49869a586f2Sreinoud 	}
49969a586f2Sreinoud 
50069a586f2Sreinoud 	/*
50169a586f2Sreinoud 	 * FS should be ok now. The superblock and the last segsum could be
50269a586f2Sreinoud 	 * updated from the repair so extract running values again.
50369a586f2Sreinoud 	 */
50469a586f2Sreinoud 	last_pseg = nilfs_rw64(nilfsdev->super.s_last_pseg); /*blknr */
50569a586f2Sreinoud 	last_cno  = nilfs_rw64(nilfsdev->super.s_last_cno);
50669a586f2Sreinoud 	last_seq  = nilfs_rw64(nilfsdev->super.s_last_seq);
50769a586f2Sreinoud 
50869a586f2Sreinoud 	nilfsdev->last_seg_seq = last_seq;
50969a586f2Sreinoud 	nilfsdev->last_seg_num = nilfs_get_segnum_of_block(nilfsdev, last_pseg);
51069a586f2Sreinoud 	nilfsdev->next_seg_num = nilfs_get_segnum_of_block(nilfsdev,
51169a586f2Sreinoud 		nilfs_rw64(nilfsdev->last_segsum.ss_next));
51269a586f2Sreinoud 	nilfsdev->last_cno     = last_cno;
51369a586f2Sreinoud 
51469a586f2Sreinoud 	DPRINTF(VOLUMES, ("nilfs_mount: accepted super root\n"));
51569a586f2Sreinoud 
51669a586f2Sreinoud 	/* create system vnodes for DAT, CP and SEGSUM */
51769a586f2Sreinoud 	error = nilfs_create_system_nodes(nilfsdev);
51869a586f2Sreinoud 	if (error)
51969a586f2Sreinoud 		nilfs_unmount_base(nilfsdev);
52069a586f2Sreinoud 	return error;
52169a586f2Sreinoud }
52269a586f2Sreinoud 
52369a586f2Sreinoud 
52469a586f2Sreinoud static void
nilfs_unmount_device(struct nilfs_device * nilfsdev)52569a586f2Sreinoud nilfs_unmount_device(struct nilfs_device *nilfsdev)
52669a586f2Sreinoud {
52769a586f2Sreinoud 	int error;
52869a586f2Sreinoud 
52969a586f2Sreinoud 	/* is there anything? */
53069a586f2Sreinoud 	if (nilfsdev == NULL)
53169a586f2Sreinoud 		return;
53269a586f2Sreinoud 
53369a586f2Sreinoud 	/* remove the device only if we're the last reference */
53469a586f2Sreinoud 	nilfsdev->refcnt--;
53569a586f2Sreinoud 	if (nilfsdev->refcnt >= 1)
53669a586f2Sreinoud 		return;
53769a586f2Sreinoud 
53869a586f2Sreinoud 	/* unmount our base */
53969a586f2Sreinoud 	nilfs_unmount_base(nilfsdev);
54069a586f2Sreinoud 
54169a586f2Sreinoud 	/* remove from our device list */
54269a586f2Sreinoud 	SLIST_REMOVE(&nilfs_devices, nilfsdev, nilfs_device, next_device);
54369a586f2Sreinoud 
54469a586f2Sreinoud 	/* close device */
54569a586f2Sreinoud 	DPRINTF(VOLUMES, ("closing device\n"));
54669a586f2Sreinoud 
54769a586f2Sreinoud 	/* remove our mount reference before closing device */
5483881f4f3Shannken 	spec_node_setmountedfs(nilfsdev->devvp, NULL);
54969a586f2Sreinoud 
55069a586f2Sreinoud 	/* devvp is still locked by us */
55169a586f2Sreinoud 	vn_lock(nilfsdev->devvp, LK_EXCLUSIVE | LK_RETRY);
55269a586f2Sreinoud 	error = VOP_CLOSE(nilfsdev->devvp, FREAD | FWRITE, NOCRED);
55369a586f2Sreinoud 	if (error)
55469a586f2Sreinoud 		printf("Error during closure of device! error %d, "
55569a586f2Sreinoud 		       "device might stay locked\n", error);
55669a586f2Sreinoud 	DPRINTF(VOLUMES, ("device close ok\n"));
55769a586f2Sreinoud 
55869a586f2Sreinoud 	/* clear our mount reference and release device node */
55969a586f2Sreinoud 	vput(nilfsdev->devvp);
56069a586f2Sreinoud 
56169a586f2Sreinoud 	/* free our device info */
56252473f33Shannken 	cv_destroy(&nilfsdev->sync_cv);
56369a586f2Sreinoud 	free(nilfsdev, M_NILFSMNT);
56469a586f2Sreinoud }
56569a586f2Sreinoud 
56669a586f2Sreinoud 
56769a586f2Sreinoud static int
nilfs_check_mounts(struct nilfs_device * nilfsdev,struct mount * mp,struct nilfs_args * args)56869a586f2Sreinoud nilfs_check_mounts(struct nilfs_device *nilfsdev, struct mount *mp,
56969a586f2Sreinoud 	struct nilfs_args *args)
57069a586f2Sreinoud {
57169a586f2Sreinoud 	struct nilfs_mount  *ump;
57269a586f2Sreinoud 	uint64_t last_cno;
57369a586f2Sreinoud 
57469a586f2Sreinoud 	/* no double-mounting of the same checkpoint */
57569a586f2Sreinoud 	STAILQ_FOREACH(ump, &nilfsdev->mounts, next_mount) {
57669a586f2Sreinoud 		if (ump->mount_args.cpno == args->cpno)
57769a586f2Sreinoud 			return EBUSY;
57869a586f2Sreinoud 	}
57969a586f2Sreinoud 
58069a586f2Sreinoud 	/* allow readonly mounts without questioning here */
58169a586f2Sreinoud 	if (mp->mnt_flag & MNT_RDONLY)
58269a586f2Sreinoud 		return 0;
58369a586f2Sreinoud 
58469a586f2Sreinoud 	/* readwrite mount you want */
58569a586f2Sreinoud 	STAILQ_FOREACH(ump, &nilfsdev->mounts, next_mount) {
58669a586f2Sreinoud 		/* only one RW mount on this device! */
58769a586f2Sreinoud 		if ((ump->vfs_mountp->mnt_flag & MNT_RDONLY)==0)
58869a586f2Sreinoud 			return EROFS;
58969a586f2Sreinoud 		/* RDONLY on last mountpoint is device busy */
59069a586f2Sreinoud 		last_cno = nilfs_rw64(ump->nilfsdev->super.s_last_cno);
59169a586f2Sreinoud 		if (ump->mount_args.cpno == last_cno)
59269a586f2Sreinoud 			return EBUSY;
59369a586f2Sreinoud 	}
59469a586f2Sreinoud 
59569a586f2Sreinoud 	/* OK for now */
59669a586f2Sreinoud 	return 0;
59769a586f2Sreinoud }
59869a586f2Sreinoud 
59969a586f2Sreinoud 
60069a586f2Sreinoud static int
nilfs_mount_device(struct vnode * devvp,struct mount * mp,struct nilfs_args * args,struct nilfs_device ** nilfsdev_p)60169a586f2Sreinoud nilfs_mount_device(struct vnode *devvp, struct mount *mp, struct nilfs_args *args,
60269a586f2Sreinoud 	struct nilfs_device **nilfsdev_p)
60369a586f2Sreinoud {
6043aa8e3d3Schristos 	uint64_t psize;
6053aa8e3d3Schristos 	unsigned secsize;
60669a586f2Sreinoud 	struct nilfs_device *nilfsdev;
60769a586f2Sreinoud 	struct lwp *l = curlwp;
60869a586f2Sreinoud 	int openflags, accessmode, error;
60969a586f2Sreinoud 
61069a586f2Sreinoud 	DPRINTF(VOLUMES, ("Mounting NILFS device\n"));
61169a586f2Sreinoud 
61269a586f2Sreinoud 	/* lookup device in our nilfs_mountpoints */
61369a586f2Sreinoud 	*nilfsdev_p = NULL;
61469a586f2Sreinoud 	SLIST_FOREACH(nilfsdev, &nilfs_devices, next_device)
61569a586f2Sreinoud 		if (nilfsdev->devvp == devvp)
61669a586f2Sreinoud 			break;
61769a586f2Sreinoud 
61869a586f2Sreinoud 	if (nilfsdev) {
61969a586f2Sreinoud 		DPRINTF(VOLUMES, ("device already mounted\n"));
62069a586f2Sreinoud 		error = nilfs_check_mounts(nilfsdev, mp, args);
62169a586f2Sreinoud 		if (error)
62269a586f2Sreinoud 			return error;
62369a586f2Sreinoud 		nilfsdev->refcnt++;
62469a586f2Sreinoud 		*nilfsdev_p = nilfsdev;
62569a586f2Sreinoud 		return 0;
62669a586f2Sreinoud 	}
62769a586f2Sreinoud 
62869a586f2Sreinoud 	DPRINTF(VOLUMES, ("no previous mounts on this device, mounting device\n"));
62969a586f2Sreinoud 
63069a586f2Sreinoud 	/* check if its a block device specified */
63169a586f2Sreinoud 	if (devvp->v_type != VBLK) {
63269a586f2Sreinoud 		vrele(devvp);
63369a586f2Sreinoud 		return ENOTBLK;
63469a586f2Sreinoud 	}
63569a586f2Sreinoud 	if (bdevsw_lookup(devvp->v_rdev) == NULL) {
63669a586f2Sreinoud 		vrele(devvp);
63769a586f2Sreinoud 		return ENXIO;
63869a586f2Sreinoud 	}
63969a586f2Sreinoud 
64069a586f2Sreinoud 	/*
64169a586f2Sreinoud 	 * If mount by non-root, then verify that user has necessary
64269a586f2Sreinoud 	 * permissions on the device.
64369a586f2Sreinoud 	 */
64469a586f2Sreinoud 	accessmode = VREAD;
64569a586f2Sreinoud 	if ((mp->mnt_flag & MNT_RDONLY) == 0)
64669a586f2Sreinoud 		accessmode |= VWRITE;
64769a586f2Sreinoud 	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
6480c9d8d15Selad 	error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
6490c9d8d15Selad 	    KAUTH_REQ_SYSTEM_MOUNT_DEVICE, mp, devvp, KAUTH_ARG(accessmode));
6501423e65bShannken 	VOP_UNLOCK(devvp);
65169a586f2Sreinoud 	if (error) {
65269a586f2Sreinoud 		vrele(devvp);
65369a586f2Sreinoud 		return error;
65469a586f2Sreinoud 	}
65569a586f2Sreinoud 
65669a586f2Sreinoud 	/*
65769a586f2Sreinoud 	 * Open device read-write; TODO how about upgrading later when needed?
65869a586f2Sreinoud 	 */
65969a586f2Sreinoud 	openflags = FREAD | FWRITE;
660d84a65ddShannken 	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
66169a586f2Sreinoud 	error = VOP_OPEN(devvp, openflags, FSCRED);
662d84a65ddShannken 	VOP_UNLOCK(devvp);
66369a586f2Sreinoud 	if (error) {
66469a586f2Sreinoud 		vrele(devvp);
66569a586f2Sreinoud 		return error;
66669a586f2Sreinoud 	}
66769a586f2Sreinoud 
66869a586f2Sreinoud 	/* opened ok, try mounting */
6693aa8e3d3Schristos 	nilfsdev = malloc(sizeof(*nilfsdev), M_NILFSMNT, M_WAITOK | M_ZERO);
67069a586f2Sreinoud 
67169a586f2Sreinoud 	/* initialise */
67269a586f2Sreinoud 	nilfsdev->refcnt        = 1;
67369a586f2Sreinoud 	nilfsdev->devvp         = devvp;
67469a586f2Sreinoud 	nilfsdev->uncomitted_bl = 0;
6754973fb4eSpgoyette 	cv_init(&nilfsdev->sync_cv, "nilfssyn");
67669a586f2Sreinoud 	STAILQ_INIT(&nilfsdev->mounts);
67769a586f2Sreinoud 
6780b69cddaSdholland 	/* register nilfs_device in list */
6790b69cddaSdholland 	SLIST_INSERT_HEAD(&nilfs_devices, nilfsdev, next_device);
6800b69cddaSdholland 
68169a586f2Sreinoud 	/* get our device's size */
6823aa8e3d3Schristos 	error = getdisksize(devvp, &psize, &secsize);
68369a586f2Sreinoud 	if (error) {
68469a586f2Sreinoud 		/* remove all our information */
68569a586f2Sreinoud 		nilfs_unmount_device(nilfsdev);
68669a586f2Sreinoud 		return EINVAL;
68769a586f2Sreinoud 	}
6883aa8e3d3Schristos 
6893aa8e3d3Schristos 	nilfsdev->devsize = psize * secsize;
69069a586f2Sreinoud 
69169a586f2Sreinoud 	/* connect to the head for most recent files XXX really pass mp and args? */
69269a586f2Sreinoud 	error = nilfs_mount_base(nilfsdev, mp, args);
69369a586f2Sreinoud 	if (error) {
69469a586f2Sreinoud 		/* remove all our information */
69569a586f2Sreinoud 		nilfs_unmount_device(nilfsdev);
69669a586f2Sreinoud 		return EINVAL;
69769a586f2Sreinoud 	}
69869a586f2Sreinoud 
69969a586f2Sreinoud 	*nilfsdev_p = nilfsdev;
70069a586f2Sreinoud 	DPRINTF(VOLUMES, ("NILFS device mounted ok\n"));
70169a586f2Sreinoud 
70269a586f2Sreinoud 	return 0;
70369a586f2Sreinoud }
70469a586f2Sreinoud 
70569a586f2Sreinoud 
70669a586f2Sreinoud static int
nilfs_mount_checkpoint(struct nilfs_mount * ump)70769a586f2Sreinoud nilfs_mount_checkpoint(struct nilfs_mount *ump)
70869a586f2Sreinoud {
70969a586f2Sreinoud 	struct nilfs_cpfile_header *cphdr;
71069a586f2Sreinoud 	struct nilfs_checkpoint *cp;
71169a586f2Sreinoud 	struct nilfs_inode  ifile_inode;
71269a586f2Sreinoud 	struct nilfs_node  *cp_node;
71369a586f2Sreinoud 	struct buf *bp;
71469a586f2Sreinoud 	uint64_t ncp, nsn, fcpno, blocknr, last_cno;
71569a586f2Sreinoud 	uint32_t off, dlen;
71669a586f2Sreinoud 	int cp_per_block, error;
71769a586f2Sreinoud 
71869a586f2Sreinoud 	DPRINTF(VOLUMES, ("mount_nilfs: trying to mount checkpoint number "
71969a586f2Sreinoud 		"%"PRIu64"\n", ump->mount_args.cpno));
72069a586f2Sreinoud 
72169a586f2Sreinoud 	cp_node = ump->nilfsdev->cp_node;
72269a586f2Sreinoud 
72369a586f2Sreinoud 	/* get cpfile header from 1st block of cp file */
7246e392401Smaxv 	error = nilfs_bread(cp_node, 0, 0, &bp);
72569a586f2Sreinoud 	if (error)
72669a586f2Sreinoud 		return error;
72769a586f2Sreinoud 	cphdr = (struct nilfs_cpfile_header *) bp->b_data;
72869a586f2Sreinoud 	ncp = nilfs_rw64(cphdr->ch_ncheckpoints);
72969a586f2Sreinoud 	nsn = nilfs_rw64(cphdr->ch_nsnapshots);
73069a586f2Sreinoud 
73169a586f2Sreinoud 	brelse(bp, BC_AGE);
73269a586f2Sreinoud 
73369a586f2Sreinoud 	DPRINTF(VOLUMES, ("mount_nilfs: checkpoint header read in\n"));
73469a586f2Sreinoud 	DPRINTF(VOLUMES, ("\tNumber of checkpoints %"PRIu64"\n", ncp));
73569a586f2Sreinoud 	DPRINTF(VOLUMES, ("\tNumber of snapshots   %"PRIu64"\n", nsn));
7369ec4136dSchristos #ifndef NILFS_DEBUG
7379ec4136dSchristos 	__USE(ncp);
7389ec4136dSchristos 	__USE(nsn);
7399ec4136dSchristos #endif
74069a586f2Sreinoud 
74169a586f2Sreinoud 	/* read in our specified checkpoint */
74269a586f2Sreinoud 	dlen = nilfs_rw16(ump->nilfsdev->super.s_checkpoint_size);
74369a586f2Sreinoud 	cp_per_block = ump->nilfsdev->blocksize / dlen;
74469a586f2Sreinoud 
74569a586f2Sreinoud 	fcpno = ump->mount_args.cpno + NILFS_CPFILE_FIRST_CHECKPOINT_OFFSET -1;
74669a586f2Sreinoud 	blocknr =  fcpno / cp_per_block;
74769a586f2Sreinoud 	off     = (fcpno % cp_per_block) * dlen;
74869a586f2Sreinoud 
7496e392401Smaxv 	error = nilfs_bread(cp_node, blocknr, 0, &bp);
75069a586f2Sreinoud 	if (error) {
75169a586f2Sreinoud 		printf("mount_nilfs: couldn't read cp block %"PRIu64"\n",
75269a586f2Sreinoud 			fcpno);
75369a586f2Sreinoud 		return EINVAL;
75469a586f2Sreinoud 	}
75569a586f2Sreinoud 
75669a586f2Sreinoud 	/* needs to be a valid checkpoint */
75769a586f2Sreinoud 	cp = (struct nilfs_checkpoint *) ((uint8_t *) bp->b_data + off);
75869a586f2Sreinoud 	if (cp->cp_flags & NILFS_CHECKPOINT_INVALID) {
75969a586f2Sreinoud 		printf("mount_nilfs: checkpoint marked invalid\n");
76069a586f2Sreinoud 		brelse(bp, BC_AGE);
76169a586f2Sreinoud 		return EINVAL;
76269a586f2Sreinoud 	}
76369a586f2Sreinoud 
76469a586f2Sreinoud 	/* is this really the checkpoint we want? */
76569a586f2Sreinoud 	if (nilfs_rw64(cp->cp_cno) != ump->mount_args.cpno) {
76669a586f2Sreinoud 		printf("mount_nilfs: checkpoint file corrupt? "
76769a586f2Sreinoud 			"expected cpno %"PRIu64", found cpno %"PRIu64"\n",
76869a586f2Sreinoud 			ump->mount_args.cpno, nilfs_rw64(cp->cp_cno));
76969a586f2Sreinoud 		brelse(bp, BC_AGE);
77069a586f2Sreinoud 		return EINVAL;
77169a586f2Sreinoud 	}
77269a586f2Sreinoud 
77369a586f2Sreinoud 	/* check if its a snapshot ! */
77469a586f2Sreinoud 	last_cno = nilfs_rw64(ump->nilfsdev->super.s_last_cno);
77569a586f2Sreinoud 	if (ump->mount_args.cpno != last_cno) {
77669a586f2Sreinoud 		/* only allow snapshots if not mounting on the last cp */
77769a586f2Sreinoud 		if ((cp->cp_flags & NILFS_CHECKPOINT_SNAPSHOT) == 0) {
77869a586f2Sreinoud 			printf( "mount_nilfs: checkpoint %"PRIu64" is not a "
77969a586f2Sreinoud 				"snapshot\n", ump->mount_args.cpno);
78069a586f2Sreinoud 			brelse(bp, BC_AGE);
78169a586f2Sreinoud 			return EINVAL;
78269a586f2Sreinoud 		}
78369a586f2Sreinoud 	}
78469a586f2Sreinoud 
78569a586f2Sreinoud 	ifile_inode = cp->cp_ifile_inode;
78669a586f2Sreinoud 	brelse(bp, BC_AGE);
78769a586f2Sreinoud 
78869a586f2Sreinoud 	/* get ifile inode */
78969a586f2Sreinoud 	error = nilfs_get_node_raw(ump->nilfsdev, NULL, NILFS_IFILE_INO,
79069a586f2Sreinoud 		&ifile_inode, &ump->ifile_node);
79169a586f2Sreinoud 	if (error) {
79269a586f2Sreinoud 		printf("mount_nilfs: can't read ifile node\n");
79369a586f2Sreinoud 		return EINVAL;
79469a586f2Sreinoud 	}
79569a586f2Sreinoud 
79669a586f2Sreinoud 	/* get root node? */
79769a586f2Sreinoud 
79869a586f2Sreinoud 	return 0;
79969a586f2Sreinoud }
80069a586f2Sreinoud 
80169a586f2Sreinoud 
80269a586f2Sreinoud static int
nilfs_stop_writing(struct nilfs_mount * ump)80369a586f2Sreinoud nilfs_stop_writing(struct nilfs_mount *ump)
80469a586f2Sreinoud {
80569a586f2Sreinoud 	/* readonly mounts won't write */
80669a586f2Sreinoud 	if (ump->vfs_mountp->mnt_flag & MNT_RDONLY)
80769a586f2Sreinoud 		return 0;
80869a586f2Sreinoud 
80969a586f2Sreinoud 	DPRINTF(CALL, ("nilfs_stop_writing called for RW mount\n"));
81069a586f2Sreinoud 
81169a586f2Sreinoud 	/* TODO writeout super_block? */
81269a586f2Sreinoud 	/* XXX no support for writing yet anyway */
81369a586f2Sreinoud 	return 0;
81469a586f2Sreinoud }
81569a586f2Sreinoud 
81669a586f2Sreinoud 
81769a586f2Sreinoud /* --------------------------------------------------------------------- */
81869a586f2Sreinoud 
81969a586f2Sreinoud 
82069a586f2Sreinoud 
82169a586f2Sreinoud #define MPFREE(a, lst) \
82269a586f2Sreinoud 	if ((a)) free((a), lst);
82369a586f2Sreinoud static void
free_nilfs_mountinfo(struct mount * mp)82469a586f2Sreinoud free_nilfs_mountinfo(struct mount *mp)
82569a586f2Sreinoud {
82669a586f2Sreinoud 	struct nilfs_mount *ump = VFSTONILFS(mp);
82769a586f2Sreinoud 
82869a586f2Sreinoud 	if (ump == NULL)
82969a586f2Sreinoud 		return;
83069a586f2Sreinoud 
83169a586f2Sreinoud 	MPFREE(ump, M_NILFSMNT);
83269a586f2Sreinoud }
83369a586f2Sreinoud #undef MPFREE
83469a586f2Sreinoud 
83569a586f2Sreinoud int
nilfs_mount(struct mount * mp,const char * path,void * data,size_t * data_len)83669a586f2Sreinoud nilfs_mount(struct mount *mp, const char *path,
83769a586f2Sreinoud 	  void *data, size_t *data_len)
83869a586f2Sreinoud {
83969a586f2Sreinoud 	struct nilfs_args   *args = data;
84069a586f2Sreinoud 	struct nilfs_device *nilfsdev;
84169a586f2Sreinoud 	struct nilfs_mount  *ump;
84269a586f2Sreinoud 	struct vnode *devvp;
843668c7daaShannken 	int error;
84469a586f2Sreinoud 
84569a586f2Sreinoud 	DPRINTF(VFSCALL, ("nilfs_mount called\n"));
84669a586f2Sreinoud 
84723f76b6dSmaxv 	if (args == NULL)
84823f76b6dSmaxv 		return EINVAL;
84969a586f2Sreinoud 	if (*data_len < sizeof *args)
85069a586f2Sreinoud 		return EINVAL;
85169a586f2Sreinoud 
85269a586f2Sreinoud 	if (mp->mnt_flag & MNT_GETARGS) {
85369a586f2Sreinoud 		/* request for the mount arguments */
85469a586f2Sreinoud 		ump = VFSTONILFS(mp);
85569a586f2Sreinoud 		if (ump == NULL)
85669a586f2Sreinoud 			return EINVAL;
85769a586f2Sreinoud 		*args = ump->mount_args;
85869a586f2Sreinoud 		*data_len = sizeof *args;
85969a586f2Sreinoud 		return 0;
86069a586f2Sreinoud 	}
86169a586f2Sreinoud 
86269a586f2Sreinoud 	/* check/translate struct version */
86369a586f2Sreinoud 	if (args->version != 1) {
86469a586f2Sreinoud 		printf("mount_nilfs: unrecognized argument structure version\n");
86569a586f2Sreinoud 		return EINVAL;
86669a586f2Sreinoud 	}
86769a586f2Sreinoud 	/* TODO sanity checking other mount arguments */
86869a586f2Sreinoud 
86969a586f2Sreinoud 	/* handle request for updating mount parameters */
87069a586f2Sreinoud 	if (mp->mnt_flag & MNT_UPDATE) {
87169a586f2Sreinoud 		/* TODO can't update my mountpoint yet */
87269a586f2Sreinoud 		return EOPNOTSUPP;
87369a586f2Sreinoud 	}
87469a586f2Sreinoud 
87569a586f2Sreinoud 	/* lookup name to get its vnode */
87669a586f2Sreinoud 	error = namei_simple_user(args->fspec, NSM_FOLLOW_NOEMULROOT, &devvp);
87769a586f2Sreinoud 	if (error)
87869a586f2Sreinoud 		return error;
87969a586f2Sreinoud 
88069a586f2Sreinoud #ifdef DEBUG
88169a586f2Sreinoud 	if (nilfs_verbose & NILFS_DEBUG_VOLUMES)
88269a586f2Sreinoud 		vprint("NILFS mount, trying to mount \n", devvp);
88369a586f2Sreinoud #endif
88469a586f2Sreinoud 
88569a586f2Sreinoud 	error = nilfs_mount_device(devvp, mp, args, &nilfsdev);
88640e39321Smaxv 	if (error)
88769a586f2Sreinoud 		return error;
88869a586f2Sreinoud 
88969a586f2Sreinoud 	/*
89069a586f2Sreinoud 	 * Create a nilfs_mount on the specified checkpoint. Note that only
89169a586f2Sreinoud 	 * ONE RW mount point can exist and it needs to have the highest
89269a586f2Sreinoud 	 * checkpoint nr. If mounting RW and its not on the last checkpoint we
89369a586f2Sreinoud 	 * need to invalidate all checkpoints that follow!!! This is an
89469a586f2Sreinoud 	 * advanced option.
89569a586f2Sreinoud 	 */
89669a586f2Sreinoud 
89769a586f2Sreinoud 	/* setup basic mountpoint structure */
89869a586f2Sreinoud 	mp->mnt_data = NULL;
89969a586f2Sreinoud 	mp->mnt_stat.f_fsidx.__fsid_val[0] = (uint32_t) devvp->v_rdev;
90069a586f2Sreinoud 	mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_NILFS);
90169a586f2Sreinoud 	mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
90269a586f2Sreinoud 	mp->mnt_stat.f_namemax = NILFS_NAME_LEN;
90369a586f2Sreinoud 	mp->mnt_flag  |= MNT_LOCAL;
90469a586f2Sreinoud 
90569a586f2Sreinoud 	/* XXX can't enable MPSAFE yet since genfs barfs on bad CV */
90669a586f2Sreinoud 	// mp->mnt_iflag |= IMNT_MPSAFE;
90769a586f2Sreinoud 
90869a586f2Sreinoud 	/* set our dev and fs units */
90969a586f2Sreinoud 	mp->mnt_dev_bshift = nilfs_rw32(nilfsdev->super.s_log_block_size) + 10;
91069a586f2Sreinoud 	mp->mnt_fs_bshift  = mp->mnt_dev_bshift;
91169a586f2Sreinoud 
91269a586f2Sreinoud 	/* allocate nilfs part of mount structure; malloc always succeeds */
91369a586f2Sreinoud 	ump = malloc(sizeof(struct nilfs_mount), M_NILFSMNT, M_WAITOK | M_ZERO);
91469a586f2Sreinoud 
91569a586f2Sreinoud 	/* set up linkage */
91669a586f2Sreinoud 	mp->mnt_data    =  ump;
91769a586f2Sreinoud 	ump->vfs_mountp =  mp;
91869a586f2Sreinoud 	ump->nilfsdev   =  nilfsdev;
91969a586f2Sreinoud 
92069a586f2Sreinoud #if 0
92169a586f2Sreinoud #ifndef NILFS_READWRITE
92269a586f2Sreinoud 	/* force read-only for now */
92369a586f2Sreinoud 	if ((mp->mnt_flag & MNT_RDONLY) == 0) {
92469a586f2Sreinoud 		printf( "Enable kernel/module option NILFS_READWRITE for "
92569a586f2Sreinoud 			"writing, downgrading access to read-only\n");
92669a586f2Sreinoud 		mp->mnt_flag |= MNT_RDONLY;
92769a586f2Sreinoud 	}
92869a586f2Sreinoud #endif
92969a586f2Sreinoud #endif
93069a586f2Sreinoud 
93169a586f2Sreinoud 	/* DONT register our nilfs mountpoint on our vfs mountpoint */
9323881f4f3Shannken 	spec_node_setmountedfs(devvp, NULL);
93369a586f2Sreinoud #if 0
9343881f4f3Shannken 	if (spec_node_getmountedfs(devvp) == NULL)
9353881f4f3Shannken 		spec_node_setmountedfs(devvp, mp);
93669a586f2Sreinoud 	if ((mp->mnt_flag & MNT_RDONLY) == 0)
9373881f4f3Shannken 		spec_node_setmountedfs(devvp, mp);
93869a586f2Sreinoud #endif
93969a586f2Sreinoud 
94069a586f2Sreinoud 	/* add our mountpoint */
94169a586f2Sreinoud 	STAILQ_INSERT_TAIL(&nilfsdev->mounts, ump, next_mount);
94269a586f2Sreinoud 
94369a586f2Sreinoud 	/* get our selected checkpoint */
94469a586f2Sreinoud 	if (args->cpno == 0)
94569a586f2Sreinoud 		args->cpno = nilfsdev->last_cno;
94669a586f2Sreinoud 	args->cpno = MIN(args->cpno, nilfsdev->last_cno);
94769a586f2Sreinoud 
94869a586f2Sreinoud 	/* setting up other parameters */
94969a586f2Sreinoud 	ump->mount_args = *args;
95069a586f2Sreinoud 	error = nilfs_mount_checkpoint(ump);
95169a586f2Sreinoud 	if (error) {
95269a586f2Sreinoud 		nilfs_unmount(mp, MNT_FORCE);
95369a586f2Sreinoud 		return error;
95469a586f2Sreinoud 	}
95569a586f2Sreinoud 
95669a586f2Sreinoud 	/* set VFS info */
95769a586f2Sreinoud 	error = set_statvfs_info(path, UIO_USERSPACE, args->fspec, UIO_USERSPACE,
95869a586f2Sreinoud 			mp->mnt_op->vfs_name, mp, curlwp);
95969a586f2Sreinoud 	if (error) {
96069a586f2Sreinoud 		nilfs_unmount(mp, MNT_FORCE);
96169a586f2Sreinoud 		return error;
96269a586f2Sreinoud 	}
96369a586f2Sreinoud 
96469a586f2Sreinoud 	/* successfully mounted */
965*b5860281Sandvar 	DPRINTF(VOLUMES, ("nilfs_mount() successful\n"));
96669a586f2Sreinoud 
96769a586f2Sreinoud 	return 0;
96869a586f2Sreinoud }
96969a586f2Sreinoud 
97069a586f2Sreinoud /* --------------------------------------------------------------------- */
97169a586f2Sreinoud 
97269a586f2Sreinoud 
97369a586f2Sreinoud /* remove our mountpoint and if its the last reference, remove our device */
97469a586f2Sreinoud int
nilfs_unmount(struct mount * mp,int mntflags)97569a586f2Sreinoud nilfs_unmount(struct mount *mp, int mntflags)
97669a586f2Sreinoud {
97769a586f2Sreinoud 	struct nilfs_device *nilfsdev;
97869a586f2Sreinoud 	struct nilfs_mount  *ump;
97969a586f2Sreinoud 	int error, flags;
98069a586f2Sreinoud 
98169a586f2Sreinoud 	DPRINTF(VFSCALL, ("nilfs_umount called\n"));
98269a586f2Sreinoud 
98369a586f2Sreinoud 	ump = VFSTONILFS(mp);
98469a586f2Sreinoud 	if (!ump)
98569a586f2Sreinoud 		panic("NILFS unmount: empty ump\n");
98669a586f2Sreinoud 	nilfsdev = ump->nilfsdev;
98769a586f2Sreinoud 
98869a586f2Sreinoud 	/*
98952473f33Shannken 	 * Flush all nodes associated to this mountpoint.
99069a586f2Sreinoud 	 */
99169a586f2Sreinoud 	flags = (mntflags & MNT_FORCE) ? FORCECLOSE : 0;
99252473f33Shannken 	if ((error = vflush(mp, NULLVP, flags)) != 0)
99369a586f2Sreinoud 		return error;
99469a586f2Sreinoud 
99569a586f2Sreinoud 	/* if we're the write mount, we ought to close the writing session */
99669a586f2Sreinoud 	error = nilfs_stop_writing(ump);
99769a586f2Sreinoud 	if (error)
99869a586f2Sreinoud 		return error;
99969a586f2Sreinoud 
100069a586f2Sreinoud 	nilfs_dispose_node(&ump->ifile_node);
100169a586f2Sreinoud 
100269a586f2Sreinoud 	/* remove our mount point */
100369a586f2Sreinoud 	STAILQ_REMOVE(&nilfsdev->mounts, ump, nilfs_mount, next_mount);
100469a586f2Sreinoud 	free_nilfs_mountinfo(mp);
100569a586f2Sreinoud 
100669a586f2Sreinoud 	/* free ump struct references */
100769a586f2Sreinoud 	mp->mnt_data = NULL;
100869a586f2Sreinoud 	mp->mnt_flag &= ~MNT_LOCAL;
100969a586f2Sreinoud 
101069a586f2Sreinoud 	/* unmount the device itself when we're the last one */
101169a586f2Sreinoud 	nilfs_unmount_device(nilfsdev);
101269a586f2Sreinoud 
101369a586f2Sreinoud 	DPRINTF(VOLUMES, ("Fin unmount\n"));
101469a586f2Sreinoud 	return error;
101569a586f2Sreinoud }
101669a586f2Sreinoud 
101769a586f2Sreinoud /* --------------------------------------------------------------------- */
101869a586f2Sreinoud 
101969a586f2Sreinoud int
nilfs_start(struct mount * mp,int flags)102069a586f2Sreinoud nilfs_start(struct mount *mp, int flags)
102169a586f2Sreinoud {
102269a586f2Sreinoud 	/* do we have to do something here? */
102369a586f2Sreinoud 	return 0;
102469a586f2Sreinoud }
102569a586f2Sreinoud 
102669a586f2Sreinoud /* --------------------------------------------------------------------- */
102769a586f2Sreinoud 
102869a586f2Sreinoud int
nilfs_root(struct mount * mp,int lktype,struct vnode ** vpp)1029c2e9cb94Sad nilfs_root(struct mount *mp, int lktype, struct vnode **vpp)
103069a586f2Sreinoud {
1031668c7daaShannken 	uint64_t ino = NILFS_ROOT_INO;
103269a586f2Sreinoud 	int error;
103369a586f2Sreinoud 
103469a586f2Sreinoud 	DPRINTF(NODE, ("nilfs_root called\n"));
103569a586f2Sreinoud 
1036668c7daaShannken 	error = vcache_get(mp, &ino, sizeof(ino), vpp);
103752473f33Shannken 	if (error == 0) {
1038c2e9cb94Sad 		error = vn_lock(*vpp, lktype);
103952473f33Shannken 		if (error) {
104052473f33Shannken 			vrele(*vpp);
104152473f33Shannken 			*vpp = NULL;
104252473f33Shannken 			return error;
104369a586f2Sreinoud 		}
104452473f33Shannken 	}
104552473f33Shannken 	KASSERT(error != 0 || ((*vpp)->v_vflag & VV_ROOT));
104669a586f2Sreinoud 
104769a586f2Sreinoud 	DPRINTF(NODE, ("nilfs_root finished\n"));
104869a586f2Sreinoud 	return error;
104969a586f2Sreinoud }
105069a586f2Sreinoud 
105169a586f2Sreinoud /* --------------------------------------------------------------------- */
105269a586f2Sreinoud 
105369a586f2Sreinoud int
nilfs_statvfs(struct mount * mp,struct statvfs * sbp)105469a586f2Sreinoud nilfs_statvfs(struct mount *mp, struct statvfs *sbp)
105569a586f2Sreinoud {
105669a586f2Sreinoud 	struct nilfs_mount *ump = VFSTONILFS(mp);
105769a586f2Sreinoud 	uint32_t blocksize;
105869a586f2Sreinoud 
105969a586f2Sreinoud 	DPRINTF(VFSCALL, ("nilfs_statvfs called\n"));
106069a586f2Sreinoud 
106169a586f2Sreinoud 	blocksize = ump->nilfsdev->blocksize;
106269a586f2Sreinoud 	sbp->f_flag   = mp->mnt_flag;
106369a586f2Sreinoud 	sbp->f_bsize  = blocksize;
106469a586f2Sreinoud 	sbp->f_frsize = blocksize;
106569a586f2Sreinoud 	sbp->f_iosize = blocksize;
106669a586f2Sreinoud 
106769a586f2Sreinoud 	copy_statvfs_info(sbp, mp);
106869a586f2Sreinoud 	return 0;
106969a586f2Sreinoud }
107069a586f2Sreinoud 
107169a586f2Sreinoud /* --------------------------------------------------------------------- */
107269a586f2Sreinoud 
107369a586f2Sreinoud int
nilfs_sync(struct mount * mp,int waitfor,kauth_cred_t cred)107469a586f2Sreinoud nilfs_sync(struct mount *mp, int waitfor, kauth_cred_t cred)
107569a586f2Sreinoud {
107669a586f2Sreinoud //	struct nilfs_mount *ump = VFSTONILFS(mp);
107769a586f2Sreinoud 
107869a586f2Sreinoud 	DPRINTF(VFSCALL, ("nilfs_sync called\n"));
107969a586f2Sreinoud 	/* if called when mounted readonly, just ignore */
108069a586f2Sreinoud 	if (mp->mnt_flag & MNT_RDONLY)
108169a586f2Sreinoud 		return 0;
108269a586f2Sreinoud 
108369a586f2Sreinoud 	DPRINTF(VFSCALL, ("end of nilfs_sync()\n"));
108469a586f2Sreinoud 
108569a586f2Sreinoud 	return 0;
108669a586f2Sreinoud }
108769a586f2Sreinoud 
108869a586f2Sreinoud /* --------------------------------------------------------------------- */
108969a586f2Sreinoud 
109069a586f2Sreinoud /*
109169a586f2Sreinoud  * Get vnode for the file system type specific file id ino for the fs. Its
109269a586f2Sreinoud  * used for reference to files by unique ID and for NFSv3.
109369a586f2Sreinoud  * (optional) TODO lookup why some sources state NFSv3
109469a586f2Sreinoud  */
109569a586f2Sreinoud int
nilfs_vget(struct mount * mp,ino_t ino,int lktype,struct vnode ** vpp)1096c2e9cb94Sad nilfs_vget(struct mount *mp, ino_t ino, int lktype,
109769a586f2Sreinoud     struct vnode **vpp)
109869a586f2Sreinoud {
109969a586f2Sreinoud 	DPRINTF(NOTIMPL, ("nilfs_vget called\n"));
110069a586f2Sreinoud 	return EOPNOTSUPP;
110169a586f2Sreinoud }
110269a586f2Sreinoud 
110369a586f2Sreinoud /* --------------------------------------------------------------------- */
110469a586f2Sreinoud 
110569a586f2Sreinoud /*
1106668c7daaShannken  * Read an inode from disk and initialize this vnode / inode pair.
1107668c7daaShannken  * Caller assures no other thread will try to load this inode.
1108668c7daaShannken  */
1109668c7daaShannken int
nilfs_loadvnode(struct mount * mp,struct vnode * vp,const void * key,size_t key_len,const void ** new_key)1110668c7daaShannken nilfs_loadvnode(struct mount *mp, struct vnode *vp,
1111668c7daaShannken     const void *key, size_t key_len, const void **new_key)
1112668c7daaShannken {
1113668c7daaShannken 	uint64_t ino;
1114668c7daaShannken 	struct nilfs_device *nilfsdev;
1115668c7daaShannken 	struct nilfs_inode   inode, *entry;
1116668c7daaShannken 	struct nilfs_node *node;
1117668c7daaShannken 	struct nilfs_mount *ump;
1118668c7daaShannken 	struct buf *bp;
1119668c7daaShannken 	uint64_t ivblocknr;
1120668c7daaShannken 	uint32_t entry_in_block;
1121668c7daaShannken 	int error;
1122668c7daaShannken 	extern int (**nilfs_vnodeop_p)(void *);
1123668c7daaShannken 
1124668c7daaShannken 	KASSERT(key_len == sizeof(ino));
1125668c7daaShannken 	memcpy(&ino, key, key_len);
1126668c7daaShannken 
1127668c7daaShannken 	ump = VFSTONILFS(mp);
1128668c7daaShannken 
1129668c7daaShannken 	/* create new inode; XXX check could be handier */
1130668c7daaShannken 	if ((ino < NILFS_USER_INO) && (ino != NILFS_ROOT_INO)) {
1131668c7daaShannken 		printf("nilfs_get_node: system ino %"PRIu64" not in mount "
1132668c7daaShannken 			"point!\n", ino);
1133668c7daaShannken 		return ENOENT;
1134668c7daaShannken 	}
1135668c7daaShannken 
1136668c7daaShannken 	/* lookup inode in the ifile */
1137668c7daaShannken 	DPRINTF(NODE, ("lookup ino %"PRIu64"\n", ino));
1138668c7daaShannken 
1139668c7daaShannken 	/* lookup inode structure in mountpoints ifile */
1140668c7daaShannken 	nilfsdev = ump->nilfsdev;
1141668c7daaShannken 	nilfs_mdt_trans(&nilfsdev->ifile_mdt, ino, &ivblocknr, &entry_in_block);
1142668c7daaShannken 
11436e392401Smaxv 	error = nilfs_bread(ump->ifile_node, ivblocknr, 0, &bp);
1144668c7daaShannken 	if (error)
1145668c7daaShannken 		return ENOENT;
1146668c7daaShannken 
1147668c7daaShannken 	/* get inode entry */
1148668c7daaShannken 	entry =  (struct nilfs_inode *) bp->b_data + entry_in_block;
1149668c7daaShannken 	inode = *entry;
1150668c7daaShannken 	brelse(bp, BC_AGE);
1151668c7daaShannken 
1152668c7daaShannken 	/* get node */
1153668c7daaShannken 	error = nilfs_get_node_raw(ump->nilfsdev, ump, ino, &inode, &node);
1154668c7daaShannken 	if (error)
1155668c7daaShannken 		return error;
1156668c7daaShannken 
1157668c7daaShannken 	vp->v_type = IFTOVT(inode.i_mode);
1158668c7daaShannken 	switch (vp->v_type) {
1159668c7daaShannken 	case VREG:
1160668c7daaShannken 	case VDIR:
1161668c7daaShannken 	case VLNK:
1162668c7daaShannken 		break;
1163668c7daaShannken 	/* other types not yet supported. */
1164668c7daaShannken 	default:
1165668c7daaShannken 		vp->v_type = VNON;
1166668c7daaShannken 		nilfs_dispose_node(&node);
1167668c7daaShannken 		return ENXIO;
1168668c7daaShannken 	}
1169668c7daaShannken 
1170668c7daaShannken 	vp->v_tag = VT_NILFS;
1171668c7daaShannken 	vp->v_op = nilfs_vnodeop_p;
1172668c7daaShannken 	vp->v_data = node;
1173668c7daaShannken 	node->vnode = vp;
1174668c7daaShannken 
1175668c7daaShannken 	/* initialise genfs */
1176668c7daaShannken 	genfs_node_init(vp, &nilfs_genfsops);
1177668c7daaShannken 
1178668c7daaShannken 	/* check if we're fetching the root */
1179668c7daaShannken 	if (ino == NILFS_ROOT_INO)
1180668c7daaShannken 		vp->v_vflag |= VV_ROOT;
1181668c7daaShannken 
1182668c7daaShannken 	uvm_vnp_setsize(vp, nilfs_rw64(inode.i_size));
1183668c7daaShannken 	*new_key = &node->ino;
1184668c7daaShannken 
1185668c7daaShannken 	return 0;
1186668c7daaShannken 
1187668c7daaShannken }
1188668c7daaShannken 
1189668c7daaShannken /* --------------------------------------------------------------------- */
1190668c7daaShannken 
1191668c7daaShannken /*
119269a586f2Sreinoud  * Lookup vnode for file handle specified
119369a586f2Sreinoud  */
119469a586f2Sreinoud int
nilfs_fhtovp(struct mount * mp,struct fid * fhp,int lktype,struct vnode ** vpp)1195c2e9cb94Sad nilfs_fhtovp(struct mount *mp, struct fid *fhp, int lktype,
119669a586f2Sreinoud     struct vnode **vpp)
119769a586f2Sreinoud {
119869a586f2Sreinoud 	DPRINTF(NOTIMPL, ("nilfs_fhtovp called\n"));
119969a586f2Sreinoud 	return EOPNOTSUPP;
120069a586f2Sreinoud }
120169a586f2Sreinoud 
120269a586f2Sreinoud /* --------------------------------------------------------------------- */
120369a586f2Sreinoud 
120469a586f2Sreinoud /*
120569a586f2Sreinoud  * Create an unique file handle. Its structure is opaque and won't be used by
120669a586f2Sreinoud  * other subsystems. It should uniquely identify the file in the filingsystem
120769a586f2Sreinoud  * and enough information to know if a file has been removed and/or resources
120869a586f2Sreinoud  * have been recycled.
120969a586f2Sreinoud  */
121069a586f2Sreinoud int
nilfs_vptofh(struct vnode * vp,struct fid * fid,size_t * fh_size)121169a586f2Sreinoud nilfs_vptofh(struct vnode *vp, struct fid *fid,
121269a586f2Sreinoud     size_t *fh_size)
121369a586f2Sreinoud {
121469a586f2Sreinoud 	DPRINTF(NOTIMPL, ("nilfs_vptofh called\n"));
121569a586f2Sreinoud 	return EOPNOTSUPP;
121669a586f2Sreinoud }
121769a586f2Sreinoud 
121869a586f2Sreinoud /* --------------------------------------------------------------------- */
121969a586f2Sreinoud 
122069a586f2Sreinoud /*
122169a586f2Sreinoud  * Create a file system snapshot at the specified timestamp.
122269a586f2Sreinoud  */
122369a586f2Sreinoud int
nilfs_snapshot(struct mount * mp,struct vnode * vp,struct timespec * tm)122469a586f2Sreinoud nilfs_snapshot(struct mount *mp, struct vnode *vp,
122569a586f2Sreinoud     struct timespec *tm)
122669a586f2Sreinoud {
122769a586f2Sreinoud 	DPRINTF(NOTIMPL, ("nilfs_snapshot called\n"));
122869a586f2Sreinoud 	return EOPNOTSUPP;
122969a586f2Sreinoud }
123069a586f2Sreinoud 
123169a586f2Sreinoud /* --------------------------------------------------------------------- */
1232