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