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;
}
Exemplo n.º 2
0
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;
}