From 5b8d935ab3b9b70302d53292f024999a2259ca7b Mon Sep 17 00:00:00 2001 From: Ralf Kirchner Date: Wed, 5 Dec 2012 14:11:26 +0100 Subject: dosfs: Add skip_alignment for msdos_format() Add skip_alignment parameter of msdos_format_request_param_t. Delete cluster_align parameter of msdos_format_request_param_t. By default the FAT, data cluster, and root directory for FAT12 and FAT16 is aligned on a cluster boundary to optimize performance. Format changes throughout. --- cpukit/libfs/src/dosfs/dosfs.h | 9 +- cpukit/libfs/src/dosfs/fat.h | 1 + cpukit/libfs/src/dosfs/msdos_format.c | 111 +++++++++++++++++++------ cpukit/libmisc/shell/main_msdosfmt.c | 4 +- testsuites/fstests/mdosfs_support/fs_support.c | 2 +- 5 files changed, 93 insertions(+), 34 deletions(-) diff --git a/cpukit/libfs/src/dosfs/dosfs.h b/cpukit/libfs/src/dosfs/dosfs.h index 93d77892d7..530d23ecd5 100644 --- a/cpukit/libfs/src/dosfs/dosfs.h +++ b/cpukit/libfs/src/dosfs/dosfs.h @@ -49,12 +49,9 @@ typedef struct { uint8_t fattype; /* request value: MSDOS_FMT_FAT12/16/32 */ uint8_t media; /* media code. default: 0xF8 */ bool quick_format; /* true: do not clear out data sectors */ - uint32_t cluster_align; /* requested value: cluster alignment */ - /* make sector number of first sector */ - /* of first cluster divisible by this */ - /* value. This can optimize clusters */ - /* to be located at start of track */ - /* or start of flash block */ + bool skip_alignment; /* do not align FAT, data cluster, and */ + /* root directory for FAT12 and FAT16 to */ + /* a cluster boundary */ int info_level; /* The amount of info to output */ } msdos_format_request_param_t; diff --git a/cpukit/libfs/src/dosfs/fat.h b/cpukit/libfs/src/dosfs/fat.h index 260d8aafd9..dab2471900 100644 --- a/cpukit/libfs/src/dosfs/fat.h +++ b/cpukit/libfs/src/dosfs/fat.h @@ -271,6 +271,7 @@ extern "C" { #define FAT_TOTAL_FSINFO_SIZE 512 #define MS_BYTES_PER_CLUSTER_LIMIT 0x8000 /* 32K */ +#define MS_BYTES_PER_CLUSTER_LIMIT_FAT12 0x1000 /* 4K */ #define FAT_BR_EXT_FLAGS_MIRROR 0x0080 diff --git a/cpukit/libfs/src/dosfs/msdos_format.c b/cpukit/libfs/src/dosfs/msdos_format.c index 1c31b98609..69bba0c14f 100644 --- a/cpukit/libfs/src/dosfs/msdos_format.c +++ b/cpukit/libfs/src/dosfs/msdos_format.c @@ -64,8 +64,23 @@ typedef struct { char VolLabel[FAT_BR_VOLLAB_SIZE+1]; bool VolLabel_present; uint32_t vol_id; + bool skip_alignment; } msdos_format_param_t; +/* + * Align to cluster borders + */ +static uint32_t + loc_align_object (const uint32_t sectors, + const uint32_t clustersize, + const bool skip_alignment) +{ + if (! skip_alignment) + return (sectors + clustersize - 1) & ~(clustersize - 1); + else + return sectors; +} + /* * Formatted output. */ @@ -278,9 +293,12 @@ static int msdos_format_eval_sectors_per_cluster \*-------------------------------------------------------------------------*/ int fattype, /* type code of FAT (FAT_FAT12 ...) */ uint32_t bytes_per_sector, /* byte count per sector (512) */ - uint32_t fatdata_sec_cnt, /* sectors available for FAT and data */ + const uint32_t total_sector_cnt, /* total number of secters per volume */ + const uint32_t rsvd_sector_cnt, /* number of reserved sectors */ + const uint32_t root_dir_sector_cnt,/* number of sectors for the root dir */ uint8_t fat_num, /* number of fat copies */ uint32_t sectors_per_cluster, /* sectors per cluster (requested) */ + const bool skip_alignment, /* true for no cluster alignment */ uint32_t *sectors_per_cluster_adj, /* ret: sec per cluster (granted) */ uint32_t *sectors_per_fat_ptr /* ret: sectors needed for one FAT */ ) @@ -296,6 +314,8 @@ static int msdos_format_eval_sectors_per_cluster uint32_t fat_capacity; uint32_t sectors_per_fat; uint32_t data_cluster_cnt; + uint32_t fatdata_sect_cnt; + uint32_t fat_sectors_cnt; /* * ensure, that maximum cluster size (32KByte) is not exceeded */ @@ -310,27 +330,39 @@ static int msdos_format_eval_sectors_per_cluster * - compute storage size for FAT * - subtract from total cluster count */ - fatdata_cluster_cnt = fatdata_sec_cnt/sectors_per_cluster; + fatdata_sect_cnt = total_sector_cnt + - loc_align_object (rsvd_sector_cnt, sectors_per_cluster, skip_alignment); if (fattype == FAT_FAT12) { - fat_capacity = fatdata_cluster_cnt * 3 / 2; + fatdata_sect_cnt = fatdata_sect_cnt + - loc_align_object (root_dir_sector_cnt, sectors_per_cluster, skip_alignment); + fatdata_cluster_cnt = fatdata_sect_cnt/sectors_per_cluster; + fat_capacity = fatdata_cluster_cnt * 3 / 2; } else if (fattype == FAT_FAT16) { - fat_capacity = fatdata_cluster_cnt * 2; + fatdata_sect_cnt = fatdata_sect_cnt + - loc_align_object (root_dir_sector_cnt, sectors_per_cluster, skip_alignment); + fatdata_cluster_cnt = fatdata_sect_cnt/sectors_per_cluster; + fat_capacity = fatdata_cluster_cnt * 2; } else { /* FAT32 */ - fat_capacity = fatdata_cluster_cnt * 4; + fatdata_cluster_cnt = fatdata_sect_cnt/sectors_per_cluster; + fat_capacity = fatdata_cluster_cnt * 4; } sectors_per_fat = ((fat_capacity + (bytes_per_sector - 1)) / bytes_per_sector); + fat_sectors_cnt = loc_align_object (sectors_per_fat * fat_num, + sectors_per_cluster, + skip_alignment); + data_cluster_cnt = (fatdata_cluster_cnt - - (((sectors_per_fat * fat_num) + ((fat_sectors_cnt + (sectors_per_cluster - 1)) / sectors_per_cluster)); /* - * data cluster count too big? then make sectors bigger + * data cluster count too big? Then make clusters bigger */ if (((fattype == FAT_FAT12) && (data_cluster_cnt > FAT_FAT12_MAX_CLN)) || ((fattype == FAT_FAT16) && (data_cluster_cnt > FAT_FAT16_MAX_CLN))) { @@ -342,7 +374,12 @@ static int msdos_format_eval_sectors_per_cluster /* * when maximum cluster size is exceeded, we have invalid data, abort... */ - if ((sectors_per_cluster * bytes_per_sector) + if (fattype == FAT_FAT12) { + if (MS_BYTES_PER_CLUSTER_LIMIT_FAT12 < (sectors_per_cluster * bytes_per_sector)) { + ret_val = EINVAL; + finished = true; + } + } else if ((sectors_per_cluster * bytes_per_sector) > MS_BYTES_PER_CLUSTER_LIMIT) { ret_val = EINVAL; finished = true; @@ -352,11 +389,11 @@ static int msdos_format_eval_sectors_per_cluster if (ret_val != 0) { rtems_set_errno_and_return_minus_one(ret_val); } - else { - *sectors_per_cluster_adj = sectors_per_cluster; - *sectors_per_fat_ptr = sectors_per_fat; - return 0; - } + + *sectors_per_cluster_adj = sectors_per_cluster; + *sectors_per_fat_ptr = fat_sectors_cnt / fat_num; + + return 0; } @@ -381,7 +418,6 @@ static int msdos_format_determine_fmt_params \*=========================================================================*/ { int ret_val = 0; - uint32_t fatdata_sect_cnt; uint32_t onebit; uint32_t sectors_per_cluster_adj = 0; uint64_t total_size = 0; @@ -393,7 +429,8 @@ static int msdos_format_determine_fmt_params * At least one thing we don't have to magically guess... */ if (ret_val == 0) { - ret_val = rtems_disk_fd_get_block_size(fd, &fmt_params->bytes_per_sector); + ret_val = rtems_disk_fd_get_media_block_size(fd, &fmt_params->bytes_per_sector); + } if (ret_val == 0) { ret_val = rtems_disk_fd_get_block_count(fd, &fmt_params->totl_sector_cnt); @@ -542,6 +579,10 @@ static int msdos_format_determine_fmt_params } } + if (ret_val == 0 && rqdata != NULL) { + fmt_params->skip_alignment = rqdata->skip_alignment; + } + if (ret_val == 0) { msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL, "sectors per cluster: %d\n", fmt_params->sectors_per_cluster); @@ -588,10 +629,6 @@ static int msdos_format_determine_fmt_params / fmt_params->bytes_per_sector); } if (ret_val == 0) { - fatdata_sect_cnt = (fmt_params->totl_sector_cnt - - fmt_params->rsvd_sector_cnt - - fmt_params->root_dir_sectors); - /* * check values to get legal arrangement of FAT type and cluster count */ @@ -599,14 +636,32 @@ static int msdos_format_determine_fmt_params ret_val = msdos_format_eval_sectors_per_cluster (fmt_params->fattype, fmt_params->bytes_per_sector, - fatdata_sect_cnt, + fmt_params->totl_sector_cnt, + fmt_params->rsvd_sector_cnt, + fmt_params->root_dir_sectors, fmt_params->fat_num, fmt_params->sectors_per_cluster, + fmt_params->skip_alignment, §ors_per_cluster_adj, &(fmt_params->sectors_per_fat)); fmt_params->sectors_per_cluster = sectors_per_cluster_adj; } + if (0 == ret_val) + { + if (FAT_FAT32 != fmt_params->fattype) + { + fmt_params->files_per_root_dir = loc_align_object (fmt_params->root_dir_sectors, + fmt_params->sectors_per_cluster, + fmt_params->skip_alignment) + * (fmt_params->bytes_per_sector / FAT_DIRENTRY_SIZE); + } + + fmt_params->rsvd_sector_cnt = loc_align_object (fmt_params->rsvd_sector_cnt, + fmt_params->sectors_per_cluster, + fmt_params->skip_alignment); + } + /* * determine media code */ @@ -1064,6 +1119,8 @@ int msdos_format * allocate directory in a FAT32 FS */ if (ret_val == 0) { + uint32_t start_sector; + /* * empty sector: all clusters are free/do not link further on */ @@ -1106,15 +1163,19 @@ int msdos_format */ FAT_SET_VAL32(tmp_sec,8,FAT_FAT32_EOC); } + + start_sector = loc_align_object (fmt_params.rsvd_sector_cnt, + fmt_params.sectors_per_cluster, + fmt_params.skip_alignment); for (i = 0; (i < fmt_params.fat_num) && (ret_val == 0); i++) { ret_val = msdos_format_write_sec - (fd, - fmt_params.rsvd_sector_cnt - + (i * fmt_params.sectors_per_fat), - fmt_params.bytes_per_sector, - tmp_sec); + (fd, + start_sector + + (i * fmt_params.sectors_per_fat), + fmt_params.bytes_per_sector, + tmp_sec); } } /* diff --git a/cpukit/libmisc/shell/main_msdosfmt.c b/cpukit/libmisc/shell/main_msdosfmt.c index e684246979..000b8e8400 100644 --- a/cpukit/libmisc/shell/main_msdosfmt.c +++ b/cpukit/libmisc/shell/main_msdosfmt.c @@ -36,7 +36,7 @@ static int rtems_shell_main_msdos_format( .fattype = MSDOS_FMT_FATANY, .media = 0, .quick_format = TRUE, - .cluster_align = 0, + .skip_alignment = 0, .info_level = 0 }; @@ -149,7 +149,7 @@ static int rtems_shell_main_msdos_format( printf (" %-20s: %i\n", "fat type", rqdata.fattype); printf (" %-20s: %d\n", "media", rqdata.media); printf (" %-20s: %d\n", "quick_format", rqdata.quick_format); - printf (" %-20s: %" PRIu32 "\n", "cluster align", rqdata.cluster_align); + printf (" %-20s: %s\n", "skip_alignment", (0 == rqdata.skip_alignment) ? "false" : "true"); } if (msdos_format (driver, &rqdata) < 0) { diff --git a/testsuites/fstests/mdosfs_support/fs_support.c b/testsuites/fstests/mdosfs_support/fs_support.c index ef4356e65b..c58379ac3a 100644 --- a/testsuites/fstests/mdosfs_support/fs_support.c +++ b/testsuites/fstests/mdosfs_support/fs_support.c @@ -34,7 +34,7 @@ msdos_format_request_param_t rqdata = { fattype: MSDOS_FMT_FATANY, media: 0, quick_format: FALSE, - cluster_align: 0, + skip_alignment: 0, info_level: 0 }; -- cgit v1.2.3