Ejemplo n.º 1
0
int nxffs_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
  FAR struct nxffs_volume_s *volume;
  int ret;

  fvdbg("cmd: %d arg: %08lx\n", cmd, arg);

  /* Sanity checks */

  DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL);

  /* Recover the file system state from the open file */

  volume = filep->f_inode->i_private;
  DEBUGASSERT(volume != NULL);

  /* Get exclusive access to the volume.  Note that the volume exclsem
   * protects the open file list.
   */

  ret = sem_wait(&volume->exclsem);
  if (ret != OK)
    {
      ret = -errno;
      fdbg("sem_wait failed: %d\n", ret);
      goto errout;
    }

  /* Only a reformat and optimize commands are supported */

  if (cmd == FIOC_REFORMAT)
    {
      fvdbg("Reformat command\n");

      /* We cannot reformat the volume if there are any open inodes */

      if (volume->ofiles)
        {
          fdbg("Open files\n");
          ret = -EBUSY;
          goto errout_with_semaphore;
        }

      /* Re-format the volume -- all is lost */

      ret = nxffs_reformat(volume);
    }

  else if (cmd == FIOC_OPTIMIZE)
    {
      fvdbg("Optimize command\n");

      /* Pack the volume */

      ret = nxffs_pack(volume);
    }
  else
    {
      /* No other commands supported */

      ret = -ENOTTY;
    }

errout_with_semaphore:
  sem_post(&volume->exclsem);
errout:
  return ret;
}
Ejemplo n.º 2
0
int nxffs_initialize(FAR struct mtd_dev_s *mtd)
{
  FAR struct nxffs_volume_s *volume;
  struct nxffs_blkstats_s stats;
  off_t threshold;
  int ret;

  /* If CONFIG_NXFFS_PREALLOCATED is defined, then this is the single, pre-
   * allocated NXFFS volume instance.
   */

#ifdef CONFIG_NXFFS_PREALLOCATED

  volume = &g_volume;
  memset(volume, 0, sizeof(struct nxffs_volume_s));

#else

  /* Allocate a NXFFS volume structure */

  volume = (FAR struct nxffs_volume_s *)kzalloc(sizeof(struct nxffs_volume_s));
  if (!volume)
    {
      ret = -ENOMEM;
      goto errout;
    }
#endif

  /* Initialize the NXFFS volume structure */

  volume->mtd    = mtd;
  volume->cblock = (off_t)-1;
  sem_init(&volume->exclsem, 0, 1);
  sem_init(&volume->wrsem, 0, 1);

  /* Get the volume geometry. (casting to uintptr_t first eliminates
   * complaints on some architectures where the sizeof long is different
   * from the size of a pointer).
   */

  ret = MTD_IOCTL(mtd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&volume->geo));
  if (ret < 0)
    {
      fdbg("MTD ioctl(MTDIOC_GEOMETRY) failed: %d\n", -ret);
      goto errout_with_volume;
    }

  /* Allocate one I/O block buffer to general files system access */

  volume->cache = (FAR uint8_t *)kmalloc(volume->geo.blocksize);
  if (!volume->cache)
    {
      fdbg("Failed to allocate an erase block buffer\n");
      ret = -ENOMEM;
      goto errout_with_volume;
    }

  /* Pre-allocate one, full, in-memory erase block.  This is needed for filesystem
   * packing (but is useful in other places as well). This buffer is not needed
   * often, but is best to have pre-allocated and in-place.
   */

  volume->pack = (FAR uint8_t *)kmalloc(volume->geo.erasesize);
  if (!volume->pack)
    {
      fdbg("Failed to allocate an I/O block buffer\n");
      ret = -ENOMEM;
      goto errout_with_cache;
    }

  /* Get the number of R/W blocks per erase block and the total number o
   * R/W blocks
   */

  volume->blkper  = volume->geo.erasesize / volume->geo.blocksize;
  volume->nblocks = volume->geo.neraseblocks * volume->blkper;
  DEBUGASSERT((off_t)volume->blkper * volume->geo.blocksize == volume->geo.erasesize);

  /* Check if there is a valid NXFFS file system on the flash */

  ret = nxffs_blockstats(volume, &stats);
  if (ret < 0)
    {
      fdbg("Failed to collect block statistics: %d\n", -ret);
      goto errout_with_buffer;
    }

  /* If the proportion of good blocks is low or the proportion of unformatted
   * blocks is high, then reformat the FLASH.
   */

  threshold = stats.nblocks / 5;
  if (stats.ngood < threshold || stats.nunformat > threshold)
    {
      /* Reformat the volume */

      ret = nxffs_reformat(volume);
      if (ret < 0)
        {
          fdbg("Failed to reformat the volume: %d\n", -ret);
          goto errout_with_buffer;
        }

      /* Get statistics on the re-formatted volume */

#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_FS)
      ret = nxffs_blockstats(volume, &stats);
      if (ret < 0)
        {
          fdbg("Failed to collect block statistics: %d\n", -ret);
          goto errout_with_buffer;
        }
#endif
    }

  /* Get the file system limits */

  ret = nxffs_limits(volume);
  if (ret == OK)
    {
      return OK;
    }
  fdbg("Failed to calculate file system limits: %d\n", -ret);

errout_with_buffer:
  kfree(volume->pack);
errout_with_cache:
  kfree(volume->cache);
errout_with_volume:
#ifndef CONFIG_NXFFS_PREALLOCATED
  kfree(volume);
#endif
  return ret;
}