static bool rtems_rfs_check_config (rtems_rfs_file_system* fs, const rtems_rfs_format_config* config) { fs->block_size = config->block_size; if (!fs->block_size) { uint64_t total_size = rtems_rfs_fs_media_size (fs); if (total_size >= GIGS (1)) { uint32_t gigs = (total_size + GIGS (1)) / GIGS (1); int b; for (b = 31; b > 0; b--) if ((gigs & (1 << b)) != 0) break; fs->block_size = 1 << b; } if (fs->block_size < 512) fs->block_size = 512; if (fs->block_size > (4 * 1024)) fs->block_size = (4 * 1024); } if ((fs->block_size % rtems_rfs_fs_media_block_size (fs)) != 0) { printf ("block size (%zd) is not a multiple of media block size (%" PRId32 ")\n", fs->block_size, rtems_rfs_fs_media_block_size (fs)); return false; } fs->group_blocks = config->group_blocks; if (!fs->group_blocks) { /* * The number of blocks per group is defined by the number of bits in a * block. */ fs->group_blocks = rtems_rfs_bitmap_numof_bits (fs->block_size); } if (fs->group_blocks > rtems_rfs_bitmap_numof_bits (fs->block_size)) { printf ("group block count is higher than bits in block\n"); return false; } fs->blocks = rtems_rfs_fs_media_size (fs) / fs->block_size; /* * The bits per block sets the upper limit for the number of blocks in a * group. The disk will be divided into groups which are the number of bits * per block. */ fs->group_count = rtems_rfs_rup_quotient (rtems_rfs_fs_blocks (fs), rtems_rfs_bits_per_block (fs)); fs->group_inodes = config->group_inodes; if (!fs->group_inodes) { int inode_overhead = RTEMS_RFS_INODE_OVERHEAD_PERCENTAGE; /* * The number of inodes per group is set as a percentage. */ if (config->inode_overhead) inode_overhead = config->inode_overhead; fs->group_inodes = rtems_rfs_inodes_from_percent (fs, inode_overhead); } /* * Round up to fill a block because the minimum allocation unit is a block. */ fs->inodes_per_block = rtems_rfs_fs_block_size (fs) / RTEMS_RFS_INODE_SIZE; fs->group_inodes = rtems_rfs_rup_quotient (fs->group_inodes, fs->inodes_per_block) * fs->inodes_per_block; if (fs->group_inodes > rtems_rfs_bitmap_numof_bits (fs->block_size)) fs->group_inodes = rtems_rfs_bitmap_numof_bits (fs->block_size); fs->max_name_length = config->max_name_length; if (!fs->max_name_length) { fs->max_name_length = 512; } return true; }
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; }
/** * Return the number of bits that fit in the block size. */ static int rtems_rfs_bits_per_block (rtems_rfs_file_system* fs) { return rtems_rfs_bitmap_numof_bits (rtems_rfs_fs_block_size (fs)); }