/* ----> 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 @brief Implements routines for the inline imap. The inline imap is used on volumes that are small enough for the imap bitmap to be entirely contained within the metaroot. */ #include #if REDCONF_IMAP_INLINE == 1 #include /** @brief Get the allocation bit of a block from either metaroot. @param bMR The metaroot index: either 0 or 1. @param ulBlock The block number to query. @param pfAllocated On successful return, populated with the allocation bit of the block. @return A negated ::REDSTATUS code indicating the operation result. @retval 0 Operation was successful. @retval -RED_EINVAL @p bMR is out of range; or @p ulBlock is out of range; @p pfAllocated is `NULL`; or the current volume does not use the inline imap. */ REDSTATUS RedImapIBlockGet( uint8_t bMR, uint32_t ulBlock, bool *pfAllocated) { REDSTATUS ret; if( (!gpRedCoreVol->fImapInline) || (bMR > 1U) || (ulBlock < gpRedCoreVol->ulInodeTableStartBN) || (ulBlock >= gpRedVolume->ulBlockCount) || (pfAllocated == NULL)) { REDERROR(); ret = -RED_EINVAL; } else { *pfAllocated = RedBitGet(gpRedCoreVol->aMR[bMR].abEntries, ulBlock - gpRedCoreVol->ulInodeTableStartBN); ret = 0; } return ret; } #if REDCONF_READ_ONLY == 0 /** @brief Set the allocation bit of a block in the working metaroot. @param ulBlock The block number to allocate or free. @param fAllocated Whether to allocate the block (true) or free it (false). @return A negated ::REDSTATUS code indicating the operation result. @retval 0 Operation was successful. @retval -RED_EINVAL @p ulBlock is out of range; or the current volume does not use the inline imap. */ REDSTATUS RedImapIBlockSet( uint32_t ulBlock, bool fAllocated) { REDSTATUS ret; if( (!gpRedCoreVol->fImapInline) || (ulBlock < gpRedCoreVol->ulInodeTableStartBN) || (ulBlock >= gpRedVolume->ulBlockCount)) { REDERROR(); ret = -RED_EINVAL; } else { uint32_t ulOffset = ulBlock - gpRedCoreVol->ulInodeTableStartBN; if(RedBitGet(gpRedMR->abEntries, ulOffset) == fAllocated) { /* The driver shouldn't ever set a bit in the imap to its current value. This is more of a problem with the external imap, but it is checked here for consistency. */ CRITICAL_ERROR(); ret = -RED_EFUBAR; } else if(fAllocated) { RedBitSet(gpRedMR->abEntries, ulOffset); ret = 0; } else { RedBitClear(gpRedMR->abEntries, ulOffset); ret = 0; } } return ret; } #endif #endif /* REDCONF_IMAP_INLINE == 1 */