Home | History | Annotate | Line # | Download | only in chfs
chfs.h revision 1.9.16.1
      1  1.9.16.1  pgoyette /*	$NetBSD: chfs.h,v 1.9.16.1 2018/04/22 07:20:29 pgoyette 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.9.16.1  pgoyette 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.8     ttoth /* struct chfs_tmp_dnode - used temporarly 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.9.16.1  pgoyette 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.9.16.1  pgoyette 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.8     ttoth 	 * free: completly 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.9.16.1  pgoyette 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.9.16.1  pgoyette 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.9.16.1  pgoyette 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.9.16.1  pgoyette 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.9.16.1  pgoyette 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