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  *  @brief Implements routines for the inline imap.
29  *
30  *  The inline imap is used on volumes that are small enough for the imap bitmap
31  *  to be entirely contained within the metaroot.
32  */
33 #include <redfs.h>
34 
35 #if REDCONF_IMAP_INLINE == 1
36 
37     #include <redcore.h>
38 
39 
40 /** @brief Get the allocation bit of a block from either metaroot.
41  *
42  *  @param bMR          The metaroot index: either 0 or 1.
43  *  @param ulBlock      The block number to query.
44  *  @param pfAllocated  On successful return, populated with the allocation bit
45  *                      of the block.
46  *
47  *  @return A negated ::REDSTATUS code indicating the operation result.
48  *
49  *  @retval 0           Operation was successful.
50  *  @retval -RED_EINVAL @p bMR is out of range; or @p ulBlock is out of range;
51  *                      @p pfAllocated is `NULL`; or the current volume does not
52  *                      use the inline imap.
53  */
RedImapIBlockGet(uint8_t bMR,uint32_t ulBlock,bool * pfAllocated)54     REDSTATUS RedImapIBlockGet( uint8_t bMR,
55                                 uint32_t ulBlock,
56                                 bool * pfAllocated )
57     {
58         REDSTATUS ret;
59 
60         if( ( !gpRedCoreVol->fImapInline ) ||
61             ( bMR > 1U ) ||
62             ( ulBlock < gpRedCoreVol->ulInodeTableStartBN ) ||
63             ( ulBlock >= gpRedVolume->ulBlockCount ) ||
64             ( pfAllocated == NULL ) )
65         {
66             REDERROR();
67             ret = -RED_EINVAL;
68         }
69         else
70         {
71             *pfAllocated = RedBitGet( gpRedCoreVol->aMR[ bMR ].abEntries, ulBlock - gpRedCoreVol->ulInodeTableStartBN );
72             ret = 0;
73         }
74 
75         return ret;
76     }
77 
78 
79     #if REDCONF_READ_ONLY == 0
80 
81 /** @brief Set the allocation bit of a block in the working metaroot.
82  *
83  *  @param ulBlock      The block number to allocate or free.
84  *  @param fAllocated   Whether to allocate the block (true) or free it (false).
85  *
86  *  @return A negated ::REDSTATUS code indicating the operation result.
87  *
88  *  @retval 0           Operation was successful.
89  *  @retval -RED_EINVAL @p ulBlock is out of range; or the current volume does
90  *                      not use the inline imap.
91  */
RedImapIBlockSet(uint32_t ulBlock,bool fAllocated)92         REDSTATUS RedImapIBlockSet( uint32_t ulBlock,
93                                     bool fAllocated )
94         {
95             REDSTATUS ret;
96 
97             if( ( !gpRedCoreVol->fImapInline ) ||
98                 ( ulBlock < gpRedCoreVol->ulInodeTableStartBN ) ||
99                 ( ulBlock >= gpRedVolume->ulBlockCount ) )
100             {
101                 REDERROR();
102                 ret = -RED_EINVAL;
103             }
104             else
105             {
106                 uint32_t ulOffset = ulBlock - gpRedCoreVol->ulInodeTableStartBN;
107 
108                 if( RedBitGet( gpRedMR->abEntries, ulOffset ) == fAllocated )
109                 {
110                     /*  The driver shouldn't ever set a bit in the imap to its current
111                      *  value.  This is more of a problem with the external imap, but it
112                      *  is checked here for consistency.
113                      */
114                     CRITICAL_ERROR();
115                     ret = -RED_EFUBAR;
116                 }
117                 else if( fAllocated )
118                 {
119                     RedBitSet( gpRedMR->abEntries, ulOffset );
120                     ret = 0;
121                 }
122                 else
123                 {
124                     RedBitClear( gpRedMR->abEntries, ulOffset );
125                     ret = 0;
126                 }
127             }
128 
129             return ret;
130         }
131     #endif /* if REDCONF_READ_ONLY == 0 */
132 
133 #endif /* REDCONF_IMAP_INLINE == 1 */
134