2 * Copyright (c) 2011-2012 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@dragonflybsd.org>
6 * by Venkatesh Srinivas <vsrinivas@dragonflybsd.org>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
18 * 3. Neither the name of The DragonFly Project nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific, prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <sys/cdefs.h>
36 #include <sys/cdefs.h>
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/types.h>
48 * HAMMER2 offers shared locks, update locks, and exclusive locks on inodes.
50 * Shared locks allow concurrent access to an inode's fields, but exclude
51 * access by concurrent exclusive locks.
53 * Update locks are interesting -- an update lock will be taken after all
54 * shared locks on an inode are released, but once it is in place, shared
55 * locks may proceed. The update field is signalled by a busy flag in the
56 * inode. Only one update lock may be in place at a given time on an inode.
58 * Exclusive locks prevent concurrent access to the inode.
60 * XXX: What do we use each for? How is visibility to the inode controlled?
64 hammer2_inode_lock_sh(hammer2_inode_t *ip)
66 lockmgr(&ip->lk, LK_SHARED);
70 hammer2_inode_lock_up(hammer2_inode_t *ip)
72 lockmgr(&ip->lk, LK_EXCLUSIVE);
74 lockmgr(&ip->lk, LK_DOWNGRADE);
78 hammer2_inode_lock_ex(hammer2_inode_t *ip)
80 lockmgr(&ip->lk, LK_EXCLUSIVE);
84 hammer2_inode_unlock_ex(hammer2_inode_t *ip)
86 lockmgr(&ip->lk, LK_RELEASE);
90 hammer2_inode_unlock_up(hammer2_inode_t *ip)
92 lockmgr(&ip->lk, LK_UPGRADE);
94 lockmgr(&ip->lk, LK_RELEASE);
98 hammer2_inode_unlock_sh(hammer2_inode_t *ip)
100 lockmgr(&ip->lk, LK_RELEASE);
108 hammer2_mount_exlock(hammer2_mount_t *hmp)
110 lockmgr(&hmp->lk, LK_EXCLUSIVE);
114 hammer2_mount_shlock(hammer2_mount_t *hmp)
116 lockmgr(&hmp->lk, LK_SHARED);
120 hammer2_mount_unlock(hammer2_mount_t *hmp)
122 lockmgr(&hmp->lk, LK_RELEASE);
126 * Inode/vnode subroutines
130 * Get the vnode associated with the given inode, allocating the vnode if
133 * Great care must be taken to avoid deadlocks and vnode acquisition/reclaim
136 * The vnode will be returned exclusively locked and referenced. The
137 * reference on the vnode prevents it from being reclaimed.
139 * The inode (ip) must be referenced by the caller and not locked to avoid
140 * it getting ripped out from under us or deadlocked.
143 hammer2_igetv(hammer2_inode_t *ip, int *errorp)
146 hammer2_mount_t *hmp;
153 * Attempt to reuse an existing vnode assignment. It is
154 * possible to race a reclaim so the vget() may fail. The
155 * inode must be unlocked during the vget() to avoid a
156 * deadlock against a reclaim.
161 * Lock the inode and check for a reclaim race
163 hammer2_inode_lock_ex(ip);
165 hammer2_inode_unlock_ex(ip);
170 * Inode must be unlocked during the vget() to avoid
171 * possible deadlocks, vnode is held to prevent
172 * destruction during the vget(). The vget() can
173 * still fail if we lost a reclaim race on the vnode.
175 vhold_interlocked(vp);
176 hammer2_inode_unlock_ex(ip);
177 if (vget(vp, LK_EXCLUSIVE)) {
182 /* vp still locked and ref from vget */
188 * No vnode exists, allocate a new vnode. Beware of
189 * allocation races. This function will return an
190 * exclusively locked and referenced vnode.
192 *errorp = getnewvnode(VT_HAMMER2, H2TOMP(hmp), &vp, 0, 0);
199 * Lock the inode and check for an allocation race.
201 hammer2_inode_lock_ex(ip);
202 if (ip->vp != NULL) {
205 hammer2_inode_unlock_ex(ip);
209 kprintf("igetv new\n");
210 switch (ip->type & HAMMER2_INODE_TYPE_MASK) {
211 case HAMMER2_INODE_TYPE_DIR:
214 case HAMMER2_INODE_TYPE_FILE:
216 vinitvmio(vp, 0, HAMMER2_LBUFSIZE,
217 (int)ip->data.size & HAMMER2_LBUFMASK);
224 if (ip->type & HAMMER2_INODE_TYPE_ROOT)
225 vsetflags(vp, VROOT);
229 hammer2_inode_unlock_ex(ip);
234 * Return non-NULL vp and *errorp == 0, or NULL vp and *errorp != 0.
240 * Allocate a HAMMER2 inode memory structure.
242 * The returned inode is locked exclusively and referenced.
243 * The HAMMER2 mountpoint must be locked on entry.
246 hammer2_alloci(hammer2_mount_t *hmp)
252 ip = kmalloc(sizeof(hammer2_inode_t), hmp->inodes, M_WAITOK | M_ZERO);
261 lockinit(&ip->lk, "h2inode", 0, 0);
264 hammer2_inode_lock_ex(ip);
270 * Free a HAMMER2 inode memory structure.
272 * The inode must be locked exclusively with one reference and will
273 * be destroyed on return.
276 hammer2_freei(hammer2_inode_t *ip)
278 hammer2_mount_t *hmp = ip->hmp;
280 KKASSERT(ip->hmp != NULL);
281 KKASSERT(ip->vp == NULL);
282 KKASSERT(ip->refs == 1);
283 hammer2_inode_unlock_ex(ip);
284 kfree(ip, hmp->inodes);