1 1.11 andvar /* $NetBSD: chfs.h,v 1.11 2021/12/07 21:37:37 andvar Exp $ */ 2 1.1 ahoka 3 1.1 ahoka /*- 4 1.1 ahoka * Copyright (c) 2010 Department of Software Engineering, 5 1.1 ahoka * University of Szeged, Hungary 6 1.1 ahoka * Copyright (C) 2009 Ferenc Havasi <havasi (at) inf.u-szeged.hu> 7 1.1 ahoka * Copyright (C) 2009 Zoltan Sogor <weth (at) inf.u-szeged.hu> 8 1.1 ahoka * Copyright (C) 2009 David Tengeri <dtengeri (at) inf.u-szeged.hu> 9 1.1 ahoka * Copyright (C) 2009 Tamas Toth <ttoth (at) inf.u-szeged.hu> 10 1.1 ahoka * Copyright (C) 2010 Adam Hoka <ahoka (at) NetBSD.org> 11 1.1 ahoka * All rights reserved. 12 1.1 ahoka * 13 1.1 ahoka * This code is derived from software contributed to The NetBSD Foundation 14 1.1 ahoka * by the Department of Software Engineering, University of Szeged, Hungary 15 1.1 ahoka * 16 1.1 ahoka * Redistribution and use in source and binary forms, with or without 17 1.1 ahoka * modification, are permitted provided that the following conditions 18 1.1 ahoka * are met: 19 1.1 ahoka * 1. Redistributions of source code must retain the above copyright 20 1.1 ahoka * notice, this list of conditions and the following disclaimer. 21 1.1 ahoka * 2. Redistributions in binary form must reproduce the above copyright 22 1.1 ahoka * notice, this list of conditions and the following disclaimer in the 23 1.1 ahoka * documentation and/or other materials provided with the distribution. 24 1.1 ahoka * 25 1.1 ahoka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 26 1.1 ahoka * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 27 1.1 ahoka * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28 1.1 ahoka * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 29 1.1 ahoka * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 30 1.1 ahoka * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31 1.1 ahoka * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 32 1.1 ahoka * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 33 1.1 ahoka * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 1.1 ahoka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 1.1 ahoka * SUCH DAMAGE. 36 1.1 ahoka */ 37 1.1 ahoka 38 1.1 ahoka #ifndef __CHFS_H__ 39 1.1 ahoka #define __CHFS_H__ 40 1.1 ahoka 41 1.6 ttoth 42 1.6 ttoth #ifdef _KERNEL 43 1.6 ttoth 44 1.3 ahoka #if 0 45 1.8 ttoth #define DBG_MSG /* debug messages */ 46 1.8 ttoth #define DBG_MSG_GC /* garbage collector's debug messages */ 47 1.3 ahoka #endif 48 1.1 ahoka 49 1.1 ahoka #include <sys/param.h> 50 1.1 ahoka #include <sys/kernel.h> 51 1.1 ahoka #include <sys/cdefs.h> 52 1.1 ahoka #include <sys/stdint.h> 53 1.1 ahoka #include <sys/types.h> 54 1.1 ahoka #include <sys/tree.h> 55 1.1 ahoka #include <sys/queue.h> 56 1.1 ahoka #include <sys/kmem.h> 57 1.1 ahoka #include <sys/endian.h> 58 1.1 ahoka #include <sys/rwlock.h> 59 1.1 ahoka #include <sys/condvar.h> 60 1.1 ahoka #include <sys/mutex.h> 61 1.1 ahoka #include <sys/kthread.h> 62 1.1 ahoka #include <sys/rbtree.h> 63 1.1 ahoka #include <sys/vnode.h> 64 1.1 ahoka #include <sys/mount.h> 65 1.1 ahoka #include <sys/hash.h> 66 1.1 ahoka #include <sys/module.h> 67 1.1 ahoka #include <sys/dirent.h> 68 1.1 ahoka 69 1.1 ahoka #include <ufs/ufs/quota.h> 70 1.1 ahoka #include <ufs/ufs/ufsmount.h> 71 1.1 ahoka #include <ufs/ufs/dir.h> 72 1.1 ahoka 73 1.1 ahoka /* XXX shouldnt be defined here, but needed by chfs_inode.h */ 74 1.1 ahoka TAILQ_HEAD(chfs_dirent_list, chfs_dirent); 75 1.1 ahoka 76 1.1 ahoka #include "chfs_pool.h" 77 1.6 ttoth #endif /* _KERNEL */ 78 1.6 ttoth 79 1.1 ahoka #include "ebh.h" 80 1.1 ahoka #include "media.h" 81 1.1 ahoka #include "chfs_inode.h" 82 1.1 ahoka 83 1.8 ttoth /* padding - last two bits used for node masks */ 84 1.6 ttoth #define CHFS_PAD(x) (((x)+3)&~3) 85 1.6 ttoth 86 1.6 ttoth #ifdef _KERNEL 87 1.6 ttoth 88 1.1 ahoka #ifndef MOUNT_CHFS 89 1.1 ahoka #define MOUNT_CHFS "chfs" 90 1.6 ttoth #endif /* MOUNT_CHFS */ 91 1.1 ahoka 92 1.8 ttoth /* state of a vnode */ 93 1.1 ahoka enum { 94 1.8 ttoth VNO_STATE_UNCHECKED, /* CRC checks not yet done */ 95 1.8 ttoth VNO_STATE_CHECKING, /* CRC checks in progress */ 96 1.8 ttoth VNO_STATE_PRESENT, /* In core */ 97 1.8 ttoth VNO_STATE_CHECKEDABSENT, /* Checked, cleared again */ 98 1.8 ttoth VNO_STATE_GC, /* GCing a 'pristine' node */ 99 1.8 ttoth VNO_STATE_READING, /* In read_inode() */ 100 1.8 ttoth VNO_STATE_CLEARING /* In clear_inode() */ 101 1.1 ahoka }; 102 1.1 ahoka 103 1.5 ttoth 104 1.8 ttoth /* size of the vnode cache (hashtable) */ 105 1.1 ahoka #define VNODECACHE_SIZE 128 106 1.1 ahoka 107 1.1 ahoka #define MAX_READ_FREE(chmp) (((chmp)->chm_ebh)->eb_size / 8) 108 1.1 ahoka /* an eraseblock will be clean if its dirty size is smaller than this */ 109 1.1 ahoka #define MAX_DIRTY_TO_CLEAN 255 110 1.1 ahoka #define VERY_DIRTY(chmp, size) ((size) >= (((chmp)->chm_ebh)->eb_size / 2)) 111 1.1 ahoka 112 1.8 ttoth /* node errors */ 113 1.1 ahoka enum { 114 1.1 ahoka CHFS_NODE_OK = 0, 115 1.1 ahoka CHFS_NODE_BADMAGIC, 116 1.1 ahoka CHFS_NODE_BADCRC, 117 1.1 ahoka CHFS_NODE_BADNAMECRC 118 1.1 ahoka }; 119 1.1 ahoka 120 1.8 ttoth /* eraseblock states */ 121 1.1 ahoka enum { 122 1.1 ahoka CHFS_BLK_STATE_FREE = 100, 123 1.1 ahoka CHFS_BLK_STATE_CLEAN, 124 1.1 ahoka CHFS_BLK_STATE_PARTDIRTY, 125 1.1 ahoka CHFS_BLK_STATE_ALLDIRTY 126 1.1 ahoka }; 127 1.1 ahoka 128 1.1 ahoka extern struct pool chfs_inode_pool; 129 1.1 ahoka extern const struct genfs_ops chfs_genfsops; 130 1.1 ahoka 131 1.8 ttoth /* struct chfs_node_ref - a reference to a node which is on the media */ 132 1.1 ahoka struct chfs_node_ref 133 1.1 ahoka { 134 1.8 ttoth struct chfs_node_ref *nref_next; /* next data node which belongs to the same vnode */ 135 1.8 ttoth uint32_t nref_lnr; /* nref's LEB number */ 136 1.8 ttoth uint32_t nref_offset; /* nref's offset */ 137 1.1 ahoka }; 138 1.1 ahoka 139 1.8 ttoth /* 140 1.8 ttoth * constants for allocating node refs 141 1.8 ttoth * they're allocated in blocks 142 1.8 ttoth */ 143 1.1 ahoka #define REFS_BLOCK_LEN (255/sizeof(struct chfs_node_ref)) 144 1.1 ahoka #define REF_EMPTY_NODE (UINT_MAX) 145 1.1 ahoka #define REF_LINK_TO_NEXT (UINT_MAX - 1) 146 1.1 ahoka 147 1.8 ttoth /* node masks - last two bits of the nodes ("state" of an nref) */ 148 1.1 ahoka enum { 149 1.1 ahoka CHFS_NORMAL_NODE_MASK, 150 1.1 ahoka CHFS_UNCHECKED_NODE_MASK, 151 1.1 ahoka CHFS_OBSOLETE_NODE_MASK, 152 1.1 ahoka CHFS_PRISTINE_NODE_MASK 153 1.1 ahoka }; 154 1.1 ahoka 155 1.1 ahoka #define CHFS_REF_FLAGS(ref) ((ref)->nref_offset & 3) 156 1.1 ahoka #define CHFS_REF_OBSOLETE(ref) (((ref)->nref_offset & 3) == CHFS_OBSOLETE_NODE_MASK) 157 1.1 ahoka #define CHFS_MARK_REF_NORMAL(ref) \ 158 1.1 ahoka do { \ 159 1.1 ahoka (ref)->nref_offset = CHFS_GET_OFS((ref)->nref_offset) | CHFS_NORMAL_NODE_MASK; \ 160 1.1 ahoka } while(0) 161 1.1 ahoka 162 1.1 ahoka #define CHFS_GET_OFS(ofs) (ofs & ~ 3) 163 1.1 ahoka 164 1.8 ttoth /* 165 1.8 ttoth * Nrefs are allocated in blocks, get the (in-memory) next. Usually the next 166 1.8 ttoth * doesn't belongs to the same vnode. 167 1.8 ttoth */ 168 1.10 christos static __inline struct chfs_node_ref * 169 1.1 ahoka node_next(struct chfs_node_ref *nref) 170 1.1 ahoka { 171 1.8 ttoth /* step to the next nref in the same block */ 172 1.1 ahoka nref++; 173 1.1 ahoka 174 1.8 ttoth /* REF_LINK_TO_NEXT means that the next node will be in the next block */ 175 1.1 ahoka if (nref->nref_lnr == REF_LINK_TO_NEXT) { 176 1.1 ahoka nref = nref->nref_next; 177 1.1 ahoka if (!nref) 178 1.1 ahoka return nref; 179 1.1 ahoka } 180 1.1 ahoka 181 1.8 ttoth /* REF_EMPTY_NODE means that this is the last node */ 182 1.1 ahoka if (nref->nref_lnr == REF_EMPTY_NODE) { 183 1.1 ahoka return NULL; 184 1.1 ahoka } 185 1.1 ahoka 186 1.1 ahoka return nref; 187 1.1 ahoka } 188 1.1 ahoka 189 1.8 ttoth /* struct chfs_dirent - full representation of a directory entry */ 190 1.1 ahoka struct chfs_dirent 191 1.1 ahoka { 192 1.8 ttoth struct chfs_node_ref *nref; /* nref of the dirent */ 193 1.8 ttoth TAILQ_ENTRY(chfs_dirent) fds; /* directory entries */ 194 1.8 ttoth uint64_t version; /* version */ 195 1.8 ttoth ino_t vno; /* vnode number */ 196 1.8 ttoth uint32_t nhash; /* name hash */ 197 1.8 ttoth enum chtype type; /* type of the dirent */ 198 1.8 ttoth uint8_t nsize; /* length of its name */ 199 1.8 ttoth uint8_t name[0]; /* name of the directory */ 200 1.1 ahoka }; 201 1.1 ahoka 202 1.11 andvar /* struct chfs_tmp_dnode - used temporarily while building a data node */ 203 1.1 ahoka struct chfs_tmp_dnode { 204 1.8 ttoth struct chfs_full_dnode *node; /* associated full dnode */ 205 1.8 ttoth uint64_t version; /* version of the tmp node */ 206 1.8 ttoth uint32_t data_crc; /* CRC of the data */ 207 1.8 ttoth uint16_t overlapped; /* is overlapped */ 208 1.8 ttoth struct chfs_tmp_dnode *next; /* next tmp node */ 209 1.1 ahoka }; 210 1.1 ahoka 211 1.8 ttoth /* struct chfs_tmp_dnode_info - tmp nodes are stored in rb trees */ 212 1.1 ahoka struct chfs_tmp_dnode_info { 213 1.8 ttoth struct rb_node rb_node; /* rb tree entry */ 214 1.8 ttoth struct chfs_tmp_dnode *tmpnode; /* associated tmp node */ 215 1.1 ahoka }; 216 1.1 ahoka 217 1.8 ttoth /* struct chfs_readinode_info - collection of tmp_dnodes */ 218 1.1 ahoka struct chfs_readinode_info { 219 1.8 ttoth struct rb_tree tdi_root; /* root of the rb tree */ 220 1.8 ttoth struct chfs_tmp_dnode_info *mdata_tn; /* metadata (eg: symlink) */ 221 1.8 ttoth uint64_t highest_version; /* highest version of the nodes */ 222 1.8 ttoth struct chfs_node_ref *latest_ref; /* latest node reference */ 223 1.1 ahoka }; 224 1.1 ahoka 225 1.8 ttoth /* struct chfs_full_dnode - full data node */ 226 1.1 ahoka struct chfs_full_dnode { 227 1.8 ttoth struct chfs_node_ref *nref; /* nref of the node */ 228 1.8 ttoth uint64_t ofs; /* offset of the data node */ 229 1.8 ttoth uint32_t size; /* size of the data node */ 230 1.8 ttoth uint32_t frags; /* number of fragmentations */ 231 1.1 ahoka }; 232 1.1 ahoka 233 1.8 ttoth /* struct chfs_node_frag - a fragment of a data node */ 234 1.1 ahoka struct chfs_node_frag { 235 1.8 ttoth struct rb_node rb_node; /* rb tree entry */ 236 1.8 ttoth struct chfs_full_dnode *node; /* associated full dnode */ 237 1.8 ttoth uint32_t size; /* size of the fragment */ 238 1.8 ttoth uint64_t ofs; /* offset of the fragment */ 239 1.1 ahoka }; 240 1.1 ahoka 241 1.8 ttoth /* find the first fragment of a data node */ 242 1.10 christos static __inline struct chfs_node_frag * 243 1.1 ahoka frag_first(struct rb_tree *tree) 244 1.1 ahoka { 245 1.1 ahoka struct chfs_node_frag *frag; 246 1.1 ahoka 247 1.1 ahoka frag = (struct chfs_node_frag *)RB_TREE_MIN(tree); 248 1.1 ahoka 249 1.1 ahoka return frag; 250 1.1 ahoka } 251 1.1 ahoka 252 1.8 ttoth /* find the last fragment of a data node */ 253 1.10 christos static __inline struct chfs_node_frag * 254 1.1 ahoka frag_last(struct rb_tree *tree) 255 1.1 ahoka { 256 1.1 ahoka struct chfs_node_frag *frag; 257 1.1 ahoka 258 1.1 ahoka frag = (struct chfs_node_frag *)RB_TREE_MAX(tree); 259 1.1 ahoka 260 1.1 ahoka return frag; 261 1.1 ahoka } 262 1.1 ahoka 263 1.8 ttoth /* iterate the fragtree */ 264 1.1 ahoka #define frag_next(tree, frag) (struct chfs_node_frag *)rb_tree_iterate(tree, frag, RB_DIR_RIGHT) 265 1.1 ahoka #define frag_prev(tree, frag) (struct chfs_node_frag *)rb_tree_iterate(tree, frag, RB_DIR_LEFT) 266 1.1 ahoka 267 1.1 ahoka 268 1.8 ttoth /* struct chfs_vnode_cache - in memory representation of a file or directory */ 269 1.1 ahoka struct chfs_vnode_cache { 270 1.8 ttoth /* 271 1.8 ttoth * void *p must be the first field of the structure 272 1.8 ttoth * but I can't remember where we use it and exactly for what 273 1.8 ttoth */ 274 1.1 ahoka void *p; 275 1.8 ttoth struct chfs_dirent_list scan_dirents; /* used during scanning */ 276 1.8 ttoth 277 1.8 ttoth struct chfs_node_ref *v; /* list of node informations */ 278 1.8 ttoth struct chfs_node_ref *dnode; /* list of data nodes */ 279 1.8 ttoth struct chfs_node_ref *dirents; /* list of directory entries */ 280 1.8 ttoth 281 1.8 ttoth uint64_t *vno_version; /* version of the vnode */ 282 1.8 ttoth uint64_t highest_version; /* highest version of dnodes */ 283 1.1 ahoka 284 1.8 ttoth uint8_t flags; /* flags */ 285 1.8 ttoth uint16_t state; /* actual state */ 286 1.8 ttoth ino_t vno; /* vnode number */ 287 1.8 ttoth ino_t pvno; /* vnode number of parent */ 288 1.8 ttoth struct chfs_vnode_cache* next; /* next element of vnode cache */ 289 1.8 ttoth uint32_t nlink; /* number of links to the file */ 290 1.1 ahoka }; 291 1.1 ahoka 292 1.8 ttoth /* struct chfs_eraseblock - representation of an eraseblock */ 293 1.1 ahoka struct chfs_eraseblock 294 1.1 ahoka { 295 1.8 ttoth uint32_t lnr; /* LEB number of the block*/ 296 1.1 ahoka 297 1.8 ttoth TAILQ_ENTRY(chfs_eraseblock) queue; /* queue entry */ 298 1.1 ahoka 299 1.8 ttoth uint32_t unchecked_size; /* GC doesn't checked yet */ 300 1.8 ttoth uint32_t used_size; /* size of nodes */ 301 1.8 ttoth uint32_t dirty_size; /* size of obsoleted nodes */ 302 1.8 ttoth uint32_t free_size; /* available size */ 303 1.8 ttoth uint32_t wasted_size; /* paddings */ 304 1.1 ahoka 305 1.8 ttoth struct chfs_node_ref *first_node; /* first node of the block */ 306 1.8 ttoth struct chfs_node_ref *last_node; /* last node of the block */ 307 1.8 ttoth 308 1.8 ttoth struct chfs_node_ref *gc_node; /* next node from the block 309 1.8 ttoth which isn't garbage collected yet */ 310 1.1 ahoka }; 311 1.1 ahoka 312 1.8 ttoth /* eraseblock queue */ 313 1.1 ahoka TAILQ_HEAD(chfs_eraseblock_queue, chfs_eraseblock); 314 1.1 ahoka 315 1.8 ttoth /* space allocation types */ 316 1.8 ttoth #define ALLOC_NORMAL 0 /* allocating for normal usage (write, etc.) */ 317 1.8 ttoth #define ALLOC_DELETION 1 /* allocating for deletion */ 318 1.8 ttoth #define ALLOC_GC 2 /* allocating for the GC */ 319 1.1 ahoka 320 1.8 ttoth /* struct garbage_collector_thread - descriptor of GC thread */ 321 1.1 ahoka struct garbage_collector_thread { 322 1.1 ahoka lwp_t *gcth_thread; 323 1.1 ahoka kcondvar_t gcth_wakeup; 324 1.1 ahoka bool gcth_running; 325 1.1 ahoka }; 326 1.1 ahoka 327 1.8 ttoth /* states of mounting */ 328 1.1 ahoka #define CHFS_MP_FLAG_SCANNING 2 329 1.1 ahoka #define CHFS_MP_FLAG_BUILDING 4 330 1.1 ahoka 331 1.8 ttoth /* struct chfs_mount - CHFS main descriptor structure */ 332 1.1 ahoka struct chfs_mount { 333 1.8 ttoth struct mount *chm_fsmp; /* general mount descriptor */ 334 1.8 ttoth struct chfs_ebh *chm_ebh; /* eraseblock handler */ 335 1.8 ttoth int chm_fs_version; /* version of the FS */ 336 1.8 ttoth uint64_t chm_gbl_version; /* */ 337 1.8 ttoth ino_t chm_max_vno; /* maximum of vnode numbers */ 338 1.8 ttoth ino_t chm_checked_vno; /* vnode number of the last checked node */ 339 1.8 ttoth unsigned int chm_flags; /* filesystem flags */ 340 1.8 ttoth 341 1.8 ttoth /* 342 1.8 ttoth * chm_lock_mountfields: 343 1.8 ttoth * Used to protect all the following fields. 344 1.8 ttoth */ 345 1.8 ttoth kmutex_t chm_lock_mountfields; 346 1.1 ahoka 347 1.8 ttoth struct chfs_vnode_cache **chm_vnocache_hash; /* hash table 348 1.8 ttoth of vnode caches */ 349 1.1 ahoka 350 1.8 ttoth /* 351 1.8 ttoth * chm_lock_vnocache: 352 1.1 ahoka * Used to protect the vnode cache. 353 1.1 ahoka * If you have to lock chm_lock_mountfields and also chm_lock_vnocache, 354 1.8 ttoth * you must lock chm_lock_mountfields first. 355 1.8 ttoth */ 356 1.1 ahoka kmutex_t chm_lock_vnocache; 357 1.1 ahoka 358 1.8 ttoth struct chfs_eraseblock *chm_blocks; /* list of eraseblocks */ 359 1.8 ttoth 360 1.8 ttoth struct chfs_node *chm_root; /* root node */ 361 1.1 ahoka 362 1.8 ttoth uint32_t chm_free_size; /* available space */ 363 1.8 ttoth uint32_t chm_dirty_size; /* size of contained obsoleted nodes */ 364 1.8 ttoth uint32_t chm_unchecked_size; /* GC doesn't checked yet */ 365 1.8 ttoth uint32_t chm_used_size; /* size of contained nodes */ 366 1.8 ttoth uint32_t chm_wasted_size; /* padding */ 367 1.1 ahoka 368 1.8 ttoth /* 369 1.8 ttoth * chm_lock_sizes: 370 1.1 ahoka * Used to protect the (free, used, etc.) sizes of the FS 371 1.1 ahoka * (and also the sizes of each eraseblock). 372 1.1 ahoka * If you have to lock chm_lock_mountfields and also chm_lock_sizes, 373 1.8 ttoth * you must lock chm_lock_mountfields first. 374 1.8 ttoth */ 375 1.1 ahoka kmutex_t chm_lock_sizes; 376 1.1 ahoka 377 1.8 ttoth /* 378 1.8 ttoth * eraseblock queues 379 1.11 andvar * free: completely free 380 1.8 ttoth * clean: contains only valid data 381 1.8 ttoth * dirty: contains valid and deleted data 382 1.8 ttoth * very_dirty: contains mostly deleted data (should be GC'd) 383 1.8 ttoth * erasable: doesn't contain valid data (should be erased) 384 1.8 ttoth * erase_pending: we can erase blocks from this queue 385 1.8 ttoth */ 386 1.1 ahoka struct chfs_eraseblock_queue chm_free_queue; 387 1.1 ahoka struct chfs_eraseblock_queue chm_clean_queue; 388 1.1 ahoka struct chfs_eraseblock_queue chm_dirty_queue; 389 1.1 ahoka struct chfs_eraseblock_queue chm_very_dirty_queue; 390 1.1 ahoka struct chfs_eraseblock_queue chm_erasable_pending_wbuf_queue; 391 1.1 ahoka struct chfs_eraseblock_queue chm_erase_pending_queue; 392 1.1 ahoka 393 1.8 ttoth /* reserved blocks */ 394 1.1 ahoka uint8_t chm_resv_blocks_deletion; 395 1.1 ahoka uint8_t chm_resv_blocks_write; 396 1.1 ahoka uint8_t chm_resv_blocks_gctrigger; 397 1.1 ahoka uint8_t chm_resv_blocks_gcmerge; 398 1.1 ahoka uint8_t chm_nospc_dirty; 399 1.1 ahoka 400 1.8 ttoth uint8_t chm_vdirty_blocks_gctrigger; /* GC trigger if the filesystem is 401 1.8 ttoth very dirty */ 402 1.1 ahoka 403 1.8 ttoth struct chfs_eraseblock *chm_nextblock; /* next block for usage */ 404 1.1 ahoka 405 1.8 ttoth struct garbage_collector_thread chm_gc_thread; /* descriptor of 406 1.8 ttoth GC thread */ 407 1.8 ttoth struct chfs_eraseblock *chm_gcblock; /* next block for GC */ 408 1.1 ahoka 409 1.8 ttoth int chm_nr_free_blocks; /* number of free blocks */ 410 1.8 ttoth int chm_nr_erasable_blocks; /* number of eraseable blocks */ 411 1.1 ahoka 412 1.8 ttoth /* FS constants, used during writing */ 413 1.1 ahoka int32_t chm_fs_bmask; 414 1.1 ahoka int32_t chm_fs_bsize; 415 1.1 ahoka int32_t chm_fs_qbmask; 416 1.1 ahoka int32_t chm_fs_bshift; 417 1.1 ahoka int32_t chm_fs_fmask; 418 1.1 ahoka int64_t chm_fs_qfmask; 419 1.1 ahoka 420 1.1 ahoka /* TODO will we use these? */ 421 1.1 ahoka unsigned int chm_pages_max; 422 1.1 ahoka unsigned int chm_pages_used; 423 1.1 ahoka struct chfs_pool chm_dirent_pool; 424 1.1 ahoka struct chfs_pool chm_node_pool; 425 1.1 ahoka struct chfs_str_pool chm_str_pool; 426 1.1 ahoka /**/ 427 1.1 ahoka 428 1.8 ttoth size_t chm_wbuf_pagesize; /* writebuffer's size */ 429 1.8 ttoth unsigned char* chm_wbuf; /* writebuffer */ 430 1.8 ttoth size_t chm_wbuf_ofs; /* actual offset of writebuffer */ 431 1.8 ttoth size_t chm_wbuf_len; /* actual length of writebuffer */ 432 1.8 ttoth 433 1.8 ttoth /* 434 1.8 ttoth * chm_lock_wbuf: 435 1.1 ahoka * Used to protect the write buffer. 436 1.1 ahoka * If you have to lock chm_lock_mountfields and also chm_lock_wbuf, 437 1.8 ttoth * you must lock chm_lock_mountfields first. 438 1.8 ttoth */ 439 1.1 ahoka krwlock_t chm_lock_wbuf; 440 1.1 ahoka }; 441 1.1 ahoka 442 1.1 ahoka /* 443 1.1 ahoka * TODO we should move here all of these from the bottom of the file 444 1.1 ahoka * Macros/functions to convert from generic data structures to chfs 445 1.1 ahoka * specific ones. 446 1.1 ahoka */ 447 1.1 ahoka 448 1.8 ttoth /* directory entry offsets */ 449 1.8 ttoth #define CHFS_OFFSET_DOT 0 /* this */ 450 1.8 ttoth #define CHFS_OFFSET_DOTDOT 1 /* parent */ 451 1.8 ttoth #define CHFS_OFFSET_EOF 2 /* after last */ 452 1.8 ttoth #define CHFS_OFFSET_FIRST 3 /* first */ 453 1.1 ahoka 454 1.1 ahoka 455 1.1 ahoka /*---------------------------------------------------------------------------*/ 456 1.1 ahoka 457 1.1 ahoka /* chfs_build.c */ 458 1.1 ahoka void chfs_calc_trigger_levels(struct chfs_mount *); 459 1.1 ahoka int chfs_build_filesystem(struct chfs_mount *); 460 1.4 ahoka void chfs_build_set_vnodecache_nlink(struct chfs_mount *, 461 1.4 ahoka struct chfs_vnode_cache *); 462 1.4 ahoka void chfs_build_remove_unlinked_vnode(struct chfs_mount *, 463 1.4 ahoka struct chfs_vnode_cache *, struct chfs_dirent_list *); 464 1.1 ahoka 465 1.1 ahoka /* chfs_scan.c */ 466 1.1 ahoka int chfs_scan_eraseblock(struct chfs_mount *, struct chfs_eraseblock *); 467 1.4 ahoka struct chfs_vnode_cache *chfs_scan_make_vnode_cache(struct chfs_mount *, 468 1.4 ahoka ino_t); 469 1.4 ahoka int chfs_scan_check_node_hdr(struct chfs_flash_node_hdr *); 470 1.4 ahoka int chfs_scan_check_vnode(struct chfs_mount *, 471 1.4 ahoka struct chfs_eraseblock *, void *, off_t); 472 1.4 ahoka int chfs_scan_mark_dirent_obsolete(struct chfs_mount *, 473 1.4 ahoka struct chfs_vnode_cache *, struct chfs_dirent *); 474 1.4 ahoka void chfs_add_fd_to_list(struct chfs_mount *, 475 1.4 ahoka struct chfs_dirent *, struct chfs_vnode_cache *); 476 1.4 ahoka int chfs_scan_check_dirent_node(struct chfs_mount *, 477 1.4 ahoka struct chfs_eraseblock *, void *, off_t); 478 1.4 ahoka int chfs_scan_check_data_node(struct chfs_mount *, 479 1.4 ahoka struct chfs_eraseblock *, void *, off_t); 480 1.4 ahoka int chfs_scan_classify_cheb(struct chfs_mount *, 481 1.4 ahoka struct chfs_eraseblock *); 482 1.4 ahoka 483 1.1 ahoka /* chfs_nodeops.c */ 484 1.4 ahoka int chfs_update_eb_dirty(struct chfs_mount *, 485 1.4 ahoka struct chfs_eraseblock *, uint32_t); 486 1.1 ahoka void chfs_add_node_to_list(struct chfs_mount *, struct chfs_vnode_cache *, 487 1.1 ahoka struct chfs_node_ref *, struct chfs_node_ref **); 488 1.7 ttoth void chfs_remove_node_from_list(struct chfs_mount *, struct chfs_vnode_cache *, 489 1.7 ttoth struct chfs_node_ref *, struct chfs_node_ref **); 490 1.7 ttoth void chfs_remove_and_obsolete(struct chfs_mount *, struct chfs_vnode_cache *, 491 1.7 ttoth struct chfs_node_ref *, struct chfs_node_ref **); 492 1.1 ahoka void chfs_add_fd_to_inode(struct chfs_mount *, 493 1.1 ahoka struct chfs_inode *, struct chfs_dirent *); 494 1.1 ahoka void chfs_add_vnode_ref_to_vc(struct chfs_mount *, struct chfs_vnode_cache *, 495 1.1 ahoka struct chfs_node_ref *); 496 1.1 ahoka struct chfs_node_ref* chfs_nref_next(struct chfs_node_ref *); 497 1.1 ahoka int chfs_nref_len(struct chfs_mount *, 498 1.1 ahoka struct chfs_eraseblock *, struct chfs_node_ref *); 499 1.1 ahoka int chfs_close_eraseblock(struct chfs_mount *, 500 1.1 ahoka struct chfs_eraseblock *); 501 1.1 ahoka int chfs_reserve_space_normal(struct chfs_mount *, uint32_t, int); 502 1.1 ahoka int chfs_reserve_space_gc(struct chfs_mount *, uint32_t); 503 1.1 ahoka int chfs_reserve_space(struct chfs_mount *, uint32_t); 504 1.1 ahoka void chfs_mark_node_obsolete(struct chfs_mount *, struct chfs_node_ref *); 505 1.1 ahoka 506 1.8 ttoth /* 507 1.8 ttoth * Find out the corresponding vnode cache from an nref. 508 1.8 ttoth * Every last element of a linked list of nrefs is the vnode cache. 509 1.8 ttoth */ 510 1.10 christos static __inline struct chfs_vnode_cache * 511 1.1 ahoka chfs_nref_to_vc(struct chfs_node_ref *nref) 512 1.1 ahoka { 513 1.8 ttoth /* iterate the whole list */ 514 1.1 ahoka while (nref->nref_next) { 515 1.1 ahoka nref = nref->nref_next; 516 1.1 ahoka if (nref->nref_lnr == REF_LINK_TO_NEXT) { 517 1.1 ahoka dbg("Link to next!\n"); 518 1.1 ahoka } else if (nref->nref_lnr == REF_EMPTY_NODE) { 519 1.1 ahoka dbg("Empty!\n"); 520 1.1 ahoka } 521 1.1 ahoka } 522 1.1 ahoka 523 1.1 ahoka struct chfs_vnode_cache *vc = (struct chfs_vnode_cache *) nref; 524 1.2 ahoka dbg("vno: %ju, pvno: %ju, hv: %ju, nlink: %u\n", (intmax_t )vc->vno, 525 1.2 ahoka (intmax_t )vc->pvno, (intmax_t )vc->highest_version, vc->nlink); 526 1.1 ahoka return vc; 527 1.1 ahoka } 528 1.1 ahoka 529 1.1 ahoka 530 1.1 ahoka /* chfs_malloc.c */ 531 1.1 ahoka int chfs_alloc_pool_caches(void); 532 1.1 ahoka void chfs_destroy_pool_caches(void); 533 1.1 ahoka struct chfs_vnode_cache* chfs_vnode_cache_alloc(ino_t); 534 1.1 ahoka void chfs_vnode_cache_free(struct chfs_vnode_cache *); 535 1.1 ahoka struct chfs_node_ref* chfs_alloc_node_ref( 536 1.1 ahoka struct chfs_eraseblock *); 537 1.4 ahoka void chfs_free_node_refs(struct chfs_eraseblock *); 538 1.1 ahoka struct chfs_dirent* chfs_alloc_dirent(int); 539 1.1 ahoka void chfs_free_dirent(struct chfs_dirent *); 540 1.1 ahoka struct chfs_flash_vnode* chfs_alloc_flash_vnode(void); 541 1.1 ahoka void chfs_free_flash_vnode(struct chfs_flash_vnode *); 542 1.1 ahoka struct chfs_flash_dirent_node* chfs_alloc_flash_dirent(void); 543 1.1 ahoka void chfs_free_flash_dirent(struct chfs_flash_dirent_node *); 544 1.1 ahoka struct chfs_flash_data_node* chfs_alloc_flash_dnode(void); 545 1.1 ahoka void chfs_free_flash_dnode(struct chfs_flash_data_node *); 546 1.1 ahoka struct chfs_node_frag* chfs_alloc_node_frag(void); 547 1.1 ahoka void chfs_free_node_frag(struct chfs_node_frag *); 548 1.1 ahoka struct chfs_node_ref* chfs_alloc_refblock(void); 549 1.4 ahoka void chfs_free_refblock(struct chfs_node_ref *); 550 1.1 ahoka struct chfs_full_dnode* chfs_alloc_full_dnode(void); 551 1.4 ahoka void chfs_free_full_dnode(struct chfs_full_dnode *); 552 1.1 ahoka struct chfs_tmp_dnode * chfs_alloc_tmp_dnode(void); 553 1.1 ahoka void chfs_free_tmp_dnode(struct chfs_tmp_dnode *); 554 1.1 ahoka struct chfs_tmp_dnode_info * chfs_alloc_tmp_dnode_info(void); 555 1.1 ahoka void chfs_free_tmp_dnode_info(struct chfs_tmp_dnode_info *); 556 1.1 ahoka 557 1.1 ahoka /* chfs_readinode.c */ 558 1.1 ahoka int chfs_read_inode(struct chfs_mount *, struct chfs_inode *); 559 1.1 ahoka int chfs_read_inode_internal(struct chfs_mount *, struct chfs_inode *); 560 1.7 ttoth void chfs_remove_frags_of_node(struct chfs_mount *, struct rb_tree *, 561 1.7 ttoth struct chfs_node_ref *); 562 1.7 ttoth void chfs_kill_fragtree(struct chfs_mount *, struct rb_tree *); 563 1.1 ahoka uint32_t chfs_truncate_fragtree(struct chfs_mount *, 564 1.1 ahoka struct rb_tree *, uint32_t); 565 1.1 ahoka int chfs_add_full_dnode_to_inode(struct chfs_mount *, 566 1.1 ahoka struct chfs_inode *, 567 1.1 ahoka struct chfs_full_dnode *); 568 1.1 ahoka int chfs_read_data(struct chfs_mount*, struct vnode *, 569 1.1 ahoka struct buf *); 570 1.1 ahoka 571 1.1 ahoka /* chfs_erase.c */ 572 1.4 ahoka int chfs_remap_leb(struct chfs_mount *); 573 1.1 ahoka 574 1.1 ahoka /* chfs_gc.c */ 575 1.1 ahoka void chfs_gc_trigger(struct chfs_mount *); 576 1.1 ahoka int chfs_gc_thread_should_wake(struct chfs_mount *); 577 1.1 ahoka void chfs_gc_thread(void *); 578 1.1 ahoka void chfs_gc_thread_start(struct chfs_mount *); 579 1.1 ahoka void chfs_gc_thread_stop(struct chfs_mount *); 580 1.1 ahoka int chfs_gcollect_pass(struct chfs_mount *); 581 1.1 ahoka 582 1.1 ahoka /* chfs_vfsops.c*/ 583 1.4 ahoka int chfs_gop_alloc(struct vnode *, off_t, off_t, int, kauth_cred_t); 584 1.4 ahoka int chfs_mountfs(struct vnode *, struct mount *); 585 1.1 ahoka 586 1.1 ahoka /* chfs_vnops.c */ 587 1.1 ahoka extern int (**chfs_vnodeop_p)(void *); 588 1.1 ahoka extern int (**chfs_specop_p)(void *); 589 1.1 ahoka extern int (**chfs_fifoop_p)(void *); 590 1.1 ahoka int chfs_lookup(void *); 591 1.1 ahoka int chfs_create(void *); 592 1.1 ahoka int chfs_mknod(void *); 593 1.1 ahoka int chfs_open(void *); 594 1.1 ahoka int chfs_close(void *); 595 1.1 ahoka int chfs_access(void *); 596 1.1 ahoka int chfs_getattr(void *); 597 1.1 ahoka int chfs_setattr(void *); 598 1.1 ahoka int chfs_chown(struct vnode *, uid_t, gid_t, kauth_cred_t); 599 1.1 ahoka int chfs_chmod(struct vnode *, int, kauth_cred_t); 600 1.1 ahoka int chfs_read(void *); 601 1.1 ahoka int chfs_write(void *); 602 1.1 ahoka int chfs_fsync(void *); 603 1.1 ahoka int chfs_remove(void *); 604 1.1 ahoka int chfs_link(void *); 605 1.1 ahoka int chfs_rename(void *); 606 1.1 ahoka int chfs_mkdir(void *); 607 1.1 ahoka int chfs_rmdir(void *); 608 1.1 ahoka int chfs_symlink(void *); 609 1.1 ahoka int chfs_readdir(void *); 610 1.1 ahoka int chfs_readlink(void *); 611 1.1 ahoka int chfs_inactive(void *); 612 1.1 ahoka int chfs_reclaim(void *); 613 1.1 ahoka int chfs_advlock(void *); 614 1.1 ahoka int chfs_strategy(void *); 615 1.1 ahoka int chfs_bmap(void *); 616 1.1 ahoka 617 1.1 ahoka /* chfs_vnode.c */ 618 1.1 ahoka struct vnode *chfs_vnode_lookup(struct chfs_mount *, ino_t); 619 1.1 ahoka int chfs_readvnode(struct mount *, ino_t, struct vnode **); 620 1.1 ahoka int chfs_readdirent(struct mount *, struct chfs_node_ref *, 621 1.1 ahoka struct chfs_inode *); 622 1.1 ahoka int chfs_makeinode(int, struct vnode *, struct vnode **, 623 1.5 ttoth struct componentname *, enum vtype ); 624 1.1 ahoka void chfs_set_vnode_size(struct vnode *, size_t); 625 1.1 ahoka void chfs_change_size_free(struct chfs_mount *, 626 1.1 ahoka struct chfs_eraseblock *, int); 627 1.1 ahoka void chfs_change_size_dirty(struct chfs_mount *, 628 1.1 ahoka struct chfs_eraseblock *, int); 629 1.1 ahoka void chfs_change_size_unchecked(struct chfs_mount *, 630 1.1 ahoka struct chfs_eraseblock *, int); 631 1.1 ahoka void chfs_change_size_used(struct chfs_mount *, 632 1.1 ahoka struct chfs_eraseblock *, int); 633 1.1 ahoka void chfs_change_size_wasted(struct chfs_mount *, 634 1.1 ahoka struct chfs_eraseblock *, int); 635 1.1 ahoka 636 1.1 ahoka /* chfs_vnode_cache.c */ 637 1.1 ahoka struct chfs_vnode_cache **chfs_vnocache_hash_init(void); 638 1.1 ahoka void chfs_vnocache_hash_destroy(struct chfs_vnode_cache **); 639 1.4 ahoka struct chfs_vnode_cache* chfs_vnode_cache_get(struct chfs_mount *, ino_t); 640 1.4 ahoka void chfs_vnode_cache_add(struct chfs_mount *, struct chfs_vnode_cache *); 641 1.4 ahoka void chfs_vnode_cache_remove(struct chfs_mount *, struct chfs_vnode_cache *); 642 1.1 ahoka 643 1.1 ahoka /* chfs_wbuf.c */ 644 1.4 ahoka int chfs_write_wbuf(struct chfs_mount*, 645 1.4 ahoka const struct iovec *, long, off_t, size_t *); 646 1.1 ahoka int chfs_flush_pending_wbuf(struct chfs_mount *); 647 1.1 ahoka 648 1.1 ahoka /* chfs_write.c */ 649 1.1 ahoka int chfs_write_flash_vnode(struct chfs_mount *, struct chfs_inode *, int); 650 1.1 ahoka int chfs_write_flash_dirent(struct chfs_mount *, struct chfs_inode *, 651 1.1 ahoka struct chfs_inode *, struct chfs_dirent *, ino_t, int); 652 1.1 ahoka int chfs_write_flash_dnode(struct chfs_mount *, struct vnode *, 653 1.1 ahoka struct buf *, struct chfs_full_dnode *); 654 1.4 ahoka int chfs_do_link(struct chfs_inode *, 655 1.5 ttoth struct chfs_inode *, const char *, int, enum chtype); 656 1.4 ahoka int chfs_do_unlink(struct chfs_inode *, 657 1.4 ahoka struct chfs_inode *, const char *, int); 658 1.1 ahoka 659 1.1 ahoka /* chfs_subr.c */ 660 1.1 ahoka size_t chfs_mem_info(bool); 661 1.1 ahoka struct chfs_dirent * chfs_dir_lookup(struct chfs_inode *, 662 1.1 ahoka struct componentname *); 663 1.5 ttoth int chfs_filldir (struct uio *, ino_t, const char *, int, enum chtype); 664 1.1 ahoka int chfs_chsize(struct vnode *, u_quad_t, kauth_cred_t); 665 1.1 ahoka int chfs_chflags(struct vnode *, int, kauth_cred_t); 666 1.1 ahoka void chfs_itimes(struct chfs_inode *, const struct timespec *, 667 1.1 ahoka const struct timespec *, const struct timespec *); 668 1.1 ahoka int chfs_update(struct vnode *, const struct timespec *, 669 1.1 ahoka const struct timespec *, int); 670 1.1 ahoka 671 1.1 ahoka /*---------------------------------------------------------------------------*/ 672 1.1 ahoka 673 1.1 ahoka /* Some inline functions temporarily placed here */ 674 1.8 ttoth 675 1.8 ttoth /* chfs_map_leb - corresponds to ebh_map_leb */ 676 1.10 christos static __inline int 677 1.1 ahoka chfs_map_leb(struct chfs_mount *chmp, int lnr) 678 1.1 ahoka { 679 1.1 ahoka int err; 680 1.1 ahoka 681 1.1 ahoka err = ebh_map_leb(chmp->chm_ebh, lnr); 682 1.1 ahoka if (err) 683 1.1 ahoka chfs_err("unmap leb %d failed, error: %d\n",lnr, err); 684 1.1 ahoka 685 1.1 ahoka return err; 686 1.1 ahoka 687 1.1 ahoka } 688 1.1 ahoka 689 1.8 ttoth /* chfs_unmap_leb - corresponds to ebh_unmap_leb */ 690 1.10 christos static __inline int 691 1.1 ahoka chfs_unmap_leb(struct chfs_mount *chmp, int lnr) 692 1.1 ahoka { 693 1.1 ahoka int err; 694 1.1 ahoka 695 1.1 ahoka err = ebh_unmap_leb(chmp->chm_ebh, lnr); 696 1.1 ahoka if (err) 697 1.1 ahoka chfs_err("unmap leb %d failed, error: %d\n",lnr, err); 698 1.1 ahoka 699 1.1 ahoka return err; 700 1.1 ahoka } 701 1.1 ahoka 702 1.8 ttoth /* chfs_read_leb - corresponds to ebh_read_leb */ 703 1.10 christos static __inline int 704 1.1 ahoka chfs_read_leb(struct chfs_mount *chmp, int lnr, char *buf, 705 1.1 ahoka int offset, int len, size_t *retlen) 706 1.1 ahoka { 707 1.1 ahoka int err; 708 1.1 ahoka 709 1.1 ahoka err = ebh_read_leb(chmp->chm_ebh, lnr, buf, offset, len, retlen); 710 1.1 ahoka if (err) 711 1.4 ahoka chfs_err("read leb %d:%d failed, error: %d\n", 712 1.4 ahoka lnr, offset, err); 713 1.1 ahoka 714 1.1 ahoka return err; 715 1.1 ahoka } 716 1.1 ahoka 717 1.8 ttoth /* chfs_write_leb - corresponds to ebh_write_leb */ 718 1.10 christos static __inline int chfs_write_leb(struct chfs_mount *chmp, int lnr, char *buf, 719 1.1 ahoka int offset, int len, size_t *retlen) 720 1.1 ahoka { 721 1.1 ahoka int err; 722 1.1 ahoka err = ebh_write_leb(chmp->chm_ebh, lnr, buf, offset, len, retlen); 723 1.1 ahoka if (err) 724 1.4 ahoka chfs_err("write leb %d:%d failed, error: %d\n", 725 1.4 ahoka lnr, offset, err); 726 1.1 ahoka 727 1.1 ahoka return err; 728 1.1 ahoka } 729 1.1 ahoka 730 1.1 ahoka /* --------------------------------------------------------------------- */ 731 1.1 ahoka 732 1.1 ahoka #define CHFS_PAGES_RESERVED (4 * 1024 * 1024 / PAGE_SIZE) 733 1.1 ahoka 734 1.1 ahoka static __inline size_t 735 1.1 ahoka CHFS_PAGES_MAX(struct chfs_mount *chmp) 736 1.1 ahoka { 737 1.1 ahoka size_t freepages; 738 1.1 ahoka 739 1.1 ahoka freepages = chfs_mem_info(false); 740 1.1 ahoka if (freepages < CHFS_PAGES_RESERVED) 741 1.1 ahoka freepages = 0; 742 1.1 ahoka else 743 1.1 ahoka freepages -= CHFS_PAGES_RESERVED; 744 1.1 ahoka 745 1.1 ahoka return MIN(chmp->chm_pages_max, freepages + chmp->chm_pages_used); 746 1.1 ahoka } 747 1.1 ahoka 748 1.1 ahoka #define CHFS_ITIMES(ip, acc, mod, cre) \ 749 1.1 ahoka while ((ip)->iflag & (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY)) \ 750 1.1 ahoka chfs_itimes(ip, acc, mod, cre) 751 1.4 ahoka 752 1.1 ahoka /* used for KASSERTs */ 753 1.1 ahoka #define IMPLIES(a, b) (!(a) || (b)) 754 1.1 ahoka #define IFF(a, b) (IMPLIES(a, b) && IMPLIES(b, a)) 755 1.1 ahoka 756 1.6 ttoth #endif /* _KERNEL */ 757 1.1 ahoka #endif /* __CHFS_H__ */ 758