/* ----> 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 /* if REDCONF_READ_ONLY == 0 */ #endif /* REDCONF_IMAP_INLINE == 1 */