www.pudn.com > drivers.rar > core.h


/****************************************************************************** 
 * Flash File System (ffs) 
 * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com 
 * 
 * ffs core functions 
 * 
 * $Id: core.h 1.80.1.15.1.36 Thu, 08 Jan 2004 15:05:23 +0100 tsj $ 
 * 
 ******************************************************************************/ 
 
#ifndef _CORE_H_ 
#define _CORE_H_ 
 
#ifndef TARGET 
#include "ffs.cfg" 
#endif 
 
#if (TARGET == 1) 
#include "rv/rv_defined_swe.h" 
#else 
#include "ffs/board/tffs.h" 
#endif 
 
/****************************************************************************** 
 * Compile option switches 
 ******************************************************************************/ 
 
// FFS compiled with extra test functionality 
#define FFS_TEST 1 
 
// Default max number of simultaneous open files 
#ifdef RVM_MSFE_SWE 
#define FFS_FD_MAX 20 
#else 
#define FFS_FD_MAX 10 
#endif 
 
#define FFS_RECLAIM_NEW 1 
 
/****************************************************************************** 
 * Compile constants 
 ******************************************************************************/ 
 
// FFS API version (in four-digit BCD format) 
#define FFS_API_VERSION ((uint16) 0x0642) 
 
// FFS_DRV_VERSION is in drv.h 
 
// TMFFS protocol version is in tmffs.h 
 
// Magic for determining (formatted) file system version. First two digits 
// represent major version, bottom two digits represent minor version. An 
// ffs code compiled for one major version X is compatible with any other 
// format version with major = X. Minor version is incremented when adding 
// new features that does not break compatibility. 
#define FFS_FORMAT_VERSION (0x0300) 
#define BLOCK_MAGIC_LOW    ('f'<<8|'F') // "Ffs#" 
#define BLOCK_MAGIC_HIGH   ('#'<<8|'s') 
#define BLOCK_MAGIC        ((BLOCK_MAGIC_HIGH << 8)|(BLOCK_MAGIC_LOW)) 
 
// Absolute maximum number of inodes allowed 
#define FFS_INODES_MAX 2048 
 
// Default maximum number of inodes allowed 
#define FFS_INODES_MAX_DEFAULT 1024 
 
// Default number of path components (limit due to recursiveness of 
// inodes_reclaim()) 
#define FFS_PATH_DEPTH_MAX 6 
 
// Maximum number of blocks (flash sectors) in a ffs system. FFS_BLOCKS_MAX 
// must be >= the number of blocks in the largest flash device memory 
// map. It is used to allocate the number of entries in the static bstat 
// array. 
#if	(LOCOSTO_LITE) 
#define FFS_BLOCKS_MAX 32 
#else 
#define FFS_BLOCKS_MAX 128 
#endif // LOCOSTO_LITE 
// Default size of journal file (represented as 256'ths of the blocksize) 
#define FFS_JOURNAL_SIZE_IN256THS 16  // one 16'ths of the block size.  
 
// Without the min size will the maximum of files (fs.blocks_files_max) in 
// one block be 32 files if the blocksize is 8kB! 
#define FFS_JOURNAL_SIZE_MIN 1024 
 
#define FFS_JOURNAL_NAME ".journal" 
 
// Default max size of file name (excluding null terminator) 
#define FFS_FILENAME_MAX 20 
 
// Maximum distance in age between youngest and oldest blocks 
#define FFS_DAGE_MAX 256 
#define FFS_DAGE_GAIN_MIN (FFS_DAGE_MAX / 4) 
#define FFS_DAGE_EARLY_WIDTH 64 
 
// Offset on file descriptors  
#define FFS_FD_OFFSET '1' 
 
// Number of free inodes and journal entries to keep for "emergencies" 
#define FFS_INODES_MARGIN  10 
#define FFS_JOURNAL_MARGIN 10 
#define FFS_REPLACEMENT_INODES_MAX 5 
 
/****************************************************************************** 
 * Macros used in both drv.c and core.c 
 ******************************************************************************/ 
 
// Convert a offset_t value to a block index 
#define offset2block(offset) (((uint32) offset) >> dev.binfo[0].size_ld) 
  
// Convert between offset and address 
#define offset2addr(offset) (dev.base + (offset)) 
 
// Size of a block 
#define blocksize(block) (1 << dev.binfo[block].size_ld) 
 
// Test if flag is set 
#define is_open_option(options, flags) ((options & flags) == flags) 
 
// Amount of reserved space.  
#define	RESERVED_LOW  2 * fs.journal_size  
#define RESERVED_NONE 0 
 
// We have to saturate because a recently reclaimed inodes block could 
// theoretically possess a high age 
#define saturate_dage(dage) (dage > (2*FFS_DAGE_MAX) ? (2*FFS_DAGE_MAX) : dage)  
 
// Macros to set flags and test bits in flash memory words (negative logic) 
#define BIT_SET(value, bits) ((value) & (~bits)) 
#define IS_BIT_SET(value, bits) (~(value) & (bits)) 
 
/****************************************************************************** 
 * External declarations 
 ******************************************************************************/ 
 
extern struct fs_s fs; 
extern struct block_stat_s bstat[FFS_BLOCKS_MAX]; 
 
extern struct ffs_stats_s stats; 
 
extern const struct block_info_s *binfo; 
 
 
/****************************************************************************** 
 * Block Types 
 ******************************************************************************/ 
 
// Block age, ie. number of times block has been erased 
typedef uint16 age_t; 
 
// Maximum age a block can have 
#define BLOCK_AGE_MAX 0xFFFF 
 
// ffs block status flags. These are stored in the first 2 bytes of 
// the ffs block in the flash sector. 
enum BLOCK_FLAGS { 
// Shared 
    BF_WRITING     =  0x0003,  //  
    BF_FREE        =  0x000C,  // free (preformatted and with block magic) 
    BF_LOST        =  0x3000,  // block is lost and will soon be erased 
// Data 
    BF_DATA        =  0x0030,  // data 
    BF_CLEANING    =  0x0C00,  // block is being cleaned 
// Inode 
    BF_INODES      =  0x0300,  // block contains inodes 
    BF_COPYING     =  0x0C00   // block is a coming inodes block 
}; 
 
enum BLOCK_STATES { 
    BF_IS_EMPTY       = ~(0), 
    BF_IS_WRITING     = ~(BF_WRITING), 
    BF_IS_FREE        = ~(BF_FREE | BF_WRITING), 
 
    BF_IS_DATA        = ~(BF_FREE | BF_WRITING | BF_DATA), 
    BF_IS_CLEANING    = ~(BF_FREE | BF_WRITING | BF_DATA | BF_CLEANING), 
    BF_IS_DATA_LOST   = ~(BF_FREE | BF_WRITING | BF_DATA | BF_CLEANING | BF_LOST), 
 
    BF_IS_COPYING     = ~(BF_FREE | BF_WRITING | BF_COPYING), 
    BF_IS_INODES      = ~(BF_FREE | BF_WRITING | BF_COPYING | BF_INODES), 
    BF_IS_INODES_LOST = ~(BF_FREE | BF_WRITING | BF_COPYING | BF_INODES | BF_LOST) 
}; 
 
// Header of each FFS block 
struct block_header_s { 
    uint16 magic_low;  // 32-bit magic number 
    uint16 magic_high; 
    uint16 version;    // FFS_FORMAT_VERSION used for formatting 
    age_t  age;        // number of times this block has been erased 
    uint16 flags;      // status flags of this block (BLOCK_FLAGS) 
    uint16 reserved0; 
    uint16 reserved1; 
    uint16 reserved2; 
}; 
 
// Important the below define MUST fit to the size of the header that is written 
#define BHEADER_SIZE sizeof(struct block_header_s) 
 
// Block status. This struct holds the status of one ffs block This relation 
// is always valid:  =  +  + . The block size 
// is obtained from the corresponding block_info structure.  and 
//  variables always holds a value which is a multiple of 
// FFS_GRANULARITY.  For inodes,  is number of inodes in active use, 
//  is number of deleted/lost inodes,  is the index of the 
// first free inode. 
struct block_stat_s { 
    blocksize_t used;    // number of used bytes 
    blocksize_t lost;    // number of lost bytes 
    uint16      flags;   // flash block flags (first 16 bits of each block) 
    uint16      objects; // number of valid objects 
}; 
 
 
/****************************************************************************** 
 * Object Types 
 ******************************************************************************/ 
 
// This enum MUST be in sync with the one in ffs.h. 
enum OBJECT_TYPE_E { 
    OTE_FILE    = 0x0E, 
    OTE_SEGMENT = 0x0C, 
    OTE_DIR     = 0x0A, 
    OTE_LINK    = 0x06, 
 
   // remaining filetypes are in ffs.h 
    OT_ERASED     = 0x3F, 
    OT_ERASED_MSb = 0x80, // Not a real flag 
 
    OT_VALID      = 0xCF, 
    OT_VALID_MSb  = 0x20, // Not a real flag 
 
    OT_REP        = 0x03, 
 
    OT_MASK       = 0x0E, 
    OT_MAX        = 4 
}; 
 
// This enum MUST be in sync with the one in ffs.h. 
enum OBJECT_FLAGS_E { 
    OFE_READONLY = 0x1, 
 
    // remaining object flags are in ffs.h 
    OF_ALL      = OFE_READONLY, // all flags allowed to be changed by user 
    OF_MASK     = 0xF1 
}; 
 
struct inode_s { 
    uint16      size; 
    uint8       reserved;  // size extension? 
    objflags_t  flags; 
    iref_t      child;     // link to first inode in dir (this inode is a dir) 
    iref_t      sibling;   // link to next inode in same directory 
    location_t  location;  // location of object 
    uint16      sequence;  //  
    uint16      updates;   // times this object has been updated 
}; 
 
struct file_descriptor_s {       
    char    *buf;          // Write buffer  
    iref_t  seghead;       // First chunk. Contain file name and optional data  
    iref_t  wch;           // Inode of work chunk (if chunk is read to buf) 
    int     fp;            // File pointer 
    int     wfp;           // Work file pointer always points to start of wch 
    int     size;          // Size of object (all chunks and data from buf) 
    int8    options;       // Open options 
    int     dirty;         // Indicate if buf contain valid data or not 
#if (FFS_SEEK_OPT == 1) 
	/* optimization on ffs_seek & ffs_read */ 
	iref_t  rch;			// Inode of read chunk 
	int     roffset;		// offset in read chunk  
#endif 
 
#if (FFS_READ_CACHE_ENBALE == 1) 
    /* Includes a simpler read buffering */ 
	iref_t  cache_i; 
	char 	*cache_read_buf; 
	int		cache_read_buf_size; 
#endif 
}; 
 
 
/****************************************************************************** 
 * Journal types and global fs structure 
 ******************************************************************************/ 
 
enum JOURNAL_FLAGS { 
    JOURNAL_WRITING  = 0x03,  // journal is being written to journal file 
    JOURNAL_READY    = 0x0C,  // journal has been written to journal file 
    JOURNAL_DONE     = 0x30   // journal has been written to ffs 
}; 
 
enum JOURNAL_STATES { 
    JOURNAL_IS_EMPTY    = ~(0), 
    JOURNAL_IS_WRITING  = ~(JOURNAL_WRITING), 
    JOURNAL_IS_READY    = ~(JOURNAL_WRITING | JOURNAL_READY), 
    JOURNAL_IS_DONE     = ~(JOURNAL_WRITING | JOURNAL_READY | JOURNAL_DONE) 
}; 
 
// Journal entry structure. Note that the state byte *MUST* be the first 
// byte of the structure! 
struct journal_s { 
    uint8      state;    // state of journal entry. 
    uint8      align;    // Dummy 
    iref_t     i;        // iref of object 
    iref_t     diri;     // iref of object that is this object's parent/sibling 
    iref_t     oldi;     // iref of object being replaced (only for updates) 
}; 
 
// RAM journal struct. Not saved in the flash journal file. 
struct journal_ram_s { 
    objflags_t flags;    // type of object 
    location_t location; // object's location 
    uint16     size;     // object's size 
    iref_t     repli;    // inode which is replaced 
}; 
 
// Main ffs info struct (initialised by ffs_initialize()) 
struct fs_s { 
    struct inode_s *inodes_addr; // base address of inodes 
    iref_t    root;            // iref of root directory 
    bref_t    inodes;          // index into bstat containing inode block 
    bref_t    newinodes;       // index into bstat containing new inode block 
    bref_t    blocks_free_min; // Number of spare blocks (0 or 1) 
    int       filesize_max;    // Max size of object data 
    int       reserved_space;  // Byte size of space reserved for journal relocation 
    iref_t    inodes_max;      // Max number of inodes possible 
    iref_t    inodes_high;     // number of inodes triggering an inodes_reclaim() 
    iref_t    objects_max;     // Max number of objects (valid inodes) allowed 
    iref_t    repi_table[FFS_REPLACEMENT_INODES_MAX];   // Table of replacement inodes 
    age_t     age_max;         // Max block age found by blocks_fsck() 
    iref_t    block_files_max; // max number of files in a block 
	iref_t	  block_files_reserved;    // Reserved for journals 
    uint16    format;          // FFS version as formatted in flash blocks 
    uint16    sequence;        // Object sequence number (for debug only) 
    effs_t    initerror;       // ffs_initialize() return code 
    uint8     flags;           // Global FFS options/flags 
    uint8     filename_max;    // Max length of a filename 
    uint8     path_depth_max;  // Max path componenents allowed 
    uint8     numfds;          // Mumber of available file descriptors 
    uint8     testflags; 
    int8      journal_depth;   // Current journal nesting depth (0 or 1) 
    iref_t    ijournal;        // iref of journal file 
    uint32    journal_size;    // Byte size of journal file 
    uint32    journal_pos;     // Byte offset to first free entry in journal file 
    struct journal_s journal; 
    struct journal_ram_s journal_ram; 
    uint8     fd_max;          // number of max available file descriptors 
    int       fd_buf_size;     // size of stream buffer 
    struct file_descriptor_s fd[FFS_FD_MAX]; 
    struct journal_s ojournal; // "Old" journal 
    struct journal_ram_s ojournal_ram; // "Old" journal 
    int       link_child;      // Link child in journal or not 
    iref_t    i_backup;        // Used by ffs_file_write() 
    uint8     is_reclaim_running; // Flag used to avoid reclaim loop 
    int       chunk_size_max;  // Max size of one chunk 
    int       chunk_size_min;  // Min size of one chunk  
    uint32    debug[4]; 
}; 
 
// This is the layout of the FFS performance statistics file. The file is 
// created with the name ".statistics" in the root directory at format. It 
// is updated after each data and inodes reclaim (after writing the file 
// that provoked the reclaim). The file is only updated if it exists, so if 
// the user does not want the file, she can erase it after the initial 
// format. FIXME: The use of the .statistics file is not yet implemented 
struct ffs_stats_s { 
    uint32 data_allocated;   // implemented 
 
    struct {                 // Not yet implemented 
        uint32 created; 
        uint32 updated; 
        uint32 read; 
    } files; 
    struct {                 // Not yet implemented 
        uint32 written[2]; 
        uint32 read[2]; 
    } bytes; 
    struct { 
        uint32 most_lost;    // Block candidate 
        uint32 youngest;     // Block candidate 
        uint32 valid[2];     // Amount of valid reclaimed data  
        uint32 lost[2];      // Amount of lost reclaimed data  
    } drec; 
    struct {  
        uint32 num;          // Number of inode reclaims 
        uint32 valid;        // Number of valid reclaimed inodes 
        uint32 lost;         // Number of lost reclaimed inodes 
    } irec; 
}; 
extern struct ffs_stats_s stats; 
 
 
/****************************************************************************** 
 * Miscellaneous types 
 ******************************************************************************/ 
 
// only used with (FFS_TEST == 1) 
enum TEST_RECOVERY { 
	JOURNAL_TEST_BASE       = 0x10, 
    JOURNAL_TEST_EMPTY, 
    JOURNAL_TEST_WRITING, 
    JOURNAL_TEST_READY, 
    JOURNAL_TEST_COMMITTING, 
    JOURNAL_TEST_COMMITTED, 
    JOURNAL_TEST_DONE, 
	BLOCK_COMMIT_BASE       = 0x20, 
    BLOCK_COMMIT_BEFORE, 
	BLOCK_COMMIT_NO_VALID, 
    BLOCK_COMMIT_OLD_FREE, 
    BLOCK_COMMIT_AFTER, 
	BLOCK_RECLAIM_BASE      = 0x40, 
	BLOCK_RECLAIM_ALLOC, 
	BLOCK_RECLAIM_CLEANING, 
	BLOCK_RECLAIM_NO_CLEAN, 
	BLOCK_RECOVER_OBJECTS 
}; 
 
enum FLASH_DATA { 
    FLASH_NULL8  = 0xFF, 
    FLASH_NULL16 = 0xFFFF, 
    FLASH_NULL32 = 0xFFFFFFFFL, 
    IREF_NULL    = FLASH_NULL16 
 }; 
 
 
// This enum MUST be in sync with the one in ffs.h. 
enum OBJECT_CONTROL { 
    // remaining object control codes are in ffs.h 
    OC_FS_FLAGS       =  80, 
    OC_TRACE_INIT     =  82, 
    OC_DEV_MANUFACT   =  88, 
    OC_DEV_DEVICE     =  89, 
 
    OC_DEBUG_FIRST    = 120, 
    OC_DEBUG_0        = 120, 
    OC_DEBUG_1        = 121, 
    OC_DEBUG_2        = 122, 
    OC_DEBUG_3        = 123, 
    OC_DEBUG_LAST     = 123, 
 
    OC_FS_TESTFLAGS   = 127 
}; 
 
enum FS_FLAGS { 
    FS_DIR_DATA   = 0x01   // allow directory objects to contain data. 
}; 
 
enum RECLAIM_CANDIDATE { 
    MOST_LOST, 
    MOST_UNUSED, 
    YOUNGEST 
}; 
 
/****************************************************************************** 
 * Macros 
 ******************************************************************************/ 
 
// Convert between location and offset 
#define location2offset(location) ((location) << dev.atomlog2) 
#define offset2location(offset) (((uint32) offset) >> dev.atomlog2) 
 
// test if object is valid (directory, file or symlink) 
#define is_object_valid(ip) (((ip->flags & OT_ERASED_MSb) != 0) && ((ip->flags & OT_VALID_MSb) == 0)) 
 
#define is_object_erased(ip) ((ip->flags & OT_ERASED_MSb)== 0) 
 
// test if object is of a specific type (and valid) 
#define is_object(ip, type) (is_object_valid(ip) && ((ip->flags & OT_MASK) == ((type) & OT_MASK))) 
 
// test if block is in a specific state 
#define is_block(block, state) (bstat[block].flags == (uint16) (state)) 
 
// test if block has certain flags set 
#define is_block_flag(block, bits) (IS_BIT_SET(bstat[block].flags, (bits))) 
 
// convert an object's data address to the address of the object's name 
#define addr2name(addr) (addr) 
 
// Convert a size to an aligned size 
#define atomalign(size) (((size) + dev.atomsize-1) & ~dev.atomnotmask) 
#define wordalign(size) (((size) + 3) & ~3) 
#define halfwordalign(size) (((size) + 1) & ~1) 
 
#define inode_addr(i)   (fs.inodes_addr + i) 
 
#define JOURNAL_POS_INITIAL (wordalign(2 + sizeof(FFS_JOURNAL_NAME) + 1)) 
 
#define get_child(ip) (ip->child != 0 ? ip->child : lookup_child(ip)) 
#define get_sibling(ip) (ip->sibling != 0 ? ip->sibling : lookup_sibling(ip)) 
 
/****************************************************************************** 
 * Types used for power-fail framework 
 ******************************************************************************/ 
 
enum POWERFAIL_MODE { 
    PFM_NOINIT        = 0x001,	// Skip initialization after powerfail 
    PFM_RANDOM        = 0x002,	// Any write can trigger a powerfail 
    PFM_NEXTINODE     = 0x004,	// Domain, use inode addr as base addr 
    PFM_BLOCKHEADER   = 0x008,	// Domain, use block header addr as base addr 
    PFM_JOURNAL       = 0x010, 
    PFM_DIRI          = 0x020, 
    PFM_OLDI          = 0x040, 
    PFM_CHUNK         = 0x080, 
    PFM_ERASE         = 0x100, 
    PFM_NEXTERASE     = 0x200 
}; 
 
// All inode releated powerfail modes 
#define PFM_INODES (PFM_NEXTINODE | PFM_DIRI | PFM_OLDI)  
#define PFM_JOURNALING (PFM_JOURNAL | PFM_INODES)  
 
#if (TARGET == 0) 
 
void powerfail_write(volatile uint16 *addr, uint16 value); 
void powerfail_erase(uint8 block); 
void powerfail_domain_begin(int domain); 
void powerfail_domain_end(void); 
void powerfail_set_addr(int addr); 
 
#define POWERFAIL_DOMAIN_BEGIN(domain) powerfail_domain_begin(domain) 
#define POWERFAIL_DOMAIN_END()         powerfail_domain_end() 
#define POWERFAIL_SET_ADDR(addr)       powerfail_set_addr(addr) 
#define POWERFAIL_BOUNDARY(where)      powerfail.boundary = where 
#define POWERFAIL_WRITE(addr, value)   powerfail_write(addr, value) 
#define POWERFAIL_ERASE(block)         powerfail_erase(block) 
#define POWERFAIL_ENABLED (powerfail.enable > 0) 
 
#else  
 
#define POWERFAIL_DOMAIN_BEGIN(domain) 
#define POWERFAIL_DOMAIN_END()  
#define POWERFAIL_SET_ADDR(addr) 
#define POWERFAIL_BOUNDARY(where) 
#define POWERFAIL_WRITE(addr, value)  
#define POWERFAIL_ERASE(block)        
#define POWERFAIL_ENABLED (0) 
 
#endif 
 
/****************************************************************************** 
 * Function prototypes 
 ******************************************************************************/ 
 
// Helper functions 
 
effs_t is_filename(const char *s); 
int ffs_strlen(const char *s); 
int ffs_strcmp(const char *s, const char *p); 
char *addr2data(const char *addr, const struct inode_s *ip); 
 
int object_datasize(iref_t i); 
iref_t is_readonly(iref_t i, const char *name); 
iref_t dir_traverse(iref_t i, iref_t *entries); 
 
bref_t block_alloc(bref_t n, uint16 flags); 
bref_t block_alloc_try(bref_t *n); 
void block_flags_write(uint8 block, uint16 flags); 
 
offset_t data_alloc(int size); 
offset_t data_alloc_try(int size); 
offset_t data_reserved_alloc(int size); 
 
iref_t inode_alloc(void); 
 
effs_t is_fd_valid(fd_t fdi); 
effs_t is_offset_in_buf(int offset, fd_t fdi); 
 
iref_t chunk_alloc(int realsize, int is_journal, offset_t *offset);   
 
iref_t inode_alloc_try(void); 
fd_t get_fdi(iref_t i); 
 
offset_t data_prealloc(int realsize); 
 
iref_t get_repi(iref_t i); 
iref_t lookup_child(struct inode_s *ip); 
iref_t lookup_sibling(struct inode_s *ip); 
 
// Functions used by API 
 
effs_t object_update(iref_t oldi); 
iref_t object_create(const char *name, const char *buf, int size, 
                         iref_t dir); 
int file_read(const char *name, void *addr, int size); 
int stream_read(fd_t fdi, void *src, int size); 
int object_read(const char *name, char *buf, int size, int linkflag); 
 
iref_t object_stat(const char *name, struct xstat_s *stat, 
                       int linkflag, int fdi, int extended); 
effs_t object_remove(iref_t i); 
iref_t object_rename(iref_t oldi, const char *newname, iref_t newdir); 
effs_t object_control(iref_t i, int8 action, int value); 
int object_truncate(const char *pathname, fd_t fdi, offset_t length); 
iref_t object_lookup(const char *path, char **leaf, iref_t *dir); 
iref_t object_lookup_once(const char *path, char **leaf, iref_t *dir); 
iref_t dir_open(const char *name); 
iref_t dir_next (iref_t dir, iref_t i, char *name, int8 size); 
 
 
// Journalling 
 
void journal_begin(iref_t oldi); 
void journal_end(uint8 type); 
void journal_commit(uint8 type); 
int journal_push(void); 
int journal_pop(void); 
iref_t journal_create(iref_t oldi); 
effs_t journal_init(iref_t i); 
 
// Replacementinode 
void validate_replacementinode(struct journal_s *addr); 
void create_replacementinode(struct journal_s *old_addr); 
 
// Format, Init and Reclaim' 
 
void block_preformat(bref_t b, age_t age); 
effs_t fs_preformat(void); 
effs_t is_formattable(int8 flag); 
effs_t fs_format(const char *fsname_and_options); 
 
effs_t ffs_initialize(void); 
void fs_params_init(const char *p); 
blocksize_t block_used(bref_t b); 
 
effs_t ffs_begin(void); 
int ffs_end(int error); 
 
int block_reclaim(bref_t b); 
int blocks_reclaim(void); 
void block_commit(void); 
 
iref_t data_reclaim(void); 
int data_reclaim_try(void); 
iref_t data_block_reclaim(bref_t b, int reclaim_candidate); 
iref_t object_relocate(iref_t oldi); 
iref_t block_clean(bref_t b); 
 
void block_free(bref_t block); 
 
void inodes_set(iref_t i); 
effs_t inodes_reclaim(void); 
 
int reclaim(void); 
 
// Internally used functions 
 
effs_t file_read_int(const char *path, void *src, int size); 
effs_t file_update(const char *path, void *src, int size); 
 
int statistics_file_create(void); 
int statistics_write(void); 
void statistics_init(void); 
void statistics_update_drec(int valid, int lost, int candidate); 
void statistics_update_irec(int valid, int lost); 
void ffs_panic(int error); 
 
// Chunk Operations 
iref_t segment_create(const char *buf, int size, iref_t dir); 
int segment_datasize(const struct inode_s *ip); 
int segment_read(iref_t i, char *buf, int size, int offset); 
#if (FFS_READ_CACHE_ENBALE == 1) 
int segment_read_cache(fd_t fdi,iref_t i, char *buf, int size, int offset); 
#endif 
iref_t segment_next(iref_t i); 
iref_t segment_traverse(iref_t i, iref_t *entries); 
int segfile_seek(iref_t in_i, int in_pos,  
                     iref_t *out_i, int *out_pos_i); 
iref_t chunk_traverse(iref_t i); 
effs_t datasync(fd_t fdi); 
// debug/test functions 
 
void tr_bstat(void); 
void tr_fd(fd_t fdi); 
 
// These prototypes really belong in ffs.h but as they have not been 
// implemented, we will not show these prototypes to application 
// programmers. 
//effs_t fcntl(fd_t fd, int8 action, uint32 *param); 
 
#endif // _CORE_H_