コード例 #1
0
ファイル: rtems-rfs-buffer.c プロジェクト: AndroidMarv/rtems
int
rtems_rfs_buffer_setblksize (rtems_rfs_file_system* fs, size_t size)
{
  int rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SETBLKSIZE))
    printf ("rtems-rfs: buffer-setblksize: block size: %zu\n", size);

  rc = rtems_rfs_buffers_release (fs);
  if ((rc > 0) && rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SETBLKSIZE))
    printf ("rtems-rfs: buffer-setblksize: buffer release failed: %d: %s\n",
            rc, strerror (rc));

  rc = rtems_rfs_buffer_sync (fs);
  if ((rc > 0) && rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SETBLKSIZE))
    printf ("rtems-rfs: buffer-setblksize: device sync failed: %d: %s\n",
            rc, strerror (rc));

#if RTEMS_RFS_USE_LIBBLOCK
  rc = fs->disk->ioctl (fs->disk, RTEMS_BLKIO_SETBLKSIZE, &size);
  if (rc < 0)
    rc = errno;
#endif
  return rc;
}
コード例 #2
0
ファイル: rtems-rfs-buffer.c プロジェクト: AndroidMarv/rtems
int
rtems_rfs_buffer_close (rtems_rfs_file_system* fs)
{
  int rc = 0;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CLOSE))
    printf ("rtems-rfs: buffer-close: closing\n");

  /*
   * Change the block size to the media device size. It will release and sync
   * all buffers.
   */
  rc = rtems_rfs_buffer_setblksize (fs, rtems_rfs_fs_media_block_size (fs));

  if ((rc > 0) && rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CLOSE))
    printf ("rtems-rfs: buffer-close: set media block size failed: %d: %s\n",
            rc, strerror (rc));

  if (close (fs->device) < 0)
  {
    rc = errno;
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CLOSE))
      printf ("rtems-rfs: buffer-close: file close failed: %d: %s\n",
              rc, strerror (rc));
  }

  return rc;
}
コード例 #3
0
ファイル: rtems-rfs-buffer.c プロジェクト: AndroidMarv/rtems
int
rtems_rfs_buffer_sync (rtems_rfs_file_system* fs)
{
  int result = 0;
#if RTEMS_RFS_USE_LIBBLOCK
  rtems_status_code sc;
#endif

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SYNC))
    printf ("rtems-rfs: buffer-sync: syncing\n");

  /*
   * @todo Split in the separate files for each type.
   */
#if RTEMS_RFS_USE_LIBBLOCK
  sc = rtems_bdbuf_syncdev (rtems_rfs_fs_device (fs));
  if (sc != RTEMS_SUCCESSFUL)
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SYNC))
      printf ("rtems-rfs: buffer-sync: device sync failed: %s\n",
              rtems_status_text (sc));
    result = EIO;
  }
  rtems_disk_release (fs->disk);
#else
  if (fsync (fs->device) < 0)
  {
    result = errno;
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CLOSE))
      printf ("rtems-rfs: buffer-sync: file sync failed: %d: %s\n",
              result, strerror (result));
  }
#endif
  return result;
}
コード例 #4
0
ファイル: rtems-rfs-group.c プロジェクト: rtemss/rtems
int
rtems_rfs_group_close (rtems_rfs_file_system* fs, rtems_rfs_group* group)
{
  int result = 0;
  int rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_CLOSE))
    printf ("rtems-rfs: group-close: base=%" PRId32 "\n", group->base);

  /*
   * We need to close as much as possible and also return any error if one
   * occurs but this may result in one even more important error being lost but
   * we cannot OR the errors together so this is a reasonable compromise.
   */
  rc = rtems_rfs_bitmap_close (&group->inode_bitmap);
  if (rc > 0)
    result = rc;
  rc = rtems_rfs_buffer_handle_close (fs, &group->inode_bitmap_buffer);
  if (rc > 0)
    result = rc;
  rc = rtems_rfs_bitmap_close (&group->block_bitmap);
  if (rc > 0)
    result = rc;
  rc = rtems_rfs_buffer_handle_close (fs, &group->block_bitmap_buffer);
  if (rc > 0)
    result = rc;
  
  return result;
}
コード例 #5
0
ファイル: rtems-rfs-inode.c プロジェクト: 0871087123/rtems
int
rtems_rfs_inode_unload (rtems_rfs_file_system*  fs,
                        rtems_rfs_inode_handle* handle,
                        bool                    update_ctime)
{
  int rc = 0;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_UNLOAD))
    printf ("rtems-rfs: inode-unload: ino=%" PRIu32 " loads=%i loaded=%s\n",
            handle->ino, handle->loads,
            rtems_rfs_inode_is_loaded (handle) ? "yes" : "no");

  if (rtems_rfs_inode_is_loaded (handle))
  {
    if (handle->loads == 0)
      return EIO;

    handle->loads--;

    if (handle->loads == 0)
    {
      /*
       * If the buffer is dirty it will be release. Also set the ctime.
       */
      if (rtems_rfs_buffer_dirty (&handle->buffer) && update_ctime)
        rtems_rfs_inode_set_ctime (handle, time (NULL));
      rc = rtems_rfs_buffer_handle_release (fs, &handle->buffer);
      handle->node = NULL;
    }
  }

  return rc;
}
コード例 #6
0
ファイル: rtems-rfs-inode.c プロジェクト: 0871087123/rtems
int
rtems_rfs_inode_load (rtems_rfs_file_system*  fs,
                      rtems_rfs_inode_handle* handle)
{
  if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_LOAD))
    printf ("rtems-rfs: inode-load: ino=%" PRIu32 " loads=%i loaded=%s\n",
            handle->ino, handle->loads,
            rtems_rfs_inode_is_loaded (handle) ? "yes" : "no");

  /*
   * An inode does not move so once loaded no need to do again.
   */

  if (!rtems_rfs_inode_is_loaded (handle))
  {
    int rc;

    rc = rtems_rfs_buffer_handle_request (fs,&handle->buffer,
                                          handle->block, true);
    if (rc > 0)
      return rc;

    handle->node = rtems_rfs_buffer_data (&handle->buffer);
    handle->node += handle->offset;
  }

  handle->loads++;

  return 0;
}
コード例 #7
0
/**
 * Find a block indirectly held in a table of block numbers.
 *
 * @param fs The file system.
 * @param buffer The handle to access the block data by.
 * @param block The block number of the table of block numbers.
 * @param offset The offset in the table of the block number to return. This is
 *               a block number offset not a byte offset into the table.
 * @param result Pointer to the result of the search.
 * @return int The error number (errno). No error if 0.
 */
static int
rtems_rfs_block_find_indirect (rtems_rfs_file_system*   fs,
                               rtems_rfs_buffer_handle* buffer,
                               rtems_rfs_block_no       block,
                               int                      offset,
                               rtems_rfs_block_no*      result)
{
   int rc;

  /*
   * If the handle has a buffer and this request is a different block the current
   * buffer is released.
   */
  rc = rtems_rfs_buffer_handle_request (fs, buffer, block, true);
  if (rc > 0)
    return rc;

  *result = rtems_rfs_block_get_number (buffer, offset);
  if ((*result + 1) == 0)
    *result = 0;

  if (*result >= rtems_rfs_fs_blocks (fs))
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BLOCK_FIND))
      printf ("rtems-rfs: block-find: invalid block in table:"
              " block=%" PRId32 ", indirect=%" PRId32 "/%d\n", *result, block, offset);
    *result = 0;
    rc = EIO;
  }

  return 0;
}
コード例 #8
0
int
rtems_rfs_buffer_bdbuf_release (rtems_rfs_buffer* buffer,
                                bool              modified)
{
  rtems_status_code sc;
  int               rc = 0;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_RELEASE))
    printf ("rtems-rfs: bdbuf-release: block=%" PRIuPTR " bdbuf=%" PRIu32 " %s\n",
            ((intptr_t) buffer->user),
            buffer->block, modified ? "(modified)" : "");

  if (modified)
    sc = rtems_bdbuf_release_modified (buffer);
  else
    sc = rtems_bdbuf_release (buffer);

  if (sc != RTEMS_SUCCESSFUL)
  {
#if RTEMS_RFS_BUFFER_ERRORS
    printf ("rtems-rfs: buffer-release: bdbuf-%s: %s(%d)\n",
            modified ? "modified" : "not-modified",
            rtems_status_text (sc), sc);
#endif
    rc = EIO;
  }

  return rc;
}
コード例 #9
0
ファイル: rtems-rfs-buffer.c プロジェクト: AndroidMarv/rtems
static int
rtems_rfs_release_chain (rtems_chain_control* chain,
                         uint32_t*            count,
                         bool                 modified)
{
  rtems_rfs_buffer* buffer;
  int               rrc = 0;
  int               rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CHAINS))
    printf ("rtems-rfs: release-chain: count=%" PRIu32 "\n", *count);

  while (!rtems_chain_is_empty (chain))
  {
    buffer = (rtems_rfs_buffer*) rtems_chain_get (chain);
    (*count)--;

    buffer->user = (void*) 0;

    rc = rtems_rfs_buffer_io_release (buffer, modified);
    if ((rc > 0) && (rrc == 0))
      rrc = rc;
  }
  return rrc;
}
コード例 #10
0
ファイル: rtems-rfs-buffer.c プロジェクト: AndroidMarv/rtems
int
rtems_rfs_buffer_open (const char* name, rtems_rfs_file_system* fs)
{
  struct stat st;
#if RTEMS_RFS_USE_LIBBLOCK
  int rv;
#endif

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SYNC))
    printf ("rtems-rfs: buffer-open: opening: %s\n", name);

  fs->device = open (name, O_RDWR);
  if (fs->device < 0)
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_OPEN))
      printf ("rtems-rfs: buffer-open: cannot open file\n");
    return ENXIO;
  }

  if (fstat (fs->device, &st) < 0)
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_OPEN))
      printf ("rtems-rfs: buffer-open: stat '%s' failed: %s\n",
              name, strerror (errno));
    return ENXIO;
  }

#if RTEMS_RFS_USE_LIBBLOCK
  /*
   * Is the device a block device ?
   */
  if (!S_ISBLK (st.st_mode))
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_OPEN))
      printf ("rtems-rfs: buffer-open: '%s' is not a block device\n", name);
    return ENXIO;
  }

  /*
   * Check that device is registred as a block device and lock it.
   */
  rv = rtems_disk_fd_get_disk_device (fs->device, &fs->disk);
  if (rv != 0)
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_OPEN))
      printf ("rtems-rfs: buffer-open: cannot obtain the disk\n");
    return ENXIO;
  }
#else
  fs->media_size = st.st_size;
  strcat (fs->name, name);
#endif

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_SYNC))
    printf ("rtems-rfs: buffer-open: blks=%" PRId32 ", blk-size=%" PRId32 "\n",
            rtems_rfs_fs_media_blocks (fs),
            rtems_rfs_fs_media_block_size (fs));

  return 0;
}
コード例 #11
0
ファイル: rtems-rfs-buffer.c プロジェクト: AndroidMarv/rtems
/**
 * Scan the chain for a buffer that matches the block number.
 *
 * @param chain The chain to scan.
 * @param count The number of items on the chain.
 * @param block The block number to find.
 * @return  rtems_rfs_buffer* The buffer if found else NULL.
 */
static rtems_rfs_buffer*
rtems_rfs_scan_chain (rtems_chain_control*   chain,
                      uint32_t*              count,
                      rtems_rfs_buffer_block block)
{
  rtems_rfs_buffer* buffer;
  rtems_chain_node* node;

  node = rtems_chain_last (chain);

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CHAINS))
    printf ("rtems-rfs: buffer-scan: count=%" PRIu32 ", block=%" PRIu32 ": ", *count, block);

  while (!rtems_chain_is_head (chain, node))
  {
    buffer = (rtems_rfs_buffer*) node;

    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CHAINS))
      printf ("%" PRIuPTR " ", ((intptr_t) buffer->user));

    if (((rtems_rfs_buffer_block) ((intptr_t)(buffer->user))) == block)
    {
      if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CHAINS))
        printf (": found block=%" PRIuPTR "\n",
                ((intptr_t)(buffer->user)));

      (*count)--;
      rtems_chain_extract (node);
      rtems_chain_set_off_chain (node);
      return buffer;
    }
    node = rtems_chain_previous (node);
  }

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_CHAINS))
    printf (": not found\n");

  return NULL;
}
コード例 #12
0
ファイル: rtems-rfs-inode.c プロジェクト: 0871087123/rtems
int
rtems_rfs_inode_close (rtems_rfs_file_system*  fs,
                       rtems_rfs_inode_handle* handle)
{
  int rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_CLOSE))
    printf ("rtems-rfs: inode-close: ino: %" PRIu32 "\n", handle->ino);

  rc = rtems_rfs_inode_unload (fs, handle, true);

  if ((rc == 0) && (handle->loads > 0))
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_CLOSE))
      printf ("rtems-rfs: inode-close: bad loads number: %d\n",
              handle->loads);
    rc = EIO;
  }

  handle->ino = 0;
  return rc;
}
コード例 #13
0
int
rtems_rfs_fs_close (rtems_rfs_file_system* fs)
{
  int group;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_CLOSE))
    printf ("rtems-rfs: close\n");

  for (group = 0; group < fs->group_count; group++)
    rtems_rfs_group_close (fs, &fs->groups[group]);

  rtems_rfs_buffer_close (fs);

  free (fs);
  return 0;
}
コード例 #14
0
ファイル: rtems-rfs-mutex.c プロジェクト: epicsdeb/rtems
int
rtems_rfs_mutex_destroy (rtems_rfs_mutex* mutex)
{
#if __rtems__
  rtems_status_code sc;
  sc = rtems_semaphore_delete (*mutex);
  if (sc != RTEMS_SUCCESSFUL)
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_MUTEX))
      printf ("rtems-rfs: mutex: close failed: %s\n", 
              rtems_status_text (sc));
    return EIO;
  }
#endif
  return 0;
}
コード例 #15
0
ファイル: rtems-rfs-inode.c プロジェクト: 0871087123/rtems
int
rtems_rfs_inode_delete (rtems_rfs_file_system*  fs,
                        rtems_rfs_inode_handle* handle)
{
  int rc = 0;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_DELETE))
    printf("rtems-rfs: inode-delete: ino:%" PRIu32 " loaded:%s\n",
           rtems_rfs_inode_ino (handle),
           rtems_rfs_inode_is_loaded (handle) ? "yes" : "no");

  if (rtems_rfs_inode_is_loaded (handle))
  {
    rtems_rfs_block_map map;

    /*
     * Free the ino number.
     */
    rc = rtems_rfs_inode_free (fs, handle->ino);
    if (rc > 0)
      return rc;

    /*
     * Free the blocks the inode may have attached.
     */
    rc = rtems_rfs_block_map_open (fs, handle, &map);
    if (rc == 0)
    {
      int rrc;
      rrc = rtems_rfs_block_map_free_all (fs, &map);
      rc = rtems_rfs_block_map_close (fs, &map);
      if (rc > 0)
        rrc = rc;
      memset (handle->node, 0xff, RTEMS_RFS_INODE_SIZE);
      rtems_rfs_buffer_mark_dirty (&handle->buffer);
      /*
       * Do the release here to avoid the ctime field being set on a
       * close. Also if there loads is greater then one then other loads
       * active. Forcing the loads count to 0.
       */
      rc = rtems_rfs_buffer_handle_release (fs, &handle->buffer);
      handle->loads = 0;
      handle->node = NULL;
    }
  }
  return rc;
}
コード例 #16
0
ファイル: rtems-rfs-mutex.c プロジェクト: epicsdeb/rtems
int
rtems_rfs_mutex_create (rtems_rfs_mutex* mutex)
{
#if __rtems__
  rtems_status_code sc;
  sc = rtems_semaphore_create (rtems_build_name ('R', 'F', 'S', 'm'),
                               1, RTEMS_RFS_MUTEX_ATTRIBS, 0,
                               mutex);
  if (sc != RTEMS_SUCCESSFUL)
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_MUTEX))
      printf ("rtems-rfs: mutex: open failed: %s\n", 
              rtems_status_text (sc));
    return EIO;
  }
#endif
  return 0;
}
コード例 #17
0
ファイル: rtems-rfs-group.c プロジェクト: rtemss/rtems
int
rtems_rfs_group_bitmap_test (rtems_rfs_file_system* fs,
                             bool                   inode,
                             rtems_rfs_bitmap_bit   no,
                             bool*                  state)
{
  rtems_rfs_bitmap_control* bitmap;
  unsigned int              group;
  rtems_rfs_bitmap_bit      bit;
  size_t                    size;
  int                       rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_BITMAPS))
    printf ("rtems-rfs: group-bitmap-test: %s test: %" PRId32 "\n",
            inode ? "inode" : "block", no);

  if (inode)
  {
    if ((no < RTEMS_RFS_ROOT_INO) || (no > rtems_rfs_fs_inodes (fs)))
        return EINVAL;
    no -= RTEMS_RFS_ROOT_INO;
    size = fs->group_inodes;
  }    
  else
  {
    if (no >= rtems_rfs_fs_blocks (fs))
        return EINVAL;
    size = fs->group_blocks;
  }
  
  group = no / size;
  bit = (rtems_rfs_bitmap_bit) (no % size);
  
  if (inode)
    bitmap = &fs->groups[group].inode_bitmap;
  else
    bitmap = &fs->groups[group].block_bitmap;

  rc = rtems_rfs_bitmap_map_test (bitmap, bit, state);
  
  rtems_rfs_bitmap_release_buffer (fs, bitmap);
  
  return rc;
}
コード例 #18
0
ファイル: rtems-rfs-group.c プロジェクト: rtemss/rtems
int
rtems_rfs_group_bitmap_free (rtems_rfs_file_system* fs,
                             bool                   inode,
                             rtems_rfs_bitmap_bit   no)
{
  rtems_rfs_bitmap_control* bitmap;
  unsigned int              group;
  rtems_rfs_bitmap_bit      bit;
  size_t                    size;
  int                       rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_GROUP_BITMAPS))
    printf ("rtems-rfs: group-bitmap-free: %s free: %" PRId32 "\n",
            inode ? "inode" : "block", no);

  if (inode)
  {
    no -= RTEMS_RFS_ROOT_INO;
    size = fs->group_inodes;
  }    
  else
  {
    no -= RTEMS_RFS_SUPERBLOCK_SIZE;
    size = fs->group_blocks;
  }
  
  group = no / size;
  bit = (rtems_rfs_bitmap_bit) (no % size);
  
  if (inode)
    bitmap = &fs->groups[group].inode_bitmap;
  else
    bitmap = &fs->groups[group].block_bitmap;

  rc = rtems_rfs_bitmap_map_clear (bitmap, bit);
  
  rtems_rfs_bitmap_release_buffer (fs, bitmap);
  
  return rc;
}
コード例 #19
0
/**
 * Allocate an indirect block to a map.
 *
 * @param fs The file system data.
 * @param map The map the allocation is for.
 * @param buffer The buffer the indirect block is accessed by.
 * @param block The block number of the indirect block allocated.
 * @param upping True is upping the map to the next indirect level.
 * @return int The error number (errno). No error if 0.
 */
static int
rtems_rfs_block_map_indirect_alloc (rtems_rfs_file_system*   fs,
                                    rtems_rfs_block_map*     map,
                                    rtems_rfs_buffer_handle* buffer,
                                    rtems_rfs_block_no*      block,
                                    bool                     upping)
{
  rtems_rfs_bitmap_bit new_block;
  int                  rc;
  /*
   * Save the new block locally because upping can have *block pointing to the
   * slots which are cleared when upping.
   */
  rc = rtems_rfs_group_bitmap_alloc (fs, map->last_map_block, false, &new_block);
  if (rc > 0)
    return rc;
  rc = rtems_rfs_buffer_handle_request (fs, buffer, new_block, false);
  if (rc > 0)
  {
    rtems_rfs_group_bitmap_free (fs, false, new_block);
    return rc;
  }
  memset (rtems_rfs_buffer_data (buffer), 0xff, rtems_rfs_fs_block_size (fs));
  if (upping)
  {
    int b;
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BLOCK_MAP_GROW))
      printf ("rtems-rfs: block-map-grow: upping: block-count=%" PRId32 "\n",
              map->size.count);
    for (b = 0; b < RTEMS_RFS_INODE_BLOCKS; b++)
      rtems_rfs_block_set_number (buffer, b, map->blocks[b]);
    memset (map->blocks, 0, sizeof (map->blocks));
  }
  rtems_rfs_buffer_mark_dirty (buffer);
  *block = new_block;
  map->last_map_block = new_block;
  return 0;
}
コード例 #20
0
ファイル: rtems-rfs-inode.c プロジェクト: 0871087123/rtems
int
rtems_rfs_inode_open (rtems_rfs_file_system*  fs,
                      rtems_rfs_ino           ino,
                      rtems_rfs_inode_handle* handle,
                      bool                    load)
{
  int group;
  int gino;
  int index;
  int rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_OPEN))
    printf ("rtems-rfs: inode-open: ino: %" PRIu32 "\n", ino);

  if (ino == RTEMS_RFS_EMPTY_INO)
    return EINVAL;

  if ((ino - RTEMS_RFS_ROOT_INO) > rtems_rfs_fs_inodes (fs))
    return EINVAL;

  handle->ino = ino;
  handle->node = NULL;
  handle->loads = 0;

  gino  = ino - RTEMS_RFS_ROOT_INO;
  group = gino / fs->group_inodes;
  gino  = gino % fs->group_inodes;
  index = (gino / fs->inodes_per_block) + RTEMS_RFS_GROUP_INODE_BLOCK;

  handle->offset = gino % fs->inodes_per_block;
  handle->block  = rtems_rfs_group_block (&fs->groups[group], index);

  rc = rtems_rfs_buffer_handle_open (fs, &handle->buffer);
  if ((rc == 0) && load)
    rc = rtems_rfs_inode_load (fs, handle);
  return rc;
}
コード例 #21
0
ファイル: rtems-rfs-buffer.c プロジェクト: AndroidMarv/rtems
int
rtems_rfs_buffers_release (rtems_rfs_file_system* fs)
{
  int rrc = 0;
  int rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_RELEASE))
    printf ("rtems-rfs: buffers-release: active:%" PRIu32 " "
            "release:%" PRIu32 " release-modified:%" PRIu32 "\n",
            fs->buffers_count, fs->release_count, fs->release_modified_count);

  rc = rtems_rfs_release_chain (&fs->release,
                                &fs->release_count,
                                false);
  if ((rc > 0) && (rrc == 0))
    rrc = rc;
  rc = rtems_rfs_release_chain (&fs->release_modified,
                                &fs->release_modified_count,
                                true);
  if ((rc > 0) && (rrc == 0))
    rrc = rc;

  return rrc;
}
コード例 #22
0
ファイル: rtems-rfs-dir.c プロジェクト: epicsdeb/rtems
int
rtems_rfs_dir_del_entry (rtems_rfs_file_system*  fs,
                         rtems_rfs_inode_handle* dir,
                         rtems_rfs_ino           ino,
                         uint32_t                offset)
{  
  rtems_rfs_block_map     map;
  rtems_rfs_block_no      block;
  rtems_rfs_buffer_handle buffer;
  bool                    search;
  int                     rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_DEL_ENTRY))
    printf ("rtems-rfs: dir-del-entry: dir=%" PRId32 ", entry=%" PRId32 " offset=%" PRIu32 "\n",
            rtems_rfs_inode_ino (dir), ino, offset);

  rc = rtems_rfs_block_map_open (fs, dir, &map);
  if (rc > 0)
    return rc;

  rc = rtems_rfs_block_map_seek (fs, &map, offset, &block);
  if (rc > 0)
  {
    if (rc == ENXIO)
      rc = ENOENT;
    rtems_rfs_block_map_close (fs, &map);
    return rc;
  }

  rc = rtems_rfs_buffer_handle_open (fs, &buffer);
  if (rc > 0)
  {
    rtems_rfs_block_map_close (fs, &map);
    return rc;
  }

  /*
   * Only search if the offset is 0 else we are at that position.
   */
  search = offset ? false : true;

  while (rc == 0)
  {
    uint8_t* entry;
    int      eoffset;
    
    rc = rtems_rfs_buffer_handle_request (fs, &buffer, block, true);
    if (rc > 0)
    {
      if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_DEL_ENTRY))
        printf ("rtems-rfs: dir-del-entry: "
                "block buffer req failed for ino %" PRIu32 ": %d: %s\n",
                rtems_rfs_inode_ino (dir), rc, strerror (rc));
      break;
    }

    /*
     * If we are searching start at the beginning of the block. If not searching
     * skip to the offset in the block.
     */
    if (search)
      eoffset = 0;
    else
      eoffset = offset % rtems_rfs_fs_block_size (fs);
    
    entry = rtems_rfs_buffer_data (&buffer) + eoffset;
    
    while (eoffset < (rtems_rfs_fs_block_size (fs) - RTEMS_RFS_DIR_ENTRY_SIZE))
    {
      rtems_rfs_ino eino;
      int           elength;

      elength = rtems_rfs_dir_entry_length (entry);
      eino    = rtems_rfs_dir_entry_ino (entry);

      if (elength == RTEMS_RFS_DIR_ENTRY_EMPTY)
        break;
      
      if (rtems_rfs_dir_entry_valid (fs, elength, eino))
      {
        if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_DEL_ENTRY))
          printf ("rtems-rfs: dir-del-entry: "
                  "bad length or ino for ino %" PRIu32 ": %u/%" PRId32
                  " @ %" PRIu32 ".%04x\n",
                  rtems_rfs_inode_ino (dir), elength, eino, block, eoffset);
        rc = EIO;
        break;
      }

      if (ino == rtems_rfs_dir_entry_ino (entry))
      {
        uint32_t remaining;
        remaining = rtems_rfs_fs_block_size (fs) - (eoffset + elength);
        memmove (entry, entry + elength, remaining);
        memset (entry + remaining, 0xff, elength);

        /*
         * If the remainder of the block is empty and this is the start of the
         * block and it is the last block in the map shrink the map.
         *
         * @note We could check again to see if the new end block in the map is
         *       also empty. This way we could clean up an empty directory.
         */
        elength = rtems_rfs_dir_entry_length (entry);

        if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_DEL_ENTRY))
          printf ("rtems-rfs: dir-del-entry: "
                  "last block free for ino %" PRIu32 ": elength=%i block=%" PRIu32
                  " offset=%d last=%s\n",
                  ino, elength, block, eoffset,
                  rtems_rfs_block_map_last (&map) ? "yes" : "no");

        if ((elength == RTEMS_RFS_DIR_ENTRY_EMPTY) &&
            (eoffset == 0) && rtems_rfs_block_map_last (&map))
        {
          rc = rtems_rfs_block_map_shrink (fs, &map, 1);
          if (rc > 0)
          {
            if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_DEL_ENTRY))
              printf ("rtems-rfs: dir-del-entry: "
                      "block map shrink failed for ino %" PRIu32 ": %d: %s\n",
                      rtems_rfs_inode_ino (dir), rc, strerror (rc));
          }
        }
        
        rtems_rfs_buffer_mark_dirty (&buffer);
        rtems_rfs_buffer_handle_close (fs, &buffer);
        rtems_rfs_block_map_close (fs, &map);
        return 0;
      }

      if (!search)
      {
        rc = EIO;
        break;
      }
      
      entry   += elength;
      eoffset += elength;
    }

    if (rc == 0)
    {
      rc = rtems_rfs_block_map_next_block (fs, &map, &block);
      if (rc == ENXIO)
        rc = ENOENT;
    }
  }
  
  rtems_rfs_buffer_handle_close (fs, &buffer);
  rtems_rfs_block_map_close (fs, &map);
  return rc;
}
コード例 #23
0
ファイル: rtems-rfs-dir.c プロジェクト: epicsdeb/rtems
int
rtems_rfs_dir_add_entry (rtems_rfs_file_system*  fs,
                         rtems_rfs_inode_handle* dir,
                         const char*             name,
                         size_t                  length,
                         rtems_rfs_ino           ino)
{
  rtems_rfs_block_map     map;
  rtems_rfs_block_pos     bpos;
  rtems_rfs_buffer_handle buffer;
  int                     rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_ADD_ENTRY))
  {
    int c;
    printf ("rtems-rfs: dir-add-entry: dir=%" PRId32 ", name=",
            rtems_rfs_inode_ino (dir));
    for (c = 0; c < length; c++)
      printf ("%c", name[c]);
    printf (", len=%zd\n", length);
  }
        
  rc = rtems_rfs_block_map_open (fs, dir, &map);
  if (rc > 0)
    return rc;

  rc = rtems_rfs_buffer_handle_open (fs, &buffer);
  if (rc > 0)
  {
    rtems_rfs_block_map_close (fs, &map);
    return rc;
  }
  
  /*
   * Search the map from the beginning to find any empty space.
   */
  rtems_rfs_block_set_bpos_zero (&bpos);
  
  while (true)
  {
    rtems_rfs_block_no block;
    uint8_t*           entry;
    int                offset;
    bool               read = true;
    
    /*
     * Locate the first block. If an error the block will be 0. If the map is
     * empty which happens when creating a directory and adding the first entry
     * the seek will return ENXIO. In this case we need to grow the directory.
     */
    rc = rtems_rfs_block_map_find (fs, &map, &bpos, &block);
    if (rc > 0)
    {
      if (rc != ENXIO)
      {
        if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_ADD_ENTRY))
          printf ("rtems-rfs: dir-add-entry: "
                  "block map find failed for ino %" PRIu32 ": %d: %s\n",
                  rtems_rfs_inode_ino (dir), rc, strerror (rc));
        break;
      }

      /*
       * We have reached the end of the directory so add a block.
       */
      rc = rtems_rfs_block_map_grow (fs, &map, 1, &block);
      if (rc > 0)
      {
        if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_ADD_ENTRY))
          printf ("rtems-rfs: dir-add-entry: "
                  "block map grow failed for ino %" PRIu32 ": %d: %s\n",
                  rtems_rfs_inode_ino (dir), rc, strerror (rc));
        break;
      }

      read = false;
    }

    bpos.bno++;
    
    rc = rtems_rfs_buffer_handle_request (fs, &buffer, block, read);
    if (rc > 0)
    {
      if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_ADD_ENTRY))
        printf ("rtems-rfs: dir-add-entry: "
                "block buffer req failed for ino %" PRIu32 ": %d: %s\n",
                rtems_rfs_inode_ino (dir), rc, strerror (rc));
      break;
    }
    
    entry  = rtems_rfs_buffer_data (&buffer);
    
    if (!read)
      memset (entry, 0xff, rtems_rfs_fs_block_size (fs));

    offset = 0;
    
    while (offset < (rtems_rfs_fs_block_size (fs) - RTEMS_RFS_DIR_ENTRY_SIZE))
    {
      rtems_rfs_ino eino;
      int           elength;

      elength = rtems_rfs_dir_entry_length (entry);
      eino    = rtems_rfs_dir_entry_ino (entry);

      if (elength == RTEMS_RFS_DIR_ENTRY_EMPTY)
      {
        if ((length + RTEMS_RFS_DIR_ENTRY_SIZE) <
            (rtems_rfs_fs_block_size (fs) - offset))
        {
          uint32_t hash;
          hash = rtems_rfs_dir_hash (name, length);
          rtems_rfs_dir_set_entry_hash (entry, hash);
          rtems_rfs_dir_set_entry_ino (entry, ino);
          rtems_rfs_dir_set_entry_length (entry,
                                          RTEMS_RFS_DIR_ENTRY_SIZE + length);
          memcpy (entry + RTEMS_RFS_DIR_ENTRY_SIZE, name, length);
          rtems_rfs_buffer_mark_dirty (&buffer);
          rtems_rfs_buffer_handle_close (fs, &buffer);
          rtems_rfs_block_map_close (fs, &map);
          return 0;
        }

        break;
      }
      
      if (rtems_rfs_dir_entry_valid (fs, elength, eino))
      {
        if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_ADD_ENTRY))
          printf ("rtems-rfs: dir-add-entry: "
                  "bad length or ino for ino %" PRIu32 ": %u/%" PRId32 " @ %04x\n",
                  rtems_rfs_inode_ino (dir), elength, eino, offset);
        rtems_rfs_buffer_handle_close (fs, &buffer);
        rtems_rfs_block_map_close (fs, &map);
        return EIO;
      }
        
      entry  += elength;
      offset += elength;
    }
  }
  
  rtems_rfs_buffer_handle_close (fs, &buffer);
  rtems_rfs_block_map_close (fs, &map);
  return rc;
}
コード例 #24
0
ファイル: rtems-rfs-buffer.c プロジェクト: AndroidMarv/rtems
int
rtems_rfs_buffer_handle_release (rtems_rfs_file_system*   fs,
                                 rtems_rfs_buffer_handle* handle)
{
  int rc = 0;

  if (rtems_rfs_buffer_handle_has_block (handle))
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_RELEASE))
      printf ("rtems-rfs: buffer-release: block=%" PRIu32 " %s refs=%d %s\n",
              rtems_rfs_buffer_bnum (handle),
              rtems_rfs_buffer_dirty (handle) ? "(dirty)" : "",
              rtems_rfs_buffer_refs (handle),
              rtems_rfs_buffer_refs (handle) == 0 ? "BAD REF COUNT" : "");

    if (rtems_rfs_buffer_refs (handle) > 0)
      rtems_rfs_buffer_refs_down (handle);

    if (rtems_rfs_buffer_refs (handle) == 0)
    {
      rtems_chain_extract (rtems_rfs_buffer_link (handle));
      fs->buffers_count--;

      if (rtems_rfs_fs_no_local_cache (fs))
      {
        handle->buffer->user = (void*) 0;
        rc = rtems_rfs_buffer_io_release (handle->buffer,
                                          rtems_rfs_buffer_dirty (handle));
      }
      else
      {
        /*
         * If the total number of held buffers is higher than the configured
         * value remove a buffer from the queue with the most buffers and
         * release. The buffers are held on the queues with the newest at the
         * head.
         *
         * This code stops a large series of transactions causing all the
         * buffers in the cache being held in queues of this file system.
         */
        if ((fs->release_count +
             fs->release_modified_count) >= fs->max_held_buffers)
        {
          rtems_rfs_buffer* buffer;
          bool              modified;

          if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_RELEASE))
            printf ("rtems-rfs: buffer-release: local cache overflow:"
                    " %" PRIu32 "\n", fs->release_count + fs->release_modified_count);

          if (fs->release_count > fs->release_modified_count)
          {
            buffer = (rtems_rfs_buffer*) rtems_chain_get (&fs->release);
            fs->release_count--;
            modified = false;
          }
          else
          {
            buffer =
              (rtems_rfs_buffer*) rtems_chain_get (&fs->release_modified);
            fs->release_modified_count--;
            modified = true;
          }
          buffer->user = (void*) 0;
          rc = rtems_rfs_buffer_io_release (buffer, modified);
        }

        if (rtems_rfs_buffer_dirty (handle))
        {
          rtems_chain_append (&fs->release_modified,
                              rtems_rfs_buffer_link (handle));
          fs->release_modified_count++;
        }
        else
        {
          rtems_chain_append (&fs->release, rtems_rfs_buffer_link (handle));
          fs->release_count++;
        }
      }
    }
    handle->buffer = NULL;
  }

  return rc;
}
コード例 #25
0
static int
rtems_rfs_fs_read_superblock (rtems_rfs_file_system* fs)
{
  rtems_rfs_buffer_handle handle;
  uint8_t*                sb;
  int                     group;
  int                     rc;

  rc = rtems_rfs_buffer_handle_open (fs, &handle);
  if (rc > 0)
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
      printf ("rtems-rfs: read-superblock: handle open failed: %d: %s\n",
              rc, strerror (rc));
    return rc;
  }

  rc = rtems_rfs_buffer_handle_request (fs, &handle, 0, true);
  if (rc > 0)
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
      printf ("rtems-rfs: read-superblock: request failed%d: %s\n",
              rc, strerror (rc));
    return rc;
  }

  sb = rtems_rfs_buffer_data (&handle);

#define read_sb(_o) rtems_rfs_read_u32 (sb + (_o))

  if (read_sb (RTEMS_RFS_SB_OFFSET_MAGIC) != RTEMS_RFS_SB_MAGIC)
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
      printf ("rtems-rfs: read-superblock: invalid superblock, bad magic\n");
    rtems_rfs_buffer_handle_close (fs, &handle);
    return EIO;
  }

  fs->blocks     = read_sb (RTEMS_RFS_SB_OFFSET_BLOCKS);
  fs->block_size = read_sb (RTEMS_RFS_SB_OFFSET_BLOCK_SIZE);

  if (rtems_rfs_fs_size(fs) > rtems_rfs_fs_media_size (fs))
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
      printf ("rtems-rfs: read-superblock: invalid superblock block/size count\n");
    rtems_rfs_buffer_handle_close (fs, &handle);
    return EIO;
  }

  if ((read_sb (RTEMS_RFS_SB_OFFSET_VERSION) & RTEMS_RFS_VERSION_MASK) !=
      (RTEMS_RFS_VERSION * RTEMS_RFS_VERSION_MASK))
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
      printf ("rtems-rfs: read-superblock: incompatible version: %08" PRIx32 " (%08" PRIx32 ")\n",
              read_sb (RTEMS_RFS_SB_OFFSET_VERSION), RTEMS_RFS_VERSION_MASK);
    rtems_rfs_buffer_handle_close (fs, &handle);
    return EIO;
  }

  if (read_sb (RTEMS_RFS_SB_OFFSET_INODE_SIZE) != RTEMS_RFS_INODE_SIZE)
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
      printf ("rtems-rfs: read-superblock: inode size mismatch: fs:%" PRId32 " target:%" PRId32 "\n",
              read_sb (RTEMS_RFS_SB_OFFSET_VERSION), RTEMS_RFS_VERSION_MASK);
    rtems_rfs_buffer_handle_close (fs, &handle);
    return EIO;
  }

  fs->bad_blocks      = read_sb (RTEMS_RFS_SB_OFFSET_BAD_BLOCKS);
  fs->max_name_length = read_sb (RTEMS_RFS_SB_OFFSET_MAX_NAME_LENGTH);
  fs->group_count     = read_sb (RTEMS_RFS_SB_OFFSET_GROUPS);
  fs->group_blocks    = read_sb (RTEMS_RFS_SB_OFFSET_GROUP_BLOCKS);
  fs->group_inodes    = read_sb (RTEMS_RFS_SB_OFFSET_GROUP_INODES);

  fs->blocks_per_block =
    rtems_rfs_fs_block_size (fs) / sizeof (rtems_rfs_inode_block);

  fs->block_map_singly_blocks =
    fs->blocks_per_block * RTEMS_RFS_INODE_BLOCKS;
  fs->block_map_doubly_blocks =
    fs->blocks_per_block * fs->blocks_per_block * RTEMS_RFS_INODE_BLOCKS;

  fs->inodes = fs->group_count * fs->group_inodes;

  fs->inodes_per_block = fs->block_size / RTEMS_RFS_INODE_SIZE;

  if (fs->group_blocks >
      rtems_rfs_bitmap_numof_bits (rtems_rfs_fs_block_size (fs)))
  {
    rtems_rfs_buffer_handle_close (fs, &handle);
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
      printf ("rtems-rfs: read-superblock: groups blocks larger than block bits\n");
    return EIO;
  }

  rtems_rfs_buffer_handle_close (fs, &handle);

  /*
   * Change the block size to the value in the superblock.
   */
  rc = rtems_rfs_buffer_setblksize (fs, rtems_rfs_fs_block_size (fs));
  if (rc > 0)
  {
    rtems_rfs_buffer_handle_close (fs, &handle);
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
      printf ("rtems-rfs: read-superblock: invalid superblock block size%d: %s\n",
              rc, strerror (rc));
    return rc;
  }

  fs->groups = calloc (fs->group_count, sizeof (rtems_rfs_group));

  if (!fs->groups)
  {
    rtems_rfs_buffer_handle_close (fs, &handle);
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
      printf ("rtems-rfs: read-superblock: no memory for group table\n");
    return ENOMEM;
  }

  /*
   * Perform each phase of group initialisation at the same time. This way we
   * know how far the initialisation has gone if an error occurs and we need to
   * close everything.
   */
  for (group = 0; group < fs->group_count; group++)
  {
    rc = rtems_rfs_group_open (fs,
                               rtems_rfs_fs_block (fs, group, 0),
                               fs->group_blocks,
                               fs->group_inodes,
                               &fs->groups[group]);
    if (rc > 0)
    {
      int g;
      for (g = 0; g < group; g++)
        rtems_rfs_group_close (fs, &fs->groups[g]);
      rtems_rfs_buffer_handle_close (fs, &handle);
      if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
        printf ("rtems-rfs: read-superblock: no memory for group table%d: %s\n",
                rc, strerror (rc));
      return rc;
    }
  }

  return 0;
}
コード例 #26
0
int
rtems_rfs_fs_open (const char*             name,
                   void*                   user,
                   uint32_t                flags,
                   uint32_t                max_held_buffers,
                   rtems_rfs_file_system** fs)
{
#if UNUSED
  rtems_rfs_group*       group;
  size_t                 group_base;
#endif
  rtems_rfs_inode_handle inode;
  uint16_t               mode;
  int                    rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
    printf ("rtems-rfs: open: %s\n", name);

  *fs = malloc (sizeof (rtems_rfs_file_system));
  if (!*fs)
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
      printf ("rtems-rfs: open: no memory for file system data\n");
    errno = ENOMEM;
    return -1;
  }

  memset (*fs, 0, sizeof (rtems_rfs_file_system));

  (*fs)->user = user;
  rtems_chain_initialize_empty (&(*fs)->buffers);
  rtems_chain_initialize_empty (&(*fs)->release);
  rtems_chain_initialize_empty (&(*fs)->release_modified);
  rtems_chain_initialize_empty (&(*fs)->file_shares);

  (*fs)->max_held_buffers = max_held_buffers;
  (*fs)->buffers_count = 0;
  (*fs)->release_count = 0;
  (*fs)->release_modified_count = 0;
  (*fs)->flags = flags;

#if UNUSED
  group = &(*fs)->groups[0];
  group_base = 0;
#endif

  /*
   * Open the buffer interface.
   */
  rc = rtems_rfs_buffer_open (name, *fs);
  if (rc > 0)
  {
    free (*fs);
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
      printf ("rtems-rfs: open: buffer open failed: %d: %s\n",
              rc, strerror (rc));
    errno = rc;
    return -1;
  }

  rc = rtems_rfs_fs_read_superblock (*fs);
  if (rc > 0)
  {
    rtems_rfs_buffer_close (*fs);
    free (*fs);
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
      printf ("rtems-rfs: open: reading superblock: %d: %s\n",
              rc, strerror (rc));
    errno = rc;
    return -1;
  }

  rc = rtems_rfs_inode_open (*fs, RTEMS_RFS_ROOT_INO, &inode, true);
  if (rc > 0)
  {
    rtems_rfs_buffer_close (*fs);
    free (*fs);
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
      printf ("rtems-rfs: open: reading root inode: %d: %s\n",
              rc, strerror (rc));
    errno = rc;
    return -1;
  }

  if (((*fs)->flags & RTEMS_RFS_FS_FORCE_OPEN) == 0)
  {
    mode = rtems_rfs_inode_get_mode (&inode);

    if ((mode == 0xffff) || !RTEMS_RFS_S_ISDIR (mode))
    {
      rtems_rfs_inode_close (*fs, &inode);
      rtems_rfs_buffer_close (*fs);
      free (*fs);
      if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
        printf ("rtems-rfs: open: invalid root inode mode\n");
      errno = EIO;
      return -1;
    }
  }

  rc = rtems_rfs_inode_close (*fs, &inode);
  if (rc > 0)
  {
    rtems_rfs_buffer_close (*fs);
    free (*fs);
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN))
      printf ("rtems-rfs: open: closing root inode: %d: %s\n", rc, strerror (rc));
    errno = rc;
    return -1;
  }

  errno = 0;
  return 0;
}
コード例 #27
0
ファイル: rtems-rfs-dir.c プロジェクト: epicsdeb/rtems
int
rtems_rfs_dir_empty (rtems_rfs_file_system*  fs,
                     rtems_rfs_inode_handle* dir)
{
  rtems_rfs_block_map     map;
  rtems_rfs_buffer_handle buffer;
  rtems_rfs_block_no      block;
  bool                    empty;
  int                     rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_READ))
    printf ("rtems-rfs: dir-empty: dir=%" PRId32 "\n", rtems_rfs_inode_ino (dir));

  empty = true;
  
  rc = rtems_rfs_block_map_open (fs, dir, &map);
  if (rc > 0)
    return rc;

  rc = rtems_rfs_block_map_seek (fs, &map, 0, &block);
  if (rc > 0)
  {
    rtems_rfs_block_map_close (fs, &map);
    return rc;
  }
  
  rc = rtems_rfs_buffer_handle_open (fs, &buffer);
  if (rc > 0)
  {
    rtems_rfs_block_map_close (fs, &map);
    return rc;
  }

  /*
   * Look for an empty entry and if this is the last block that is the end of
   * the directory.
   */
  while (empty)
  {
    uint8_t* entry;
    int      offset;
    
    rc = rtems_rfs_buffer_handle_request (fs, &buffer, block, true);
    if (rc > 0)
      break;

    entry  = rtems_rfs_buffer_data (&buffer);
    offset = 0;
    
    while (offset < (rtems_rfs_fs_block_size (fs) - RTEMS_RFS_DIR_ENTRY_SIZE))
    {
      rtems_rfs_ino eino;
      int           elength;

      elength = rtems_rfs_dir_entry_length (entry);
      eino    = rtems_rfs_dir_entry_ino (entry);

      if (elength == RTEMS_RFS_DIR_ENTRY_EMPTY)
        break;

      if (rtems_rfs_dir_entry_valid (fs, elength, eino))
      {
        if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_EMPTY))
          printf ("rtems-rfs: dir-empty: "
                  "bad length or ino for ino %" PRIu32 ": %u/%" PRIu32 " @ %04x\n",
                  rtems_rfs_inode_ino (dir), elength, eino, offset);
        rc = EIO;
        break;
      }
        
      /*
       * Ignore the current (.) and parent (..) entries. Anything else means
       * the directory is not empty.
       */
      if (((elength != (RTEMS_RFS_DIR_ENTRY_SIZE + 1)) ||
           (entry[RTEMS_RFS_DIR_ENTRY_SIZE] != '.')) &&
          ((elength != (RTEMS_RFS_DIR_ENTRY_SIZE + 2)) ||
           (entry[RTEMS_RFS_DIR_ENTRY_SIZE] != '.') ||
           (entry[RTEMS_RFS_DIR_ENTRY_SIZE + 1] != '.')))
      {
        empty = false;
        break;
      }

      entry  += elength;
      offset += elength;
    }

    if (empty)
    {
      rc = rtems_rfs_block_map_next_block (fs, &map, &block);
      if (rc > 0)
      {
        if (rc == ENXIO)
          rc = 0;
        break;
      }
    }
  }

  if ((rc == 0) && !empty)
    rc = ENOTEMPTY;
  
  rtems_rfs_buffer_handle_close (fs, &buffer);
  rtems_rfs_block_map_close (fs, &map);
  return rc;
}
コード例 #28
0
ファイル: rtems-rfs-dir.c プロジェクト: epicsdeb/rtems
int
rtems_rfs_dir_lookup_ino (rtems_rfs_file_system*  fs,
                          rtems_rfs_inode_handle* inode,
                          const char*             name,
                          int                     length,
                          rtems_rfs_ino*          ino,
                          uint32_t*               offset)
{
  rtems_rfs_block_map     map;
  rtems_rfs_buffer_handle entries;
  int                     rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_LOOKUP_INO))
  {
    int c;
    printf ("rtems-rfs: dir-lookup-ino: lookup ino: root=%" PRId32 ", path=",
            inode->ino);
    for (c = 0; c < length; c++)
      printf ("%c", name[c]);
    printf (", len=%d\n", length);
  }

  *ino = RTEMS_RFS_EMPTY_INO;
  *offset = 0;
  
  rc = rtems_rfs_block_map_open (fs, inode, &map);
  if (rc > 0)
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_LOOKUP_INO))
      printf ("rtems-rfs: dir-lookup-ino: map open failed for ino %" PRIu32 ": %d: %s",
              rtems_rfs_inode_ino (inode), rc, strerror (rc));
    return rc;
  }
  
  rc = rtems_rfs_buffer_handle_open (fs, &entries);
  if (rc > 0)
  {
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_LOOKUP_INO))
      printf ("rtems-rfs: dir-lookup-ino: handle open failed for ino %" PRIu32 ": %d: %s",
              rtems_rfs_inode_ino (inode), rc, strerror (rc));
    rtems_rfs_block_map_close (fs, &map);
    return rc;
  }
  else
  {
    rtems_rfs_block_no block;
    uint32_t           hash;

    /*
     * Calculate the hash of the look up string.
     */
    hash = rtems_rfs_dir_hash (name, length);
  
    /*
     * Locate the first block. The map points to the start after open so just
     * seek 0. If an error the block will be 0.
     */
    rc = rtems_rfs_block_map_seek (fs, &map, 0, &block);
    if (rc > 0)
    {
      if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_LOOKUP_INO))
        printf ("rtems-rfs: dir-lookup-ino: block map find failed: %d: %s\n",
                rc, strerror (rc));
      if (rc == ENXIO)
        rc = ENOENT;
      rtems_rfs_buffer_handle_close (fs, &entries);
      rtems_rfs_block_map_close (fs, &map);
      return rc;
    }
        
    while ((rc == 0) && block)
    {
      uint8_t* entry;
      
      if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_LOOKUP_INO))
        printf ("rtems-rfs: dir-lookup-ino: block read, ino=%" PRIu32 " bno=%" PRId32 "\n",
                rtems_rfs_inode_ino (inode), map.bpos.bno);
      
      rc = rtems_rfs_buffer_handle_request (fs, &entries, block, true); 
      if (rc > 0)
      {
        if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_LOOKUP_INO))
          printf ("rtems-rfs: dir-lookup-ino: block read, ino=%" PRIu32 " block=%" PRId32 ": %d: %s\n",
                  rtems_rfs_inode_ino (inode), block, rc, strerror (rc));
        break;
      }

      /*
       * Search the block to see if the name matches. A hash of 0xffff or 0x0
       * means the entry is empty.
       */

      entry = rtems_rfs_buffer_data (&entries);
      
      map.bpos.boff = 0;

      while (map.bpos.boff < (rtems_rfs_fs_block_size (fs) - RTEMS_RFS_DIR_ENTRY_SIZE))
      {
        uint32_t ehash;
        int      elength;
      
        ehash  = rtems_rfs_dir_entry_hash (entry);
        elength = rtems_rfs_dir_entry_length (entry);
        *ino = rtems_rfs_dir_entry_ino (entry);

        if (elength == RTEMS_RFS_DIR_ENTRY_EMPTY)
          break;
        
        if (rtems_rfs_dir_entry_valid (fs, elength, *ino))
        {
          if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_LOOKUP_INO))
            printf ("rtems-rfs: dir-lookup-ino: "
                    "bad length or ino for ino %" PRIu32 ": %u/%" PRId32 " @ %04" PRIx32 "\n",
                    rtems_rfs_inode_ino (inode), elength, *ino, map.bpos.boff);
          rc = EIO;
          break;
        }
          
        if (ehash == hash)
        {
          if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_LOOKUP_INO_CHECK))
            printf ("rtems-rfs: dir-lookup-ino: "
                    "checking entry for ino %" PRId32 ": bno=%04" PRIx32 "/off=%04" PRIx32
                    " length:%d ino:%" PRId32 "\n",
                    rtems_rfs_inode_ino (inode), map.bpos.bno, map.bpos.boff,
                    elength, rtems_rfs_dir_entry_ino (entry));

          if (memcmp (entry + RTEMS_RFS_DIR_ENTRY_SIZE, name, length) == 0)
          {
            *offset = rtems_rfs_block_map_pos (fs, &map);
            
            if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_LOOKUP_INO_FOUND))
              printf ("rtems-rfs: dir-lookup-ino: "
                      "entry found in ino %" PRIu32 ", ino=%" PRIu32 " offset=%" PRIu32 "\n",
                      rtems_rfs_inode_ino (inode), *ino, *offset);

            rtems_rfs_buffer_handle_close (fs, &entries);
            rtems_rfs_block_map_close (fs, &map);
            return 0;
          }
        }

        map.bpos.boff += elength;
        entry += elength;
      }

      if (rc == 0)
      {
        rc = rtems_rfs_block_map_next_block (fs, &map, &block);
        if ((rc > 0) && (rc != ENXIO))
        {
          if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_LOOKUP_INO))
            printf ("rtems-rfs: dir-lookup-ino: "
                    "block map next block failed in ino %" PRIu32 ": %d: %s\n",
                    rtems_rfs_inode_ino (inode), rc, strerror (rc));
        }
        if (rc == ENXIO)
          rc = ENOENT;
      }
    }

    if ((rc == 0) && (block == 0))
    {
      rc = EIO;
      if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_LOOKUP_INO))
        printf ("rtems-rfs: dir-lookup-ino: block is 0 in ino %" PRIu32 ": %d: %s\n",
                rtems_rfs_inode_ino (inode), rc, strerror (rc));
    }
  }
  
  rtems_rfs_buffer_handle_close (fs, &entries);
  rtems_rfs_block_map_close (fs, &map);
  return rc;
}
コード例 #29
0
ファイル: rtems-rfs-buffer.c プロジェクト: AndroidMarv/rtems
int
rtems_rfs_buffer_handle_request (rtems_rfs_file_system*   fs,
                                 rtems_rfs_buffer_handle* handle,
                                 rtems_rfs_buffer_block   block,
                                 bool                     read)
{
  int rc;

  /*
   * If the handle has a buffer release it. This allows a handle to be reused
   * without needing to close then open it again.
   */
  if (rtems_rfs_buffer_handle_has_block (handle))
  {
    /*
     * Treat block 0 as special to handle the loading of the super block.
     */
    if (block && (rtems_rfs_buffer_bnum (handle) == block))
      return 0;

    if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_REQUEST))
      printf ("rtems-rfs: buffer-request: handle has buffer: %" PRIu32 "\n",
              rtems_rfs_buffer_bnum (handle));

    rc = rtems_rfs_buffer_handle_release (fs, handle);
    if (rc > 0)
      return rc;
    handle->dirty = false;
    handle->bnum = 0;
  }

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_REQUEST))
    printf ("rtems-rfs: buffer-request: block=%" PRIu32 "\n", block);

  /*
   * First check to see if the buffer has already been requested and is
   * currently attached to a handle. If it is share the access. A buffer could
   * be shared where different parts of the block have separate functions. An
   * example is an inode block and the file system needs to handle 2 inodes in
   * the same block at the same time.
   */
  if (fs->buffers_count)
  {
    /*
     * Check the active buffer list for shared buffers.
     */
    handle->buffer = rtems_rfs_scan_chain (&fs->buffers,
                                           &fs->buffers_count,
                                           block);
    if (rtems_rfs_buffer_handle_has_block (handle) &&
        rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_REQUEST))
      printf ("rtems-rfs: buffer-request: buffer shared: refs: %d\n",
              rtems_rfs_buffer_refs (handle) + 1);
  }

  /*
   * If the buffer has not been found check the local cache of released
   * buffers. There are release and released modified lists to preserve the
   * state.
   */
  if (!rtems_rfs_fs_no_local_cache (fs) &&
      !rtems_rfs_buffer_handle_has_block (handle))
  {
    /*
     * Check the local cache of released buffers.
     */
    if (fs->release_count)
      handle->buffer = rtems_rfs_scan_chain (&fs->release,
                                             &fs->release_count,
                                             block);

    if (!rtems_rfs_buffer_handle_has_block (handle) &&
        fs->release_modified_count)
    {
      handle->buffer = rtems_rfs_scan_chain (&fs->release_modified,
                                             &fs->release_modified_count,
                                             block);
      /*
       * If we found a buffer retain the dirty buffer state.
       */
      if (rtems_rfs_buffer_handle_has_block (handle))
        rtems_rfs_buffer_mark_dirty (handle);
    }
  }

  /*
   * If not located we request the buffer from the I/O layer.
   */
  if (!rtems_rfs_buffer_handle_has_block (handle))
  {
    rc = rtems_rfs_buffer_io_request (fs, block, read, &handle->buffer);

    if (rc > 0)
    {
      if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_REQUEST))
        printf ("rtems-rfs: buffer-request: block=%" PRIu32 ": bdbuf-%s: %d: %s\n",
                block, read ? "read" : "get", rc, strerror (rc));
      return rc;
    }

    rtems_chain_set_off_chain (rtems_rfs_buffer_link(handle));
  }

  /*
   * Increase the reference count of the buffer.
   */
  rtems_rfs_buffer_refs_up (handle);
  rtems_chain_append (&fs->buffers, rtems_rfs_buffer_link (handle));
  fs->buffers_count++;

  handle->buffer->user = (void*) ((intptr_t) block);
  handle->bnum = block;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_BUFFER_HANDLE_REQUEST))
    printf ("rtems-rfs: buffer-request: block=%" PRIu32 " bdbuf-%s=%" PRIu32 " refs=%d\n",
            block, read ? "read" : "get", handle->buffer->block,
            handle->buffer->references);

  return 0;
}
コード例 #30
0
ファイル: rtems-rfs-dir.c プロジェクト: epicsdeb/rtems
int
rtems_rfs_dir_read (rtems_rfs_file_system*  fs,
                    rtems_rfs_inode_handle* dir,
                    rtems_rfs_pos_rel       offset,
                    struct dirent*          dirent,
                    size_t*                 length)
{
  rtems_rfs_block_map     map;
  rtems_rfs_buffer_handle buffer;
  rtems_rfs_block_no      block;
  int                     rc;

  if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_READ))
    printf ("rtems-rfs: dir-read: dir=%" PRId32 " offset=%" PRId64 "\n",
            rtems_rfs_inode_ino (dir), offset);

  *length = 0;
  
  rc = rtems_rfs_block_map_open (fs, dir, &map);
  if (rc > 0)
    return rc;

  if (((rtems_rfs_fs_block_size (fs) -
        (offset % rtems_rfs_fs_block_size (fs))) <= RTEMS_RFS_DIR_ENTRY_SIZE))
    offset = (((offset / rtems_rfs_fs_block_size (fs)) + 1) *
              rtems_rfs_fs_block_size (fs));
  
  rc = rtems_rfs_block_map_seek (fs, &map, offset, &block);
  if (rc > 0)
  {
    if (rc == ENXIO)
      rc = ENOENT;
    rtems_rfs_block_map_close (fs, &map);
    return rc;
  }
  
  rc = rtems_rfs_buffer_handle_open (fs, &buffer);
  if (rc > 0)
  {
    rtems_rfs_block_map_close (fs, &map);
    return rc;
  }

  /*
   * Look for an empty entry and if this is the last block that is the end of
   * the directory.
   */
  while (rc == 0)
  {
    uint8_t*      entry;
    rtems_rfs_ino eino;
    int           elength;    
    int           remaining;
    
    rc = rtems_rfs_buffer_handle_request (fs, &buffer, block, true);
    if (rc > 0)
    {
      rtems_rfs_buffer_handle_close (fs, &buffer);
      rtems_rfs_block_map_close (fs, &map);
      return rc;
    }

    entry  = rtems_rfs_buffer_data (&buffer);
    entry += map.bpos.boff;
    
    elength = rtems_rfs_dir_entry_length (entry);
    eino    = rtems_rfs_dir_entry_ino (entry);

    if (elength != RTEMS_RFS_DIR_ENTRY_EMPTY)
    {
      if (rtems_rfs_dir_entry_valid (fs, elength, eino))
      {
        if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_READ))
          printf ("rtems-rfs: dir-read: "
                  "bad length or ino for ino %" PRIu32 ": %u/%" PRId32 " @ %04" PRIx32 "\n",
                  rtems_rfs_inode_ino (dir), elength, eino, map.bpos.boff);
        rc = EIO;
        break;
      }
        
      memset (dirent, 0, sizeof (struct dirent));
      dirent->d_off = offset;
      dirent->d_reclen = sizeof (struct dirent);

      *length += elength;

      remaining = rtems_rfs_fs_block_size (fs) - (map.bpos.boff + elength);
      
      if (remaining <= RTEMS_RFS_DIR_ENTRY_SIZE)
        *length += remaining;
      
      elength -= RTEMS_RFS_DIR_ENTRY_SIZE;
      if (elength > NAME_MAX)
        elength = NAME_MAX;
      
      memcpy (dirent->d_name, entry + RTEMS_RFS_DIR_ENTRY_SIZE, elength);

      dirent->d_ino = rtems_rfs_dir_entry_ino (entry);
      dirent->d_namlen = elength;
      
      if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_READ))
        printf ("rtems-rfs: dir-read: found off:%" PRIdoff_t " ino:%ld name=%s\n",
                dirent->d_off, dirent->d_ino, dirent->d_name);
      break;
    }

    *length += rtems_rfs_fs_block_size (fs) - map.bpos.boff;
    
    if (rtems_rfs_trace (RTEMS_RFS_TRACE_DIR_READ))
      printf ("rtems-rfs: dir-read: next block: off:%" PRId64 " length:%zd\n",
              offset, *length);
      
    rc = rtems_rfs_block_map_next_block (fs, &map, &block);
    if (rc == ENXIO)
      rc = ENOENT;
  }

  rtems_rfs_buffer_handle_close (fs, &buffer);
  rtems_rfs_block_map_close (fs, &map);
  return rc;
}