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