[PATCH 2/2] dosfs: Lazy update of FAT32 FS info sector

Claus, Ric claus at slac.stanford.edu
Thu Nov 8 18:34:13 UTC 2012


Unlike as for Linux and Windows, there is no shutdown procedure for RTEMS.  Even if there were one, I don't know how it would get invoked since everyone I know who uses RTOSes effectively pushes the reset button when they want to go again.  Consequently, the unmount is in most cases never called.  Given that, what is the effect of this patch on FAT formatted persistent storage devices that have been modified during a boot cycle?  Are they somehow cleaned up on the next mount?

Ric

________________________________________
From: rtems-devel-bounces at rtems.org [rtems-devel-bounces at rtems.org] On Behalf Of Sebastian Huber [sebastian.huber at embedded-brains.de]
Sent: Thursday, November 08, 2012 6:45 AM
To: rtems-devel at rtems.org
Subject: [PATCH 2/2] dosfs: Lazy update of FAT32 FS info sector

Update the free cluster count and next free culster in the FAT32 FS info
sector only during unmount and only if the values have changed since
mount time.  This avoids writes to the FS info sector and conforms to
the behaviour of Linux and Windows.
---
 cpukit/libfs/src/dosfs/fat.c |  106 ++++++++++++++++++++----------------------
 cpukit/libfs/src/dosfs/fat.h |   11 ++---
 2 files changed, 55 insertions(+), 62 deletions(-)

diff --git a/cpukit/libfs/src/dosfs/fat.c b/cpukit/libfs/src/dosfs/fat.c
index d40aaf0..017829c 100644
--- a/cpukit/libfs/src/dosfs/fat.c
+++ b/cpukit/libfs/src/dosfs/fat.c
@@ -574,16 +574,12 @@ fat_init_volume_info(fat_fs_info_t *fs_info, const char *device)
                     return -1;
                 }

-                vol->free_cls = FAT_GET_FSINFO_FREE_CLUSTER_COUNT(fs_info_sector);
-                vol->next_cl = FAT_GET_FSINFO_NEXT_FREE_CLUSTER(fs_info_sector);
-                rc = fat_fat32_update_fsinfo_sector(fs_info, FAT_UNDEFINED_VALUE,
-                                                    FAT_UNDEFINED_VALUE);
-                if ( rc != RC_OK )
-                {
-                    _fat_block_release(fs_info);
-                    close(vol->fd);
-                    return rc;
-                }
+                vol->free_cls_in_fs_info =
+                  FAT_GET_FSINFO_FREE_CLUSTER_COUNT(fs_info_sector);
+                vol->free_cls = vol->free_cls_in_fs_info;
+                vol->next_cl_in_fs_info =
+                  FAT_GET_FSINFO_NEXT_FREE_CLUSTER(fs_info_sector);
+                vol->next_cl = vol->next_cl_in_fs_info;
             }
         }
     }
@@ -645,6 +641,50 @@ fat_init_volume_info(fat_fs_info_t *fs_info, const char *device)
     return RC_OK;
 }

+/* fat_fat32_update_fsinfo_sector --
+ *     Synchronize fsinfo sector for FAT32 volumes
+ *
+ * PARAMETERS:
+ *     fs_info    - FS info
+ *
+ * RETURNS:
+ *     RC_OK on success, or -1 if error occured (errno set appropriately)
+ */
+static int
+fat_fat32_update_fsinfo_sector(fat_fs_info_t *fs_info)
+{
+    ssize_t                 ret1 = 0, ret2 = 0;
+    uint32_t                free_count = fs_info->vol.free_cls;
+    uint32_t                next_free = fs_info->vol.next_cl;
+
+    if (free_count != fs_info->vol.free_cls_in_fs_info)
+    {
+        uint32_t le_free_count = CT_LE_L(free_count);
+
+        ret1 = _fat_block_write(fs_info,
+                                fs_info->vol.info_sec,
+                                FAT_FSINFO_FREE_CLUSTER_COUNT_OFFSET,
+                                4,
+                                (char *)(&le_free_count));
+    }
+
+    if (next_free != fs_info->vol.next_cl_in_fs_info)
+    {
+        uint32_t le_next_free = CT_LE_L(next_free);
+
+        ret2 = _fat_block_write(fs_info,
+                                fs_info->vol.info_sec,
+                                FAT_FSINFO_NEXT_FREE_CLUSTER_OFFSET,
+                                4,
+                                (char *)(&le_next_free));
+    }
+
+    if ( (ret1 < 0) || (ret2 < 0) )
+        return -1;
+
+    return RC_OK;
+}
+
 /* fat_shutdown_drive --
  *     Free all allocated resources and synchronize all necessary data
  *
@@ -663,8 +703,7 @@ fat_shutdown_drive(fat_fs_info_t *fs_info)

     if (fs_info->vol.type & FAT_FAT32)
     {
-        rc = fat_fat32_update_fsinfo_sector(fs_info, fs_info->vol.free_cls,
-                                            fs_info->vol.next_cl);
+        rc = fat_fat32_update_fsinfo_sector(fs_info);
         if ( rc != RC_OK )
             rc = -1;
     }
@@ -849,46 +888,3 @@ fat_ino_is_unique(

     return (ino >= fs_info->uino_base);
 }
-
-/* fat_fat32_update_fsinfo_sector --
- *     Synchronize fsinfo sector for FAT32 volumes
- *
- * PARAMETERS:
- *     fs_info    - FS info
- *     free_count - count of free clusters
- *     next_free  - the next free cluster num
- *
- * RETURNS:
- *     RC_OK on success, or -1 if error occured (errno set appropriately)
- */
-int
-fat_fat32_update_fsinfo_sector(
-    fat_fs_info_t                        *fs_info,
-    uint32_t                              free_count,
-    uint32_t                              next_free
-    )
-{
-    ssize_t                 ret1 = 0, ret2 = 0;
-    uint32_t                le_free_count = 0;
-    uint32_t                le_next_free = 0;
-
-    le_free_count = CT_LE_L(free_count);
-    le_next_free = CT_LE_L(next_free);
-
-    ret1 = _fat_block_write(fs_info,
-                            fs_info->vol.info_sec,
-                            FAT_FSINFO_FREE_CLUSTER_COUNT_OFFSET,
-                            4,
-                            (char *)(&le_free_count));
-
-    ret2 = _fat_block_write(fs_info,
-                            fs_info->vol.info_sec,
-                            FAT_FSINFO_NEXT_FREE_CLUSTER_OFFSET,
-                            4,
-                            (char *)(&le_next_free));
-
-    if ( (ret1 < 0) || (ret2 < 0) )
-        return -1;
-
-    return RC_OK;
-}
diff --git a/cpukit/libfs/src/dosfs/fat.h b/cpukit/libfs/src/dosfs/fat.h
index 3a9c9c6..196bac5 100644
--- a/cpukit/libfs/src/dosfs/fat.h
+++ b/cpukit/libfs/src/dosfs/fat.h
@@ -313,7 +313,11 @@ typedef struct fat_vol_s
     uint32_t           rdir_cl;        /* first cluster of the root directory */
     uint16_t           info_sec;       /* FSInfo Sector Structure location */
     uint32_t           free_cls;       /* last known free clusters count */
+    uint32_t           free_cls_in_fs_info; /* last known free clusters count
+                                               in FS info sector */
     uint32_t           next_cl;        /* next free cluster number */
+    uint32_t           next_cl_in_fs_info; /* next free cluster number in FS
+                                              info sector */
     uint8_t            mirror;         /* mirroring enabla/disable */
     uint32_t           afat_loc;       /* active FAT location */
     uint8_t            afat;           /* the number of active FAT */
@@ -499,13 +503,6 @@ void
 fat_free_unique_ino(fat_fs_info_t                        *fs_info,
                     uint32_t                              ino);

-int
-fat_fat32_update_fsinfo_sector(
-  fat_fs_info_t                        *fs_info,
-  uint32_t                              free_count,
-  uint32_t                              next_free
-  );
-
 #ifdef __cplusplus
 }
 #endif
--
1.7.7

_______________________________________________
rtems-devel mailing list
rtems-devel at rtems.org
http://www.rtems.org/mailman/listinfo/rtems-devel




More information about the devel mailing list