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