1235537Sgber/*-
2235537Sgber * Copyright (c) 2010-2012 Semihalf.
3235537Sgber * All rights reserved.
4235537Sgber *
5235537Sgber * Redistribution and use in source and binary forms, with or without
6235537Sgber * modification, are permitted provided that the following conditions
7235537Sgber * are met:
8235537Sgber * 1. Redistributions of source code must retain the above copyright
9235537Sgber *    notice, this list of conditions and the following disclaimer.
10235537Sgber * 2. Redistributions in binary form must reproduce the above copyright
11235537Sgber *    notice, this list of conditions and the following disclaimer in the
12235537Sgber *    documentation and/or other materials provided with the distribution.
13235537Sgber *
14235537Sgber * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15235537Sgber * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16235537Sgber * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17235537Sgber * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18235537Sgber * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19235537Sgber * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20235537Sgber * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21235537Sgber * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22235537Sgber * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23235537Sgber * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24235537Sgber * SUCH DAMAGE.
25235537Sgber */
26235537Sgber
27235537Sgber#include <sys/cdefs.h>
28235537Sgber__FBSDID("$FreeBSD$");
29235537Sgber
30235537Sgber#include <sys/param.h>
31235537Sgber#include <sys/systm.h>
32235537Sgber#include <sys/conf.h>
33235537Sgber#include <sys/kernel.h>
34235537Sgber#include <sys/lock.h>
35235537Sgber#include <sys/malloc.h>
36235537Sgber#include <sys/mount.h>
37235537Sgber#include <sys/mutex.h>
38235537Sgber#include <sys/namei.h>
39235537Sgber#include <sys/sysctl.h>
40235537Sgber#include <sys/vnode.h>
41235537Sgber#include <sys/buf.h>
42235537Sgber#include <sys/bio.h>
43235537Sgber
44235537Sgber#include <vm/vm.h>
45235537Sgber#include <vm/vm_param.h>
46235537Sgber#include <vm/vm_kern.h>
47235537Sgber#include <vm/vm_page.h>
48235537Sgber
49235537Sgber#include <fs/nandfs/nandfs_mount.h>
50235537Sgber#include <fs/nandfs/nandfs.h>
51235537Sgber#include <fs/nandfs/nandfs_subr.h>
52235537Sgber
53235537Sgberint
54235537Sgbernandfs_node_create(struct nandfsmount *nmp, struct nandfs_node **node,
55235537Sgber    uint16_t mode)
56235537Sgber{
57235537Sgber	struct nandfs_alloc_request req;
58235537Sgber	struct nandfs_device *nandfsdev;
59235537Sgber	struct nandfs_mdt *mdt;
60235537Sgber	struct nandfs_node *ifile;
61235537Sgber	struct nandfs_inode *inode;
62235537Sgber	struct vnode *vp;
63235537Sgber	uint32_t entry;
64235537Sgber	int error = 0;
65235537Sgber
66235537Sgber	nandfsdev = nmp->nm_nandfsdev;
67235537Sgber	mdt = &nandfsdev->nd_ifile_mdt;
68235537Sgber	ifile = nmp->nm_ifile_node;
69235537Sgber	vp = NTOV(ifile);
70235537Sgber
71235537Sgber	VOP_LOCK(vp, LK_EXCLUSIVE);
72235537Sgber	/* Allocate new inode in ifile */
73235537Sgber	req.entrynum = nandfsdev->nd_last_ino + 1;
74235537Sgber	error = nandfs_find_free_entry(mdt, ifile, &req);
75235537Sgber	if (error) {
76235537Sgber		VOP_UNLOCK(vp, 0);
77235537Sgber		return (error);
78235537Sgber	}
79235537Sgber
80235537Sgber	error = nandfs_get_entry_block(mdt, ifile, &req, &entry, 1);
81235537Sgber	if (error) {
82235537Sgber		VOP_UNLOCK(vp, 0);
83235537Sgber		return (error);
84235537Sgber	}
85235537Sgber
86235537Sgber	/* Inode initialization */
87235537Sgber	inode = ((struct nandfs_inode *) req.bp_entry->b_data) + entry;
88235537Sgber	nandfs_inode_init(inode, mode);
89235537Sgber
90235537Sgber	error = nandfs_alloc_entry(mdt, &req);
91235537Sgber	if (error) {
92235537Sgber		VOP_UNLOCK(vp, 0);
93235537Sgber		return (error);
94235537Sgber	}
95235537Sgber
96235537Sgber	VOP_UNLOCK(vp, 0);
97235537Sgber
98235537Sgber	nandfsdev->nd_last_ino = req.entrynum;
99235537Sgber	error = nandfs_get_node(nmp, req.entrynum, node);
100235537Sgber	DPRINTF(IFILE, ("%s: node: %p ino: %#jx\n",
101235537Sgber	    __func__, node, (uintmax_t)((*node)->nn_ino)));
102235537Sgber
103235537Sgber	return (error);
104235537Sgber}
105235537Sgber
106235537Sgberint
107235537Sgbernandfs_node_destroy(struct nandfs_node *node)
108235537Sgber{
109235537Sgber	struct nandfs_alloc_request req;
110235537Sgber	struct nandfsmount *nmp;
111235537Sgber	struct nandfs_mdt *mdt;
112235537Sgber	struct nandfs_node *ifile;
113235537Sgber	struct vnode *vp;
114235537Sgber	int error = 0;
115235537Sgber
116235537Sgber	nmp = node->nn_nmp;
117235537Sgber	req.entrynum = node->nn_ino;
118235537Sgber	mdt = &nmp->nm_nandfsdev->nd_ifile_mdt;
119235537Sgber	ifile = nmp->nm_ifile_node;
120235537Sgber	vp = NTOV(ifile);
121235537Sgber
122235537Sgber	DPRINTF(IFILE, ("%s: destroy node: %p ino: %#jx\n",
123235537Sgber	    __func__, node, (uintmax_t)node->nn_ino));
124235537Sgber	VOP_LOCK(vp, LK_EXCLUSIVE);
125235537Sgber
126235537Sgber	error = nandfs_find_entry(mdt, ifile, &req);
127235537Sgber	if (error) {
128235537Sgber		nandfs_error("%s: finding entry error:%d node %p(%jx)",
129235537Sgber		    __func__, error, node, node->nn_ino);
130235537Sgber		VOP_UNLOCK(vp, 0);
131235537Sgber		return (error);
132235537Sgber	}
133235537Sgber
134235537Sgber	nandfs_inode_destroy(&node->nn_inode);
135235537Sgber
136235537Sgber	error = nandfs_free_entry(mdt, &req);
137235537Sgber	if (error) {
138235537Sgber		nandfs_error("%s: freing entry error:%d node %p(%jx)",
139235537Sgber		    __func__, error, node, node->nn_ino);
140235537Sgber		VOP_UNLOCK(vp, 0);
141235537Sgber		return (error);
142235537Sgber	}
143235537Sgber
144235537Sgber	VOP_UNLOCK(vp, 0);
145235537Sgber	DPRINTF(IFILE, ("%s: freed node %p ino %#jx\n",
146235537Sgber	    __func__, node, (uintmax_t)node->nn_ino));
147235537Sgber	return (error);
148235537Sgber}
149235537Sgber
150235537Sgberint
151235537Sgbernandfs_node_update(struct nandfs_node *node)
152235537Sgber{
153235537Sgber	struct nandfs_alloc_request req;
154235537Sgber	struct nandfsmount *nmp;
155235537Sgber	struct nandfs_mdt *mdt;
156235537Sgber	struct nandfs_node *ifile;
157235537Sgber	struct nandfs_inode *inode;
158235537Sgber	uint32_t index;
159235537Sgber	int error = 0;
160235537Sgber
161235537Sgber	nmp = node->nn_nmp;
162235537Sgber	ifile = nmp->nm_ifile_node;
163235537Sgber	ASSERT_VOP_LOCKED(NTOV(ifile), __func__);
164235537Sgber
165235537Sgber	req.entrynum = node->nn_ino;
166235537Sgber	mdt = &nmp->nm_nandfsdev->nd_ifile_mdt;
167235537Sgber
168235537Sgber	DPRINTF(IFILE, ("%s: node:%p ino:%#jx\n",
169235537Sgber	    __func__, &node->nn_inode, (uintmax_t)node->nn_ino));
170235537Sgber
171235537Sgber	error = nandfs_get_entry_block(mdt, ifile, &req, &index, 0);
172235537Sgber	if (error) {
173235537Sgber		printf("nandfs_get_entry_block returned with ERROR=%d\n",
174235537Sgber		    error);
175235537Sgber		return (error);
176235537Sgber	}
177235537Sgber
178235537Sgber	inode = ((struct nandfs_inode *) req.bp_entry->b_data) + index;
179235537Sgber	memcpy(inode, &node->nn_inode, sizeof(*inode));
180235537Sgber	error = nandfs_dirty_buf(req.bp_entry, 0);
181235537Sgber
182235537Sgber	return (error);
183235537Sgber}
184235537Sgber
185235537Sgberint
186235537Sgbernandfs_get_node_entry(struct nandfsmount *nmp, struct nandfs_inode **inode,
187235537Sgber    uint64_t ino, struct buf **bp)
188235537Sgber{
189235537Sgber	struct nandfs_alloc_request req;
190235537Sgber	struct nandfs_mdt *mdt;
191235537Sgber	struct nandfs_node *ifile;
192235537Sgber	struct vnode *vp;
193235537Sgber	uint32_t index;
194235537Sgber	int error = 0;
195235537Sgber
196235537Sgber	req.entrynum = ino;
197235537Sgber	mdt = &nmp->nm_nandfsdev->nd_ifile_mdt;
198235537Sgber	ifile = nmp->nm_ifile_node;
199235537Sgber	vp = NTOV(ifile);
200235537Sgber
201235537Sgber	VOP_LOCK(vp, LK_EXCLUSIVE);
202235537Sgber	error = nandfs_get_entry_block(mdt, ifile, &req, &index, 0);
203235537Sgber	if (error) {
204235537Sgber		VOP_UNLOCK(vp, 0);
205235537Sgber		return (error);
206235537Sgber	}
207235537Sgber
208235537Sgber	*inode = ((struct nandfs_inode *) req.bp_entry->b_data) + index;
209235537Sgber	*bp = req.bp_entry;
210235537Sgber	VOP_UNLOCK(vp, 0);
211235537Sgber	return (0);
212235537Sgber}
213235537Sgber
214