shithub: lwext4

Download patch

ref: 029801c149836ea76776a9bbebe7bed532febdba
parent: 74d0e84547710dcb8bc93b23aa0a5c9450af52a9
author: gkostka <kostka.grzegorz@gmail.com>
date: Sat Jan 18 14:34:13 EST 2014

Write back cache mode.

--- a/demos/generic/main.c
+++ b/demos/generic/main.c
@@ -231,6 +231,7 @@
     }
 
 
+    ext4_cache_write_back("/mp/", 1);
     printf("Add files to: /mp/dir1\n");
     for (i = 0; i < len; ++i) {
         sprintf(path, "/mp/dir1/f%d", i);
@@ -240,6 +241,7 @@
             return false;
         }
     }
+    ext4_cache_write_back("/mp/", 0);
 
     stop =  get_ms();
     diff = stop - start;
--- a/ext4.h
+++ b/ext4.h
@@ -204,6 +204,44 @@
 int ext4_mount_point_stats(const char *mount_point,
     struct ext4_mount_stats *stats);
 
+
+/**@brief   Enable/disable write back cache mode.
+ * @warning Default model of cache is write trough. It means that when You do:
+ *
+ *          ext4_fopen(...);
+ *          ext4_fwrie(...);
+ *                           < --- data is flushed to physical drive
+ *
+ *          When you do:
+ *          ext4_cache_write_back(..., 1);
+ *          ext4_fopen(...);
+ *          ext4_fwrie(...);
+ *                           < --- data is NOT flushed to physical drive
+ *          ext4_cache_write_back(..., 0);
+ *                           < --- when write back mode is disabled all
+ *                                 cache data will be flushed
+ * To enable write back mode permanently just call this function
+ * once after ext4_mount (and disable before ext4_umount).
+ *
+ * Some of the function use write back cache mode internally.
+ * If you enable write back mode twice you have to disable it twice
+ * to flush all data:
+ *
+ *      ext4_cache_write_back(..., 1);
+ *      ext4_cache_write_back(..., 1);
+ *
+ *      ext4_cache_write_back(..., 0);
+ *      ext4_cache_write_back(..., 0);
+ *
+ * Write back mode is useful when you want to create a lot of empty
+ * files/directories.
+ *
+ * @param   path moutnpoint path
+ * @param   on enable/disable
+ *
+ * @return  standard error code */
+int ext4_cache_write_back(const char *path, bool on);
+
 /********************************FILE OPERATIONS*****************************/
 
 /**@brief   Remove file by path.
--- a/lwext4/ext4.c
+++ b/lwext4/ext4.c
@@ -95,7 +95,6 @@
 struct ext4_mountpoint _mp[CONFIG_EXT4_MOUNTPOINTS_COUNT];
 
 
-
 int ext4_device_register(struct ext4_blockdev *bd, struct ext4_bcache *bc,
     const char *dev_name)
 {
@@ -129,7 +128,6 @@
 
 static int ext4_has_children(bool *has_children, struct ext4_inode_ref *enode)
 {
-
     struct ext4_fs *fs = enode->fs;
 
     /* Check if node is directory */
@@ -683,6 +681,20 @@
 
 /****************************************************************************/
 
+int ext4_cache_write_back(const char *path, bool on)
+{
+    struct ext4_mountpoint *mp = ext4_get_mount(path);
+
+    if(!mp)
+        return ENOENT;
+
+    EXT4_MP_LOCK(mp);
+    ext4_block_cache_write_back(mp->fs.bdev, on);
+    EXT4_MP_UNLOCK(mp);
+    return EOK;
+}
+
+
 int ext4_fremove(const char *path)
 {
     ext4_file   f;
@@ -722,10 +734,10 @@
     }
 
     /*Turncate.*/
-    ext4_block_delay_cache_flush(mp->fs.bdev, 1);
-    /*Truncate may be IO heavy. Do it with delayed cache flush mode.*/
+    ext4_block_cache_write_back(mp->fs.bdev, 1);
+    /*Truncate may be IO heavy. Do it writeback cache mode.*/
     r = ext4_fs_truncate_inode(&child, 0);
-    ext4_block_delay_cache_flush(mp->fs.bdev, 0);
+    ext4_block_cache_write_back(mp->fs.bdev, 0);
 
     if(r != EOK)
         goto Finish;
@@ -751,7 +763,6 @@
     return r;
 }
 
-
 int ext4_fopen (ext4_file *f, const char *path, const char *flags)
 {
     struct ext4_mountpoint *mp = ext4_get_mount(path);
@@ -761,9 +772,9 @@
         return ENOENT;
 
     EXT4_MP_LOCK(mp);
-    ext4_block_delay_cache_flush(mp->fs.bdev, 1);
+    ext4_block_cache_write_back(mp->fs.bdev, 1);
     r = ext4_generic_open(f, path, flags, true, 0, 0);
-    ext4_block_delay_cache_flush(mp->fs.bdev, 0);
+    ext4_block_cache_write_back(mp->fs.bdev, 0);
     EXT4_MP_UNLOCK(mp);
     return r;
 }
@@ -993,8 +1004,8 @@
     }
 
 
-    /*Start delay cache flush mode.*/
-    r = ext4_block_delay_cache_flush(f->mp->fs.bdev, 1);
+    /*Start write back cache mode.*/
+    r = ext4_block_cache_write_back(f->mp->fs.bdev, 1);
     if(r != EOK)
         goto Finish;
 
@@ -1041,8 +1052,8 @@
         fblock_cnt = 1;
     }
 
-    /*Stop delay cache flush mode*/
-    ext4_block_delay_cache_flush(f->mp->fs.bdev, 0);
+    /*Stop write back cache mode*/
+    ext4_block_cache_write_back(f->mp->fs.bdev, 0);
 
     if(r != EOK)
         goto Finish;
@@ -1165,7 +1176,7 @@
     inode_current = f.inode;
     dir_end = false;
 
-    ext4_block_delay_cache_flush(mp->fs.bdev, 1);
+    ext4_block_cache_write_back(mp->fs.bdev, 1);
 
     do {
         /*Load directory node.*/
@@ -1300,7 +1311,7 @@
 
     }while(depth);
 
-    ext4_block_delay_cache_flush(mp->fs.bdev, 0);
+    ext4_block_cache_write_back(mp->fs.bdev, 0);
     EXT4_MP_UNLOCK(mp);
     return r;
 }
--- a/lwext4/ext4_bcache.h
+++ b/lwext4/ext4_bcache.h
@@ -76,7 +76,7 @@
     /**@brief   Last recently used ID table (cnt)*/
     uint32_t *lru_id;
 
-    /**@brief   Free delay mode table (cnt)*/
+    /**@brief   Writeback free delay mode table (cnt)*/
     uint8_t *free_delay;
 
     /**@brief   Logical block table (cnt).*/
@@ -143,6 +143,7 @@
 /**@brief   Free block from cache memory (decrement reference counter).
  * @param   bc block cache descriptor
  * @param   b block to free
+ * @param   cache writeback mode
  * @return  standard error code*/
 int ext4_bcache_free (struct ext4_bcache *bc, struct ext4_block *b,
     uint8_t free_delay);
--- a/lwext4/ext4_blockdev.c
+++ b/lwext4/ext4_blockdev.c
@@ -110,7 +110,7 @@
     b->lb_id = lba;
 
     /*If cache is full we have to flush it anyway :(*/
-    if(ext4_bcache_is_full(bdev->bc) && bdev->cache_flush_delay){
+    if(ext4_bcache_is_full(bdev->bc) && bdev->cache_write_back){
         for (i = 0; i < bdev->bc->cnt; ++i) {
             /*Check if buffer free was delayed.*/
             if(!bdev->bc->free_delay[i])
@@ -182,10 +182,10 @@
     }
 
     /*Free cache delay mode*/
-    if(bdev->cache_flush_delay){
+    if(bdev->cache_write_back){
 
         /*Free cahe block and mark as free delayed*/
-        return ext4_bcache_free(bdev->bc, b, bdev->cache_flush_delay);
+        return ext4_bcache_free(bdev->bc, b, bdev->cache_write_back);
     }
 
     pba = (b->lb_id * bdev->lg_bsize) / bdev->ph_bsize;
@@ -319,8 +319,6 @@
 }
 
 
-
-
 int ext4_block_readbytes(struct ext4_blockdev *bdev, uint64_t off, void *buf,
     uint32_t len)
 {
@@ -387,15 +385,20 @@
     return r;
 }
 
-int ext4_block_delay_cache_flush(struct ext4_blockdev *bdev,
+int ext4_block_cache_write_back(struct ext4_blockdev *bdev,
     uint8_t on_off)
 {
     int r;
     uint32_t i;
-    bdev->cache_flush_delay = on_off;
 
+    if(on_off)
+        bdev->cache_write_back++;
+
+    if(!on_off && bdev->cache_write_back)
+        bdev->cache_write_back--;
+
     /*Flush all delayed cache blocks*/
-    if(!on_off){
+    if(!bdev->cache_write_back){
         for (i = 0; i < bdev->bc->cnt; ++i) {
 
             /*Check if buffer free was delayed.*/
--- a/lwext4/ext4_blockdev.h
+++ b/lwext4/ext4_blockdev.h
@@ -93,10 +93,10 @@
     uint64_t    lg_bcnt;
 
     /**@brief   Flags of te block device.*/
-    uint8_t     flags;
+    uint32_t    flags;
 
-    /**@brief   Cache flush delay mode flag.*/
-    uint8_t     cache_flush_delay;
+    /**@brief   Cache write back mode refference counter.*/
+    uint32_t    cache_write_back;
 
     /**@brief   Physical read counter*/
     uint32_t    bread_ctr;
@@ -200,13 +200,13 @@
 int ext4_block_readbytes(struct ext4_blockdev *bdev, uint64_t off,
     void *buf, uint32_t len);
 
-/**@brief   Enable/disable delayed cache flush mode.
+/**@brief   Enable/disable write back cache mode
  * @param   bdev block device descriptor
  * @param   on_off
  *              !0 - ENABLE
  *               0 - DISABLE (all delayed cache buffers will be flushed)
  * @return  standard error code*/
-int ext4_block_delay_cache_flush(struct ext4_blockdev *bdev, uint8_t on_off);
+int ext4_block_cache_write_back(struct ext4_blockdev *bdev, uint8_t on_off);
 
 #endif /* EXT4_BLOCKDEV_H_ */