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_ */