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 REDCORE_H
30 #define REDCORE_H
31 
32 
33 #include <redstat.h>
34 #include <redvolume.h>
35 #include "rednodes.h"
36 #include "redcoremacs.h"
37 #include "redcorevol.h"
38 
39 
40 #define META_SIG_MASTER      ( 0x5453414DU ) /* 'MAST' */
41 #define META_SIG_METAROOT    ( 0x4154454DU ) /* 'META' */
42 #define META_SIG_IMAP        ( 0x50414D49U ) /* 'IMAP' */
43 #define META_SIG_INODE       ( 0x444F4E49U ) /* 'INOD' */
44 #define META_SIG_DINDIR      ( 0x494C4244U ) /* 'DBLI' */
45 #define META_SIG_INDIR       ( 0x49444E49U ) /* 'INDI' */
46 
47 
48 REDSTATUS RedIoRead( uint8_t bVolNum,
49                      uint32_t ulBlockStart,
50                      uint32_t ulBlockCount,
51                      void * pBuffer );
52 #if REDCONF_READ_ONLY == 0
53     REDSTATUS RedIoWrite( uint8_t bVolNum,
54                           uint32_t ulBlockStart,
55                           uint32_t ulBlockCount,
56                           const void * pBuffer );
57     REDSTATUS RedIoFlush( uint8_t bVolNum );
58 #endif
59 
60 
61 /** Indicates a block buffer is dirty (its contents are different than the
62  *  contents of the corresponding block on disk); or, when passed into
63  *  RedBufferGet(), indicates that the buffer should be marked dirty.
64  */
65 #define BFLAG_DIRTY          ( ( uint16_t ) 0x0001U )
66 
67 /** Tells RedBufferGet() that the buffer is for a newly allocated block, and its
68  *  contents should be zeroed instead of being read from disk.  Always used in
69  *  combination with BFLAG_DIRTY.
70  */
71 #define BFLAG_NEW            ( ( uint16_t ) 0x0002U )
72 
73 /** Indicates that a block buffer is a master block (MASTERBLOCK) metadata node.
74  */
75 #define BFLAG_META_MASTER    ( ( uint16_t ) ( 0x0004U | BFLAG_META ) )
76 
77 /** Indicates that a block buffer is an imap (IMAPNODE) metadata node.
78  */
79 #define BFLAG_META_IMAP      ( ( uint16_t ) ( 0x0008U | BFLAG_META ) )
80 
81 /** Indicates that a block buffer is an inode (INODE) metadata node.
82  */
83 #define BFLAG_META_INODE     ( ( uint16_t ) ( 0x0010U | BFLAG_META ) )
84 
85 /** Indicates that a block buffer is an indirect (INDIR) metadata node.
86  */
87 #define BFLAG_META_INDIR     ( ( uint16_t ) ( 0x0020U | BFLAG_META ) )
88 
89 /** Indicates that a block buffer is a double indirect (DINDIR) metadata node.
90  */
91 #define BFLAG_META_DINDIR    ( ( uint16_t ) ( 0x0040U | BFLAG_META ) )
92 
93 /** Indicates that a block buffer is a metadata node.  Callers of RedBufferGet()
94  *  should not use this flag; instead, use one of the BFLAG_META_* flags.
95  */
96 #define BFLAG_META           ( ( uint16_t ) 0x8000U )
97 
98 
99 void RedBufferInit( void );
100 REDSTATUS RedBufferGet( uint32_t ulBlock,
101                         uint16_t uFlags,
102                         void ** ppBuffer );
103 void RedBufferPut( const void * pBuffer );
104 #if REDCONF_READ_ONLY == 0
105     REDSTATUS RedBufferFlush( uint32_t ulBlockStart,
106                               uint32_t ulBlockCount );
107     void RedBufferDirty( const void * pBuffer );
108     void RedBufferBranch( const void * pBuffer,
109                           uint32_t ulBlockNew );
110     #if ( REDCONF_API_POSIX == 1 ) || FORMAT_SUPPORTED
111         void RedBufferDiscard( const void * pBuffer );
112     #endif
113 #endif
114 REDSTATUS RedBufferDiscardRange( uint32_t ulBlockStart,
115                                  uint32_t ulBlockCount );
116 
117 
118 /** @brief Allocation state of a block.
119  */
120 typedef enum
121 {
122     ALLOCSTATE_FREE, /**< Free and may be allocated; writeable. */
123     ALLOCSTATE_USED, /**< In-use and transacted; not writeable. */
124     ALLOCSTATE_NEW,  /**< In-use but not transacted; writeable. */
125     ALLOCSTATE_AFREE /**< Will become free after a transaction; not writeable. */
126 } ALLOCSTATE;
127 
128 REDSTATUS RedImapBlockGet( uint8_t bMR,
129                            uint32_t ulBlock,
130                            bool * pfAllocated );
131 #if REDCONF_READ_ONLY == 0
132     REDSTATUS RedImapBlockSet( uint32_t ulBlock,
133                                bool fAllocated );
134     REDSTATUS RedImapAllocBlock( uint32_t * pulBlock );
135 #endif
136 REDSTATUS RedImapBlockState( uint32_t ulBlock,
137                              ALLOCSTATE * pState );
138 
139 #if REDCONF_IMAP_INLINE == 1
140     REDSTATUS RedImapIBlockGet( uint8_t bMR,
141                                 uint32_t ulBlock,
142                                 bool * pfAllocated );
143     REDSTATUS RedImapIBlockSet( uint32_t ulBlock,
144                                 bool fAllocated );
145 #endif
146 
147 #if REDCONF_IMAP_EXTERNAL == 1
148     REDSTATUS RedImapEBlockGet( uint8_t bMR,
149                                 uint32_t ulBlock,
150                                 bool * pfAllocated );
151     REDSTATUS RedImapEBlockSet( uint32_t ulBlock,
152                                 bool fAllocated );
153     uint32_t RedImapNodeBlock( uint8_t bMR,
154                                uint32_t ulImapNode );
155 #endif
156 
157 
158 /** @brief Cached inode structure.
159  */
160 typedef struct
161 {
162     uint32_t ulInode;    /**< The inode number of the cached inode. */
163     #if REDCONF_API_POSIX == 1
164         bool fDirectory; /**< True if the inode is a directory. */
165     #endif
166     #if REDCONF_READ_ONLY == 0
167         bool fBranched;   /**< True if the inode is branched (writeable). */
168         bool fDirty;      /**< True if the inode buffer is dirty. */
169     #endif
170     bool fCoordInited;    /**< True after the first seek. */
171 
172     INODE * pInodeBuf;    /**< Pointer to the inode buffer. */
173     #if DINDIR_POINTERS > 0U
174         DINDIR * pDindir; /**< Pointer to the double indirect node buffer. */
175     #endif
176     #if REDCONF_DIRECT_POINTERS < INODE_ENTRIES
177         INDIR * pIndir; /**< Pointer to the indirect node buffer. */
178     #endif
179     uint8_t * pbData;   /**< Pointer to the data block buffer. */
180 
181     /*  All the members below this point are part of the seek coordinates; see
182      *  RedInodeDataSeek().
183      */
184     uint32_t ulLogicalBlock;    /**< Logical block offset into the inode. */
185     #if DINDIR_POINTERS > 0U
186         uint32_t ulDindirBlock; /**< Physical block number of the double indirect node. */
187     #endif
188     #if REDCONF_DIRECT_POINTERS < INODE_ENTRIES
189         uint32_t ulIndirBlock; /**< Physical block number of the indirect node. */
190     #endif
191     uint32_t ulDataBlock;      /**< Physical block number of the file data block. */
192 
193     uint16_t uInodeEntry;      /**< Which inode entry to traverse to reach ulLogicalBlock. */
194     #if DINDIR_POINTERS > 0U
195         uint16_t uDindirEntry; /**< Which double indirect entry to traverse to reach ulLogicalBlock. */
196     #endif
197     #if REDCONF_DIRECT_POINTERS < INODE_ENTRIES
198         uint16_t uIndirEntry; /**< Which indirect entry to traverse to reach ulLogicalBlock. */
199     #endif
200 } CINODE;
201 
202 #define CINODE_IS_MOUNTED( pInode )    ( ( ( pInode ) != NULL ) && INODE_IS_VALID( ( pInode )->ulInode ) && ( ( pInode )->pInodeBuf != NULL ) )
203 #define CINODE_IS_DIRTY( pInode )      ( CINODE_IS_MOUNTED( pInode ) && ( pInode )->fDirty )
204 
205 
206 #define IPUT_UPDATE_ATIME    ( 0x01U )
207 #define IPUT_UPDATE_MTIME    ( 0x02U )
208 #define IPUT_UPDATE_CTIME    ( 0x04U )
209 #define IPUT_UPDATE_MASK     ( IPUT_UPDATE_ATIME | IPUT_UPDATE_MTIME | IPUT_UPDATE_CTIME )
210 
211 
212 REDSTATUS RedInodeMount( CINODE * pInode,
213                          FTYPE type,
214                          bool fBranch );
215 #if REDCONF_READ_ONLY == 0
216     REDSTATUS RedInodeBranch( CINODE * pInode );
217 #endif
218 #if ( REDCONF_READ_ONLY == 0 ) && ( ( REDCONF_API_POSIX == 1 ) || FORMAT_SUPPORTED )
219     REDSTATUS RedInodeCreate( CINODE * pInode,
220                               uint32_t ulPInode,
221                               uint16_t uMode );
222 #endif
223 #if DELETE_SUPPORTED
224     REDSTATUS RedInodeDelete( CINODE * pInode );
225     REDSTATUS RedInodeLinkDec( CINODE * pInode );
226 #endif
227 #if ( REDCONF_READ_ONLY == 0 ) && ( REDCONF_API_POSIX == 1 )
228     REDSTATUS RedInodeFree( CINODE * pInode );
229 #endif
230 void RedInodePut( CINODE * pInode,
231                   uint8_t bTimeFields );
232 void RedInodePutCoord( CINODE * pInode );
233 #if DINDIR_POINTERS > 0U
234     void RedInodePutDindir( CINODE * pInode );
235 #endif
236 #if REDCONF_DIRECT_POINTERS < INODE_ENTRIES
237     void RedInodePutIndir( CINODE * pInode );
238 #endif
239 void RedInodePutData( CINODE * pInode );
240 #if ( ( REDCONF_READ_ONLY == 0 ) && ( ( REDCONF_API_POSIX == 1 ) || FORMAT_SUPPORTED ) ) || ( REDCONF_CHECKER == 1 )
241     REDSTATUS RedInodeIsFree( uint32_t ulInode,
242                               bool * pfFree );
243 #endif
244 REDSTATUS RedInodeBitGet( uint8_t bMR,
245                           uint32_t ulInode,
246                           uint8_t bWhich,
247                           bool * pfAllocated );
248 
249 REDSTATUS RedInodeDataRead( CINODE * pInode,
250                             uint64_t ullStart,
251                             uint32_t * pulLen,
252                             void * pBuffer );
253 #if REDCONF_READ_ONLY == 0
254     REDSTATUS RedInodeDataWrite( CINODE * pInode,
255                                  uint64_t ullStart,
256                                  uint32_t * pulLen,
257                                  const void * pBuffer );
258     #if DELETE_SUPPORTED || TRUNCATE_SUPPORTED
259         REDSTATUS RedInodeDataTruncate( CINODE * pInode,
260                                         uint64_t ullSize );
261     #endif
262 #endif
263 REDSTATUS RedInodeDataSeekAndRead( CINODE * pInode,
264                                    uint32_t ulBlock );
265 REDSTATUS RedInodeDataSeek( CINODE * pInode,
266                             uint32_t ulBlock );
267 
268 #if REDCONF_API_POSIX == 1
269     #if REDCONF_READ_ONLY == 0
270         REDSTATUS RedDirEntryCreate( CINODE * pPInode,
271                                      const char * pszName,
272                                      uint32_t ulInode );
273     #endif
274     #if DELETE_SUPPORTED
275         REDSTATUS RedDirEntryDelete( CINODE * pPInode,
276                                      uint32_t ulDeleteIdx );
277     #endif
278     REDSTATUS RedDirEntryLookup( CINODE * pPInode,
279                                  const char * pszName,
280                                  uint32_t * pulEntryIdx,
281                                  uint32_t * pulInode );
282     #if ( REDCONF_API_POSIX_READDIR == 1 ) || ( REDCONF_CHECKER == 1 )
283         REDSTATUS RedDirEntryRead( CINODE * pPInode,
284                                    uint32_t * pulIdx,
285                                    char * pszName,
286                                    uint32_t * pulInode );
287     #endif
288     #if ( REDCONF_READ_ONLY == 0 ) && ( REDCONF_API_POSIX_RENAME == 1 )
289         REDSTATUS RedDirEntryRename( CINODE * pSrcPInode,
290                                      const char * pszSrcName,
291                                      CINODE * pSrcInode,
292                                      CINODE * pDstPInode,
293                                      const char * pszDstName,
294                                      CINODE * pDstInode );
295     #endif
296 #endif /* if REDCONF_API_POSIX == 1 */
297 
298 REDSTATUS RedVolMount( void );
299 REDSTATUS RedVolMountMaster( void );
300 REDSTATUS RedVolMountMetaroot( void );
301 #if REDCONF_READ_ONLY == 0
302     REDSTATUS RedVolTransact( void );
303 #endif
304 void RedVolCriticalError( const char * pszFileName,
305                           uint32_t ulLineNum );
306 REDSTATUS RedVolSeqNumIncrement( void );
307 
308 #if FORMAT_SUPPORTED
309     REDSTATUS RedVolFormat( void );
310 #endif
311 
312 
313 #endif /* ifndef REDCORE_H */
314