1 /*             ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
2  *
3  *                 Copyright (c) 2014-2015 Datalight, Inc.
4  *                     All Rights Reserved Worldwide.
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; use version 2 of the License.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
12  *  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License along
16  *  with this program; if not, write to the Free Software Foundation, Inc.,
17  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 /*  Businesses and individuals that for commercial or other reasons cannot
21  *  comply with the terms of the GPLv2 license may obtain a commercial license
22  *  before incorporating Reliance Edge into proprietary software for
23  *  distribution in any form.  Visit http://www.datalight.com/reliance-edge for
24  *  more information.
25  */
26 
27 /** @file
28  */
29 #ifndef REDNODES_H
30 #define REDNODES_H
31 
32 
33 #define NODEHEADER_SIZE          ( 16U )
34 #define NODEHEADER_OFFSET_SIG    ( 0U )
35 #define NODEHEADER_OFFSET_CRC    ( 4U )
36 #define NODEHEADER_OFFSET_SEQ    ( 8U )
37 
38 /** @brief Common header for all metadata nodes.
39  */
40 typedef struct
41 {
42     uint32_t ulSignature; /**< Value which uniquely identifies the metadata node type. */
43     uint32_t ulCRC;       /**< CRC-32 checksum of the node contents, starting after the CRC. */
44     uint64_t ullSequence; /**< Current sequence number at the time the node was written to disk. */
45 } NODEHEADER;
46 
47 
48 /** Flag set in the master block when REDCONF_API_POSIX == 1. */
49 #define MBFLAG_API_POSIX           ( 0x01U )
50 
51 /** Flag set in the master block when REDCONF_INODE_TIMESTAMPS == 1. */
52 #define MBFLAG_INODE_TIMESTAMPS    ( 0x02U )
53 
54 /** Flag set in the master block when REDCONF_INODE_BLOCKS == 1. */
55 #define MBFLAG_INODE_BLOCKS        ( 0x04U )
56 
57 /** Flag set in the master block when (REDCONF_API_POSIX == 1) && (REDCONF_API_POSIX_LINK == 1). */
58 #define MBFLAG_INODE_NLINK         ( 0x08U )
59 
60 
61 /** @brief Node which identifies the volume and stores static volume information.
62  */
63 typedef struct
64 {
65     NODEHEADER hdr;             /**< Common node header. */
66 
67     uint32_t ulVersion;         /**< On-disk layout version number. */
68     char acBuildNum[ 8U ];      /**< Build number of the product (not null terminated). */
69     uint32_t ulFormatTime;      /**< Date and time the volume was formatted. */
70     uint32_t ulInodeCount;      /**< Compile-time configured number of inodes. */
71     uint32_t ulBlockCount;      /**< Compile-time configured number of logical blocks. */
72     uint16_t uMaxNameLen;       /**< Compile-time configured maximum file name length. */
73     uint16_t uDirectPointers;   /**< Compile-time configured number of direct pointers per inode. */
74     uint16_t uIndirectPointers; /**< Compile-time configured number of indirect pointers per inode. */
75     uint8_t bBlockSizeP2;       /**< Compile-time configured block size, expressed as a power of two. */
76     uint8_t bFlags;             /**< Compile-time booleans which affect on-disk structures. */
77 } MASTERBLOCK;
78 
79 
80 #if REDCONF_API_POSIX == 1
81     #define METAROOT_HEADER_SIZE    ( NODEHEADER_SIZE + 16U )                     /* Size in bytes of the metaroot header fields. */
82 #else
83     #define METAROOT_HEADER_SIZE    ( NODEHEADER_SIZE + 12U )                     /* Size in bytes of the metaroot header fields. */
84 #endif
85 #define METAROOT_ENTRY_BYTES        ( REDCONF_BLOCK_SIZE - METAROOT_HEADER_SIZE ) /* Number of bytes remaining in the metaroot block for entries. */
86 #define METAROOT_ENTRIES            ( METAROOT_ENTRY_BYTES * 8U )
87 
88 /** @brief Metadata root node; each volume has two.
89  */
90 typedef struct
91 {
92     NODEHEADER hdr;            /**< Common node header. */
93 
94     uint32_t ulSectorCRC;      /**< CRC-32 checksum of the first sector. */
95     uint32_t ulFreeBlocks;     /**< Number of allocable blocks that are free. */
96     #if REDCONF_API_POSIX == 1
97         uint32_t ulFreeInodes; /**< Number of inode slots that are free. */
98     #endif
99     uint32_t ulAllocNextBlock; /**< Forward allocation pointer. */
100 
101     /** Imap bitmap.  With inline imaps, this is the imap bitmap that indicates
102      *  which inode blocks are used and which allocable blocks are used.
103      *  Otherwise, this bitmap toggles nodes in the external imap between one
104      *  of two possible block locations.
105      */
106     uint8_t abEntries[ METAROOT_ENTRY_BYTES ];
107 } METAROOT;
108 
109 
110 #if REDCONF_IMAP_EXTERNAL == 1
111     #define IMAPNODE_HEADER_SIZE    ( NODEHEADER_SIZE )                           /* Size in bytes of the imap node header fields. */
112     #define IMAPNODE_ENTRY_BYTES    ( REDCONF_BLOCK_SIZE - IMAPNODE_HEADER_SIZE ) /* Number of bytes remaining in the imap node for entries. */
113     #define IMAPNODE_ENTRIES        ( IMAPNODE_ENTRY_BYTES * 8U )
114 
115 /** @brief One node of the external imap.
116  */
117     typedef struct
118     {
119         NODEHEADER hdr; /**< Common node header. */
120 
121         /** Bitmap which indicates which inode blocks are used and which allocable
122          *  blocks are used.
123          */
124         uint8_t abEntries[ IMAPNODE_ENTRY_BYTES ];
125     } IMAPNODE;
126 #endif /* if REDCONF_IMAP_EXTERNAL == 1 */
127 
128 
129 #define INODE_HEADER_SIZE                                                  \
130     ( NODEHEADER_SIZE + 8U + ( ( REDCONF_INODE_BLOCKS == 1 ) ? 4U : 0U ) + \
131       ( ( REDCONF_INODE_TIMESTAMPS == 1 ) ? 12U : 0U ) + 4U + ( ( REDCONF_API_POSIX == 1 ) ? 4U : 0U ) )
132 #define INODE_ENTRIES    ( ( REDCONF_BLOCK_SIZE - INODE_HEADER_SIZE ) / 4U )
133 
134 #if ( REDCONF_DIRECT_POINTERS < 0 ) || ( REDCONF_DIRECT_POINTERS > ( INODE_ENTRIES - REDCONF_INDIRECT_POINTERS ) )
135     #error "Configuration error: invalid value of REDCONF_DIRECT_POINTERS"
136 #endif
137 #if ( REDCONF_INDIRECT_POINTERS < 0 ) || ( REDCONF_INDIRECT_POINTERS > ( INODE_ENTRIES - REDCONF_DIRECT_POINTERS ) )
138     #error "Configuration error: invalid value of REDCONF_INDIRECT_POINTERS"
139 #endif
140 
141 /** @brief Stores metadata for a file or directory.
142  */
143 typedef struct
144 {
145     NODEHEADER hdr;        /**< Common node header. */
146 
147     uint64_t ullSize;      /**< Size of the inode, in bytes. */
148     #if REDCONF_INODE_BLOCKS == 1
149         uint32_t ulBlocks; /**< Total number file data blocks allocated to the inode. */
150     #endif
151     #if REDCONF_INODE_TIMESTAMPS == 1
152         uint32_t ulATime;       /**< Time of last access (seconds since January 1, 1970). */
153         uint32_t ulMTime;       /**< Time of last modification (seconds since January 1, 1970). */
154         uint32_t ulCTime;       /**< Time of last status change (seconds since January 1, 1970). */
155     #endif
156     uint16_t uMode;             /**< Inode type (file or directory) and permissions (reserved). */
157     #if ( REDCONF_API_POSIX == 1 ) && ( REDCONF_API_POSIX_LINK == 1 )
158         uint16_t uNLink;        /**< Link count, number of names pointing to the inode. */
159     #else
160         uint8_t abPadding[ 2 ]; /**< Padding to 32-bit align the next member. */
161     #endif
162     #if REDCONF_API_POSIX == 1
163         uint32_t ulPInode; /**< Parent inode number.  Only guaranteed to be accurate for directories. */
164     #endif
165 
166     /** Block numbers for lower levels of the file metadata structure.  Some
167      *  fraction of these entries are for direct pointers (file data block
168      *  numbers), some for indirect pointers, some for double-indirect
169      *  pointers; the number allocated to each is static but user-configurable.
170      *  For all types, an array slot is zero if the range is sparse or beyond
171      *  the end of file.
172      */
173     uint32_t aulEntries[ INODE_ENTRIES ];
174 } INODE;
175 
176 
177 #define INDIR_HEADER_SIZE    ( NODEHEADER_SIZE + 4U )
178 #define INDIR_ENTRIES        ( ( REDCONF_BLOCK_SIZE - INDIR_HEADER_SIZE ) / 4U )
179 
180 /** @brief Node for storing block pointers.
181  */
182 typedef struct
183 {
184     NODEHEADER hdr;   /**< Common node header. */
185 
186     uint32_t ulInode; /**< Inode which owns this indirect or double indirect. */
187 
188     /** For indirect nodes, stores block numbers of file data.  For double
189      *  indirect nodes, stores block numbers of indirect nodes.  An array
190      *  slot is zero if the corresponding block or indirect range is beyond
191      *  the end of file or entirely sparse.
192      */
193     uint32_t aulEntries[ INDIR_ENTRIES ];
194 } INDIR, DINDIR;
195 
196 
197 #endif /* ifndef REDNODES_H */
198