[rtems commit] dosfs: Support a cluster size of 64KiB

Sebastian Huber sebh at rtems.org
Wed Sep 6 08:21:25 UTC 2017


Module:    rtems
Branch:    master
Commit:    fae59c9b4248e5511d1ea469624aa9842fc289e1
Changeset: http://git.rtems.org/rtems/commit/?id=fae59c9b4248e5511d1ea469624aa9842fc289e1

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Wed Sep  6 10:12:06 2017 +0200

dosfs: Support a cluster size of 64KiB

Close #3003.

---

 cpukit/libfs/src/dosfs/fat.c              |  8 +++-----
 cpukit/libfs/src/dosfs/fat.h              |  6 +++---
 cpukit/libfs/src/dosfs/msdos_format.c     |  8 ++++----
 testsuites/fstests/fsdosfsformat01/init.c | 28 ++++++++++++++++++++++++++++
 4 files changed, 38 insertions(+), 12 deletions(-)

diff --git a/cpukit/libfs/src/dosfs/fat.c b/cpukit/libfs/src/dosfs/fat.c
index a0475d4..8701a21 100644
--- a/cpukit/libfs/src/dosfs/fat.c
+++ b/cpukit/libfs/src/dosfs/fat.c
@@ -566,16 +566,14 @@ fat_init_volume_info(fat_fs_info_t *fs_info, const char *device)
     for (vol->spc_log2 = 0, i = vol->spc; (i & 1) == 0;
          i >>= 1, vol->spc_log2++);
 
-    /*
-     * "bytes per cluster" value greater than 32K is invalid
-     */
-    if (vol->bps > (MS_BYTES_PER_CLUSTER_LIMIT >> vol->spc_log2))
+    /* Sectors per cluster must be a power of two */
+    if (vol->spc != UINT32_C(1) << vol->spc_log2)
     {
         close(vol->fd);
         rtems_set_errno_and_return_minus_one(EINVAL);
     }
 
-    vol->bpc = vol->bps << vol->spc_log2;
+    vol->bpc = ((uint32_t) vol->bps) << vol->spc_log2;
 
     for (vol->bpc_log2 = 0, i = vol->bpc; (i & 1) == 0;
          i >>= 1, vol->bpc_log2++);
diff --git a/cpukit/libfs/src/dosfs/fat.h b/cpukit/libfs/src/dosfs/fat.h
index 1cbf9a7..4839cb7 100644
--- a/cpukit/libfs/src/dosfs/fat.h
+++ b/cpukit/libfs/src/dosfs/fat.h
@@ -274,7 +274,7 @@ extern "C" {
 
 #define FAT_TOTAL_FSINFO_SIZE               512
 
-#define MS_BYTES_PER_CLUSTER_LIMIT           0x8000     /* 32K */
+#define MS_BYTES_PER_CLUSTER_LIMIT           0x10000    /* 64K */
 #define MS_BYTES_PER_CLUSTER_LIMIT_FAT12     0x1000     /*  4K */
 
 #define FAT_BR_EXT_FLAGS_MIRROR              0x0080
@@ -300,10 +300,10 @@ typedef struct fat_vol_s
     uint8_t            sec_mul;        /* log2 of 512bts sectors number per sector */
     uint8_t            spc;            /* sectors per cluster */
     uint8_t            spc_log2;       /* log2 of spc */
-    uint16_t           bpc;            /* bytes per cluster */
+    uint32_t           bpc;            /* bytes per cluster */
     uint8_t            bpc_log2;       /* log2 of bytes per cluster */
     uint8_t            sectors_per_block;    /* sectors per bdbuf block */
-    uint16_t           bytes_per_block;      /* number of bytes for the bduf block device handling */
+    uint32_t           bytes_per_block;      /* number of bytes for the bduf block device handling */
     uint8_t            bytes_per_block_log2; /* log2 of bytes_per_block */
     uint8_t            fats;           /* number of FATs */
     uint8_t            type;           /* FAT type */
diff --git a/cpukit/libfs/src/dosfs/msdos_format.c b/cpukit/libfs/src/dosfs/msdos_format.c
index 17e435d..e3ff94b 100644
--- a/cpukit/libfs/src/dosfs/msdos_format.c
+++ b/cpukit/libfs/src/dosfs/msdos_format.c
@@ -316,7 +316,7 @@ static int msdos_format_eval_sectors_per_cluster
   uint32_t fatdata_sect_cnt;
   uint32_t fat_sectors_cnt;
   /*
-   * ensure, that maximum cluster size (32KByte) is not exceeded
+   * ensure, that maximum cluster size (64KiB) is not exceeded
    */
   while (MS_BYTES_PER_CLUSTER_LIMIT / bytes_per_sector < sectors_per_cluster) {
     sectors_per_cluster /= 2;
@@ -397,7 +397,7 @@ msdos_get_fat_type( const uint32_t bytes_per_sector,
   uint32_t ms_sectors_per_cluster_limit_FAT12 =
     ( MS_BYTES_PER_CLUSTER_LIMIT_FAT12 +1 ) / bytes_per_sector;
   uint32_t ms_sectors_per_cluster_limit_FAT16 =
-    ( MS_BYTES_PER_CLUSTER_LIMIT +1 ) / bytes_per_sector;
+    ( 0x8000 +1 ) / bytes_per_sector;
   uint8_t fattype = FAT_FAT32;
 
   if (   number_of_clusters < FAT_FAT12_MAX_CLN
@@ -427,13 +427,13 @@ msdos_set_sectors_per_cluster_from_request(
    * check sectors per cluster.
    * must be power of 2
    * must be smaller than or equal to 128
-   * sectors_per_cluster*bytes_per_sector must not be bigger than 32K
+   * sectors_per_cluster*bytes_per_sector must not be bigger than 64K
    */
   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 ) {
+          <= MS_BYTES_PER_CLUSTER_LIMIT / fmt_params->bytes_per_sector ) {
         /* value is small enough so this value is ok */
         onebit = 1;
         ret_val = 0;
diff --git a/testsuites/fstests/fsdosfsformat01/init.c b/testsuites/fstests/fsdosfsformat01/init.c
index f11ef05..b7df748 100644
--- a/testsuites/fstests/fsdosfsformat01/init.c
+++ b/testsuites/fstests/fsdosfsformat01/init.c
@@ -469,6 +469,34 @@ static void test( void )
 
   rv = unlink( dev_name );
   rtems_test_assert( rv == 0 );
+
+  /* FAT32 with cluster size of 64KiB */
+
+  sc = rtems_sparse_disk_create_and_register(
+    dev_name,
+    SECTOR_SIZE,
+    1024,
+    16777216, /* 8GiB */
+    0
+  );
+  rtems_test_assert( sc == RTEMS_SUCCESSFUL );
+
+  memset( &rqdata, 0, sizeof( rqdata ) );
+  rqdata.sectors_per_cluster = 128;
+  rqdata.quick_format = true;
+  rv = msdos_format( dev_name, &rqdata );
+  rtems_test_assert( rv == 0 );
+
+  test_disk_params(
+    dev_name,
+    mount_dir,
+    SECTOR_SIZE,
+    SECTOR_SIZE * rqdata.sectors_per_cluster,
+    rqdata.sectors_per_cluster
+  );
+
+  rv = unlink( dev_name );
+  rtems_test_assert( rv == 0 );
 }
 
 static void Init( rtems_task_argument arg )



More information about the vc mailing list