[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,
        &sectors_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