int nxffs_wrverify(FAR struct nxffs_volume_s *volume, size_t size) { uint16_t iooffset; int nerased; int ret; int i; /* Search to the very last block in the volume if we have to */ while (volume->ioblock < volume->nblocks) { /* Make sure that the block is in memory */ ret = nxffs_rdcache(volume, volume->ioblock); if (ret < 0) { /* Ignore the error... just skip to the next block. This should * never happen with normal FLASH, but could occur with NAND if * the block has uncorrectable bit errors. */ fdbg("ERROR: Failed to read block %d: %d\n", volume->ioblock, -ret); } /* Search to the very end of this block if we have to */ else { iooffset = volume->iooffset; nerased = 0; for (i = volume->iooffset; i < volume->geo.blocksize; i++) { /* Is this byte erased? */ if (volume->cache[i] == CONFIG_NXFFS_ERASEDSTATE) { /* Yes.. increment the count of contiguous, erased bytes */ nerased++; /* Is the whole header memory erased? */ if (nerased >= size) { /* Yes.. this this is where we will put the object */ off_t offset = volume->ioblock * volume->geo.blocksize + iooffset; /* Update the free flash offset and return success */ volume->froffset = offset + size; return OK; } } /* This byte is not erased! (It should be unless the block is * bad) */ else { nerased = 0; iooffset = i + 1; } } } /* If we get here, then either (1) this block is not read-able, or * (2) we have looked at every byte in the block and did not find * any sequence of erased bytes long enough to hold the object. * Skip to the next, valid block. */ volume->ioblock++; ret = nxffs_validblock(volume, &volume->ioblock); if (ret < 0) { fdbg("ERROR: No more valid blocks\n"); return ret; } volume->iooffset = SIZEOF_NXFFS_BLOCK_HDR; volume->froffset = volume->ioblock * volume->geo.blocksize + SIZEOF_NXFFS_BLOCK_HDR; } /* Return -ENOSPC if there is no erased memory left in the volume for * the object. */ fdbg("ERROR: Not enough memory left to hold the file header\n"); return -ENOSPC; }
int nxffs_limits(FAR struct nxffs_volume_s *volume) { FAR struct nxffs_entry_s entry; off_t block; off_t offset; bool noinodes = false; int nerased; int ret; /* Get the offset to the first valid block on the FLASH */ block = 0; ret = nxffs_validblock(volume, &block); if (ret < 0) { fdbg("Failed to find a valid block: %d\n", -ret); return ret; } /* Then find the first valid inode in or beyond the first valid block */ offset = block * volume->geo.blocksize; ret = nxffs_nextentry(volume, offset, &entry); if (ret < 0) { /* The value -ENOENT is special. This simply means that the FLASH * was searched to the end and no valid inode was found... the file * system is empty (or, in more perverse cases, all inodes are * deleted or corrupted). */ if (ret != -ENOENT) { fdbg("nxffs_nextentry failed: %d\n", -ret); return ret; } /* Set a flag the just indicates that no inodes were found. Later, * we will set the location of the first inode to be the same as * the location of the free FLASH region. */ fvdbg("No inodes found\n"); noinodes = true; } else { /* Save the offset to the first inode */ volume->inoffset = entry.hoffset; fvdbg("First inode at offset %d\n", volume->inoffset); /* Discard this entry and set the next offset. */ offset = nxffs_inodeend(volume, &entry); nxffs_freeentry(&entry); } /* Now, search for the last valid entry */ if (!noinodes) { while ((ret = nxffs_nextentry(volume, offset, &entry)) == OK) { /* Discard the entry and guess the next offset. */ offset = nxffs_inodeend(volume, &entry); nxffs_freeentry(&entry); } fvdbg("Last inode before offset %d\n", offset); } /* No inodes were found after this offset. Now search for a block of * erased flash. */ nxffs_ioseek(volume, offset); nerased = 0; for (;;) { int ch = nxffs_getc(volume, 1); if (ch < 0) { /* Failed to read the next byte... this could mean that the FLASH * is full? */ if (volume->ioblock + 1 >= volume->nblocks && volume->iooffset + 1 >= volume->geo.blocksize) { /* Yes.. the FLASH is full. Force the offsets to the end of FLASH */ volume->froffset = volume->nblocks * volume->geo.blocksize; fvdbg("Assume no free FLASH, froffset: %d\n", volume->froffset); if (noinodes) { volume->inoffset = volume->froffset; fvdbg("No inodes, inoffset: %d\n", volume->inoffset); } return OK; } // No? Then it is some other failure that we do not know how to handle fdbg("nxffs_getc failed: %d\n", -ch); return ch; } /* Check for another erased byte */ else if (ch == CONFIG_NXFFS_ERASEDSTATE) { /* If we have encountered NXFFS_NERASED number of consecutive * erased bytes, then presume we have reached the end of valid * data. */ if (++nerased >= NXFFS_NERASED) { /* Okay.. we have a long stretch of erased FLASH in a valid * FLASH block. Let's say that this is the beginning of * the free FLASH region. */ volume->froffset = offset; fvdbg("Free FLASH region begins at offset: %d\n", volume->froffset); if (noinodes) { volume->inoffset = offset; fvdbg("First inode at offset %d\n", volume->inoffset); } return OK; } } else { offset += nerased + 1; nerased = 0; } } /* Won't get here */ return OK; }
int nxffs_wrreserve(FAR struct nxffs_volume_s *volume, size_t size) { int ret; /* Seek to the beginning of the free FLASH region */ nxffs_ioseek(volume, volume->froffset); /* Check for a seek past the end of the volume */ if (volume->ioblock >= volume->nblocks) { /* Return -ENOSPC to indicate that the volume is full */ return -ENOSPC; } /* Skip over block headers */ if (volume->iooffset < SIZEOF_NXFFS_BLOCK_HDR) { volume->iooffset = SIZEOF_NXFFS_BLOCK_HDR; } /* Make sure that there is space there to hold the entire object */ if (volume->iooffset + size > volume->geo.blocksize) { /* We will need to skip to the next block. But first, check if we are * already at the final block. */ if (volume->ioblock + 1 >= volume->nblocks) { /* Return -ENOSPC to indicate that the volume is full */ fdbg("ERROR: No space in last block\n"); return -ENOSPC; } /* This is not the last block in the volume, so just seek to the * beginning of the next, valid block. */ volume->ioblock++; ret = nxffs_validblock(volume, &volume->ioblock); if (ret < 0) { fdbg("ERROR: No more valid blocks\n"); return ret; } volume->iooffset = SIZEOF_NXFFS_BLOCK_HDR; } /* Update the pointer to the first next free FLASH memory -- reserving this * block of memory. */ volume->froffset = nxffs_iotell(volume) + size; return OK; }