[PATCH 7/8] dosfs: Block size optimization

Ralf Kirchner ralf.kirchner at embedded-brains.de
Thu Nov 29 14:32:45 UTC 2012


Change block size of bdbuf to the cluster size if the data clusters are
aligned on a cluster boundary.  This enables fast access to data
clusters.
---
 cpukit/libfs/src/dosfs/fat.c                   |  202 +++++++++++++-----------
 cpukit/libfs/src/dosfs/fat.h                   |   39 +++--
 cpukit/libfs/src/dosfs/fat_fat_operations.c    |   71 ++++-----
 cpukit/libfs/src/dosfs/msdos_file.c            |    6 +-
 testsuites/fstests/mdosfs_support/fs_support.c |    2 +-
 5 Dateien geändert, 166 Zeilen hinzugefügt(+), 154 Zeilen entfernt(-)

diff --git a/cpukit/libfs/src/dosfs/fat.c b/cpukit/libfs/src/dosfs/fat.c
index c2c3e89..033c15d 100644
--- a/cpukit/libfs/src/dosfs/fat.c
+++ b/cpukit/libfs/src/dosfs/fat.c
@@ -17,88 +17,54 @@
 #include <unistd.h>
 #include <errno.h>
 #include <stdlib.h>
+#include <stdint.h>
 
 #include <rtems/libio_.h>
 
 #include "fat.h"
 #include "fat_fat_operations.h"
 
-int
-fat_buf_access(fat_fs_info_t *fs_info, uint32_t   blk, int op_type,
-               rtems_bdbuf_buffer **buf)
-{
-    rtems_status_code sc = RTEMS_SUCCESSFUL;
-    uint8_t           i;
-    bool              sec_of_fat;
+static int
+ _fat_block_release(fat_fs_info_t *fs_info);
 
+static ssize_t
+ fat_cluster_read(fat_fs_info_t                       *fs_info,
+                  uint32_t                             cln,
+                  void                                *buff);
 
-    if (fs_info->c.state == FAT_CACHE_EMPTY)
-    {
-        if (op_type == FAT_OP_TYPE_READ)
-            sc = rtems_bdbuf_read(fs_info->vol.dd, blk, &fs_info->c.buf);
-        else
-            sc = rtems_bdbuf_get(fs_info->vol.dd, blk, &fs_info->c.buf);
-        if (sc != RTEMS_SUCCESSFUL)
-            rtems_set_errno_and_return_minus_one(EIO);
-        fs_info->c.blk_num = blk;
-        fs_info->c.modified = 0;
-        fs_info->c.state = FAT_CACHE_ACTUAL;
-    }
+static ssize_t
+ fat_cluster_write(fat_fs_info_t                      *fs_info,
+                   uint32_t                            cln,
+                   const void                         *buff);
 
-    sec_of_fat = ((fs_info->c.blk_num >= fs_info->vol.fat_loc) &&
-                  (fs_info->c.blk_num < fs_info->vol.rdir_loc));
+int
+fat_buf_access(fat_fs_info_t   *fs_info,
+               const uint32_t   sec_num,
+               const int        op_type,
+               uint8_t        **sec_buf)
+{
+    rtems_status_code sc = RTEMS_SUCCESSFUL;
+    uint32_t          blk = fat_sector_num_to_block_num (fs_info,
+                                                         sec_num);
+    uint32_t          blk_ofs = fat_sector_offset_to_block_offset (fs_info,
+                                                                   sec_num,
+                                                                   0);
 
-    if (fs_info->c.blk_num != blk)
+    if (fs_info->c.state == FAT_CACHE_EMPTY || fs_info->c.blk_num != sec_num)
     {
-        if (fs_info->c.modified)
-        {
-            if (sec_of_fat && !fs_info->vol.mirror)
-                memcpy(fs_info->sec_buf, fs_info->c.buf->buffer,
-                       fs_info->vol.bps);
-
-            sc = rtems_bdbuf_release_modified(fs_info->c.buf);
-            fs_info->c.state = FAT_CACHE_EMPTY;
-            fs_info->c.modified = 0;
-            if (sc != RTEMS_SUCCESSFUL)
-                rtems_set_errno_and_return_minus_one(EIO);
-
-            if (sec_of_fat && !fs_info->vol.mirror)
-            {
-                rtems_bdbuf_buffer *b;
+        fat_buf_release(fs_info);
 
-                for (i = 1; i < fs_info->vol.fats; i++)
-                {
-                    sc = rtems_bdbuf_get(fs_info->vol.dd,
-                                         fs_info->c.blk_num +
-                                         fs_info->vol.fat_length * i,
-                                         &b);
-                    if ( sc != RTEMS_SUCCESSFUL)
-                        rtems_set_errno_and_return_minus_one(ENOMEM);
-                    memcpy(b->buffer, fs_info->sec_buf, fs_info->vol.bps);
-                    sc = rtems_bdbuf_release_modified(b);
-                    if ( sc != RTEMS_SUCCESSFUL)
-                        rtems_set_errno_and_return_minus_one(ENOMEM);
-                }
-            }
-        }
-        else
-        {
-            sc = rtems_bdbuf_release(fs_info->c.buf);
-            fs_info->c.state = FAT_CACHE_EMPTY;
-            if (sc != RTEMS_SUCCESSFUL)
-                rtems_set_errno_and_return_minus_one(EIO);
-
-        }
         if (op_type == FAT_OP_TYPE_READ)
             sc = rtems_bdbuf_read(fs_info->vol.dd, blk, &fs_info->c.buf);
         else
             sc = rtems_bdbuf_get(fs_info->vol.dd, blk, &fs_info->c.buf);
         if (sc != RTEMS_SUCCESSFUL)
             rtems_set_errno_and_return_minus_one(EIO);
-        fs_info->c.blk_num = blk;
+        fs_info->c.blk_num = sec_num;
+        fs_info->c.modified = 0;
         fs_info->c.state = FAT_CACHE_ACTUAL;
     }
-    *buf = fs_info->c.buf;
+    *sec_buf = &fs_info->c.buf->buffer[blk_ofs];
     return RC_OK;
 }
 
@@ -106,19 +72,24 @@ int
 fat_buf_release(fat_fs_info_t *fs_info)
 {
     rtems_status_code sc = RTEMS_SUCCESSFUL;
-    uint8_t           i;
-    bool              sec_of_fat;
 
     if (fs_info->c.state == FAT_CACHE_EMPTY)
         return RC_OK;
 
-    sec_of_fat = ((fs_info->c.blk_num >= fs_info->vol.fat_loc) &&
-                  (fs_info->c.blk_num < fs_info->vol.rdir_loc));
-
     if (fs_info->c.modified)
     {
+        uint32_t sec_num = fs_info->c.blk_num;
+        bool     sec_of_fat = ((sec_num >= fs_info->vol.fat_loc) &&
+                              (sec_num < fs_info->vol.rdir_loc));
+        uint32_t blk = fat_sector_num_to_block_num(fs_info, sec_num);
+        uint32_t blk_ofs = fat_sector_offset_to_block_offset(fs_info,
+                                                             sec_num,
+                                                             0);
+
         if (sec_of_fat && !fs_info->vol.mirror)
-            memcpy(fs_info->sec_buf, fs_info->c.buf->buffer, fs_info->vol.bps);
+            memcpy(fs_info->sec_buf,
+                   fs_info->c.buf->buffer + blk_ofs,
+                   fs_info->vol.bps);
 
         sc = rtems_bdbuf_release_modified(fs_info->c.buf);
         if (sc != RTEMS_SUCCESSFUL)
@@ -127,18 +98,31 @@ fat_buf_release(fat_fs_info_t *fs_info)
 
         if (sec_of_fat && !fs_info->vol.mirror)
         {
-            rtems_bdbuf_buffer *b;
+            uint8_t i;
 
             for (i = 1; i < fs_info->vol.fats; i++)
             {
-                sc = rtems_bdbuf_get(fs_info->vol.dd,
-                                     fs_info->c.blk_num +
-                                     fs_info->vol.fat_length * i,
-                                     &b);
+                rtems_bdbuf_buffer *bd;
+
+                sec_num = fs_info->c.blk_num + fs_info->vol.fat_length * i,
+                blk = fat_sector_num_to_block_num(fs_info, sec_num);
+                blk_ofs = fat_sector_offset_to_block_offset(fs_info,
+                                                            sec_num,
+                                                            0);
+
+                if (blk_ofs == 0
+                    && fs_info->vol.bps == fs_info->vol.bytes_per_block)
+                {
+                    sc = rtems_bdbuf_get(fs_info->vol.dd, blk, &bd);
+                }
+                else
+                {
+                    sc = rtems_bdbuf_read(fs_info->vol.dd, blk, &bd);
+                }
                 if ( sc != RTEMS_SUCCESSFUL)
                     rtems_set_errno_and_return_minus_one(ENOMEM);
-                memcpy(b->buffer, fs_info->sec_buf, fs_info->vol.bps);
-                sc = rtems_bdbuf_release_modified(b);
+                memcpy(bd->buffer + blk_ofs, fs_info->sec_buf, fs_info->vol.bps);
+                sc = rtems_bdbuf_release_modified(bd);
                 if ( sc != RTEMS_SUCCESSFUL)
                     rtems_set_errno_and_return_minus_one(ENOMEM);
             }
@@ -182,23 +166,23 @@ _fat_block_read(
 {
     int                     rc = RC_OK;
     ssize_t                 cmpltd = 0;
-    uint32_t                blk = start;
+    uint32_t                sec_num = start;
     uint32_t                ofs = offset;
-    rtems_bdbuf_buffer     *block = NULL;
+    uint8_t                *sec_buf;
     uint32_t                c = 0;
 
     while (count > 0)
     {
-        rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_READ, &block);
+        rc = fat_buf_access(fs_info, sec_num, FAT_OP_TYPE_READ, &sec_buf);
         if (rc != RC_OK)
             return -1;
 
         c = MIN(count, (fs_info->vol.bps - ofs));
-        memcpy((buff + cmpltd), (block->buffer + ofs), c);
+        memcpy((buff + cmpltd), (sec_buf + ofs), c);
 
         count -= c;
         cmpltd += c;
-        blk++;
+        sec_num++;
         ofs = 0;
     }
     return cmpltd;
@@ -231,29 +215,29 @@ _fat_block_write(
 {
     int                 rc = RC_OK;
     ssize_t             cmpltd = 0;
-    uint32_t            blk  = start;
+    uint32_t            sec_num = start;
     uint32_t            ofs = offset;
-    rtems_bdbuf_buffer *block = NULL;
+    uint8_t            *sec_buf;
     uint32_t            c = 0;
 
     while(count > 0)
     {
         c = MIN(count, (fs_info->vol.bps - ofs));
 
-        if (c == fs_info->vol.bps)
-            rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_GET, &block);
+        if (c == fs_info->vol.bytes_per_block)
+            rc = fat_buf_access(fs_info, sec_num, FAT_OP_TYPE_GET, &sec_buf);
         else
-            rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_READ, &block);
+            rc = fat_buf_access(fs_info, sec_num, FAT_OP_TYPE_READ, &sec_buf);
         if (rc != RC_OK)
             return -1;
 
-        memcpy((block->buffer + ofs), (buff + cmpltd), c);
+        memcpy((sec_buf + ofs), (buff + cmpltd), c);
 
         fat_buf_mark_modified(fs_info);
 
         count -= c;
         cmpltd +=c;
-        blk++;
+        sec_num++;
         ofs = 0;
     }
     return cmpltd;
@@ -267,9 +251,9 @@ _fat_block_zero(
     uint32_t                              count)
 {
     int                 rc = RC_OK;
-    uint32_t            blk  = start;
+    uint32_t            sec_num = start;
     uint32_t            ofs = offset;
-    rtems_bdbuf_buffer *block = NULL;
+    uint8_t            *sec_buf;
     uint32_t            c = 0;
 
     while(count > 0)
@@ -277,18 +261,18 @@ _fat_block_zero(
         c = MIN(count, (fs_info->vol.bps - ofs));
 
         if (c == fs_info->vol.bps)
-            rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_GET, &block);
+            rc = fat_buf_access(fs_info, sec_num, FAT_OP_TYPE_GET, &sec_buf);
         else
-            rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_READ, &block);
+            rc = fat_buf_access(fs_info, sec_num, FAT_OP_TYPE_READ, &sec_buf);
         if (rc != RC_OK)
             return -1;
 
-        memset((block->buffer + ofs), 0, c);
+        memset((block + ofs), 0, c);
 
         fat_buf_mark_modified(fs_info);
 
         count -= c;
-        blk++;
+        sec_num++;
         ofs = 0;
     }
     return 0;
@@ -364,6 +348,11 @@ fat_cluster_write(
                           fs_info->vol.spc << fs_info->vol.sec_log2, buff);
 }
 
+static bool is_cluster_aligned(const fat_vol_t *vol, uint32_t sec_num)
+{
+    return (sec_num & (vol->spc - 1)) == 0;
+}
+
 /* fat_init_volume_info --
  *     Get inforamtion about volume on which filesystem is mounted on
  *
@@ -444,12 +433,15 @@ fat_init_volume_info(fat_fs_info_t *fs_info, const char *device)
         close(vol->fd);
         rtems_set_errno_and_return_minus_one( EINVAL );
     }
-
     for (vol->sec_mul = 0, i = (vol->bps >> FAT_SECTOR512_BITS); (i & 1) == 0;
          i >>= 1, vol->sec_mul++);
     for (vol->sec_log2 = 0, i = vol->bps; (i & 1) == 0;
          i >>= 1, vol->sec_log2++);
 
+    vol->bytes_per_block = vol->bps;
+    vol->bytes_per_block_log2 = vol->sec_log2;
+    vol->sectors_per_block = 1;
+
     vol->spc = FAT_GET_BR_SECTORS_PER_CLUSTER(boot_rec);
     /*
      * "sectors per cluster" of zero is invalid
@@ -638,6 +630,28 @@ fat_init_volume_info(fat_fs_info_t *fs_info, const char *device)
         rtems_set_errno_and_return_minus_one( ENOMEM );
     }
 
+    /*
+     * If possible we will use the cluster size as bdbuf block size for faster
+     * file access. This requires that certain sectors are aligned to cluster
+     * borders.
+     */
+    if (is_cluster_aligned(vol, vol->data_fsec)
+        && (FAT_FAT32 == vol->type || is_cluster_aligned(vol, vol->rdir_loc)))
+    {
+        vol->bytes_per_block = vol->bpc;
+        vol->bytes_per_block_log2 = vol->bpc_log2;
+        vol->sectors_per_block = vol->spc;
+        sc = rtems_bdbuf_set_block_size (vol->dd, vol->bytes_per_block, true);
+        if (RTEMS_SUCCESSFUL != sc)
+        {
+            close(vol->fd);
+            free(fs_info->vhash);
+            free(fs_info->rhash);
+            free(fs_info->uino);
+            rtems_set_errno_and_return_minus_one( EIO );
+        }
+    }
+
     return RC_OK;
 }
 
diff --git a/cpukit/libfs/src/dosfs/fat.h b/cpukit/libfs/src/dosfs/fat.h
index dab2471..48b1491 100644
--- a/cpukit/libfs/src/dosfs/fat.h
+++ b/cpukit/libfs/src/dosfs/fat.h
@@ -298,6 +298,9 @@ typedef struct fat_vol_s
     uint8_t            spc_log2;       /* log2 of spc */
     uint16_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 */
+    uint8_t            bytes_per_block_log2; /* log2 of bytes_per_block */
     uint8_t            fats;           /* number of FATs */
     uint8_t            type;           /* FAT type */
     uint32_t           mask;
@@ -436,6 +439,25 @@ fat_cluster_num_to_sector512_num(
             fs_info->vol.sec_mul);
 }
 
+static inline uint32_t
+ fat_sector_num_to_block_num (const fat_fs_info_t *fs_info,
+                              const uint32_t sector_number)
+{
+  return sector_number >> (fs_info->vol.bytes_per_block_log2 - fs_info->vol.sec_log2);
+}
+
+static inline uint32_t
+ fat_sector_offset_to_block_offset (const fat_fs_info_t *fs_info,
+                                    const uint32_t sector,
+                                    const uint32_t sector_offset)
+{
+  return sector_offset +
+           ((sector -
+              fat_block_num_to_sector_num (fs_info,
+                  fat_sector_num_to_block_num (fs_info, sector)))
+            << fs_info->vol.sec_log2);
+}
+
 static inline void
 fat_buf_mark_modified(fat_fs_info_t *fs_info)
 {
@@ -443,8 +465,10 @@ fat_buf_mark_modified(fat_fs_info_t *fs_info)
 }
 
 int
-fat_buf_access(fat_fs_info_t *fs_info, uint32_t   blk, int op_type,
-               rtems_bdbuf_buffer **buf);
+fat_buf_access(fat_fs_info_t  *fs_info,
+               uint32_t        sec_num,
+               int             op_type,
+               uint8_t       **sec_buf);
 
 int
 fat_buf_release(fat_fs_info_t *fs_info);
@@ -469,18 +493,7 @@ _fat_block_zero(fat_fs_info_t                         *fs_info,
                  uint32_t                              offset,
                  uint32_t                              count);
 
-int
-_fat_block_release(fat_fs_info_t *fs_info);
-
-ssize_t
-fat_cluster_read(fat_fs_info_t                        *fs_info,
-                  uint32_t                             cln,
-                  void                                *buff);
 
-ssize_t
-fat_cluster_write(fat_fs_info_t                        *fs_info,
-                   uint32_t                             cln,
-                   const void                          *buff);
 
 int
 fat_init_volume_info(fat_fs_info_t *fs_info, const char *device);
diff --git a/cpukit/libfs/src/dosfs/fat_fat_operations.c b/cpukit/libfs/src/dosfs/fat_fat_operations.c
index e9485d4..291819d 100644
--- a/cpukit/libfs/src/dosfs/fat_fat_operations.c
+++ b/cpukit/libfs/src/dosfs/fat_fat_operations.c
@@ -235,7 +235,7 @@ fat_get_fat_cluster(
     )
 {
     int                     rc = RC_OK;
-    rtems_bdbuf_buffer     *block0 = NULL;
+    uint8_t                *sec_buf;
     uint32_t                sec = 0;
     uint32_t                ofs = 0;
 
@@ -247,7 +247,7 @@ fat_get_fat_cluster(
           fs_info->vol.afat_loc;
     ofs = FAT_FAT_OFFSET(fs_info->vol.type, cln) & (fs_info->vol.bps - 1);
 
-    rc = fat_buf_access(fs_info, sec, FAT_OP_TYPE_READ, &block0);
+    rc = fat_buf_access(fs_info, sec, FAT_OP_TYPE_READ, &sec_buf);
     if (rc != RC_OK)
         return rc;
 
@@ -258,19 +258,19 @@ fat_get_fat_cluster(
              * we are enforced in complex computations for FAT12 to escape CPU
              * align problems for some architectures
              */
-            *ret_val = (*((uint8_t   *)(block0->buffer + ofs)));
+            *ret_val = (*(sec_buf + ofs));
             if ( ofs == (fs_info->vol.bps - 1) )
             {
                 rc = fat_buf_access(fs_info, sec + 1, FAT_OP_TYPE_READ,
-                                    &block0);
+                                    &sec_buf);
                 if (rc != RC_OK)
                     return rc;
 
-                *ret_val |= (*((uint8_t   *)(block0->buffer)))<<8;
+                *ret_val |= *sec_buf << 8;
             }
             else
             {
-                *ret_val |= (*((uint8_t   *)(block0->buffer + ofs + 1)))<<8;
+                *ret_val |= *(sec_buf + ofs + 1) << 8;
             }
 
             if ( FAT_CLUSTER_IS_ODD(cln) )
@@ -280,12 +280,12 @@ fat_get_fat_cluster(
             break;
 
         case FAT_FAT16:
-            *ret_val = *((uint16_t   *)(block0->buffer + ofs));
+            *ret_val = *((uint16_t   *)(sec_buf + ofs));
             *ret_val = CF_LE_W(*ret_val);
             break;
 
         case FAT_FAT32:
-            *ret_val = *((uint32_t   *)(block0->buffer + ofs));
+            *ret_val = *((uint32_t   *)(sec_buf + ofs));
             *ret_val = CF_LE_L(*ret_val);
             break;
 
@@ -322,7 +322,7 @@ fat_set_fat_cluster(
     uint32_t            ofs = 0;
     uint16_t            fat16_clv = 0;
     uint32_t            fat32_clv = 0;
-    rtems_bdbuf_buffer *block0 = NULL;
+    uint8_t            *sec_buf = NULL;
 
     /* sanity check */
     if ( (cln < 2) || (cln > (fs_info->vol.data_cls + 1)) )
@@ -332,7 +332,7 @@ fat_set_fat_cluster(
           fs_info->vol.afat_loc;
     ofs = FAT_FAT_OFFSET(fs_info->vol.type, cln) & (fs_info->vol.bps - 1);
 
-    rc = fat_buf_access(fs_info, sec, FAT_OP_TYPE_READ, &block0);
+    rc = fat_buf_access(fs_info, sec, FAT_OP_TYPE_READ, &sec_buf);
     if (rc != RC_OK)
         return rc;
 
@@ -342,80 +342,65 @@ fat_set_fat_cluster(
             if ( FAT_CLUSTER_IS_ODD(cln) )
             {
                 fat16_clv = ((uint16_t  )in_val) << FAT_FAT12_SHIFT;
-                *((uint8_t   *)(block0->buffer + ofs)) =
-                        (*((uint8_t   *)(block0->buffer + ofs))) & 0x0F;
+                *(sec_buf + ofs) &= 0x0F;
 
-                *((uint8_t   *)(block0->buffer + ofs)) =
-                        (*((uint8_t   *)(block0->buffer + ofs))) |
-                        (uint8_t  )(fat16_clv & 0x00FF);
+                *(sec_buf + ofs) |= (uint8_t)(fat16_clv & 0x00F0);
 
                 fat_buf_mark_modified(fs_info);
 
                 if ( ofs == (fs_info->vol.bps - 1) )
                 {
                     rc = fat_buf_access(fs_info, sec + 1, FAT_OP_TYPE_READ,
-                                        &block0);
+                                        &sec_buf);
                     if (rc != RC_OK)
                         return rc;
 
-                     *((uint8_t   *)(block0->buffer)) &= 0x00;
+                     *sec_buf &= 0x00;
 
-                     *((uint8_t   *)(block0->buffer)) =
-                            (*((uint8_t   *)(block0->buffer))) |
-                            (uint8_t  )((fat16_clv & 0xFF00)>>8);
+                     *sec_buf |= (uint8_t)((fat16_clv & 0xFF00)>>8);
 
                      fat_buf_mark_modified(fs_info);
                 }
                 else
                 {
-                    *((uint8_t   *)(block0->buffer + ofs + 1)) &= 0x00;
+                    *(sec_buf + ofs + 1) &= 0x00;
 
-                    *((uint8_t   *)(block0->buffer + ofs + 1)) =
-                            (*((uint8_t   *)(block0->buffer + ofs + 1))) |
-                            (uint8_t  )((fat16_clv & 0xFF00)>>8);
+                    *(sec_buf + ofs + 1) |= (uint8_t  )((fat16_clv & 0xFF00)>>8);
                 }
             }
             else
             {
                 fat16_clv = ((uint16_t  )in_val) & FAT_FAT12_MASK;
-                *((uint8_t   *)(block0->buffer + ofs)) &= 0x00;
+                *(sec_buf + ofs) &= 0x00;
 
-                *((uint8_t   *)(block0->buffer + ofs)) =
-                        (*((uint8_t   *)(block0->buffer + ofs))) |
-                        (uint8_t  )(fat16_clv & 0x00FF);
+                *(sec_buf + ofs) |= (uint8_t)(fat16_clv & 0x00FF);
 
                 fat_buf_mark_modified(fs_info);
 
                 if ( ofs == (fs_info->vol.bps - 1) )
                 {
                     rc = fat_buf_access(fs_info, sec + 1, FAT_OP_TYPE_READ,
-                                        &block0);
+                                        &sec_buf);
                     if (rc != RC_OK)
                         return rc;
 
-                    *((uint8_t   *)(block0->buffer)) =
-                            (*((uint8_t   *)(block0->buffer))) & 0xF0;
+                    *sec_buf &= 0xF0;
 
-                    *((uint8_t   *)(block0->buffer)) =
-                            (*((uint8_t   *)(block0->buffer))) |
-                            (uint8_t  )((fat16_clv & 0xFF00)>>8);
+                    *sec_buf |= (uint8_t)((fat16_clv & 0xFF00)>>8);
 
                     fat_buf_mark_modified(fs_info);
                 }
                 else
                 {
-                    *((uint8_t   *)(block0->buffer + ofs + 1)) =
-                      (*((uint8_t   *)(block0->buffer + ofs + 1))) & 0xF0;
+                    *(sec_buf + ofs + 1) &= 0xF0;
 
-                    *((uint8_t   *)(block0->buffer + ofs+1)) =
-                           (*((uint8_t   *)(block0->buffer + ofs+1))) |
-                           (uint8_t  )((fat16_clv & 0xFF00)>>8);
+                    *(sec_buf + ofs+1) |= (uint8_t)((fat16_clv & 0xFF00)>>8);
                 }
             }
             break;
 
         case FAT_FAT16:
-            *((uint16_t   *)(block0->buffer + ofs)) =
+            *((uint16_t   *)(sec_buf + ofs)) =
                     (uint16_t  )(CT_LE_W(in_val));
             fat_buf_mark_modified(fs_info);
             break;
@@ -423,11 +408,9 @@ fat_set_fat_cluster(
         case FAT_FAT32:
             fat32_clv = CT_LE_L((in_val & FAT_FAT32_MASK));
 
-            *((uint32_t   *)(block0->buffer + ofs)) =
-            (*((uint32_t   *)(block0->buffer + ofs))) & (CT_LE_L(0xF0000000));
+            *((uint32_t *)(sec_buf + ofs)) &= CT_LE_L(0xF0000000);
 
-            *((uint32_t   *)(block0->buffer + ofs)) =
-                   fat32_clv | (*((uint32_t   *)(block0->buffer + ofs)));
+            *((uint32_t *)(sec_buf + ofs)) |= fat32_clv;
 
             fat_buf_mark_modified(fs_info);
             break;
diff --git a/cpukit/libfs/src/dosfs/msdos_file.c b/cpukit/libfs/src/dosfs/msdos_file.c
index 0406be0..a5b9c7a 100644
--- a/cpukit/libfs/src/dosfs/msdos_file.c
+++ b/cpukit/libfs/src/dosfs/msdos_file.c
@@ -191,6 +191,7 @@ msdos_file_stat(
     rtems_status_code  sc = RTEMS_SUCCESSFUL;
     msdos_fs_info_t   *fs_info = loc->mt_entry->fs_info;
     fat_file_fd_t     *fat_fd = loc->node_access;
+    uint32_t           cl_mask = fs_info->fat.vol.bpc - 1;
 
     sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
                                 MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
@@ -202,8 +203,9 @@ msdos_file_stat(
     buf->st_mode  = S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO;
     buf->st_rdev = 0ll;
     buf->st_size = fat_fd->fat_file_size;
-    buf->st_blocks = fat_fd->fat_file_size >> FAT_SECTOR512_BITS;
-    buf->st_blksize = fs_info->fat.vol.bps;
+    buf->st_blocks = ((fat_fd->fat_file_size + cl_mask) & ~cl_mask)
+      >> FAT_SECTOR512_BITS;
+    buf->st_blksize = fs_info->fat.vol.bpc;
     buf->st_mtime = fat_fd->mtime;
 
     rtems_semaphore_release(fs_info->vol_sema);
diff --git a/testsuites/fstests/mdosfs_support/fs_support.c b/testsuites/fstests/mdosfs_support/fs_support.c
index 123e9df..62370c9 100644
--- a/testsuites/fstests/mdosfs_support/fs_support.c
+++ b/testsuites/fstests/mdosfs_support/fs_support.c
@@ -28,7 +28,7 @@
 msdos_format_request_param_t rqdata = {
     OEMName:             "RTEMS",
     VolLabel:            "RTEMSDisk",
-    sectors_per_cluster: 0,
+    sectors_per_cluster: 2,
     fat_num:             0,
     files_per_root_dir:  0,
     media:               0,
-- 
1.7.10.4




More information about the devel mailing list