| Commit | Line | Data |
|---|---|---|
| 703720e4 MD |
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 | ||
| 36 | /* | |
| 37 | * This header file contains structures used internally by the HAMMER2 | |
| 38 | * implementation. See hammer2_disk.h for on-disk structures. | |
| 39 | */ | |
| 40 | ||
| 41 | #ifndef _VFS_HAMMER2_HAMMER2_H_ | |
| 42 | #define _VFS_HAMMER2_HAMMER2_H_ | |
| 43 | ||
| 44 | #include <sys/param.h> | |
| 45 | #include <sys/types.h> | |
| 46 | #include <sys/kernel.h> | |
| 47 | #include <sys/conf.h> | |
| 48 | #include <sys/systm.h> | |
| 49 | #include <sys/tree.h> | |
| 50 | #include <sys/malloc.h> | |
| 51 | #include <sys/mount.h> | |
| 52 | #include <sys/vnode.h> | |
| 53 | #include <sys/proc.h> | |
| 54 | #include <sys/mountctl.h> | |
| 55 | #include <sys/priv.h> | |
| 56 | #include <sys/stat.h> | |
| 57 | #include <sys/globaldata.h> | |
| 58 | #include <sys/lockf.h> | |
| 59 | #include <sys/buf.h> | |
| 60 | #include <sys/queue.h> | |
| 61 | #include <sys/limits.h> | |
| 62 | #include <sys/buf2.h> | |
| 63 | #include <sys/signal2.h> | |
| 64 | #include <sys/tree.h> | |
| 65 | ||
| 66 | #include "hammer2_disk.h" | |
| 67 | #include "hammer2_mount.h" | |
| 68 | ||
| 5c23d7f1 | 69 | struct hammer2_chain; |
| 703720e4 MD |
70 | struct hammer2_inode; |
| 71 | struct hammer2_mount; | |
| 72 | ||
| 703720e4 | 73 | /* |
| 50e4f8f4 MD |
74 | * The chain structure tracks blockref recursions all the way to |
| 75 | * the root volume. These consist of indirect blocks, inodes, | |
| 76 | * and eventually the volume header. | |
| 77 | * | |
| 7cfa8da5 MD |
78 | * The chain structure is embedded in the hammer2_mount, hammer2_inode, |
| 79 | * and other system memory structures. The chain structure typically | |
| 80 | * implements the reference count and busy flag for the larger structure. | |
| 81 | * | |
| 82 | * It is always possible to track a chain element all the way back to the | |
| 83 | * root by following the (parent) links. (index) is a type-dependent index | |
| 84 | * in the parent indicating where in the parent the chain element resides. | |
| 5c23d7f1 MD |
85 | * |
| 86 | * When a blockref is added or deleted the related chain element is marked | |
| 87 | * modified and all of its parents are marked SUBMODIFIED (the parent | |
| 88 | * recursion can stop once we hit a node that is already marked SUBMODIFIED). | |
| 89 | * A deleted chain element must remain intact until synchronized against | |
| 90 | * its parent. | |
| 91 | * | |
| 92 | * The blockref at (parent, index) is not adjusted until the modified chain | |
| 93 | * element is flushed and unmarked. Until then the child's blockref may | |
| 94 | * not match the blockref at (parent, index). | |
| 50e4f8f4 | 95 | */ |
| 5c23d7f1 MD |
96 | SPLAY_HEAD(hammer2_chain_splay, hammer2_chain); |
| 97 | ||
| 50e4f8f4 MD |
98 | struct hammer2_chain { |
| 99 | struct hammer2_blockref bref; | |
| 7cfa8da5 | 100 | struct hammer2_chain *parent; /* return chain to root */ |
| 5c23d7f1 MD |
101 | struct hammer2_chain_splay shead; |
| 102 | SPLAY_ENTRY(hammer2_chain) snode; | |
| 7cfa8da5 MD |
103 | union { |
| 104 | struct hammer2_inode *ip; | |
| 5c23d7f1 MD |
105 | struct hammer2_indblock *np; |
| 106 | struct hammer2_data *dp; | |
| 107 | void *mem; | |
| 7cfa8da5 | 108 | } u; |
| 5c23d7f1 MD |
109 | |
| 110 | struct buf *bp; /* buffer cache (ro) */ | |
| 111 | hammer2_media_data_t *data; /* modified copy of data (rw) */ | |
| 112 | ||
| 113 | struct lock lk; /* lockmgr lock */ | |
| 114 | int index; /* index in parent */ | |
| 115 | u_int refs; | |
| 116 | u_int busy; /* soft-busy */ | |
| 117 | u_int flags; | |
| 50e4f8f4 MD |
118 | }; |
| 119 | ||
| 120 | typedef struct hammer2_chain hammer2_chain_t; | |
| 121 | ||
| 5c23d7f1 MD |
122 | int hammer2_chain_cmp(hammer2_chain_t *chain1, hammer2_chain_t *chain2); |
| 123 | SPLAY_PROTOTYPE(hammer2_chain_splay, hammer2_chain, snode, hammer2_chain_cmp); | |
| 124 | ||
| 125 | #define HAMMER2_CHAIN_MODIFIED 0x00000001 /* this elm modified */ | |
| b7926f31 MD |
126 | #define HAMMER2_CHAIN_COMMITTING 0x00000002 /* mods committing */ |
| 127 | #define HAMMER2_CHAIN_SUBMODIFIED 0x00000004 /* 1+ subs modified */ | |
| 128 | #define HAMMER2_CHAIN_SUBCOMMITTING 0x00000008 /* 1+ subs committing */ | |
| 129 | #define HAMMER2_CHAIN_DELETED 0x00000010 | |
| 130 | #define HAMMER2_CHAIN_INITIAL 0x00000020 /* initial write */ | |
| c667909f | 131 | #define HAMMER2_CHAIN_FLUSHED 0x00000040 /* flush on unlock */ |
| 995e78dc | 132 | #define HAMMER2_CHAIN_MOVED 0x00000080 /* moved */ |
| 37aa19df | 133 | #define HAMMER2_CHAIN_IOFLUSH 0x00000100 /* bawrite on put */ |
| c667909f MD |
134 | |
| 135 | /* | |
| 136 | * Flags passed to hammer2_chain_lookup() and hammer2_chain_next() | |
| 137 | */ | |
| 138 | #define HAMMER2_LOOKUP_NOLOCK 0x00000001 /* ref only */ | |
| 5c23d7f1 | 139 | |
| 50e4f8f4 | 140 | /* |
| 5c23d7f1 | 141 | * HAMMER2 IN-MEMORY CACHE OF MEDIA STRUCTURES |
| 7cfa8da5 | 142 | * |
| 5c23d7f1 MD |
143 | * There is an in-memory representation of all on-media data structure. |
| 144 | * | |
| 145 | * When accessed read-only the data will be mapped to the related buffer | |
| 146 | * cache buffer. | |
| 147 | * | |
| 148 | * When accessed read-write (marked modified) a kmalloc()'d copy of the | |
| 149 | * is created which can then be modified. The copy is destroyed when a | |
| 150 | * filesystem block is allocated to replace it. | |
| 151 | * | |
| 152 | * Active inodes (those with vnodes attached) will maintain the kmalloc()'d | |
| 153 | * copy for both the read-only and the read-write case. The combination of | |
| 154 | * (bp) and (data) determines whether (data) was allocated or not. | |
| 155 | * | |
| 156 | * The in-memory representation may remain cached (for example in order to | |
| 157 | * placemark clustering locks) even after the related data has been | |
| 158 | * detached. | |
| 159 | */ | |
| 160 | ||
| 161 | /* | |
| 162 | * A hammer2 inode. | |
| 703720e4 MD |
163 | */ |
| 164 | struct hammer2_inode { | |
| 54eb943b | 165 | struct hammer2_mount *hmp; |
| e028fa74 | 166 | struct hammer2_inode *pip; /* parent inode */ |
| 703720e4 | 167 | struct vnode *vp; |
| 50e4f8f4 | 168 | hammer2_chain_t chain; |
| 5c23d7f1 | 169 | struct hammer2_inode_data ip_data; |
| 37aa19df | 170 | struct lockf advlock; |
| 703720e4 MD |
171 | }; |
| 172 | ||
| 54eb943b MD |
173 | typedef struct hammer2_inode hammer2_inode_t; |
| 174 | ||
| 703720e4 | 175 | /* |
| 7cfa8da5 MD |
176 | * A hammer2 indirect block |
| 177 | */ | |
| 178 | struct hammer2_indblock { | |
| 179 | hammer2_chain_t chain; | |
| 7cfa8da5 MD |
180 | }; |
| 181 | ||
| 182 | typedef struct hammer2_indblock hammer2_indblock_t; | |
| 183 | ||
| 5c23d7f1 MD |
184 | #define np_data chain.data->npdata |
| 185 | ||
| 186 | /* | |
| 187 | * A hammer2 data block | |
| 188 | */ | |
| 189 | struct hammer2_data { | |
| 190 | hammer2_chain_t chain; | |
| 191 | }; | |
| 192 | ||
| 193 | #define dp_data chain.data->buf | |
| 194 | ||
| 195 | typedef struct hammer2_data hammer2_data_t; | |
| 196 | ||
| 7cfa8da5 | 197 | /* |
| 703720e4 MD |
198 | * Governing mount structure for filesystem (aka vp->v_mount) |
| 199 | */ | |
| 200 | struct hammer2_mount { | |
| 50e4f8f4 MD |
201 | struct mount *mp; /* kernel mount */ |
| 202 | struct vnode *devvp; /* device vnode */ | |
| 50e4f8f4 MD |
203 | struct netexport export; /* nfs export */ |
| 204 | int ronly; /* read-only mount */ | |
| 703720e4 | 205 | |
| 5c23d7f1 | 206 | struct malloc_type *minode; |
| 54eb943b MD |
207 | int ninodes; |
| 208 | int maxinodes; | |
| 703720e4 | 209 | |
| 5c23d7f1 | 210 | struct malloc_type *mchain; |
| 54eb943b MD |
211 | int nipstacks; |
| 212 | int maxipstacks; | |
| 7cfa8da5 MD |
213 | hammer2_chain_t vchain; /* anchor chain */ |
| 214 | hammer2_chain_t *schain; /* super-root */ | |
| 215 | hammer2_chain_t *rchain; /* label-root */ | |
| 216 | struct hammer2_inode *iroot; | |
| 703720e4 | 217 | |
| 54eb943b | 218 | hammer2_volume_data_t voldata; |
| df9ea374 | 219 | hammer2_off_t freecache[HAMMER2_MAX_RADIX]; |
| 703720e4 MD |
220 | }; |
| 221 | ||
| 54eb943b MD |
222 | typedef struct hammer2_mount hammer2_mount_t; |
| 223 | ||
| 703720e4 MD |
224 | #if defined(_KERNEL) |
| 225 | ||
| 226 | MALLOC_DECLARE(M_HAMMER2); | |
| 227 | ||
| e118c14f MD |
228 | static __inline |
| 229 | struct mount * | |
| 703720e4 MD |
230 | H2TOMP(struct hammer2_mount *hmp) |
| 231 | { | |
| 54eb943b | 232 | return (struct mount *) hmp->mp; |
| 703720e4 MD |
233 | } |
| 234 | ||
| 54eb943b | 235 | #define VTOI(vp) ((hammer2_inode_t *)(vp)->v_data) |
| 703720e4 MD |
236 | #define ITOV(ip) ((ip)->vp) |
| 237 | ||
| e118c14f MD |
238 | static __inline |
| 239 | struct hammer2_mount * | |
| 47902fef VS |
240 | MPTOH2(struct mount *mp) |
| 241 | { | |
| 54eb943b | 242 | return (hammer2_mount_t *) mp->mnt_data; |
| 47902fef VS |
243 | } |
| 244 | ||
| 703720e4 MD |
245 | extern struct vop_ops hammer2_vnode_vops; |
| 246 | extern struct vop_ops hammer2_spec_vops; | |
| 247 | extern struct vop_ops hammer2_fifo_vops; | |
| 248 | ||
| 37aa19df MD |
249 | extern int hammer2_debug; |
| 250 | ||
| 7cfa8da5 MD |
251 | /* |
| 252 | * hammer2_subr.c | |
| 253 | */ | |
| 54eb943b MD |
254 | void hammer2_inode_lock_ex(hammer2_inode_t *ip); |
| 255 | void hammer2_inode_unlock_ex(hammer2_inode_t *ip); | |
| 9c2e0de0 | 256 | void hammer2_inode_lock_sh(hammer2_inode_t *ip); |
| 54eb943b | 257 | void hammer2_inode_unlock_sh(hammer2_inode_t *ip); |
| 9c2e0de0 MD |
258 | void hammer2_inode_busy(hammer2_inode_t *ip); |
| 259 | void hammer2_inode_unbusy(hammer2_inode_t *ip); | |
| e118c14f | 260 | |
| 54eb943b MD |
261 | void hammer2_mount_exlock(hammer2_mount_t *hmp); |
| 262 | void hammer2_mount_shlock(hammer2_mount_t *hmp); | |
| 263 | void hammer2_mount_unlock(hammer2_mount_t *hmp); | |
| 703720e4 | 264 | |
| e028fa74 | 265 | int hammer2_get_dtype(hammer2_inode_t *ip); |
| cd4b3d92 | 266 | int hammer2_get_vtype(hammer2_inode_t *ip); |
| 37494cab | 267 | u_int8_t hammer2_get_obj_type(enum vtype vtype); |
| cd4b3d92 | 268 | void hammer2_time_to_timespec(u_int64_t xtime, struct timespec *ts); |
| 37494cab | 269 | u_int32_t hammer2_to_unix_xid(uuid_t *uuid); |
| e028fa74 | 270 | |
| 7cfa8da5 MD |
271 | hammer2_key_t hammer2_dirhash(const unsigned char *name, size_t len); |
| 272 | ||
| 273 | /* | |
| 274 | * hammer2_inode.c | |
| 275 | */ | |
| 54eb943b | 276 | struct vnode *hammer2_igetv(hammer2_inode_t *ip, int *errorp); |
| 232a50f9 | 277 | hammer2_inode_t *hammer2_inode_alloc(hammer2_mount_t *hmp, void *data); |
| 7cfa8da5 MD |
278 | void hammer2_inode_free(hammer2_inode_t *ip); |
| 279 | void hammer2_inode_ref(hammer2_inode_t *ip); | |
| 280 | void hammer2_inode_drop(hammer2_inode_t *ip); | |
| 37494cab MD |
281 | int hammer2_create_inode(hammer2_mount_t *hmp, |
| 282 | struct vattr *vap, struct ucred *cred, | |
| 283 | hammer2_inode_t *dip, | |
| 284 | const uint8_t *name, size_t name_len, | |
| 285 | hammer2_inode_t **nipp); | |
| 703720e4 | 286 | |
| 7cfa8da5 MD |
287 | /* |
| 288 | * hammer2_chain.c | |
| 289 | */ | |
| 5c23d7f1 MD |
290 | hammer2_chain_t *hammer2_chain_alloc(hammer2_mount_t *hmp, |
| 291 | hammer2_blockref_t *bref); | |
| 292 | void hammer2_chain_free(hammer2_mount_t *hmp, hammer2_chain_t *chain); | |
| 7cfa8da5 MD |
293 | void hammer2_chain_ref(hammer2_mount_t *hmp, hammer2_chain_t *chain); |
| 294 | void hammer2_chain_drop(hammer2_mount_t *hmp, hammer2_chain_t *chain); | |
| 5c23d7f1 MD |
295 | int hammer2_chain_lock(hammer2_mount_t *hmp, hammer2_chain_t *chain); |
| 296 | void hammer2_chain_modify(hammer2_mount_t *hmp, hammer2_chain_t *chain); | |
| 297 | void hammer2_chain_unlock(hammer2_mount_t *hmp, hammer2_chain_t *chain); | |
| b7926f31 MD |
298 | hammer2_chain_t *hammer2_chain_find(hammer2_mount_t *hmp, |
| 299 | hammer2_chain_t *parent, int index); | |
| 232a50f9 | 300 | hammer2_chain_t *hammer2_chain_get(hammer2_mount_t *hmp, |
| c667909f MD |
301 | hammer2_chain_t *parent, |
| 302 | int index, int flags); | |
| 232a50f9 | 303 | void hammer2_chain_put(hammer2_mount_t *hmp, hammer2_chain_t *chain); |
| 5c23d7f1 | 304 | hammer2_chain_t *hammer2_chain_lookup(hammer2_mount_t *hmp, |
| e028fa74 | 305 | hammer2_chain_t **parentp, |
| c667909f MD |
306 | hammer2_key_t key_beg, hammer2_key_t key_end, |
| 307 | int flags); | |
| 7cfa8da5 | 308 | hammer2_chain_t *hammer2_chain_next(hammer2_mount_t *hmp, |
| 5c23d7f1 MD |
309 | hammer2_chain_t **parentp, |
| 310 | hammer2_chain_t *chain, | |
| c667909f MD |
311 | hammer2_key_t key_beg, hammer2_key_t key_end, |
| 312 | int flags); | |
| 5c23d7f1 MD |
313 | hammer2_chain_t *hammer2_chain_create(hammer2_mount_t *hmp, |
| 314 | hammer2_chain_t *parent, | |
| 315 | hammer2_key_t key, int keybits, | |
| 316 | int type, size_t bytes); | |
| 317 | void hammer2_chain_delete(hammer2_mount_t *hmp, hammer2_chain_t **parentp, | |
| 318 | hammer2_chain_t *chain); | |
| b7926f31 MD |
319 | void hammer2_chain_flush(hammer2_mount_t *hmp, hammer2_chain_t *chain, |
| 320 | hammer2_blockref_t *parent_bref); | |
| 321 | void hammer2_chain_commit(hammer2_mount_t *hmp, hammer2_chain_t *chain); | |
| 50e4f8f4 | 322 | |
| df9ea374 MD |
323 | /* |
| 324 | * hammer2_freemap.c | |
| 325 | */ | |
| 5c23d7f1 | 326 | hammer2_off_t hammer2_freemap_alloc(hammer2_mount_t *hmp, size_t bytes); |
| c667909f | 327 | int hammer2_freemap_bytes_to_radix(size_t bytes); |
| df9ea374 | 328 | |
| 47902fef VS |
329 | #endif /* !_KERNEL */ |
| 330 | #endif /* !_VFS_HAMMER2_HAMMER2_H_ */ |