Update preset.
[bertos.git] / bertos / fs / battfs.c
index 9eeedb456335107bbe684bb6708810db634e5784..f40d310d8d3bae3d77f500dbd6640f30b9054700 100644 (file)
@@ -32,7 +32,6 @@
  *
  * \brief BattFS: a filesystem for embedded platforms (implementation).
  *
- * \version $Id$
  *
  * \author Francesco Sacchi <batt@develer.com>
  *
@@ -367,6 +366,7 @@ bool battfs_mount(struct BattFsSuper *disk, struct KBlock *dev, pgcnt_t *page_ar
        pgoff_t filelen_table[BATTFS_MAX_FILES];
 
        ASSERT(dev);
+       ASSERT(kblock_partialWrite(dev));
        disk->dev = dev;
 
        ASSERT(disk->dev->blk_size > BATTFS_HEADER_LEN);
@@ -545,7 +545,7 @@ static pgcnt_t renewPage(struct BattFsSuper *disk, pgcnt_t old_pos)
        if (SPACE_OVER(disk))
        {
                LOG_ERR("No disk space available!\n");
-               return PAGE_UNSET_SENTINEL;
+               return NO_SPACE;
        }
 
        /* Get a free page */
@@ -589,18 +589,31 @@ static size_t battfs_write(struct KFile *fd, const void *_buf, size_t size)
                        return total_write;
                }
 
-               new_page = renewPage(disk, fdb->start[fdb->max_off]);
-               if (new_page == NO_SPACE)
+               /*
+                * Renew page only if is not in cache.
+                * This avoids rewriting the same page continuously
+                * if the user code keeps writing in the same portion
+                * of the file.
+                */
+               if (kblock_buffered(disk->dev)
+                       && ((fdb->start[fdb->max_off] != kblock_cachedBlock(disk->dev)) || !kblock_cacheDirty(disk->dev)))
                {
-                       fdb->errors |= BATTFS_DISK_SPACEOVER_ERR;
-                       return total_write;
-               }
+                       new_page = renewPage(disk, fdb->start[fdb->max_off]);
+                       if (new_page == NO_SPACE)
+                       {
+                               fdb->errors |= BATTFS_DISK_SPACEOVER_ERR;
+                               return total_write;
+                       }
 
-               kblock_copy(disk->dev, fdb->start[fdb->max_off], new_page);
-               fdb->start[fdb->max_off] = new_page;
+                       kblock_copy(disk->dev, fdb->start[fdb->max_off], new_page);
+                       fdb->start[fdb->max_off] = new_page;
+               }
+               else
+                       new_page = fdb->start[fdb->max_off];
 
                /* Fill unused space of first page with 0s */
                uint8_t dummy = 0;
+               // TODO: write in blocks to speed up things
                pgaddr_t zero_bytes = MIN(fd->seek_pos - fd->size, (kfile_off_t)(disk->data_size - curr_hdr.fill));
                while (zero_bytes--)
                {
@@ -623,46 +636,44 @@ static size_t battfs_write(struct KFile *fd, const void *_buf, size_t size)
                /* Allocate the missing pages first. */
                pgoff_t missing_pages = fd->seek_pos / disk->data_size - fdb->max_off;
 
-               if (missing_pages)
+               LOG_INFO("missing pages: %d\n", missing_pages);
+
+               while (missing_pages--)
                {
-                       LOG_INFO("missing pages: %d\n", missing_pages);
+                       zero_bytes = MIN((kfile_off_t)disk->data_size, fd->seek_pos - fd->size);
 
-                       while (missing_pages--)
+                       new_page = allocateNewPage(disk, (fdb->start - disk->page_array) + fdb->max_off + 1, fdb->inode);
+                       if (new_page == NO_SPACE)
                        {
-                               zero_bytes = MIN((kfile_off_t)disk->data_size, fd->seek_pos - fd->size);
-
-                               new_page = allocateNewPage(disk, (fdb->start - disk->page_array) + fdb->max_off + 1, fdb->inode);
-                               if (new_page == NO_SPACE)
-                               {
-                                       fdb->errors |= BATTFS_DISK_SPACEOVER_ERR;
-                                       return total_write;
-                               }
-
+                               fdb->errors |= BATTFS_DISK_SPACEOVER_ERR;
+                               return total_write;
+                       }
 
-                               /* Fill page buffer with 0 to avoid filling unused pages with garbage */
-                               for (pgaddr_t off = 0; off < disk->data_size; off++)
-                               {
-                                       if (kblock_write(disk->dev, new_page, &dummy, off, 1) != 1)
-                                       {
-                                               fdb->errors |= BATTFS_DISK_WRITE_ERR;
-                                               return total_write;
-                                       }
-                               }
-                               curr_hdr.inode = fdb->inode;
-                               curr_hdr.pgoff = ++fdb->max_off;
-                               curr_hdr.fill = zero_bytes;
-                               curr_hdr.seq = 0;
 
-                               if (!writeHdr(disk, new_page, &curr_hdr))
+                       // TODO: write in blocks to speed up things
+                       /* Fill page buffer with 0 to avoid filling unused pages with garbage */
+                       for (pgaddr_t off = 0; off < disk->data_size; off++)
+                       {
+                               if (kblock_write(disk->dev, new_page, &dummy, off, 1) != 1)
                                {
                                        fdb->errors |= BATTFS_DISK_WRITE_ERR;
                                        return total_write;
                                }
+                       }
+                       curr_hdr.inode = fdb->inode;
+                       curr_hdr.pgoff = ++fdb->max_off;
+                       curr_hdr.fill = zero_bytes;
+                       curr_hdr.seq = 0;
 
-                               /* Update size and free space left */
-                               fd->size += zero_bytes;
-                               disk->free_bytes -= zero_bytes;
+                       if (!writeHdr(disk, new_page, &curr_hdr))
+                       {
+                               fdb->errors |= BATTFS_DISK_WRITE_ERR;
+                               return total_write;
                        }
+
+                       /* Update size and free space left */
+                       fd->size += zero_bytes;
+                       disk->free_bytes -= zero_bytes;
                }
        }
 
@@ -698,20 +709,31 @@ static size_t battfs_write(struct KFile *fd, const void *_buf, size_t size)
                                return total_write;
                        }
 
-                       new_page = renewPage(disk, fdb->start[pg_offset]);
-                       if (new_page == NO_SPACE)
+                       /* Renew page only if is not in cache. */
+                       if (kblock_buffered(disk->dev)
+                               && ((fdb->start[fdb->max_off] != kblock_cachedBlock(disk->dev)) || !kblock_cacheDirty(disk->dev)))
                        {
-                               fdb->errors |= BATTFS_DISK_SPACEOVER_ERR;
-                               return total_write;
-                       }
+                               new_page = renewPage(disk, fdb->start[pg_offset]);
+                               if (new_page == NO_SPACE)
+                               {
+                                       fdb->errors |= BATTFS_DISK_SPACEOVER_ERR;
+                                       return total_write;
+                               }
 
-                       LOG_INFO("Re-writing page %d to %d\n", fdb->start[pg_offset], new_page);
-                       if (kblock_copy(disk->dev, fdb->start[pg_offset], new_page) != 0)
+                               LOG_INFO("Re-writing page %d to %d\n", fdb->start[pg_offset], new_page);
+                               if (kblock_copy(disk->dev, fdb->start[pg_offset], new_page) != 0)
+                               {
+                                       fdb->errors |= BATTFS_DISK_WRITE_ERR;
+                                       return total_write;
+                               }
+                               fdb->start[pg_offset] = new_page;
+                       }
+                       else
                        {
-                               fdb->errors |= BATTFS_DISK_WRITE_ERR;
-                               return total_write;
+                               LOG_INFO("Using cached block %d\n", fdb->start[pg_offset]);
+                               new_page = fdb->start[pg_offset];
                        }
-                       fdb->start[pg_offset] = new_page;
+
                        curr_hdr.seq++;
                }
                //LOG_INFO("writing to buffer for page %d, offset %d, size %d\n", disk->curr_page, addr_offset, wr_len);