Merge branches 'hammer2' and 'master' of ssh://crater.dragonflybsd.org/repository...
[dragonfly.git] / sys / vfs / hammer2 / hammer2_subr.c
1 /*
2  * Copyright (c) 2011-2012 The DragonFly Project.  All rights reserved.
3  *
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>
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
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
17  *    distribution.
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.
21  *
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
33  * SUCH DAMAGE.
34  */
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>
40 #include <sys/lock.h>
41 #include <sys/uuid.h>
42
43 #include "hammer2.h"
44
45 /*
46  * HAMMER2 inode locks
47  *
48  * HAMMER2 offers shared locks, update locks, and exclusive locks on inodes.
49  *
50  * Shared locks allow concurrent access to an inode's fields, but exclude
51  * access by concurrent exclusive locks.
52  *
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.
57  *
58  * Exclusive locks prevent concurrent access to the inode.
59  *
60  * XXX: What do we use each for? How is visibility to the inode controlled?
61  */
62
63 void
64 hammer2_inode_lock_sh(hammer2_inode_t *ip)
65 {
66         lockmgr(&ip->lk, LK_SHARED);
67 }
68
69 void
70 hammer2_inode_lock_up(hammer2_inode_t *ip)
71 {
72         lockmgr(&ip->lk, LK_EXCLUSIVE);
73         ++ip->chain.busy;
74         lockmgr(&ip->lk, LK_DOWNGRADE);
75 }
76
77 void
78 hammer2_inode_lock_ex(hammer2_inode_t *ip)
79 {
80         lockmgr(&ip->lk, LK_EXCLUSIVE);
81 }
82
83 void
84 hammer2_inode_unlock_ex(hammer2_inode_t *ip)
85 {
86         lockmgr(&ip->lk, LK_RELEASE);
87 }
88
89 void
90 hammer2_inode_unlock_up(hammer2_inode_t *ip)
91 {
92         lockmgr(&ip->lk, LK_UPGRADE);
93         --ip->chain.busy;
94         lockmgr(&ip->lk, LK_RELEASE);
95 }
96
97 void
98 hammer2_inode_unlock_sh(hammer2_inode_t *ip)
99 {
100         lockmgr(&ip->lk, LK_RELEASE);
101 }
102
103 /*
104  * Mount-wide locks
105  */
106
107 void
108 hammer2_mount_exlock(hammer2_mount_t *hmp)
109 {
110         lockmgr(&hmp->lk, LK_EXCLUSIVE);
111 }
112
113 void
114 hammer2_mount_shlock(hammer2_mount_t *hmp)
115 {
116         lockmgr(&hmp->lk, LK_SHARED);
117 }
118
119 void
120 hammer2_mount_unlock(hammer2_mount_t *hmp)
121 {
122         lockmgr(&hmp->lk, LK_RELEASE);
123 }
124
125 /*
126  * Borrow HAMMER1's directory hash algorithm #1 with a few modifications.
127  * The filename is split into fields which are hashed separately and then
128  * added together.
129  *
130  * Differences include: bit 63 must be set to 1 for HAMMER2 (HAMMER1 sets
131  * it to 0), this is because bit63=0 is used for hidden hardlinked inodes.
132  * (This means we do not need to do a 0-check/or-with-0x100000000 either).
133  *
134  * Also, the iscsi crc code is used instead of the old crc32 code.
135  */
136 hammer2_key_t
137 hammer2_dirhash(const unsigned char *name, size_t len)
138 {
139         const unsigned char *aname = name;
140         uint32_t crcx;
141         uint64_t key;
142         size_t i;
143         size_t j;
144
145         key = 0;
146
147         /*
148          * m32
149          */
150         crcx = 0;
151         for (i = j = 0; i < len; ++i) {
152                 if (aname[i] == '.' ||
153                     aname[i] == '-' ||
154                     aname[i] == '_' ||
155                     aname[i] == '~') {
156                         if (i != j)
157                                 crcx += hammer2_icrc32(aname + j, i - j);
158                         j = i + 1;
159                 }
160         }
161         if (i != j)
162                 crcx += hammer2_icrc32(aname + j, i - j);
163
164         /*
165          * The directory hash utilizes the top 32 bits of the 64-bit key.
166          * Bit 63 must be set to 1.
167          */
168         crcx |= 0x80000000U;
169         key |= (uint64_t)crcx << 32;
170
171         /*
172          * l16 - crc of entire filename
173          *
174          * This crc reduces degenerate hash collision conditions
175          */
176         crcx = hammer2_icrc32(aname, len);
177         crcx = crcx ^ (crcx << 16);
178         key |= crcx & 0xFFFF0000U;
179
180         return (key);
181 }