[PATCH 3/8] dosfs: Add skip_aligment for msdos_format()
Ralf Kirchner
ralf.kirchner at embedded-brains.de
Thu Nov 29 14:32:41 UTC 2012
Add skip_aligment 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 | 231 ++++++++++++++----------
cpukit/libmisc/shell/main_msdosfmt.c | 4 +-
testsuites/fstests/mdosfs_support/fs_support.c | 2 +-
5 Dateien geändert, 143 Zeilen hinzugefügt(+), 104 Zeilen entfernt(-)
diff --git a/cpukit/libfs/src/dosfs/dosfs.h b/cpukit/libfs/src/dosfs/dosfs.h
index 93d7789..530d23e 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 260d8aa..dab2471 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 974c00d..e8107a2 100644
--- a/cpukit/libfs/src/dosfs/msdos_format.c
+++ b/cpukit/libfs/src/dosfs/msdos_format.c
@@ -64,9 +64,24 @@ 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 unsigned int
+ loc_align_object (const unsigned int sectors,
+ const unsigned int clustersize,
+ const bool skip_alignment)
+{
+ if (! skip_alignment)
+ return (sectors + clustersize - 1) & ~(clustersize - 1);
+ else
+ return sectors;
+}
+
+/*
* Formatted output.
*/
static void
@@ -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) */
+ 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,34 @@ 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 +369,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 +384,9 @@ 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 +411,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 +422,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);
@@ -410,7 +440,7 @@ static int msdos_format_determine_fmt_params
*/
if (ret_val == 0) {
if ((rqdata == NULL) ||
- (rqdata->fat_num == 0)) {
+ (rqdata->fat_num == 0)) {
fmt_params->fat_num = 2;
}
else if (rqdata->fat_num <= 6) {
@@ -462,19 +492,19 @@ static int msdos_format_determine_fmt_params
if (ret_val == 0) {
fmt_params->sectors_per_cluster = 1;
if ((rqdata != NULL) &&
- (rqdata->fattype == MSDOS_FMT_FAT12)) {
+ (rqdata->fattype == MSDOS_FMT_FAT12)) {
fmt_params->fattype = FAT_FAT12;
}
else if ((rqdata != NULL) &&
- (rqdata->fattype == MSDOS_FMT_FAT16)) {
+ (rqdata->fattype == MSDOS_FMT_FAT16)) {
fmt_params->fattype = FAT_FAT16;
}
else if ((rqdata != NULL) &&
- (rqdata->fattype == MSDOS_FMT_FAT32)) {
+ (rqdata->fattype == MSDOS_FMT_FAT32)) {
fmt_params->fattype = FAT_FAT32;
}
else if ((rqdata != NULL) &&
- (rqdata->fattype != MSDOS_FMT_FATANY)) {
+ (rqdata->fattype != MSDOS_FMT_FATANY)) {
ret_val = -1;
errno = EINVAL;
}
@@ -492,14 +522,12 @@ static int msdos_format_determine_fmt_params
fat16_sect_per_clust = rqdata->sectors_per_cluster;
}
- if (fmt_params->totl_sector_cnt
- < FAT_FAT12_MAX_CLN * fat12_sect_per_clust) {
+ if (fmt_params->totl_sector_cnt < FAT_FAT12_MAX_CLN * fat12_sect_per_clust) {
fmt_params->fattype = FAT_FAT12;
/* start trying with small clusters */
fmt_params->sectors_per_cluster = 2;
}
- else if (fmt_params->totl_sector_cnt
- < FAT_FAT16_MAX_CLN * fat16_sect_per_clust) {
+ else if (fmt_params->totl_sector_cnt < FAT_FAT16_MAX_CLN * fat16_sect_per_clust) {
fmt_params->fattype = FAT_FAT16;
/* start trying with small clusters */
fmt_params->sectors_per_cluster = 2;
@@ -520,9 +548,8 @@ static int msdos_format_determine_fmt_params
* try to use user requested cluster size
*/
if ((rqdata != NULL) &&
- (rqdata->sectors_per_cluster > 0)) {
- fmt_params->sectors_per_cluster =
- rqdata->sectors_per_cluster;
+ (rqdata->sectors_per_cluster > 0)) {
+ fmt_params->sectors_per_cluster = rqdata->sectors_per_cluster;
}
/*
* check sectors per cluster.
@@ -532,16 +559,22 @@ static int msdos_format_determine_fmt_params
*/
for (onebit = 128;onebit >= 1;onebit = onebit>>1) {
if (fmt_params->sectors_per_cluster >= onebit) {
- fmt_params->sectors_per_cluster = onebit;
- if (fmt_params->sectors_per_cluster
- <= 32768L/fmt_params->bytes_per_sector) {
- /* value is small enough so this value is ok */
- onebit = 1;
- }
+ fmt_params->sectors_per_cluster = onebit;
+ if (fmt_params->sectors_per_cluster <= 32768L/fmt_params->bytes_per_sector) {
+ /* value is small enough so this value is ok */
+ onebit = 1;
+ }
}
}
}
+ /*
+ * Skip aligning structures or d align them
+ */
+ if ( (0 == ret_val)
+ && (NULL != rqdata)) {
+ 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);
@@ -564,34 +597,31 @@ static int msdos_format_determine_fmt_params
/* for FAT12/FAT16, set files per root directory */
/* must fill up an even count of sectors */
if ((rqdata != NULL) &&
- (rqdata->files_per_root_dir > 0)) {
- fmt_params->files_per_root_dir = rqdata->files_per_root_dir;
+ (rqdata->files_per_root_dir > 0)) {
+ fmt_params->files_per_root_dir = rqdata->files_per_root_dir;
}
else {
- if (fmt_params->fattype == FAT_FAT16) {
- fmt_params->files_per_root_dir = 512;
- }
- else {
- fmt_params->files_per_root_dir = 64;
- }
+ if (fmt_params->fattype == FAT_FAT16) {
+ fmt_params->files_per_root_dir = 512;
+ }
+ else {
+ fmt_params->files_per_root_dir = 64;
+ }
}
fmt_params->files_per_root_dir = (fmt_params->files_per_root_dir +
- (2*fmt_params->bytes_per_sector/
- FAT_DIRENTRY_SIZE-1));
+ (2*fmt_params->bytes_per_sector/
+ FAT_DIRENTRY_SIZE-1));
fmt_params->files_per_root_dir -= (fmt_params->files_per_root_dir %
- (2*fmt_params->bytes_per_sector
- /FAT_DIRENTRY_SIZE));
+ (2*fmt_params->bytes_per_sector
+ /FAT_DIRENTRY_SIZE));
+
}
fmt_params->root_dir_sectors =
(((fmt_params->files_per_root_dir * FAT_DIRENTRY_SIZE)
- + fmt_params->bytes_per_sector - 1)
+ + fmt_params->bytes_per_sector - 1)
/ 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,30 +629,45 @@ 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 >> 5);
+ }
+ 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
*/
if (ret_val == 0) {
- if ((rqdata != NULL) &&
- (rqdata->media != 0)) {
+ if ((rqdata != NULL) && (rqdata->media != 0)) {
const char valid_media_codes[] =
- {0xF0,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF};
+ {0xF0,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF};
if (NULL==memchr(valid_media_codes,
rqdata->media,
sizeof(valid_media_codes))) {
- ret_val = -1;
- errno = EINVAL;
+ ret_val = -1;
+ errno = EINVAL;
}
else {
- fmt_params->media_code = rqdata->media;
+ fmt_params->media_code = rqdata->media;
}
}
else {
@@ -636,7 +681,7 @@ static int msdos_format_determine_fmt_params
if (fmt_params->root_dir_sectors > 0) {
fmt_params->root_dir_start_sec =
fmt_params->rsvd_sector_cnt
- + (fmt_params-> fat_num*fmt_params->sectors_per_fat);
+ + (fmt_params->fat_num*fmt_params->sectors_per_fat);
fmt_params->root_dir_fmt_sec_cnt = fmt_params->root_dir_sectors;
}
else {
@@ -648,6 +693,8 @@ static int msdos_format_determine_fmt_params
+ (fmt_params-> fat_num*fmt_params->sectors_per_fat);
fmt_params->root_dir_fmt_sec_cnt = fmt_params->sectors_per_cluster;
}
+
+
/*
* determine usable OEMName
*/
@@ -656,23 +703,20 @@ static int msdos_format_determine_fmt_params
char *to = fmt_params->OEMName;
int cnt;
from = "RTEMS"; /* default: make "from" point to OS Name */
- if ((rqdata != NULL) &&
- (rqdata->OEMName != NULL)) {
+ if ((rqdata != NULL) && (rqdata->OEMName != NULL)) {
from = rqdata->OEMName;
}
- for (cnt = 0;
- cnt < (sizeof(fmt_params->OEMName)-1);
- cnt++) {
+ for (cnt = 0; cnt < (sizeof(fmt_params->OEMName)-1); cnt++) {
if (isprint((unsigned char)*from)) {
- *to++ = *from++;
+ *to++ = *from++;
}
else {
- /*
- * non-printable character in given name, so keep stuck
- * at that character and replace all following characters
- * with a ' '
- */
- *to++=' ';
+ /*
+ * non-printable character in given name, so keep stuck
+ * at that character and replace all following characters
+ * with a ' '
+ */
+ *to++=' ';
}
*to = '\0';
}
@@ -686,24 +730,21 @@ static int msdos_format_determine_fmt_params
char *to = fmt_params->VolLabel;
int cnt;
from = ""; /* default: make "from" point to empty string */
- if ((rqdata != NULL) &&
- (rqdata->VolLabel != NULL)) {
+ if ((rqdata != NULL) && (rqdata->VolLabel != NULL)) {
from = rqdata->VolLabel;
fmt_params->VolLabel_present = true;
}
- for (cnt = 0;
- cnt < (sizeof(fmt_params->VolLabel)-1);
- cnt++) {
+ for (cnt = 0; cnt < (sizeof(fmt_params->VolLabel)-1); cnt++) {
if (isprint((unsigned char)*from)) {
- *to++ = *from++;
+ *to++ = *from++;
}
else {
- /*
- * non-printable character in given name, so keep stuck
- * at that character and replace all following characters
- * with a ' '
- */
- *to++=' ';
+ /*
+ * non-printable character in given name, so keep stuck
+ * at that character and replace all following characters
+ * with a ' '
+ */
+ *to++=' ';
}
*to = '\0';
}
@@ -721,9 +762,7 @@ static int msdos_format_determine_fmt_params
if (ret_val != 0) {
rtems_set_errno_and_return_minus_one(ret_val);
}
- else {
- return 0;
- }
+ return 0;
}
/*=========================================================================*\
| Function: |
@@ -1106,15 +1145,14 @@ int msdos_format
*/
FAT_SET_VAL32(tmp_sec,8,FAT_FAT32_EOC);
}
- for (i = 0;
- (i < fmt_params.fat_num) && (ret_val == 0);
- i++) {
+ unsigned int 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);
}
}
/*
@@ -1126,5 +1164,8 @@ int msdos_format
close(fd);
}
- return ret_val;
+ if (0 != ret_val)
+ return -1;
+ else
+ return 0;
}
diff --git a/cpukit/libmisc/shell/main_msdosfmt.c b/cpukit/libmisc/shell/main_msdosfmt.c
index 47dd9f1..60926b9 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 ef4356e..c58379a 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
};
--
1.7.10.4
More information about the devel
mailing list