blob: b33387854df69bf8c3912917dc33afa87d86f78a [file] [log] [blame]
/* ----> 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