Initial version
This commit is contained in:
@ -0,0 +1,257 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
*/
|
||||
#ifndef REDCORE_H
|
||||
#define REDCORE_H
|
||||
|
||||
|
||||
#include <redstat.h>
|
||||
#include <redvolume.h>
|
||||
#include "rednodes.h"
|
||||
#include "redcoremacs.h"
|
||||
#include "redcorevol.h"
|
||||
|
||||
|
||||
#define META_SIG_MASTER (0x5453414DU) /* 'MAST' */
|
||||
#define META_SIG_METAROOT (0x4154454DU) /* 'META' */
|
||||
#define META_SIG_IMAP (0x50414D49U) /* 'IMAP' */
|
||||
#define META_SIG_INODE (0x444F4E49U) /* 'INOD' */
|
||||
#define META_SIG_DINDIR (0x494C4244U) /* 'DBLI' */
|
||||
#define META_SIG_INDIR (0x49444E49U) /* 'INDI' */
|
||||
|
||||
|
||||
REDSTATUS RedIoRead(uint8_t bVolNum, uint32_t ulBlockStart, uint32_t ulBlockCount, void *pBuffer);
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
REDSTATUS RedIoWrite(uint8_t bVolNum, uint32_t ulBlockStart, uint32_t ulBlockCount, const void *pBuffer);
|
||||
REDSTATUS RedIoFlush(uint8_t bVolNum);
|
||||
#endif
|
||||
|
||||
|
||||
/** Indicates a block buffer is dirty (its contents are different than the
|
||||
contents of the corresponding block on disk); or, when passed into
|
||||
RedBufferGet(), indicates that the buffer should be marked dirty.
|
||||
*/
|
||||
#define BFLAG_DIRTY ((uint16_t) 0x0001U)
|
||||
|
||||
/** Tells RedBufferGet() that the buffer is for a newly allocated block, and its
|
||||
contents should be zeroed instead of being read from disk. Always used in
|
||||
combination with BFLAG_DIRTY.
|
||||
*/
|
||||
#define BFLAG_NEW ((uint16_t) 0x0002U)
|
||||
|
||||
/** Indicates that a block buffer is a master block (MASTERBLOCK) metadata node.
|
||||
*/
|
||||
#define BFLAG_META_MASTER ((uint16_t)(0x0004U | BFLAG_META))
|
||||
|
||||
/** Indicates that a block buffer is an imap (IMAPNODE) metadata node.
|
||||
*/
|
||||
#define BFLAG_META_IMAP ((uint16_t)(0x0008U | BFLAG_META))
|
||||
|
||||
/** Indicates that a block buffer is an inode (INODE) metadata node.
|
||||
*/
|
||||
#define BFLAG_META_INODE ((uint16_t)(0x0010U | BFLAG_META))
|
||||
|
||||
/** Indicates that a block buffer is an indirect (INDIR) metadata node.
|
||||
*/
|
||||
#define BFLAG_META_INDIR ((uint16_t)(0x0020U | BFLAG_META))
|
||||
|
||||
/** Indicates that a block buffer is a double indirect (DINDIR) metadata node.
|
||||
*/
|
||||
#define BFLAG_META_DINDIR ((uint16_t)(0x0040U | BFLAG_META))
|
||||
|
||||
/** Indicates that a block buffer is a metadata node. Callers of RedBufferGet()
|
||||
should not use this flag; instead, use one of the BFLAG_META_* flags.
|
||||
*/
|
||||
#define BFLAG_META ((uint16_t) 0x8000U)
|
||||
|
||||
|
||||
void RedBufferInit(void);
|
||||
REDSTATUS RedBufferGet(uint32_t ulBlock, uint16_t uFlags, void **ppBuffer);
|
||||
void RedBufferPut(const void *pBuffer);
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
REDSTATUS RedBufferFlush(uint32_t ulBlockStart, uint32_t ulBlockCount);
|
||||
void RedBufferDirty(const void *pBuffer);
|
||||
void RedBufferBranch(const void *pBuffer, uint32_t ulBlockNew);
|
||||
#if (REDCONF_API_POSIX == 1) || FORMAT_SUPPORTED
|
||||
void RedBufferDiscard(const void *pBuffer);
|
||||
#endif
|
||||
#endif
|
||||
REDSTATUS RedBufferDiscardRange(uint32_t ulBlockStart, uint32_t ulBlockCount);
|
||||
|
||||
|
||||
/** @brief Allocation state of a block.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ALLOCSTATE_FREE, /**< Free and may be allocated; writeable. */
|
||||
ALLOCSTATE_USED, /**< In-use and transacted; not writeable. */
|
||||
ALLOCSTATE_NEW, /**< In-use but not transacted; writeable. */
|
||||
ALLOCSTATE_AFREE /**< Will become free after a transaction; not writeable. */
|
||||
} ALLOCSTATE;
|
||||
|
||||
REDSTATUS RedImapBlockGet(uint8_t bMR, uint32_t ulBlock, bool *pfAllocated);
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
REDSTATUS RedImapBlockSet(uint32_t ulBlock, bool fAllocated);
|
||||
REDSTATUS RedImapAllocBlock(uint32_t *pulBlock);
|
||||
#endif
|
||||
REDSTATUS RedImapBlockState(uint32_t ulBlock, ALLOCSTATE *pState);
|
||||
|
||||
#if REDCONF_IMAP_INLINE == 1
|
||||
REDSTATUS RedImapIBlockGet(uint8_t bMR, uint32_t ulBlock, bool *pfAllocated);
|
||||
REDSTATUS RedImapIBlockSet(uint32_t ulBlock, bool fAllocated);
|
||||
#endif
|
||||
|
||||
#if REDCONF_IMAP_EXTERNAL == 1
|
||||
REDSTATUS RedImapEBlockGet(uint8_t bMR, uint32_t ulBlock, bool *pfAllocated);
|
||||
REDSTATUS RedImapEBlockSet(uint32_t ulBlock, bool fAllocated);
|
||||
uint32_t RedImapNodeBlock(uint8_t bMR, uint32_t ulImapNode);
|
||||
#endif
|
||||
|
||||
|
||||
/** @brief Cached inode structure.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t ulInode; /**< The inode number of the cached inode. */
|
||||
#if REDCONF_API_POSIX == 1
|
||||
bool fDirectory; /**< True if the inode is a directory. */
|
||||
#endif
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
bool fBranched; /**< True if the inode is branched (writeable). */
|
||||
bool fDirty; /**< True if the inode buffer is dirty. */
|
||||
#endif
|
||||
bool fCoordInited; /**< True after the first seek. */
|
||||
|
||||
INODE *pInodeBuf; /**< Pointer to the inode buffer. */
|
||||
#if DINDIR_POINTERS > 0U
|
||||
DINDIR *pDindir; /**< Pointer to the double indirect node buffer. */
|
||||
#endif
|
||||
#if REDCONF_DIRECT_POINTERS < INODE_ENTRIES
|
||||
INDIR *pIndir; /**< Pointer to the indirect node buffer. */
|
||||
#endif
|
||||
uint8_t *pbData; /**< Pointer to the data block buffer. */
|
||||
|
||||
/* All the members below this point are part of the seek coordinates; see
|
||||
RedInodeDataSeek().
|
||||
*/
|
||||
uint32_t ulLogicalBlock; /**< Logical block offset into the inode. */
|
||||
#if DINDIR_POINTERS > 0U
|
||||
uint32_t ulDindirBlock; /**< Physical block number of the double indirect node. */
|
||||
#endif
|
||||
#if REDCONF_DIRECT_POINTERS < INODE_ENTRIES
|
||||
uint32_t ulIndirBlock; /**< Physical block number of the indirect node. */
|
||||
#endif
|
||||
uint32_t ulDataBlock; /**< Physical block number of the file data block. */
|
||||
|
||||
uint16_t uInodeEntry; /**< Which inode entry to traverse to reach ulLogicalBlock. */
|
||||
#if DINDIR_POINTERS > 0U
|
||||
uint16_t uDindirEntry; /**< Which double indirect entry to traverse to reach ulLogicalBlock. */
|
||||
#endif
|
||||
#if REDCONF_DIRECT_POINTERS < INODE_ENTRIES
|
||||
uint16_t uIndirEntry; /**< Which indirect entry to traverse to reach ulLogicalBlock. */
|
||||
#endif
|
||||
} CINODE;
|
||||
|
||||
#define CINODE_IS_MOUNTED(pInode) (((pInode) != NULL) && INODE_IS_VALID((pInode)->ulInode) && ((pInode)->pInodeBuf != NULL))
|
||||
#define CINODE_IS_DIRTY(pInode) (CINODE_IS_MOUNTED(pInode) && (pInode)->fDirty)
|
||||
|
||||
|
||||
#define IPUT_UPDATE_ATIME (0x01U)
|
||||
#define IPUT_UPDATE_MTIME (0x02U)
|
||||
#define IPUT_UPDATE_CTIME (0x04U)
|
||||
#define IPUT_UPDATE_MASK (IPUT_UPDATE_ATIME|IPUT_UPDATE_MTIME|IPUT_UPDATE_CTIME)
|
||||
|
||||
|
||||
REDSTATUS RedInodeMount(CINODE *pInode, FTYPE type, bool fBranch);
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
REDSTATUS RedInodeBranch(CINODE *pInode);
|
||||
#endif
|
||||
#if (REDCONF_READ_ONLY == 0) && ((REDCONF_API_POSIX == 1) || FORMAT_SUPPORTED)
|
||||
REDSTATUS RedInodeCreate(CINODE *pInode, uint32_t ulPInode, uint16_t uMode);
|
||||
#endif
|
||||
#if DELETE_SUPPORTED
|
||||
REDSTATUS RedInodeDelete(CINODE *pInode);
|
||||
REDSTATUS RedInodeLinkDec(CINODE *pInode);
|
||||
#endif
|
||||
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_POSIX == 1)
|
||||
REDSTATUS RedInodeFree(CINODE *pInode);
|
||||
#endif
|
||||
void RedInodePut(CINODE *pInode, uint8_t bTimeFields);
|
||||
void RedInodePutCoord(CINODE *pInode);
|
||||
#if DINDIR_POINTERS > 0U
|
||||
void RedInodePutDindir(CINODE *pInode);
|
||||
#endif
|
||||
#if REDCONF_DIRECT_POINTERS < INODE_ENTRIES
|
||||
void RedInodePutIndir(CINODE *pInode);
|
||||
#endif
|
||||
void RedInodePutData(CINODE *pInode);
|
||||
#if ((REDCONF_READ_ONLY == 0) && ((REDCONF_API_POSIX == 1) || FORMAT_SUPPORTED)) || (REDCONF_CHECKER == 1)
|
||||
REDSTATUS RedInodeIsFree(uint32_t ulInode, bool *pfFree);
|
||||
#endif
|
||||
REDSTATUS RedInodeBitGet(uint8_t bMR, uint32_t ulInode, uint8_t bWhich, bool *pfAllocated);
|
||||
|
||||
REDSTATUS RedInodeDataRead(CINODE *pInode, uint64_t ullStart, uint32_t *pulLen, void *pBuffer);
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
REDSTATUS RedInodeDataWrite(CINODE *pInode, uint64_t ullStart, uint32_t *pulLen, const void *pBuffer);
|
||||
#if DELETE_SUPPORTED || TRUNCATE_SUPPORTED
|
||||
REDSTATUS RedInodeDataTruncate(CINODE *pInode, uint64_t ullSize);
|
||||
#endif
|
||||
#endif
|
||||
REDSTATUS RedInodeDataSeekAndRead(CINODE *pInode, uint32_t ulBlock);
|
||||
REDSTATUS RedInodeDataSeek(CINODE *pInode, uint32_t ulBlock);
|
||||
|
||||
#if REDCONF_API_POSIX == 1
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
REDSTATUS RedDirEntryCreate(CINODE *pPInode, const char *pszName, uint32_t ulInode);
|
||||
#endif
|
||||
#if DELETE_SUPPORTED
|
||||
REDSTATUS RedDirEntryDelete(CINODE *pPInode, uint32_t ulDeleteIdx);
|
||||
#endif
|
||||
REDSTATUS RedDirEntryLookup(CINODE *pPInode, const char *pszName, uint32_t *pulEntryIdx, uint32_t *pulInode);
|
||||
#if (REDCONF_API_POSIX_READDIR == 1) || (REDCONF_CHECKER == 1)
|
||||
REDSTATUS RedDirEntryRead(CINODE *pPInode, uint32_t *pulIdx, char *pszName, uint32_t *pulInode);
|
||||
#endif
|
||||
#if (REDCONF_READ_ONLY == 0) && (REDCONF_API_POSIX_RENAME == 1)
|
||||
REDSTATUS RedDirEntryRename(CINODE *pSrcPInode, const char *pszSrcName, CINODE *pSrcInode, CINODE *pDstPInode, const char *pszDstName, CINODE *pDstInode);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
REDSTATUS RedVolMount(void);
|
||||
REDSTATUS RedVolMountMaster(void);
|
||||
REDSTATUS RedVolMountMetaroot(void);
|
||||
#if REDCONF_READ_ONLY == 0
|
||||
REDSTATUS RedVolTransact(void);
|
||||
#endif
|
||||
void RedVolCriticalError(const char *pszFileName, uint32_t ulLineNum);
|
||||
REDSTATUS RedVolSeqNumIncrement(void);
|
||||
|
||||
#if FORMAT_SUPPORTED
|
||||
REDSTATUS RedVolFormat(void);
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,92 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
*/
|
||||
#ifndef REDCOREMACS_H
|
||||
#define REDCOREMACS_H
|
||||
|
||||
|
||||
#define BLOCK_NUM_MASTER (0UL) /* Block number of the master block. */
|
||||
#define BLOCK_NUM_FIRST_METAROOT (1UL) /* Block number of the first metaroot. */
|
||||
|
||||
#define BLOCK_SPARSE (0U)
|
||||
|
||||
#define DINDIR_POINTERS ((INODE_ENTRIES - REDCONF_DIRECT_POINTERS) - REDCONF_INDIRECT_POINTERS)
|
||||
#define DINDIR_DATA_BLOCKS (INDIR_ENTRIES * INDIR_ENTRIES)
|
||||
|
||||
#define INODE_INDIR_BLOCKS (REDCONF_INDIRECT_POINTERS * INDIR_ENTRIES)
|
||||
#define INODE_DINDIR_BLOCKS (DINDIR_POINTERS * DINDIR_DATA_BLOCKS)
|
||||
#define INODE_DATA_BLOCKS (REDCONF_DIRECT_POINTERS + INODE_INDIR_BLOCKS + INODE_DINDIR_BLOCKS)
|
||||
#define INODE_SIZE_MAX (UINT64_SUFFIX(1) * REDCONF_BLOCK_SIZE * INODE_DATA_BLOCKS)
|
||||
|
||||
|
||||
/* First inode number that can be allocated.
|
||||
*/
|
||||
#if REDCONF_API_POSIX == 1
|
||||
#define INODE_FIRST_FREE (INODE_FIRST_VALID + 1U)
|
||||
#else
|
||||
#define INODE_FIRST_FREE (INODE_FIRST_VALID)
|
||||
#endif
|
||||
|
||||
/** @brief Determine if an inode number is valid.
|
||||
*/
|
||||
#define INODE_IS_VALID(INODENUM) (((INODENUM) >= INODE_FIRST_VALID) && ((INODENUM) < (INODE_FIRST_VALID + gpRedVolConf->ulInodeCount)))
|
||||
|
||||
|
||||
/* The number of blocks reserved to allow a truncate or delete operation to
|
||||
complete when the disk is otherwise full.
|
||||
|
||||
The more expensive of the two operations is delete, which has to actually
|
||||
write to a file data block to remove the directory entry.
|
||||
*/
|
||||
#if REDCONF_READ_ONLY == 1
|
||||
#define RESERVED_BLOCKS 0U
|
||||
#elif (REDCONF_API_POSIX == 1) && ((REDCONF_API_POSIX_UNLINK == 1) || (REDCONF_API_POSIX_RMDIR == 1))
|
||||
#if DINDIR_POINTERS > 0U
|
||||
#define RESERVED_BLOCKS 3U
|
||||
#elif REDCONF_INDIRECT_POINTERS > 0U
|
||||
#define RESERVED_BLOCKS 2U
|
||||
#else
|
||||
#define RESERVED_BLOCKS 1U
|
||||
#endif
|
||||
#elif ((REDCONF_API_POSIX == 1) && (REDCONF_API_POSIX_FTRUNCATE == 1)) || ((REDCONF_API_FSE == 1) && (REDCONF_API_FSE_TRUNCATE == 1))
|
||||
#if DINDIR_POINTERS > 0U
|
||||
#define RESERVED_BLOCKS 2U
|
||||
#elif REDCONF_INDIRECT_POINTERS > 0U
|
||||
#define RESERVED_BLOCKS 1U
|
||||
#else
|
||||
#define RESERVED_BLOCKS 0U
|
||||
#endif
|
||||
#else
|
||||
#define RESERVED_BLOCKS 0U
|
||||
#endif
|
||||
|
||||
|
||||
#define CRITICAL_ASSERT(EXP) ((EXP) ? (void)0 : CRITICAL_ERROR())
|
||||
#define CRITICAL_ERROR() RedVolCriticalError(__FILE__, __LINE__)
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,95 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
*/
|
||||
#ifndef REDCOREVOL_H
|
||||
#define REDCOREVOL_H
|
||||
|
||||
|
||||
/** @brief Per-volume run-time data specific to the core.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/** Whether this volume uses the inline imap (true) or external imap
|
||||
(false). Computed at initialization time based on the block count.
|
||||
*/
|
||||
bool fImapInline;
|
||||
|
||||
#if REDCONF_IMAP_EXTERNAL == 1
|
||||
/** First block number of the on-disk imap. Valid only when fImapInline
|
||||
is false.
|
||||
*/
|
||||
uint32_t ulImapStartBN;
|
||||
|
||||
/** The number of double-allocated imap nodes that make up the imap.
|
||||
*/
|
||||
uint32_t ulImapNodeCount;
|
||||
#endif
|
||||
|
||||
/** Block number where the inode table starts.
|
||||
*/
|
||||
uint32_t ulInodeTableStartBN;
|
||||
|
||||
/** First block number that can be allocated.
|
||||
*/
|
||||
uint32_t ulFirstAllocableBN;
|
||||
|
||||
/** The two metaroot structures, committed and working state.
|
||||
*/
|
||||
METAROOT aMR[2U];
|
||||
|
||||
/** The index of the current metaroot; must be 0 or 1.
|
||||
*/
|
||||
uint8_t bCurMR;
|
||||
|
||||
/** Whether the volume has been branched or not.
|
||||
*/
|
||||
bool fBranched;
|
||||
|
||||
/** The number of blocks which will become free after the next transaction.
|
||||
*/
|
||||
uint32_t ulAlmostFreeBlocks;
|
||||
|
||||
#if RESERVED_BLOCKS > 0U
|
||||
/** Whether to use the blocks reserved for operations that create free
|
||||
space.
|
||||
*/
|
||||
bool fUseReservedBlocks;
|
||||
#endif
|
||||
} COREVOLUME;
|
||||
|
||||
/* Pointer to the core volume currently being accessed; populated during
|
||||
RedCoreVolSetCurrent().
|
||||
*/
|
||||
extern COREVOLUME * CONST_IF_ONE_VOLUME gpRedCoreVol;
|
||||
|
||||
/* Pointer to the metaroot currently being accessed; populated during
|
||||
RedCoreVolSetCurrent() and RedCoreVolTransact().
|
||||
*/
|
||||
extern METAROOT *gpRedMR;
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,195 @@
|
||||
/* ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
|
||||
|
||||
Copyright (c) 2014-2015 Datalight, Inc.
|
||||
All Rights Reserved Worldwide.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; use version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* Businesses and individuals that for commercial or other reasons cannot
|
||||
comply with the terms of the GPLv2 license may obtain a commercial license
|
||||
before incorporating Reliance Edge into proprietary software for
|
||||
distribution in any form. Visit http://www.datalight.com/reliance-edge for
|
||||
more information.
|
||||
*/
|
||||
/** @file
|
||||
*/
|
||||
#ifndef REDNODES_H
|
||||
#define REDNODES_H
|
||||
|
||||
|
||||
#define NODEHEADER_SIZE (16U)
|
||||
#define NODEHEADER_OFFSET_SIG (0U)
|
||||
#define NODEHEADER_OFFSET_CRC (4U)
|
||||
#define NODEHEADER_OFFSET_SEQ (8U)
|
||||
|
||||
/** @brief Common header for all metadata nodes.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t ulSignature; /**< Value which uniquely identifies the metadata node type. */
|
||||
uint32_t ulCRC; /**< CRC-32 checksum of the node contents, starting after the CRC. */
|
||||
uint64_t ullSequence; /**< Current sequence number at the time the node was written to disk. */
|
||||
} NODEHEADER;
|
||||
|
||||
|
||||
/** Flag set in the master block when REDCONF_API_POSIX == 1. */
|
||||
#define MBFLAG_API_POSIX (0x01U)
|
||||
|
||||
/** Flag set in the master block when REDCONF_INODE_TIMESTAMPS == 1. */
|
||||
#define MBFLAG_INODE_TIMESTAMPS (0x02U)
|
||||
|
||||
/** Flag set in the master block when REDCONF_INODE_BLOCKS == 1. */
|
||||
#define MBFLAG_INODE_BLOCKS (0x04U)
|
||||
|
||||
/** Flag set in the master block when (REDCONF_API_POSIX == 1) && (REDCONF_API_POSIX_LINK == 1). */
|
||||
#define MBFLAG_INODE_NLINK (0x08U)
|
||||
|
||||
|
||||
/** @brief Node which identifies the volume and stores static volume information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
NODEHEADER hdr; /**< Common node header. */
|
||||
|
||||
uint32_t ulVersion; /**< On-disk layout version number. */
|
||||
char acBuildNum[8U]; /**< Build number of the product (not null terminated). */
|
||||
uint32_t ulFormatTime; /**< Date and time the volume was formatted. */
|
||||
uint32_t ulInodeCount; /**< Compile-time configured number of inodes. */
|
||||
uint32_t ulBlockCount; /**< Compile-time configured number of logical blocks. */
|
||||
uint16_t uMaxNameLen; /**< Compile-time configured maximum file name length. */
|
||||
uint16_t uDirectPointers; /**< Compile-time configured number of direct pointers per inode. */
|
||||
uint16_t uIndirectPointers; /**< Compile-time configured number of indirect pointers per inode. */
|
||||
uint8_t bBlockSizeP2; /**< Compile-time configured block size, expressed as a power of two. */
|
||||
uint8_t bFlags; /**< Compile-time booleans which affect on-disk structures. */
|
||||
} MASTERBLOCK;
|
||||
|
||||
|
||||
#if REDCONF_API_POSIX == 1
|
||||
#define METAROOT_HEADER_SIZE (NODEHEADER_SIZE + 16U) /* Size in bytes of the metaroot header fields. */
|
||||
#else
|
||||
#define METAROOT_HEADER_SIZE (NODEHEADER_SIZE + 12U) /* Size in bytes of the metaroot header fields. */
|
||||
#endif
|
||||
#define METAROOT_ENTRY_BYTES (REDCONF_BLOCK_SIZE - METAROOT_HEADER_SIZE) /* Number of bytes remaining in the metaroot block for entries. */
|
||||
#define METAROOT_ENTRIES (METAROOT_ENTRY_BYTES * 8U)
|
||||
|
||||
/** @brief Metadata root node; each volume has two.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
NODEHEADER hdr; /**< Common node header. */
|
||||
|
||||
uint32_t ulSectorCRC; /**< CRC-32 checksum of the first sector. */
|
||||
uint32_t ulFreeBlocks; /**< Number of allocable blocks that are free. */
|
||||
#if REDCONF_API_POSIX == 1
|
||||
uint32_t ulFreeInodes; /**< Number of inode slots that are free. */
|
||||
#endif
|
||||
uint32_t ulAllocNextBlock; /**< Forward allocation pointer. */
|
||||
|
||||
/** Imap bitmap. With inline imaps, this is the imap bitmap that indicates
|
||||
which inode blocks are used and which allocable blocks are used.
|
||||
Otherwise, this bitmap toggles nodes in the external imap between one
|
||||
of two possible block locations.
|
||||
*/
|
||||
uint8_t abEntries[METAROOT_ENTRY_BYTES];
|
||||
} METAROOT;
|
||||
|
||||
|
||||
#if REDCONF_IMAP_EXTERNAL == 1
|
||||
#define IMAPNODE_HEADER_SIZE (NODEHEADER_SIZE) /* Size in bytes of the imap node header fields. */
|
||||
#define IMAPNODE_ENTRY_BYTES (REDCONF_BLOCK_SIZE - IMAPNODE_HEADER_SIZE) /* Number of bytes remaining in the imap node for entries. */
|
||||
#define IMAPNODE_ENTRIES (IMAPNODE_ENTRY_BYTES * 8U)
|
||||
|
||||
/** @brief One node of the external imap.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
NODEHEADER hdr; /**< Common node header. */
|
||||
|
||||
/** Bitmap which indicates which inode blocks are used and which allocable
|
||||
blocks are used.
|
||||
*/
|
||||
uint8_t abEntries[IMAPNODE_ENTRY_BYTES];
|
||||
} IMAPNODE;
|
||||
#endif
|
||||
|
||||
|
||||
#define INODE_HEADER_SIZE (NODEHEADER_SIZE + 8U + ((REDCONF_INODE_BLOCKS == 1) ? 4U : 0U) + \
|
||||
((REDCONF_INODE_TIMESTAMPS == 1) ? 12U : 0U) + 4U + ((REDCONF_API_POSIX == 1) ? 4U : 0U))
|
||||
#define INODE_ENTRIES ((REDCONF_BLOCK_SIZE - INODE_HEADER_SIZE) / 4U)
|
||||
|
||||
#if (REDCONF_DIRECT_POINTERS < 0) || (REDCONF_DIRECT_POINTERS > (INODE_ENTRIES - REDCONF_INDIRECT_POINTERS))
|
||||
#error "Configuration error: invalid value of REDCONF_DIRECT_POINTERS"
|
||||
#endif
|
||||
#if (REDCONF_INDIRECT_POINTERS < 0) || (REDCONF_INDIRECT_POINTERS > (INODE_ENTRIES - REDCONF_DIRECT_POINTERS))
|
||||
#error "Configuration error: invalid value of REDCONF_INDIRECT_POINTERS"
|
||||
#endif
|
||||
|
||||
/** @brief Stores metadata for a file or directory.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
NODEHEADER hdr; /**< Common node header. */
|
||||
|
||||
uint64_t ullSize; /**< Size of the inode, in bytes. */
|
||||
#if REDCONF_INODE_BLOCKS == 1
|
||||
uint32_t ulBlocks; /**< Total number file data blocks allocated to the inode. */
|
||||
#endif
|
||||
#if REDCONF_INODE_TIMESTAMPS == 1
|
||||
uint32_t ulATime; /**< Time of last access (seconds since January 1, 1970). */
|
||||
uint32_t ulMTime; /**< Time of last modification (seconds since January 1, 1970). */
|
||||
uint32_t ulCTime; /**< Time of last status change (seconds since January 1, 1970). */
|
||||
#endif
|
||||
uint16_t uMode; /**< Inode type (file or directory) and permissions (reserved). */
|
||||
#if (REDCONF_API_POSIX == 1) && (REDCONF_API_POSIX_LINK == 1)
|
||||
uint16_t uNLink; /**< Link count, number of names pointing to the inode. */
|
||||
#else
|
||||
uint8_t abPadding[2]; /**< Padding to 32-bit align the next member. */
|
||||
#endif
|
||||
#if REDCONF_API_POSIX == 1
|
||||
uint32_t ulPInode; /**< Parent inode number. Only guaranteed to be accurate for directories. */
|
||||
#endif
|
||||
|
||||
/** Block numbers for lower levels of the file metadata structure. Some
|
||||
fraction of these entries are for direct pointers (file data block
|
||||
numbers), some for indirect pointers, some for double-indirect
|
||||
pointers; the number allocated to each is static but user-configurable.
|
||||
For all types, an array slot is zero if the range is sparse or beyond
|
||||
the end of file.
|
||||
*/
|
||||
uint32_t aulEntries[INODE_ENTRIES];
|
||||
} INODE;
|
||||
|
||||
|
||||
#define INDIR_HEADER_SIZE (NODEHEADER_SIZE + 4U)
|
||||
#define INDIR_ENTRIES ((REDCONF_BLOCK_SIZE - INDIR_HEADER_SIZE) / 4U)
|
||||
|
||||
/** @brief Node for storing block pointers.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
NODEHEADER hdr; /**< Common node header. */
|
||||
|
||||
uint32_t ulInode; /**< Inode which owns this indirect or double indirect. */
|
||||
|
||||
/** For indirect nodes, stores block numbers of file data. For double
|
||||
indirect nodes, stores block numbers of indirect nodes. An array
|
||||
slot is zero if the corresponding block or indirect range is beyond
|
||||
the end of file or entirely sparse.
|
||||
*/
|
||||
uint32_t aulEntries[INDIR_ENTRIES];
|
||||
} INDIR, DINDIR;
|
||||
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user