2 * Copyright (c) 2007 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * $DragonFly: src/sys/vfs/hammer/hammer_inode.c,v 1.2 2007/11/02 00:57:15 dillon Exp $
41 static enum vtype hammer_get_vnode_type(u_int16_t obj_type);
44 hammer_vop_inactive(struct vop_inactive_args *ap)
55 hammer_vop_reclaim(struct vop_reclaim_args *ap)
57 struct hammer_mount *hmp;
58 struct hammer_inode *ip;
62 hmp = (void *)vp->v_mount->mnt_data;
63 if ((ip = vp->v_data) != NULL) {
66 RB_REMOVE(hammer_ino_rb_tree, &hmp->rb_inos_root, ip);
73 * Lookup or create the vnode associated with the specified inode number.
74 * ino_t in DragonFly is 64 bits which matches the 64 bit HAMMER inode
78 hammer_vfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
80 struct hammer_mount *hmp = (void *)mp->mnt_data;
81 struct hammer_btree_info binfo;
82 struct hammer_inode_info iinfo;
83 struct hammer_base_elm key;
84 struct hammer_inode *ip;
89 * Determine if we already have an inode cached. If we do then
95 ip = hammer_ino_rb_tree_RB_LOOKUP_INFO(&hmp->rb_inos_root, &iinfo);
98 if (vget(vp, LK_EXCLUSIVE) != 0)
100 ip = hammer_ino_rb_tree_RB_LOOKUP_INFO(&hmp->rb_inos_root,
102 if (ip == NULL || ip->vp != vp) {
111 * Lookup failed, instantiate a new vnode and inode in-memory
112 * structure so we don't block in kmalloc later on when holding
113 * locked buffer cached buffers.
115 error = getnewvnode(VT_HAMMER, mp, vpp, 0, 0);
121 ip = kmalloc(sizeof(*ip), M_HAMMER, M_WAITOK|M_ZERO);
123 ip->obj_asof = iinfo.obj_asof;
126 * If we do not have an inode cached search the HAMMER on-disk B-Tree
129 hammer_btree_info_init(&binfo, hmp->rootcl);
134 key.rec_type = HAMMER_RECTYPE_INODE;
137 error = hammer_btree_lookup(&binfo, &key, HAMMER_BTREE_GET_RECORD |
138 HAMMER_BTREE_GET_DATA);
141 * On success the B-Tree lookup will hold the appropriate
142 * buffer cache buffers and provide a pointer to the requested
143 * information. Copy the information to the in-memory inode.
146 ip->ino_rec = binfo.rec->inode;
147 ip->ino_data = binfo.data->inode;
149 hammer_btree_info_done(&binfo);
152 * On success load the inode's record and data and insert the
153 * inode into the B-Tree. It is possible to race another lookup
154 * insertion of the same inode so deal with that condition too.
157 if (RB_INSERT(hammer_ino_rb_tree, &hmp->rb_inos_root, ip)) {
164 vp->v_data = (void *)ip;
166 hammer_get_vnode_type(ip->ino_rec.base.base.obj_type);
175 * (called via RB_SCAN)
178 hammer_unload_inode(struct hammer_inode *ip, void *data)
180 struct hammer_mount *hmp = data;
183 if ((vp = ip->vp) != NULL) {
188 RB_REMOVE(hammer_ino_rb_tree, &hmp->rb_inos_root, ip);
195 * Convert a HAMMER filesystem object type to a vnode type
199 hammer_get_vnode_type(u_int16_t obj_type)
202 case HAMMER_OBJTYPE_DIRECTORY:
204 case HAMMER_OBJTYPE_REGFILE:
206 case HAMMER_OBJTYPE_DBFILE:
208 case HAMMER_OBJTYPE_FIFO:
210 case HAMMER_OBJTYPE_CDEV:
212 case HAMMER_OBJTYPE_BDEV:
214 case HAMMER_OBJTYPE_SOFTLINK:
223 * Access the filesystem buffer containing the cluster-relative byte
224 * offset, validate the buffer type, load *bufferp and return a
225 * pointer to the requested data.
227 * If buf_type is 0 the buffer is assumed to be a pure-data buffer and
228 * no type or crc check is performed.
230 * XXX add a flag for the buffer type and check the CRC here XXX
233 hammer_bread(struct hammer_cluster *cluster, int32_t cloff,
235 int *errorp, struct hammer_buffer **bufferp)
237 struct hammer_buffer *buffer;
242 * Load the correct filesystem buffer, replacing *bufferp.
244 buf_no = cloff / HAMMER_BUFSIZE;
246 if (buffer == NULL || buffer->cluster != cluster ||
247 buffer->buf_no != buf_no) {
249 hammer_put_buffer(buffer);
250 buffer = hammer_get_buffer(cluster, buf_no, 0, errorp);
257 * Validate the buffer type and crc XXX
259 buf_off = cloff & HAMMER_BUFMASK;
261 if (buf_type != buffer->ondisk->head.buf_type) {
262 kprintf("BUFFER HEAD TYPE MISMATCH %llx %llx\n",
263 buf_type, buffer->ondisk->head.buf_type);
267 if (buf_off < sizeof(buffer->ondisk->head)) {
268 kprintf("BUFFER OFFSET TOO LOW %d\n", buf_off);
276 * Return a pointer to the buffer data.
279 return((char *)buffer->ondisk + buf_off);