1 /* $NetBSD: chfs.h,v 1.9 2015/01/11 17:29:57 hannken Exp $ */
4 * Copyright (c) 2010 Department of Software Engineering,
5 * University of Szeged, Hungary
6 * Copyright (C) 2009 Ferenc Havasi <havasi@inf.u-szeged.hu>
7 * Copyright (C) 2009 Zoltan Sogor <weth@inf.u-szeged.hu>
8 * Copyright (C) 2009 David Tengeri <dtengeri@inf.u-szeged.hu>
9 * Copyright (C) 2009 Tamas Toth <ttoth@inf.u-szeged.hu>
10 * Copyright (C) 2010 Adam Hoka <ahoka@NetBSD.org>
11 * All rights reserved.
13 * This code is derived from software contributed to The NetBSD Foundation
14 * by the Department of Software Engineering, University of Szeged, Hungary
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
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.
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
45 #define DBG_MSG /* debug messages */
46 #define DBG_MSG_GC /* garbage collector's debug messages */
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>
55 #include <sys/queue.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>
66 #include <sys/module.h>
67 #include <sys/dirent.h>
69 #include <ufs/ufs/quota.h>
70 #include <ufs/ufs/ufsmount.h>
71 #include <ufs/ufs/dir.h>
73 /* XXX shouldnt be defined here, but needed by chfs_inode.h */
74 TAILQ_HEAD(chfs_dirent_list
, chfs_dirent
);
76 #include "chfs_pool.h"
81 #include "chfs_inode.h"
83 /* padding - last two bits used for node masks */
84 #define CHFS_PAD(x) (((x)+3)&~3)
89 #define MOUNT_CHFS "chfs"
90 #endif /* MOUNT_CHFS */
92 /* state of a vnode */
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() */
104 /* size of the vnode cache (hashtable) */
105 #define VNODECACHE_SIZE 128
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))
120 /* eraseblock states */
122 CHFS_BLK_STATE_FREE
= 100,
123 CHFS_BLK_STATE_CLEAN
,
124 CHFS_BLK_STATE_PARTDIRTY
,
125 CHFS_BLK_STATE_ALLDIRTY
128 extern struct pool chfs_inode_pool
;
129 extern const struct genfs_ops chfs_genfsops
;
131 /* struct chfs_node_ref - a reference to a node which is on the media */
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 */
140 * constants for allocating node refs
141 * they're allocated in blocks
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)
147 /* node masks - last two bits of the nodes ("state" of an nref) */
149 CHFS_NORMAL_NODE_MASK
,
150 CHFS_UNCHECKED_NODE_MASK
,
151 CHFS_OBSOLETE_NODE_MASK
,
152 CHFS_PRISTINE_NODE_MASK
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) \
159 (ref)->nref_offset = CHFS_GET_OFS((ref)->nref_offset) | CHFS_NORMAL_NODE_MASK; \
162 #define CHFS_GET_OFS(ofs) (ofs & ~ 3)
165 * Nrefs are allocated in blocks, get the (in-memory) next. Usually the next
166 * doesn't belongs to the same vnode.
168 static inline struct chfs_node_ref
*
169 node_next(struct chfs_node_ref
*nref
)
171 /* step to the next nref in the same block */
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
;
181 /* REF_EMPTY_NODE means that this is the last node */
182 if (nref
->nref_lnr
== REF_EMPTY_NODE
) {
189 /* struct chfs_dirent - full representation of a directory entry */
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 */
202 /* struct chfs_tmp_dnode - used temporarly 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 */
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 */
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 */
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 */
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 */
241 /* find the first fragment of a data node */
242 static inline struct chfs_node_frag
*
243 frag_first(struct rb_tree
*tree
)
245 struct chfs_node_frag
*frag
;
247 frag
= (struct chfs_node_frag
*)RB_TREE_MIN(tree
);
252 /* find the last fragment of a data node */
253 static inline struct chfs_node_frag
*
254 frag_last(struct rb_tree
*tree
)
256 struct chfs_node_frag
*frag
;
258 frag
= (struct chfs_node_frag
*)RB_TREE_MAX(tree
);
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)
268 /* struct chfs_vnode_cache - in memory representation of a file or directory */
269 struct chfs_vnode_cache
{
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
275 struct chfs_dirent_list scan_dirents
; /* used during scanning */
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 */
281 uint64_t *vno_version
; /* version of the vnode */
282 uint64_t highest_version
; /* highest version of dnodes */
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 */
292 /* struct chfs_eraseblock - representation of an eraseblock */
293 struct chfs_eraseblock
295 uint32_t lnr
; /* LEB number of the block*/
297 TAILQ_ENTRY(chfs_eraseblock
) queue
; /* queue entry */
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 */
305 struct chfs_node_ref
*first_node
; /* first node of the block */
306 struct chfs_node_ref
*last_node
; /* last node of the block */
308 struct chfs_node_ref
*gc_node
; /* next node from the block
309 which isn't garbage collected yet */
312 /* eraseblock queue */
313 TAILQ_HEAD(chfs_eraseblock_queue
, chfs_eraseblock
);
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 */
320 /* struct garbage_collector_thread - descriptor of GC thread */
321 struct garbage_collector_thread
{
323 kcondvar_t gcth_wakeup
;
327 /* states of mounting */
328 #define CHFS_MP_FLAG_SCANNING 2
329 #define CHFS_MP_FLAG_BUILDING 4
331 /* struct chfs_mount - CHFS main descriptor structure */
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 */
342 * chm_lock_mountfields:
343 * Used to protect all the following fields.
345 kmutex_t chm_lock_mountfields
;
347 struct chfs_vnode_cache
**chm_vnocache_hash
; /* hash table
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.
356 kmutex_t chm_lock_vnocache
;
358 struct chfs_eraseblock
*chm_blocks
; /* list of eraseblocks */
360 struct chfs_node
*chm_root
; /* root node */
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 */
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.
375 kmutex_t chm_lock_sizes
;
379 * free: completly 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
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
;
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
;
400 uint8_t chm_vdirty_blocks_gctrigger
; /* GC trigger if the filesystem is
403 struct chfs_eraseblock
*chm_nextblock
; /* next block for usage */
405 struct garbage_collector_thread chm_gc_thread
; /* descriptor of
407 struct chfs_eraseblock
*chm_gcblock
; /* next block for GC */
409 int chm_nr_free_blocks
; /* number of free blocks */
410 int chm_nr_erasable_blocks
; /* number of eraseable blocks */
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
;
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
;
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 */
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.
439 krwlock_t chm_lock_wbuf
;
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
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 */
455 /*---------------------------------------------------------------------------*/
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
*);
466 int chfs_scan_eraseblock(struct chfs_mount
*, struct chfs_eraseblock
*);
467 struct chfs_vnode_cache
*chfs_scan_make_vnode_cache(struct chfs_mount
*,
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
*);
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
*);
507 * Find out the corresponding vnode cache from an nref.
508 * Every last element of a linked list of nrefs is the vnode cache.
510 static inline struct chfs_vnode_cache
*
511 chfs_nref_to_vc(struct chfs_node_ref
*nref
)
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
) {
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
);
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
*);
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
*,
567 struct chfs_full_dnode
*);
568 int chfs_read_data(struct chfs_mount
*, struct vnode
*,
572 int chfs_remap_leb(struct chfs_mount
*);
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
*);
583 int chfs_gop_alloc(struct vnode
*, off_t
, off_t
, int, kauth_cred_t
);
584 int chfs_mountfs(struct vnode
*, struct mount
*);
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 *);
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);
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
*);
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
*);
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);
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);
671 /*---------------------------------------------------------------------------*/
673 /* Some inline functions temporarily placed here */
675 /* chfs_map_leb - corresponds to ebh_map_leb */
677 chfs_map_leb(struct chfs_mount
*chmp
, int lnr
)
681 err
= ebh_map_leb(chmp
->chm_ebh
, lnr
);
683 chfs_err("unmap leb %d failed, error: %d\n",lnr
, err
);
689 /* chfs_unmap_leb - corresponds to ebh_unmap_leb */
691 chfs_unmap_leb(struct chfs_mount
*chmp
, int lnr
)
695 err
= ebh_unmap_leb(chmp
->chm_ebh
, lnr
);
697 chfs_err("unmap leb %d failed, error: %d\n",lnr
, err
);
702 /* chfs_read_leb - corresponds to ebh_read_leb */
704 chfs_read_leb(struct chfs_mount
*chmp
, int lnr
, char *buf
,
705 int offset
, int len
, size_t *retlen
)
709 err
= ebh_read_leb(chmp
->chm_ebh
, lnr
, buf
, offset
, len
, retlen
);
711 chfs_err("read leb %d:%d failed, error: %d\n",
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
)
722 err
= ebh_write_leb(chmp
->chm_ebh
, lnr
, buf
, offset
, len
, retlen
);
724 chfs_err("write leb %d:%d failed, error: %d\n",
730 /* --------------------------------------------------------------------- */
732 #define CHFS_PAGES_RESERVED (4 * 1024 * 1024 / PAGE_SIZE)
734 static __inline
size_t
735 CHFS_PAGES_MAX(struct chfs_mount
*chmp
)
739 freepages
= chfs_mem_info(false);
740 if (freepages
< CHFS_PAGES_RESERVED
)
743 freepages
-= CHFS_PAGES_RESERVED
;
745 return MIN(chmp
->chm_pages_max
, freepages
+ chmp
->chm_pages_used
);
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)
752 /* used for KASSERTs */
753 #define IMPLIES(a, b) (!(a) || (b))
754 #define IFF(a, b) (IMPLIES(a, b) && IMPLIES(b, a))
757 #endif /* __CHFS_H__ */