Пример #1
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;
}
Пример #2
0
static bool
rtems_rfs_write_group (rtems_rfs_file_system* fs,
                       int                    group,
                       bool                   initialise_inodes,
                       bool                   verbose)
{
  rtems_rfs_buffer_handle  handle;
  rtems_rfs_bitmap_control bitmap;
  rtems_rfs_buffer_block   group_base;
  size_t                   group_size;
  int                      blocks;
  int                      b;
  int                      rc;
  
  group_base = rtems_rfs_fs_block (fs, group, 0);

  if (group_base > rtems_rfs_fs_blocks (fs))
  {
    printf ("rtems-rfs: write-group: group %d base beyond disk limit\n",
            group);
    return false;
  }

  group_size = fs->group_blocks;

  /*
   * Be nice to strange sizes of disks. These are embedded systems after all
   * and nice numbers do not always work out. Let the last block pick up the
   * remainder of the blocks.
   */
  if ((group_base + group_size) > rtems_rfs_fs_blocks (fs))
    group_size = rtems_rfs_fs_blocks (fs) - group_base;

  if (verbose)
    printf ("\rrtems-rfs: format: group %3d: base = %" PRId32 ", size = %zd",
            group, group_base, group_size);

  /*
   * Open a handle and request an empty buffer.
   */
  rc = rtems_rfs_buffer_handle_open (fs, &handle);
  if (rc > 0)
  {
    printf ("\nrtems-rfs: write-group: handle open failed: %d: %s\n",
            rc, strerror (rc));
    return false;
  }

  if (verbose)
    printf (", blocks");
  
  /*
   * Open the block bitmap using the new buffer.
   */
  rc = rtems_rfs_bitmap_open (&bitmap, fs, &handle, group_size,
                              group_base + RTEMS_RFS_GROUP_BLOCK_BITMAP_BLOCK);
  if (rc > 0)
  {
    rtems_rfs_buffer_handle_close (fs, &handle);
    printf ("\nrtems-rfs: write-group: group %3d: open block bitmap failed: %d: %s\n",
            group, rc, strerror (rc));
    return false;
  }

  /*
   * Force the whole buffer to a known state. The bit map may not occupy the
   * whole block.
   */
  memset (rtems_rfs_buffer_data (&handle), 0xff, rtems_rfs_fs_block_size (fs));
  
  /*
   * Clear the bitmap.
   */
  rc = rtems_rfs_bitmap_map_clear_all (&bitmap);
  if (rc > 0)
  {
    rtems_rfs_bitmap_close (&bitmap);
    rtems_rfs_buffer_handle_close (fs, &handle);
    printf ("\nrtems-rfs: write-group: group %3d: block bitmap clear all failed: %d: %s\n",
            group, rc, strerror (rc));
    return false;
  }
  
  /*
   * Forced allocation of the block bitmap.
   */
  rtems_rfs_bitmap_map_set (&bitmap, RTEMS_RFS_GROUP_BLOCK_BITMAP_BLOCK);

  /*
   * Forced allocation of the inode bitmap.
   */
  rtems_rfs_bitmap_map_set (&bitmap, RTEMS_RFS_GROUP_INODE_BITMAP_BLOCK);

  /*
   * Determine the number of inodes blocks in the group.
   */
  blocks = rtems_rfs_rup_quotient (fs->group_inodes, fs->inodes_per_block);

  /*
   * Forced allocation of the inode blocks which follow the block bitmap.
   */
  for (b = 0; b < blocks; b++)
    rtems_rfs_bitmap_map_set (&bitmap, b + RTEMS_RFS_GROUP_INODE_BLOCK);

  /*
   * Close the block bitmap.
   */
  rc = rtems_rfs_bitmap_close (&bitmap);
  if (rc > 0)
  {
    rtems_rfs_buffer_handle_close (fs, &handle);
    printf ("\nrtems-rfs: write-group: group %3d: close block bitmap failed: %d: %s\n",
            group, rc, strerror (rc));
    return false;
  }

  rtems_rfs_buffer_mark_dirty (&handle);

  if (verbose)
    printf (", inodes");
  
  /*
   * Open the inode bitmap using the old buffer. Should release any changes.
   */
  rc = rtems_rfs_bitmap_open (&bitmap, fs, &handle, group_size,
                              group_base + RTEMS_RFS_GROUP_INODE_BITMAP_BLOCK);
  if (rc > 0)
  {
    rtems_rfs_buffer_handle_close (fs, &handle);
    printf ("\nrtems-rfs: write-group: group %3d: open inode bitmap failed: %d: %s\n",
            group, rc, strerror (rc));
    return false;
  }

  /*
   * Force the whole buffer to a known state. The bit map may not occupy the
   * whole block.
   */
  memset (rtems_rfs_buffer_data (&handle), 0x00, rtems_rfs_fs_block_size (fs));
  
  /*
   * Clear the inode bitmap.
   */
  rc = rtems_rfs_bitmap_map_clear_all (&bitmap);
  if (rc > 0)
  {
    rtems_rfs_bitmap_close (&bitmap);
    rtems_rfs_buffer_handle_close (fs, &handle);
    printf ("\nrtems-rfs: write-group: group %3d: inode bitmap" \
            " clear all failed: %d: %s\n", group, rc, strerror (rc));
    return false;
  }
  
  /*
   * Close the inode bitmap.
   */
  rc = rtems_rfs_bitmap_close (&bitmap);
  if (rc > 0)
  {
    rtems_rfs_buffer_handle_close (fs, &handle);
    printf ("\nrtems-rfs: write-group: group %3d: close inode" \
            " bitmap failed: %d: %s\n", group, rc, strerror (rc));
    return false;
  }

  rtems_rfs_buffer_mark_dirty (&handle);

  /*
   * Initialise the inode tables if required to do so.
   */
  if (initialise_inodes)
  {
    for (b = 0; b < blocks; b++)
    {
      rc = rtems_rfs_buffer_handle_request (fs, &handle,
                                            group_base + b + RTEMS_RFS_GROUP_INODE_BLOCK,
                                            false);
      if (rc > 0)
      {
        rtems_rfs_buffer_handle_close (fs, &handle);
        printf ("\nrtems-rfs: write-group: group %3d: block %" PRId32 " request failed: %d: %s\n",
                group, group_base + b + RTEMS_RFS_GROUP_INODE_BLOCK,
                rc, strerror (rc));
        return false;
      }
    
      /*
       * Force the whole buffer to a known state. The bit map may not occupy the
       * whole block.
       */
      memset (rtems_rfs_buffer_data (&handle), 0xff, rtems_rfs_fs_block_size (fs));
  
      rtems_rfs_buffer_mark_dirty (&handle);
    }
  }
  
  rc = rtems_rfs_buffer_handle_close (fs, &handle);
  if (rc > 0)
  {
    printf ("\nrtems-rfs: write-group: buffer handle close failed: %d: %s\n",
            rc, strerror (rc));
    return false;
  }
  
  return true;
}