1/*-
2 * Copyright (c) 2010-2012 Semihalf.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD$");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/conf.h>
33#include <sys/kernel.h>
34#include <sys/lock.h>
35#include <sys/malloc.h>
36#include <sys/mount.h>
37#include <sys/mutex.h>
38#include <sys/namei.h>
39#include <sys/sysctl.h>
40#include <sys/vnode.h>
41#include <sys/buf.h>
42#include <sys/bio.h>
43
44#include <vm/vm.h>
45#include <vm/vm_param.h>
46#include <vm/vm_kern.h>
47#include <vm/vm_page.h>
48
49#include <fs/nandfs/nandfs_mount.h>
50#include <fs/nandfs/nandfs.h>
51#include <fs/nandfs/nandfs_subr.h>
52
53int
54nandfs_node_create(struct nandfsmount *nmp, struct nandfs_node **node,
55    uint16_t mode)
56{
57	struct nandfs_alloc_request req;
58	struct nandfs_device *nandfsdev;
59	struct nandfs_mdt *mdt;
60	struct nandfs_node *ifile;
61	struct nandfs_inode *inode;
62	struct vnode *vp;
63	uint32_t entry;
64	int error = 0;
65
66	nandfsdev = nmp->nm_nandfsdev;
67	mdt = &nandfsdev->nd_ifile_mdt;
68	ifile = nmp->nm_ifile_node;
69	vp = NTOV(ifile);
70
71	VOP_LOCK(vp, LK_EXCLUSIVE);
72	/* Allocate new inode in ifile */
73	req.entrynum = nandfsdev->nd_last_ino + 1;
74	error = nandfs_find_free_entry(mdt, ifile, &req);
75	if (error) {
76		VOP_UNLOCK(vp, 0);
77		return (error);
78	}
79
80	error = nandfs_get_entry_block(mdt, ifile, &req, &entry, 1);
81	if (error) {
82		VOP_UNLOCK(vp, 0);
83		return (error);
84	}
85
86	/* Inode initialization */
87	inode = ((struct nandfs_inode *) req.bp_entry->b_data) + entry;
88	nandfs_inode_init(inode, mode);
89
90	error = nandfs_alloc_entry(mdt, &req);
91	if (error) {
92		VOP_UNLOCK(vp, 0);
93		return (error);
94	}
95
96	VOP_UNLOCK(vp, 0);
97
98	nandfsdev->nd_last_ino = req.entrynum;
99	error = nandfs_get_node(nmp, req.entrynum, node);
100	DPRINTF(IFILE, ("%s: node: %p ino: %#jx\n",
101	    __func__, node, (uintmax_t)((*node)->nn_ino)));
102
103	return (error);
104}
105
106int
107nandfs_node_destroy(struct nandfs_node *node)
108{
109	struct nandfs_alloc_request req;
110	struct nandfsmount *nmp;
111	struct nandfs_mdt *mdt;
112	struct nandfs_node *ifile;
113	struct vnode *vp;
114	int error = 0;
115
116	nmp = node->nn_nmp;
117	req.entrynum = node->nn_ino;
118	mdt = &nmp->nm_nandfsdev->nd_ifile_mdt;
119	ifile = nmp->nm_ifile_node;
120	vp = NTOV(ifile);
121
122	DPRINTF(IFILE, ("%s: destroy node: %p ino: %#jx\n",
123	    __func__, node, (uintmax_t)node->nn_ino));
124	VOP_LOCK(vp, LK_EXCLUSIVE);
125
126	error = nandfs_find_entry(mdt, ifile, &req);
127	if (error) {
128		nandfs_error("%s: finding entry error:%d node %p(%jx)",
129		    __func__, error, node, node->nn_ino);
130		VOP_UNLOCK(vp, 0);
131		return (error);
132	}
133
134	nandfs_inode_destroy(&node->nn_inode);
135
136	error = nandfs_free_entry(mdt, &req);
137	if (error) {
138		nandfs_error("%s: freing entry error:%d node %p(%jx)",
139		    __func__, error, node, node->nn_ino);
140		VOP_UNLOCK(vp, 0);
141		return (error);
142	}
143
144	VOP_UNLOCK(vp, 0);
145	DPRINTF(IFILE, ("%s: freed node %p ino %#jx\n",
146	    __func__, node, (uintmax_t)node->nn_ino));
147	return (error);
148}
149
150int
151nandfs_node_update(struct nandfs_node *node)
152{
153	struct nandfs_alloc_request req;
154	struct nandfsmount *nmp;
155	struct nandfs_mdt *mdt;
156	struct nandfs_node *ifile;
157	struct nandfs_inode *inode;
158	uint32_t index;
159	int error = 0;
160
161	nmp = node->nn_nmp;
162	ifile = nmp->nm_ifile_node;
163	ASSERT_VOP_LOCKED(NTOV(ifile), __func__);
164
165	req.entrynum = node->nn_ino;
166	mdt = &nmp->nm_nandfsdev->nd_ifile_mdt;
167
168	DPRINTF(IFILE, ("%s: node:%p ino:%#jx\n",
169	    __func__, &node->nn_inode, (uintmax_t)node->nn_ino));
170
171	error = nandfs_get_entry_block(mdt, ifile, &req, &index, 0);
172	if (error) {
173		printf("nandfs_get_entry_block returned with ERROR=%d\n",
174		    error);
175		return (error);
176	}
177
178	inode = ((struct nandfs_inode *) req.bp_entry->b_data) + index;
179	memcpy(inode, &node->nn_inode, sizeof(*inode));
180	error = nandfs_dirty_buf(req.bp_entry, 0);
181
182	return (error);
183}
184
185int
186nandfs_get_node_entry(struct nandfsmount *nmp, struct nandfs_inode **inode,
187    uint64_t ino, struct buf **bp)
188{
189	struct nandfs_alloc_request req;
190	struct nandfs_mdt *mdt;
191	struct nandfs_node *ifile;
192	struct vnode *vp;
193	uint32_t index;
194	int error = 0;
195
196	req.entrynum = ino;
197	mdt = &nmp->nm_nandfsdev->nd_ifile_mdt;
198	ifile = nmp->nm_ifile_node;
199	vp = NTOV(ifile);
200
201	VOP_LOCK(vp, LK_EXCLUSIVE);
202	error = nandfs_get_entry_block(mdt, ifile, &req, &index, 0);
203	if (error) {
204		VOP_UNLOCK(vp, 0);
205		return (error);
206	}
207
208	*inode = ((struct nandfs_inode *) req.bp_entry->b_data) + index;
209	*bp = req.bp_entry;
210	VOP_UNLOCK(vp, 0);
211	return (0);
212}
213
214